clock34xx.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * OMAP3-specific clock framework functions
  3. *
  4. * Copyright (C) 2007-2008 Texas Instruments, Inc.
  5. * Copyright (C) 2007-2010 Nokia Corporation
  6. *
  7. * Paul Walmsley
  8. * Jouni Högander
  9. *
  10. * Parts of this code are based on code written by
  11. * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License version 2 as
  15. * published by the Free Software Foundation.
  16. */
  17. #undef DEBUG
  18. #include <linux/kernel.h>
  19. #include <linux/errno.h>
  20. #include <linux/delay.h>
  21. #include <linux/clk.h>
  22. #include <linux/io.h>
  23. #include <plat/cpu.h>
  24. #include <plat/clock.h>
  25. #include "clock.h"
  26. #include "clock34xx.h"
  27. #include "prm.h"
  28. #include "prm-regbits-34xx.h"
  29. #include "cm.h"
  30. #include "cm-regbits-34xx.h"
  31. /*
  32. * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
  33. * that are sourced by DPLL5, and both of these require this clock
  34. * to be at 120 MHz for proper operation.
  35. */
  36. #define DPLL5_FREQ_FOR_USBHOST 120000000
  37. /*
  38. * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
  39. * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
  40. * at an offset of 4 from ICK enable bit.
  41. */
  42. #define AM35XX_IPSS_ICK_MASK 0xF
  43. #define AM35XX_IPSS_ICK_EN_ACK_OFFSET 0x4
  44. #define AM35XX_IPSS_ICK_FCK_OFFSET 0x8
  45. #define AM35XX_IPSS_CLK_IDLEST_VAL 0
  46. /* needed by omap3_core_dpll_m2_set_rate() */
  47. struct clk *sdrc_ick_p, *arm_fck_p;
  48. /**
  49. * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
  50. * @clk: struct clk * being enabled
  51. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  52. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  53. * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
  54. *
  55. * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
  56. * from the CM_{I,F}CLKEN bit. Pass back the correct info via
  57. * @idlest_reg and @idlest_bit. No return value.
  58. */
  59. static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
  60. void __iomem **idlest_reg,
  61. u8 *idlest_bit,
  62. u8 *idlest_val)
  63. {
  64. u32 r;
  65. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  66. *idlest_reg = (__force void __iomem *)r;
  67. *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
  68. *idlest_val = OMAP34XX_CM_IDLEST_VAL;
  69. }
  70. const struct clkops clkops_omap3430es2_ssi_wait = {
  71. .enable = omap2_dflt_clk_enable,
  72. .disable = omap2_dflt_clk_disable,
  73. .find_idlest = omap3430es2_clk_ssi_find_idlest,
  74. .find_companion = omap2_clk_dflt_find_companion,
  75. };
  76. /**
  77. * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
  78. * @clk: struct clk * being enabled
  79. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  80. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  81. * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
  82. *
  83. * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
  84. * target IDLEST bits. For our purposes, we are concerned with the
  85. * target IDLEST bits, which exist at a different bit position than
  86. * the *CLKEN bit position for these modules (DSS and USBHOST) (The
  87. * default find_idlest code assumes that they are at the same
  88. * position.) No return value.
  89. */
  90. static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
  91. void __iomem **idlest_reg,
  92. u8 *idlest_bit,
  93. u8 *idlest_val)
  94. {
  95. u32 r;
  96. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  97. *idlest_reg = (__force void __iomem *)r;
  98. /* USBHOST_IDLE has same shift */
  99. *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
  100. *idlest_val = OMAP34XX_CM_IDLEST_VAL;
  101. }
  102. const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
  103. .enable = omap2_dflt_clk_enable,
  104. .disable = omap2_dflt_clk_disable,
  105. .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
  106. .find_companion = omap2_clk_dflt_find_companion,
  107. };
  108. /**
  109. * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
  110. * @clk: struct clk * being enabled
  111. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  112. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  113. * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
  114. *
  115. * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
  116. * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
  117. * @idlest_reg and @idlest_bit. No return value.
  118. */
  119. static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
  120. void __iomem **idlest_reg,
  121. u8 *idlest_bit,
  122. u8 *idlest_val)
  123. {
  124. u32 r;
  125. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  126. *idlest_reg = (__force void __iomem *)r;
  127. *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
  128. *idlest_val = OMAP34XX_CM_IDLEST_VAL;
  129. }
  130. const struct clkops clkops_omap3430es2_hsotgusb_wait = {
  131. .enable = omap2_dflt_clk_enable,
  132. .disable = omap2_dflt_clk_disable,
  133. .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
  134. .find_companion = omap2_clk_dflt_find_companion,
  135. };
  136. const struct clkops omap3_clkops_noncore_dpll_ops = {
  137. .enable = omap3_noncore_dpll_enable,
  138. .disable = omap3_noncore_dpll_disable,
  139. };
  140. /**
  141. * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
  142. * @clk: struct clk * being enabled
  143. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  144. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  145. * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
  146. *
  147. * The interface clocks on AM35xx IPSS reflects the clock idle status
  148. * in the enable register itsel at a bit offset of 4 from the enable
  149. * bit. A value of 1 indicates that clock is enabled.
  150. */
  151. static void am35xx_clk_find_idlest(struct clk *clk,
  152. void __iomem **idlest_reg,
  153. u8 *idlest_bit,
  154. u8 *idlest_val)
  155. {
  156. *idlest_reg = (__force void __iomem *)(clk->enable_reg);
  157. *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
  158. *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
  159. }
  160. /**
  161. * am35xx_clk_find_companion - find companion clock to @clk
  162. * @clk: struct clk * to find the companion clock of
  163. * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
  164. * @other_bit: u8 ** to return the companion clock bit shift in
  165. *
  166. * Some clocks don't have companion clocks. For example, modules with
  167. * only an interface clock (such as HECC) don't have a companion
  168. * clock. Right now, this code relies on the hardware exporting a bit
  169. * in the correct companion register that indicates that the
  170. * nonexistent 'companion clock' is active. Future patches will
  171. * associate this type of code with per-module data structures to
  172. * avoid this issue, and remove the casts. No return value.
  173. */
  174. static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
  175. u8 *other_bit)
  176. {
  177. *other_reg = (__force void __iomem *)(clk->enable_reg);
  178. if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
  179. *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
  180. else
  181. *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
  182. }
  183. const struct clkops clkops_am35xx_ipss_module_wait = {
  184. .enable = omap2_dflt_clk_enable,
  185. .disable = omap2_dflt_clk_disable,
  186. .find_idlest = am35xx_clk_find_idlest,
  187. .find_companion = am35xx_clk_find_companion,
  188. };
  189. /**
  190. * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
  191. * @clk: struct clk * being enabled
  192. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  193. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  194. * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
  195. *
  196. * The IPSS target CM_IDLEST bit is at a different shift from the
  197. * CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg
  198. * and @idlest_bit. No return value.
  199. */
  200. static void am35xx_clk_ipss_find_idlest(struct clk *clk,
  201. void __iomem **idlest_reg,
  202. u8 *idlest_bit,
  203. u8 *idlest_val)
  204. {
  205. u32 r;
  206. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  207. *idlest_reg = (__force void __iomem *)r;
  208. *idlest_bit = AM35XX_ST_IPSS_SHIFT;
  209. *idlest_val = OMAP34XX_CM_IDLEST_VAL;
  210. }
  211. const struct clkops clkops_am35xx_ipss_wait = {
  212. .enable = omap2_dflt_clk_enable,
  213. .disable = omap2_dflt_clk_disable,
  214. .find_idlest = am35xx_clk_ipss_find_idlest,
  215. .find_companion = omap2_clk_dflt_find_companion,
  216. };
  217. int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
  218. {
  219. /*
  220. * According to the 12-5 CDP code from TI, "Limitation 2.5"
  221. * on 3430ES1 prevents us from changing DPLL multipliers or dividers
  222. * on DPLL4.
  223. */
  224. if (omap_rev() == OMAP3430_REV_ES1_0) {
  225. printk(KERN_ERR "clock: DPLL4 cannot change rate due to "
  226. "silicon 'Limitation 2.5' on 3430ES1.\n");
  227. return -EINVAL;
  228. }
  229. return omap3_noncore_dpll_set_rate(clk, rate);
  230. }
  231. void __init omap3_clk_lock_dpll5(void)
  232. {
  233. struct clk *dpll5_clk;
  234. struct clk *dpll5_m2_clk;
  235. dpll5_clk = clk_get(NULL, "dpll5_ck");
  236. clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
  237. clk_enable(dpll5_clk);
  238. /* Enable autoidle to allow it to enter low power bypass */
  239. omap3_dpll_allow_idle(dpll5_clk);
  240. /* Program dpll5_m2_clk divider for no division */
  241. dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
  242. clk_enable(dpll5_m2_clk);
  243. clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
  244. clk_disable(dpll5_m2_clk);
  245. clk_disable(dpll5_clk);
  246. return;
  247. }
  248. /* Common clock code */
  249. /* REVISIT: Move this init stuff out into clock.c */
  250. /*
  251. * Switch the MPU rate if specified on cmdline.
  252. * We cannot do this early until cmdline is parsed.
  253. */
  254. static int __init omap3xxx_clk_arch_init(void)
  255. {
  256. struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck;
  257. unsigned long osc_sys_rate;
  258. if (!cpu_is_omap34xx())
  259. return 0;
  260. if (!mpurate)
  261. return -EINVAL;
  262. /* XXX test these for success */
  263. dpll1_ck = clk_get(NULL, "dpll1_ck");
  264. arm_fck = clk_get(NULL, "arm_fck");
  265. core_ck = clk_get(NULL, "core_ck");
  266. osc_sys_ck = clk_get(NULL, "osc_sys_ck");
  267. /* REVISIT: not yet ready for 343x */
  268. if (clk_set_rate(dpll1_ck, mpurate))
  269. printk(KERN_ERR "*** Unable to set MPU rate\n");
  270. recalculate_root_clocks();
  271. osc_sys_rate = clk_get_rate(osc_sys_ck);
  272. pr_info("Switched to new clocking rate (Crystal/Core/MPU): "
  273. "%ld.%01ld/%ld/%ld MHz\n",
  274. (osc_sys_rate / 1000000),
  275. ((osc_sys_rate / 100000) % 10),
  276. (clk_get_rate(core_ck) / 1000000),
  277. (clk_get_rate(arm_fck) / 1000000));
  278. calibrate_delay();
  279. return 0;
  280. }
  281. arch_initcall(omap3xxx_clk_arch_init);