clk-fractional-divider.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2014 Intel Corporation
  4. *
  5. * Adjustable fractional divider clock implementation.
  6. * Uses rational best approximation algorithm.
  7. *
  8. * Output is calculated as
  9. *
  10. * rate = (m / n) * parent_rate (1)
  11. *
  12. * This is useful when we have a prescaler block which asks for
  13. * m (numerator) and n (denominator) values to be provided to satisfy
  14. * the (1) as much as possible.
  15. *
  16. * Since m and n have the limitation by a range, e.g.
  17. *
  18. * n >= 1, n < N_width, where N_width = 2^nwidth (2)
  19. *
  20. * for some cases the output may be saturated. Hence, from (1) and (2),
  21. * assuming the worst case when m = 1, the inequality
  22. *
  23. * floor(log2(parent_rate / rate)) <= nwidth (3)
  24. *
  25. * may be derived. Thus, in cases when
  26. *
  27. * (parent_rate / rate) >> N_width (4)
  28. *
  29. * we might scale up the rate by 2^scale (see the description of
  30. * CLK_FRAC_DIVIDER_POWER_OF_TWO_PS for additional information), where
  31. *
  32. * scale = floor(log2(parent_rate / rate)) - nwidth (5)
  33. *
  34. * and assume that the IP, that needs m and n, has also its own
  35. * prescaler, which is capable to divide by 2^scale. In this way
  36. * we get the denominator to satisfy the desired range (2) and
  37. * at the same time a much better result of m and n than simple
  38. * saturated values.
  39. */
  40. #include <linux/debugfs.h>
  41. #include <linux/device.h>
  42. #include <linux/io.h>
  43. #include <linux/math.h>
  44. #include <linux/module.h>
  45. #include <linux/rational.h>
  46. #include <linux/slab.h>
  47. #include <linux/clk-provider.h>
  48. #include "clk-fractional-divider.h"
  49. static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
  50. {
  51. if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
  52. return ioread32be(fd->reg);
  53. return readl(fd->reg);
  54. }
  55. static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
  56. {
  57. if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
  58. iowrite32be(val, fd->reg);
  59. else
  60. writel(val, fd->reg);
  61. }
  62. static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract)
  63. {
  64. struct clk_fractional_divider *fd = to_clk_fd(hw);
  65. unsigned long flags = 0;
  66. unsigned long m, n;
  67. u32 mmask, nmask;
  68. u32 val;
  69. if (fd->lock)
  70. spin_lock_irqsave(fd->lock, flags);
  71. else
  72. __acquire(fd->lock);
  73. val = clk_fd_readl(fd);
  74. if (fd->lock)
  75. spin_unlock_irqrestore(fd->lock, flags);
  76. else
  77. __release(fd->lock);
  78. mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
  79. nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
  80. m = (val & mmask) >> fd->mshift;
  81. n = (val & nmask) >> fd->nshift;
  82. if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
  83. m++;
  84. n++;
  85. }
  86. fract->numerator = m;
  87. fract->denominator = n;
  88. }
  89. static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
  90. {
  91. struct u32_fract fract;
  92. u64 ret;
  93. clk_fd_get_div(hw, &fract);
  94. if (!fract.numerator || !fract.denominator)
  95. return parent_rate;
  96. ret = (u64)parent_rate * fract.numerator;
  97. do_div(ret, fract.denominator);
  98. return ret;
  99. }
  100. void clk_fractional_divider_general_approximation(struct clk_hw *hw,
  101. unsigned long rate,
  102. unsigned long *parent_rate,
  103. unsigned long *m, unsigned long *n)
  104. {
  105. struct clk_fractional_divider *fd = to_clk_fd(hw);
  106. unsigned long max_m, max_n;
  107. /*
  108. * Get rate closer to *parent_rate to guarantee there is no overflow
  109. * for m and n. In the result it will be the nearest rate left shifted
  110. * by (scale - fd->nwidth) bits.
  111. *
  112. * For the detailed explanation see the top comment in this file.
  113. */
  114. if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) {
  115. unsigned long scale = fls_long(*parent_rate / rate - 1);
  116. if (scale > fd->nwidth)
  117. rate <<= scale - fd->nwidth;
  118. }
  119. if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
  120. max_m = BIT(fd->mwidth);
  121. max_n = BIT(fd->nwidth);
  122. } else {
  123. max_m = GENMASK(fd->mwidth - 1, 0);
  124. max_n = GENMASK(fd->nwidth - 1, 0);
  125. }
  126. rational_best_approximation(rate, *parent_rate, max_m, max_n, m, n);
  127. }
  128. EXPORT_SYMBOL_GPL(clk_fractional_divider_general_approximation);
  129. static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
  130. unsigned long *parent_rate)
  131. {
  132. struct clk_fractional_divider *fd = to_clk_fd(hw);
  133. unsigned long m, n;
  134. u64 ret;
  135. if (!rate || (!clk_hw_can_set_rate_parent(hw) && rate >= *parent_rate))
  136. return *parent_rate;
  137. if (fd->approximation)
  138. fd->approximation(hw, rate, parent_rate, &m, &n);
  139. else
  140. clk_fractional_divider_general_approximation(hw, rate, parent_rate, &m, &n);
  141. ret = (u64)*parent_rate * m;
  142. do_div(ret, n);
  143. return ret;
  144. }
  145. static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
  146. unsigned long parent_rate)
  147. {
  148. struct clk_fractional_divider *fd = to_clk_fd(hw);
  149. unsigned long flags = 0;
  150. unsigned long m, n, max_m, max_n;
  151. u32 mmask, nmask;
  152. u32 val;
  153. if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
  154. max_m = BIT(fd->mwidth);
  155. max_n = BIT(fd->nwidth);
  156. } else {
  157. max_m = GENMASK(fd->mwidth - 1, 0);
  158. max_n = GENMASK(fd->nwidth - 1, 0);
  159. }
  160. rational_best_approximation(rate, parent_rate, max_m, max_n, &m, &n);
  161. if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
  162. m--;
  163. n--;
  164. }
  165. mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
  166. nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
  167. if (fd->lock)
  168. spin_lock_irqsave(fd->lock, flags);
  169. else
  170. __acquire(fd->lock);
  171. val = clk_fd_readl(fd);
  172. val &= ~(mmask | nmask);
  173. val |= (m << fd->mshift) | (n << fd->nshift);
  174. clk_fd_writel(fd, val);
  175. if (fd->lock)
  176. spin_unlock_irqrestore(fd->lock, flags);
  177. else
  178. __release(fd->lock);
  179. return 0;
  180. }
  181. #ifdef CONFIG_DEBUG_FS
  182. static int clk_fd_numerator_get(void *hw, u64 *val)
  183. {
  184. struct u32_fract fract;
  185. clk_fd_get_div(hw, &fract);
  186. *val = fract.numerator;
  187. return 0;
  188. }
  189. DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_numerator_fops, clk_fd_numerator_get, NULL, "%llu\n");
  190. static int clk_fd_denominator_get(void *hw, u64 *val)
  191. {
  192. struct u32_fract fract;
  193. clk_fd_get_div(hw, &fract);
  194. *val = fract.denominator;
  195. return 0;
  196. }
  197. DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_denominator_fops, clk_fd_denominator_get, NULL, "%llu\n");
  198. static void clk_fd_debug_init(struct clk_hw *hw, struct dentry *dentry)
  199. {
  200. debugfs_create_file("numerator", 0444, dentry, hw, &clk_fd_numerator_fops);
  201. debugfs_create_file("denominator", 0444, dentry, hw, &clk_fd_denominator_fops);
  202. }
  203. #endif
  204. const struct clk_ops clk_fractional_divider_ops = {
  205. .recalc_rate = clk_fd_recalc_rate,
  206. .round_rate = clk_fd_round_rate,
  207. .set_rate = clk_fd_set_rate,
  208. #ifdef CONFIG_DEBUG_FS
  209. .debug_init = clk_fd_debug_init,
  210. #endif
  211. };
  212. EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
  213. struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
  214. const char *name, const char *parent_name, unsigned long flags,
  215. void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
  216. u8 clk_divider_flags, spinlock_t *lock)
  217. {
  218. struct clk_fractional_divider *fd;
  219. struct clk_init_data init;
  220. struct clk_hw *hw;
  221. int ret;
  222. fd = kzalloc(sizeof(*fd), GFP_KERNEL);
  223. if (!fd)
  224. return ERR_PTR(-ENOMEM);
  225. init.name = name;
  226. init.ops = &clk_fractional_divider_ops;
  227. init.flags = flags;
  228. init.parent_names = parent_name ? &parent_name : NULL;
  229. init.num_parents = parent_name ? 1 : 0;
  230. fd->reg = reg;
  231. fd->mshift = mshift;
  232. fd->mwidth = mwidth;
  233. fd->nshift = nshift;
  234. fd->nwidth = nwidth;
  235. fd->flags = clk_divider_flags;
  236. fd->lock = lock;
  237. fd->hw.init = &init;
  238. hw = &fd->hw;
  239. ret = clk_hw_register(dev, hw);
  240. if (ret) {
  241. kfree(fd);
  242. hw = ERR_PTR(ret);
  243. }
  244. return hw;
  245. }
  246. EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider);
  247. struct clk *clk_register_fractional_divider(struct device *dev,
  248. const char *name, const char *parent_name, unsigned long flags,
  249. void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
  250. u8 clk_divider_flags, spinlock_t *lock)
  251. {
  252. struct clk_hw *hw;
  253. hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags,
  254. reg, mshift, mwidth, nshift, nwidth, clk_divider_flags,
  255. lock);
  256. if (IS_ERR(hw))
  257. return ERR_CAST(hw);
  258. return hw->clk;
  259. }
  260. EXPORT_SYMBOL_GPL(clk_register_fractional_divider);
  261. void clk_hw_unregister_fractional_divider(struct clk_hw *hw)
  262. {
  263. struct clk_fractional_divider *fd;
  264. fd = to_clk_fd(hw);
  265. clk_hw_unregister(hw);
  266. kfree(fd);
  267. }