clk-a10-pll2.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Copyright 2013 Emilio López
  3. * Emilio López <emilio@elopez.com.ar>
  4. *
  5. * Copyright 2015 Maxime Ripard
  6. * Maxime Ripard <maxime.ripard@free-electrons.com>
  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; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/clk-provider.h>
  19. #include <linux/of.h>
  20. #include <linux/of_address.h>
  21. #include <linux/slab.h>
  22. #include <dt-bindings/clock/sun4i-a10-pll2.h>
  23. #define SUN4I_PLL2_ENABLE 31
  24. #define SUN4I_PLL2_PRE_DIV_SHIFT 0
  25. #define SUN4I_PLL2_PRE_DIV_WIDTH 5
  26. #define SUN4I_PLL2_PRE_DIV_MASK GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0)
  27. #define SUN4I_PLL2_N_SHIFT 8
  28. #define SUN4I_PLL2_N_WIDTH 7
  29. #define SUN4I_PLL2_N_MASK GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0)
  30. #define SUN4I_PLL2_POST_DIV_SHIFT 26
  31. #define SUN4I_PLL2_POST_DIV_WIDTH 4
  32. #define SUN4I_PLL2_POST_DIV_MASK GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0)
  33. #define SUN4I_PLL2_POST_DIV_VALUE 4
  34. #define SUN4I_PLL2_OUTPUTS 4
  35. static DEFINE_SPINLOCK(sun4i_a10_pll2_lock);
  36. static void __init sun4i_pll2_setup(struct device_node *node,
  37. int post_div_offset)
  38. {
  39. const char *clk_name = node->name, *parent;
  40. struct clk **clks, *base_clk, *prediv_clk;
  41. struct clk_onecell_data *clk_data;
  42. struct clk_multiplier *mult;
  43. struct clk_gate *gate;
  44. void __iomem *reg;
  45. u32 val;
  46. reg = of_io_request_and_map(node, 0, of_node_full_name(node));
  47. if (IS_ERR(reg))
  48. return;
  49. clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
  50. if (!clk_data)
  51. goto err_unmap;
  52. clks = kcalloc(SUN4I_PLL2_OUTPUTS, sizeof(struct clk *), GFP_KERNEL);
  53. if (!clks)
  54. goto err_free_data;
  55. parent = of_clk_get_parent_name(node, 0);
  56. prediv_clk = clk_register_divider(NULL, "pll2-prediv",
  57. parent, 0, reg,
  58. SUN4I_PLL2_PRE_DIV_SHIFT,
  59. SUN4I_PLL2_PRE_DIV_WIDTH,
  60. CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
  61. &sun4i_a10_pll2_lock);
  62. if (IS_ERR(prediv_clk)) {
  63. pr_err("Couldn't register the prediv clock\n");
  64. goto err_free_array;
  65. }
  66. /* Setup the gate part of the PLL2 */
  67. gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
  68. if (!gate)
  69. goto err_unregister_prediv;
  70. gate->reg = reg;
  71. gate->bit_idx = SUN4I_PLL2_ENABLE;
  72. gate->lock = &sun4i_a10_pll2_lock;
  73. /* Setup the multiplier part of the PLL2 */
  74. mult = kzalloc(sizeof(struct clk_multiplier), GFP_KERNEL);
  75. if (!mult)
  76. goto err_free_gate;
  77. mult->reg = reg;
  78. mult->shift = SUN4I_PLL2_N_SHIFT;
  79. mult->width = 7;
  80. mult->flags = CLK_MULTIPLIER_ZERO_BYPASS |
  81. CLK_MULTIPLIER_ROUND_CLOSEST;
  82. mult->lock = &sun4i_a10_pll2_lock;
  83. parent = __clk_get_name(prediv_clk);
  84. base_clk = clk_register_composite(NULL, "pll2-base",
  85. &parent, 1,
  86. NULL, NULL,
  87. &mult->hw, &clk_multiplier_ops,
  88. &gate->hw, &clk_gate_ops,
  89. CLK_SET_RATE_PARENT);
  90. if (IS_ERR(base_clk)) {
  91. pr_err("Couldn't register the base multiplier clock\n");
  92. goto err_free_multiplier;
  93. }
  94. parent = __clk_get_name(base_clk);
  95. /*
  96. * PLL2-1x
  97. *
  98. * This is supposed to have a post divider, but we won't need
  99. * to use it, we just need to initialise it to 4, and use a
  100. * fixed divider.
  101. */
  102. val = readl(reg);
  103. val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT);
  104. val |= (SUN4I_PLL2_POST_DIV_VALUE - post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
  105. writel(val, reg);
  106. of_property_read_string_index(node, "clock-output-names",
  107. SUN4I_A10_PLL2_1X, &clk_name);
  108. clks[SUN4I_A10_PLL2_1X] = clk_register_fixed_factor(NULL, clk_name,
  109. parent,
  110. CLK_SET_RATE_PARENT,
  111. 1,
  112. SUN4I_PLL2_POST_DIV_VALUE);
  113. WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_1X]));
  114. /*
  115. * PLL2-2x
  116. *
  117. * This clock doesn't use the post divider, and really is just
  118. * a fixed divider from the PLL2 base clock.
  119. */
  120. of_property_read_string_index(node, "clock-output-names",
  121. SUN4I_A10_PLL2_2X, &clk_name);
  122. clks[SUN4I_A10_PLL2_2X] = clk_register_fixed_factor(NULL, clk_name,
  123. parent,
  124. CLK_SET_RATE_PARENT,
  125. 1, 2);
  126. WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_2X]));
  127. /* PLL2-4x */
  128. of_property_read_string_index(node, "clock-output-names",
  129. SUN4I_A10_PLL2_4X, &clk_name);
  130. clks[SUN4I_A10_PLL2_4X] = clk_register_fixed_factor(NULL, clk_name,
  131. parent,
  132. CLK_SET_RATE_PARENT,
  133. 1, 1);
  134. WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_4X]));
  135. /* PLL2-8x */
  136. of_property_read_string_index(node, "clock-output-names",
  137. SUN4I_A10_PLL2_8X, &clk_name);
  138. clks[SUN4I_A10_PLL2_8X] = clk_register_fixed_factor(NULL, clk_name,
  139. parent,
  140. CLK_SET_RATE_PARENT,
  141. 2, 1);
  142. WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_8X]));
  143. clk_data->clks = clks;
  144. clk_data->clk_num = SUN4I_PLL2_OUTPUTS;
  145. of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
  146. return;
  147. err_free_multiplier:
  148. kfree(mult);
  149. err_free_gate:
  150. kfree(gate);
  151. err_unregister_prediv:
  152. clk_unregister_divider(prediv_clk);
  153. err_free_array:
  154. kfree(clks);
  155. err_free_data:
  156. kfree(clk_data);
  157. err_unmap:
  158. iounmap(reg);
  159. }
  160. static void __init sun4i_a10_pll2_setup(struct device_node *node)
  161. {
  162. sun4i_pll2_setup(node, 0);
  163. }
  164. CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk",
  165. sun4i_a10_pll2_setup);
  166. static void __init sun5i_a13_pll2_setup(struct device_node *node)
  167. {
  168. sun4i_pll2_setup(node, 1);
  169. }
  170. CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk",
  171. sun5i_a13_pll2_setup);