clk-cpg.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. #include <linux/clk.h>
  2. #include <linux/compiler.h>
  3. #include <linux/slab.h>
  4. #include <linux/io.h>
  5. #include <linux/sh_clk.h>
  6. static int sh_clk_mstp32_enable(struct clk *clk)
  7. {
  8. __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
  9. clk->enable_reg);
  10. return 0;
  11. }
  12. static void sh_clk_mstp32_disable(struct clk *clk)
  13. {
  14. __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
  15. clk->enable_reg);
  16. }
  17. static struct clk_ops sh_clk_mstp32_clk_ops = {
  18. .enable = sh_clk_mstp32_enable,
  19. .disable = sh_clk_mstp32_disable,
  20. .recalc = followparent_recalc,
  21. };
  22. int __init sh_clk_mstp32_register(struct clk *clks, int nr)
  23. {
  24. struct clk *clkp;
  25. int ret = 0;
  26. int k;
  27. for (k = 0; !ret && (k < nr); k++) {
  28. clkp = clks + k;
  29. clkp->ops = &sh_clk_mstp32_clk_ops;
  30. ret |= clk_register(clkp);
  31. }
  32. return ret;
  33. }
  34. static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
  35. {
  36. return clk_rate_table_round(clk, clk->freq_table, rate);
  37. }
  38. static int sh_clk_div6_divisors[64] = {
  39. 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
  40. 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
  41. 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  42. 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
  43. };
  44. static struct clk_div_mult_table sh_clk_div6_table = {
  45. .divisors = sh_clk_div6_divisors,
  46. .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
  47. };
  48. static unsigned long sh_clk_div6_recalc(struct clk *clk)
  49. {
  50. struct clk_div_mult_table *table = &sh_clk_div6_table;
  51. unsigned int idx;
  52. clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
  53. table, NULL);
  54. idx = __raw_readl(clk->enable_reg) & 0x003f;
  55. return clk->freq_table[idx].frequency;
  56. }
  57. static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
  58. {
  59. struct clk_div_mult_table *table = &sh_clk_div6_table;
  60. u32 value;
  61. int ret, i;
  62. if (!clk->parent_table || !clk->parent_num)
  63. return -EINVAL;
  64. /* Search the parent */
  65. for (i = 0; i < clk->parent_num; i++)
  66. if (clk->parent_table[i] == parent)
  67. break;
  68. if (i == clk->parent_num)
  69. return -ENODEV;
  70. ret = clk_reparent(clk, parent);
  71. if (ret < 0)
  72. return ret;
  73. value = __raw_readl(clk->enable_reg) &
  74. ~(((1 << clk->src_width) - 1) << clk->src_shift);
  75. __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
  76. /* Rebuild the frequency table */
  77. clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
  78. table, &clk->arch_flags);
  79. return 0;
  80. }
  81. static int sh_clk_div6_set_rate(struct clk *clk,
  82. unsigned long rate, int algo_id)
  83. {
  84. unsigned long value;
  85. int idx;
  86. idx = clk_rate_table_find(clk, clk->freq_table, rate);
  87. if (idx < 0)
  88. return idx;
  89. value = __raw_readl(clk->enable_reg);
  90. value &= ~0x3f;
  91. value |= idx;
  92. __raw_writel(value, clk->enable_reg);
  93. return 0;
  94. }
  95. static int sh_clk_div6_enable(struct clk *clk)
  96. {
  97. unsigned long value;
  98. int ret;
  99. ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
  100. if (ret == 0) {
  101. value = __raw_readl(clk->enable_reg);
  102. value &= ~0x100; /* clear stop bit to enable clock */
  103. __raw_writel(value, clk->enable_reg);
  104. }
  105. return ret;
  106. }
  107. static void sh_clk_div6_disable(struct clk *clk)
  108. {
  109. unsigned long value;
  110. value = __raw_readl(clk->enable_reg);
  111. value |= 0x100; /* stop clock */
  112. value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
  113. __raw_writel(value, clk->enable_reg);
  114. }
  115. static struct clk_ops sh_clk_div6_clk_ops = {
  116. .recalc = sh_clk_div6_recalc,
  117. .round_rate = sh_clk_div_round_rate,
  118. .set_rate = sh_clk_div6_set_rate,
  119. .enable = sh_clk_div6_enable,
  120. .disable = sh_clk_div6_disable,
  121. };
  122. static struct clk_ops sh_clk_div6_reparent_clk_ops = {
  123. .recalc = sh_clk_div6_recalc,
  124. .round_rate = sh_clk_div_round_rate,
  125. .set_rate = sh_clk_div6_set_rate,
  126. .enable = sh_clk_div6_enable,
  127. .disable = sh_clk_div6_disable,
  128. .set_parent = sh_clk_div6_set_parent,
  129. };
  130. static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
  131. struct clk_ops *ops)
  132. {
  133. struct clk *clkp;
  134. void *freq_table;
  135. int nr_divs = sh_clk_div6_table.nr_divisors;
  136. int freq_table_size = sizeof(struct cpufreq_frequency_table);
  137. int ret = 0;
  138. int k;
  139. freq_table_size *= (nr_divs + 1);
  140. freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
  141. if (!freq_table) {
  142. pr_err("sh_clk_div6_register: unable to alloc memory\n");
  143. return -ENOMEM;
  144. }
  145. for (k = 0; !ret && (k < nr); k++) {
  146. clkp = clks + k;
  147. clkp->ops = ops;
  148. clkp->id = -1;
  149. clkp->freq_table = freq_table + (k * freq_table_size);
  150. clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
  151. ret = clk_register(clkp);
  152. }
  153. return ret;
  154. }
  155. int __init sh_clk_div6_register(struct clk *clks, int nr)
  156. {
  157. return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
  158. }
  159. int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
  160. {
  161. return sh_clk_div6_register_ops(clks, nr,
  162. &sh_clk_div6_reparent_clk_ops);
  163. }
  164. static unsigned long sh_clk_div4_recalc(struct clk *clk)
  165. {
  166. struct clk_div4_table *d4t = clk->priv;
  167. struct clk_div_mult_table *table = d4t->div_mult_table;
  168. unsigned int idx;
  169. clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
  170. table, &clk->arch_flags);
  171. idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
  172. return clk->freq_table[idx].frequency;
  173. }
  174. static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
  175. {
  176. struct clk_div4_table *d4t = clk->priv;
  177. struct clk_div_mult_table *table = d4t->div_mult_table;
  178. u32 value;
  179. int ret;
  180. /* we really need a better way to determine parent index, but for
  181. * now assume internal parent comes with CLK_ENABLE_ON_INIT set,
  182. * no CLK_ENABLE_ON_INIT means external clock...
  183. */
  184. if (parent->flags & CLK_ENABLE_ON_INIT)
  185. value = __raw_readl(clk->enable_reg) & ~(1 << 7);
  186. else
  187. value = __raw_readl(clk->enable_reg) | (1 << 7);
  188. ret = clk_reparent(clk, parent);
  189. if (ret < 0)
  190. return ret;
  191. __raw_writel(value, clk->enable_reg);
  192. /* Rebiuld the frequency table */
  193. clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
  194. table, &clk->arch_flags);
  195. return 0;
  196. }
  197. static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
  198. {
  199. struct clk_div4_table *d4t = clk->priv;
  200. unsigned long value;
  201. int idx = clk_rate_table_find(clk, clk->freq_table, rate);
  202. if (idx < 0)
  203. return idx;
  204. value = __raw_readl(clk->enable_reg);
  205. value &= ~(0xf << clk->enable_bit);
  206. value |= (idx << clk->enable_bit);
  207. __raw_writel(value, clk->enable_reg);
  208. if (d4t->kick)
  209. d4t->kick(clk);
  210. return 0;
  211. }
  212. static int sh_clk_div4_enable(struct clk *clk)
  213. {
  214. __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
  215. return 0;
  216. }
  217. static void sh_clk_div4_disable(struct clk *clk)
  218. {
  219. __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
  220. }
  221. static struct clk_ops sh_clk_div4_clk_ops = {
  222. .recalc = sh_clk_div4_recalc,
  223. .set_rate = sh_clk_div4_set_rate,
  224. .round_rate = sh_clk_div_round_rate,
  225. };
  226. static struct clk_ops sh_clk_div4_enable_clk_ops = {
  227. .recalc = sh_clk_div4_recalc,
  228. .set_rate = sh_clk_div4_set_rate,
  229. .round_rate = sh_clk_div_round_rate,
  230. .enable = sh_clk_div4_enable,
  231. .disable = sh_clk_div4_disable,
  232. };
  233. static struct clk_ops sh_clk_div4_reparent_clk_ops = {
  234. .recalc = sh_clk_div4_recalc,
  235. .set_rate = sh_clk_div4_set_rate,
  236. .round_rate = sh_clk_div_round_rate,
  237. .enable = sh_clk_div4_enable,
  238. .disable = sh_clk_div4_disable,
  239. .set_parent = sh_clk_div4_set_parent,
  240. };
  241. static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
  242. struct clk_div4_table *table, struct clk_ops *ops)
  243. {
  244. struct clk *clkp;
  245. void *freq_table;
  246. int nr_divs = table->div_mult_table->nr_divisors;
  247. int freq_table_size = sizeof(struct cpufreq_frequency_table);
  248. int ret = 0;
  249. int k;
  250. freq_table_size *= (nr_divs + 1);
  251. freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
  252. if (!freq_table) {
  253. pr_err("sh_clk_div4_register: unable to alloc memory\n");
  254. return -ENOMEM;
  255. }
  256. for (k = 0; !ret && (k < nr); k++) {
  257. clkp = clks + k;
  258. clkp->ops = ops;
  259. clkp->id = -1;
  260. clkp->priv = table;
  261. clkp->freq_table = freq_table + (k * freq_table_size);
  262. clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
  263. ret = clk_register(clkp);
  264. }
  265. return ret;
  266. }
  267. int __init sh_clk_div4_register(struct clk *clks, int nr,
  268. struct clk_div4_table *table)
  269. {
  270. return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
  271. }
  272. int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
  273. struct clk_div4_table *table)
  274. {
  275. return sh_clk_div4_register_ops(clks, nr, table,
  276. &sh_clk_div4_enable_clk_ops);
  277. }
  278. int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
  279. struct clk_div4_table *table)
  280. {
  281. return sh_clk_div4_register_ops(clks, nr, table,
  282. &sh_clk_div4_reparent_clk_ops);
  283. }