clk-pxa.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Marvell PXA family clocks
  3. *
  4. * Copyright (C) 2014 Robert Jarzmik
  5. *
  6. * Common clock code for PXA clocks ("CKEN" type clocks + DT)
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; version 2 of the License.
  11. *
  12. */
  13. #include <linux/clk.h>
  14. #include <linux/clk-provider.h>
  15. #include <linux/clkdev.h>
  16. #include <linux/of.h>
  17. #include <dt-bindings/clock/pxa-clock.h>
  18. #include "clk-pxa.h"
  19. DEFINE_SPINLOCK(lock);
  20. static struct clk *pxa_clocks[CLK_MAX];
  21. static struct clk_onecell_data onecell_data = {
  22. .clks = pxa_clocks,
  23. .clk_num = CLK_MAX,
  24. };
  25. #define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk_cken, hw)
  26. static unsigned long cken_recalc_rate(struct clk_hw *hw,
  27. unsigned long parent_rate)
  28. {
  29. struct pxa_clk_cken *pclk = to_pxa_clk(hw);
  30. struct clk_fixed_factor *fix;
  31. if (!pclk->is_in_low_power || pclk->is_in_low_power())
  32. fix = &pclk->lp;
  33. else
  34. fix = &pclk->hp;
  35. fix->hw.clk = hw->clk;
  36. return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate);
  37. }
  38. static struct clk_ops cken_rate_ops = {
  39. .recalc_rate = cken_recalc_rate,
  40. };
  41. static u8 cken_get_parent(struct clk_hw *hw)
  42. {
  43. struct pxa_clk_cken *pclk = to_pxa_clk(hw);
  44. if (!pclk->is_in_low_power)
  45. return 0;
  46. return pclk->is_in_low_power() ? 0 : 1;
  47. }
  48. static struct clk_ops cken_mux_ops = {
  49. .get_parent = cken_get_parent,
  50. .set_parent = dummy_clk_set_parent,
  51. };
  52. void __init clkdev_pxa_register(int ckid, const char *con_id,
  53. const char *dev_id, struct clk *clk)
  54. {
  55. if (!IS_ERR(clk) && (ckid != CLK_NONE))
  56. pxa_clocks[ckid] = clk;
  57. if (!IS_ERR(clk))
  58. clk_register_clkdev(clk, con_id, dev_id);
  59. }
  60. int __init clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks)
  61. {
  62. int i;
  63. struct pxa_clk_cken *pclk;
  64. struct clk *clk;
  65. for (i = 0; i < nb_clks; i++) {
  66. pclk = clks + i;
  67. pclk->gate.lock = &lock;
  68. clk = clk_register_composite(NULL, pclk->name,
  69. pclk->parent_names, 2,
  70. &pclk->hw, &cken_mux_ops,
  71. &pclk->hw, &cken_rate_ops,
  72. &pclk->gate.hw, &clk_gate_ops,
  73. pclk->flags);
  74. clkdev_pxa_register(pclk->ckid, pclk->con_id, pclk->dev_id,
  75. clk);
  76. }
  77. return 0;
  78. }
  79. static void __init pxa_dt_clocks_init(struct device_node *np)
  80. {
  81. of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
  82. }
  83. CLK_OF_DECLARE(pxa_clks, "marvell,pxa-clocks", pxa_dt_clocks_init);