clk-rcg2.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright (c) 2013, The Linux Foundation. All rights reserved.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/bitops.h>
  15. #include <linux/err.h>
  16. #include <linux/bug.h>
  17. #include <linux/export.h>
  18. #include <linux/clk-provider.h>
  19. #include <linux/delay.h>
  20. #include <linux/regmap.h>
  21. #include <asm/div64.h>
  22. #include "clk-rcg.h"
  23. #define CMD_REG 0x0
  24. #define CMD_UPDATE BIT(0)
  25. #define CMD_ROOT_EN BIT(1)
  26. #define CMD_DIRTY_CFG BIT(4)
  27. #define CMD_DIRTY_N BIT(5)
  28. #define CMD_DIRTY_M BIT(6)
  29. #define CMD_DIRTY_D BIT(7)
  30. #define CMD_ROOT_OFF BIT(31)
  31. #define CFG_REG 0x4
  32. #define CFG_SRC_DIV_SHIFT 0
  33. #define CFG_SRC_SEL_SHIFT 8
  34. #define CFG_SRC_SEL_MASK (0x7 << CFG_SRC_SEL_SHIFT)
  35. #define CFG_MODE_SHIFT 12
  36. #define CFG_MODE_MASK (0x3 << CFG_MODE_SHIFT)
  37. #define CFG_MODE_DUAL_EDGE (0x2 << CFG_MODE_SHIFT)
  38. #define M_REG 0x8
  39. #define N_REG 0xc
  40. #define D_REG 0x10
  41. static int clk_rcg2_is_enabled(struct clk_hw *hw)
  42. {
  43. struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  44. u32 cmd;
  45. int ret;
  46. ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
  47. if (ret)
  48. return ret;
  49. return (cmd & CMD_ROOT_OFF) != 0;
  50. }
  51. static u8 clk_rcg2_get_parent(struct clk_hw *hw)
  52. {
  53. struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  54. int num_parents = __clk_get_num_parents(hw->clk);
  55. u32 cfg;
  56. int i, ret;
  57. ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
  58. if (ret)
  59. return ret;
  60. cfg &= CFG_SRC_SEL_MASK;
  61. cfg >>= CFG_SRC_SEL_SHIFT;
  62. for (i = 0; i < num_parents; i++)
  63. if (cfg == rcg->parent_map[i])
  64. return i;
  65. return -EINVAL;
  66. }
  67. static int update_config(struct clk_rcg2 *rcg)
  68. {
  69. int count, ret;
  70. u32 cmd;
  71. struct clk_hw *hw = &rcg->clkr.hw;
  72. const char *name = __clk_get_name(hw->clk);
  73. ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
  74. CMD_UPDATE, CMD_UPDATE);
  75. if (ret)
  76. return ret;
  77. /* Wait for update to take effect */
  78. for (count = 500; count > 0; count--) {
  79. ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
  80. if (ret)
  81. return ret;
  82. if (!(cmd & CMD_UPDATE))
  83. return 0;
  84. udelay(1);
  85. }
  86. WARN(1, "%s: rcg didn't update its configuration.", name);
  87. return 0;
  88. }
  89. static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
  90. {
  91. struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  92. int ret;
  93. ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
  94. CFG_SRC_SEL_MASK,
  95. rcg->parent_map[index] << CFG_SRC_SEL_SHIFT);
  96. if (ret)
  97. return ret;
  98. return update_config(rcg);
  99. }
  100. /*
  101. * Calculate m/n:d rate
  102. *
  103. * parent_rate m
  104. * rate = ----------- x ---
  105. * hid_div n
  106. */
  107. static unsigned long
  108. calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
  109. {
  110. if (hid_div) {
  111. rate *= 2;
  112. rate /= hid_div + 1;
  113. }
  114. if (mode) {
  115. u64 tmp = rate;
  116. tmp *= m;
  117. do_div(tmp, n);
  118. rate = tmp;
  119. }
  120. return rate;
  121. }
  122. static unsigned long
  123. clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
  124. {
  125. struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  126. u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask;
  127. regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
  128. if (rcg->mnd_width) {
  129. mask = BIT(rcg->mnd_width) - 1;
  130. regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, &m);
  131. m &= mask;
  132. regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, &n);
  133. n = ~n;
  134. n &= mask;
  135. n += m;
  136. mode = cfg & CFG_MODE_MASK;
  137. mode >>= CFG_MODE_SHIFT;
  138. }
  139. mask = BIT(rcg->hid_width) - 1;
  140. hid_div = cfg >> CFG_SRC_DIV_SHIFT;
  141. hid_div &= mask;
  142. return calc_rate(parent_rate, m, n, mode, hid_div);
  143. }
  144. static const
  145. struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
  146. {
  147. if (!f)
  148. return NULL;
  149. for (; f->freq; f++)
  150. if (rate <= f->freq)
  151. return f;
  152. return NULL;
  153. }
  154. static long _freq_tbl_determine_rate(struct clk_hw *hw,
  155. const struct freq_tbl *f, unsigned long rate,
  156. unsigned long *p_rate, struct clk **p)
  157. {
  158. unsigned long clk_flags;
  159. f = find_freq(f, rate);
  160. if (!f)
  161. return -EINVAL;
  162. clk_flags = __clk_get_flags(hw->clk);
  163. *p = clk_get_parent_by_index(hw->clk, f->src);
  164. if (clk_flags & CLK_SET_RATE_PARENT) {
  165. if (f->pre_div) {
  166. rate /= 2;
  167. rate *= f->pre_div + 1;
  168. }
  169. if (f->n) {
  170. u64 tmp = rate;
  171. tmp = tmp * f->n;
  172. do_div(tmp, f->m);
  173. rate = tmp;
  174. }
  175. } else {
  176. rate = __clk_get_rate(*p);
  177. }
  178. *p_rate = rate;
  179. return f->freq;
  180. }
  181. static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
  182. unsigned long *p_rate, struct clk **p)
  183. {
  184. struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  185. return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
  186. }
  187. static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
  188. {
  189. struct clk_rcg2 *rcg = to_clk_rcg2(hw);
  190. const struct freq_tbl *f;
  191. u32 cfg, mask;
  192. int ret;
  193. f = find_freq(rcg->freq_tbl, rate);
  194. if (!f)
  195. return -EINVAL;
  196. if (rcg->mnd_width && f->n) {
  197. mask = BIT(rcg->mnd_width) - 1;
  198. ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG,
  199. mask, f->m);
  200. if (ret)
  201. return ret;
  202. ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG,
  203. mask, ~(f->n - f->m));
  204. if (ret)
  205. return ret;
  206. ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + D_REG,
  207. mask, ~f->n);
  208. if (ret)
  209. return ret;
  210. }
  211. mask = BIT(rcg->hid_width) - 1;
  212. mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
  213. cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
  214. cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
  215. if (rcg->mnd_width && f->n)
  216. cfg |= CFG_MODE_DUAL_EDGE;
  217. ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask,
  218. cfg);
  219. if (ret)
  220. return ret;
  221. return update_config(rcg);
  222. }
  223. static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
  224. unsigned long parent_rate)
  225. {
  226. return __clk_rcg2_set_rate(hw, rate);
  227. }
  228. static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
  229. unsigned long rate, unsigned long parent_rate, u8 index)
  230. {
  231. return __clk_rcg2_set_rate(hw, rate);
  232. }
  233. const struct clk_ops clk_rcg2_ops = {
  234. .is_enabled = clk_rcg2_is_enabled,
  235. .get_parent = clk_rcg2_get_parent,
  236. .set_parent = clk_rcg2_set_parent,
  237. .recalc_rate = clk_rcg2_recalc_rate,
  238. .determine_rate = clk_rcg2_determine_rate,
  239. .set_rate = clk_rcg2_set_rate,
  240. .set_rate_and_parent = clk_rcg2_set_rate_and_parent,
  241. };
  242. EXPORT_SYMBOL_GPL(clk_rcg2_ops);