clk-half-divider.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
  4. */
  5. #include <linux/clk-provider.h>
  6. #include <linux/io.h>
  7. #include <linux/slab.h>
  8. #include "clk.h"
  9. #define div_mask(width) ((1 << (width)) - 1)
  10. static bool _is_best_half_div(unsigned long rate, unsigned long now,
  11. unsigned long best, unsigned long flags)
  12. {
  13. if (flags & CLK_DIVIDER_ROUND_CLOSEST)
  14. return abs(rate - now) < abs(rate - best);
  15. return now <= rate && now > best;
  16. }
  17. static unsigned long clk_half_divider_recalc_rate(struct clk_hw *hw,
  18. unsigned long parent_rate)
  19. {
  20. struct clk_divider *divider = to_clk_divider(hw);
  21. unsigned int val;
  22. val = readl(divider->reg) >> divider->shift;
  23. val &= div_mask(divider->width);
  24. val = val * 2 + 3;
  25. return DIV_ROUND_UP_ULL(((u64)parent_rate * 2), val);
  26. }
  27. static int clk_half_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
  28. unsigned long *best_parent_rate, u8 width,
  29. unsigned long flags)
  30. {
  31. unsigned int i, bestdiv = 0;
  32. unsigned long parent_rate, best = 0, now, maxdiv;
  33. unsigned long parent_rate_saved = *best_parent_rate;
  34. if (!rate)
  35. rate = 1;
  36. maxdiv = div_mask(width);
  37. if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
  38. parent_rate = *best_parent_rate;
  39. bestdiv = DIV_ROUND_UP_ULL(((u64)parent_rate * 2), rate);
  40. if (bestdiv < 3)
  41. bestdiv = 0;
  42. else
  43. bestdiv = (bestdiv - 3) / 2;
  44. bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
  45. return bestdiv;
  46. }
  47. /*
  48. * The maximum divider we can use without overflowing
  49. * unsigned long in rate * i below
  50. */
  51. maxdiv = min(ULONG_MAX / rate, maxdiv);
  52. for (i = 0; i <= maxdiv; i++) {
  53. if (((u64)rate * (i * 2 + 3)) == ((u64)parent_rate_saved * 2)) {
  54. /*
  55. * It's the most ideal case if the requested rate can be
  56. * divided from parent clock without needing to change
  57. * parent rate, so return the divider immediately.
  58. */
  59. *best_parent_rate = parent_rate_saved;
  60. return i;
  61. }
  62. parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
  63. ((u64)rate * (i * 2 + 3)) / 2);
  64. now = DIV_ROUND_UP_ULL(((u64)parent_rate * 2),
  65. (i * 2 + 3));
  66. if (_is_best_half_div(rate, now, best, flags)) {
  67. bestdiv = i;
  68. best = now;
  69. *best_parent_rate = parent_rate;
  70. }
  71. }
  72. if (!bestdiv) {
  73. bestdiv = div_mask(width);
  74. *best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1);
  75. }
  76. return bestdiv;
  77. }
  78. static int clk_half_divider_determine_rate(struct clk_hw *hw,
  79. struct clk_rate_request *req)
  80. {
  81. struct clk_divider *divider = to_clk_divider(hw);
  82. int div;
  83. div = clk_half_divider_bestdiv(hw, req->rate, &req->best_parent_rate,
  84. divider->width,
  85. divider->flags);
  86. req->rate = DIV_ROUND_UP_ULL(((u64)req->best_parent_rate * 2), div * 2 + 3);
  87. return 0;
  88. }
  89. static int clk_half_divider_set_rate(struct clk_hw *hw, unsigned long rate,
  90. unsigned long parent_rate)
  91. {
  92. struct clk_divider *divider = to_clk_divider(hw);
  93. unsigned int value;
  94. unsigned long flags = 0;
  95. u32 val;
  96. value = DIV_ROUND_UP_ULL(((u64)parent_rate * 2), rate);
  97. value = (value - 3) / 2;
  98. value = min_t(unsigned int, value, div_mask(divider->width));
  99. if (divider->lock)
  100. spin_lock_irqsave(divider->lock, flags);
  101. else
  102. __acquire(divider->lock);
  103. if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
  104. val = div_mask(divider->width) << (divider->shift + 16);
  105. } else {
  106. val = readl(divider->reg);
  107. val &= ~(div_mask(divider->width) << divider->shift);
  108. }
  109. val |= value << divider->shift;
  110. writel(val, divider->reg);
  111. if (divider->lock)
  112. spin_unlock_irqrestore(divider->lock, flags);
  113. else
  114. __release(divider->lock);
  115. return 0;
  116. }
  117. static const struct clk_ops clk_half_divider_ops = {
  118. .recalc_rate = clk_half_divider_recalc_rate,
  119. .determine_rate = clk_half_divider_determine_rate,
  120. .set_rate = clk_half_divider_set_rate,
  121. };
  122. /*
  123. * Register a clock branch.
  124. * Most clock branches have a form like
  125. *
  126. * src1 --|--\
  127. * |M |--[GATE]-[DIV]-
  128. * src2 --|--/
  129. *
  130. * sometimes without one of those components.
  131. */
  132. struct clk *rockchip_clk_register_halfdiv(const char *name,
  133. const char *const *parent_names,
  134. u8 num_parents, void __iomem *base,
  135. int muxdiv_offset, u8 mux_shift,
  136. u8 mux_width, u8 mux_flags,
  137. u8 div_shift, u8 div_width,
  138. u8 div_flags, int gate_offset,
  139. u8 gate_shift, u8 gate_flags,
  140. unsigned long flags,
  141. spinlock_t *lock)
  142. {
  143. struct clk_hw *hw = ERR_PTR(-ENOMEM);
  144. struct clk_mux *mux = NULL;
  145. struct clk_gate *gate = NULL;
  146. struct clk_divider *div = NULL;
  147. const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
  148. *gate_ops = NULL;
  149. if (num_parents > 1) {
  150. mux = kzalloc_obj(*mux);
  151. if (!mux)
  152. return ERR_PTR(-ENOMEM);
  153. mux->reg = base + muxdiv_offset;
  154. mux->shift = mux_shift;
  155. mux->mask = BIT(mux_width) - 1;
  156. mux->flags = mux_flags;
  157. mux->lock = lock;
  158. mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
  159. : &clk_mux_ops;
  160. }
  161. if (gate_offset >= 0) {
  162. gate = kzalloc_obj(*gate);
  163. if (!gate)
  164. goto err_gate;
  165. gate->flags = gate_flags;
  166. gate->reg = base + gate_offset;
  167. gate->bit_idx = gate_shift;
  168. gate->lock = lock;
  169. gate_ops = &clk_gate_ops;
  170. }
  171. if (div_width > 0) {
  172. div = kzalloc_obj(*div);
  173. if (!div)
  174. goto err_div;
  175. div->flags = div_flags;
  176. div->reg = base + muxdiv_offset;
  177. div->shift = div_shift;
  178. div->width = div_width;
  179. div->lock = lock;
  180. div_ops = &clk_half_divider_ops;
  181. }
  182. hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
  183. mux ? &mux->hw : NULL, mux_ops,
  184. div ? &div->hw : NULL, div_ops,
  185. gate ? &gate->hw : NULL, gate_ops,
  186. flags);
  187. if (IS_ERR(hw))
  188. goto err_div;
  189. return hw->clk;
  190. err_div:
  191. kfree(gate);
  192. err_gate:
  193. kfree(mux);
  194. return ERR_CAST(hw);
  195. }