clock34xx.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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. /* needed by omap3_core_dpll_m2_set_rate() */
  38. struct clk *sdrc_ick_p, *arm_fck_p;
  39. /**
  40. * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
  41. * @clk: struct clk * being enabled
  42. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  43. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  44. *
  45. * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
  46. * from the CM_{I,F}CLKEN bit. Pass back the correct info via
  47. * @idlest_reg and @idlest_bit. No return value.
  48. */
  49. static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
  50. void __iomem **idlest_reg,
  51. u8 *idlest_bit)
  52. {
  53. u32 r;
  54. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  55. *idlest_reg = (__force void __iomem *)r;
  56. *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
  57. }
  58. const struct clkops clkops_omap3430es2_ssi_wait = {
  59. .enable = omap2_dflt_clk_enable,
  60. .disable = omap2_dflt_clk_disable,
  61. .find_idlest = omap3430es2_clk_ssi_find_idlest,
  62. .find_companion = omap2_clk_dflt_find_companion,
  63. };
  64. /**
  65. * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
  66. * @clk: struct clk * being enabled
  67. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  68. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  69. *
  70. * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
  71. * target IDLEST bits. For our purposes, we are concerned with the
  72. * target IDLEST bits, which exist at a different bit position than
  73. * the *CLKEN bit position for these modules (DSS and USBHOST) (The
  74. * default find_idlest code assumes that they are at the same
  75. * position.) No return value.
  76. */
  77. static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
  78. void __iomem **idlest_reg,
  79. u8 *idlest_bit)
  80. {
  81. u32 r;
  82. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  83. *idlest_reg = (__force void __iomem *)r;
  84. /* USBHOST_IDLE has same shift */
  85. *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
  86. }
  87. const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
  88. .enable = omap2_dflt_clk_enable,
  89. .disable = omap2_dflt_clk_disable,
  90. .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
  91. .find_companion = omap2_clk_dflt_find_companion,
  92. };
  93. /**
  94. * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
  95. * @clk: struct clk * being enabled
  96. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  97. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  98. *
  99. * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
  100. * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
  101. * @idlest_reg and @idlest_bit. No return value.
  102. */
  103. static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
  104. void __iomem **idlest_reg,
  105. u8 *idlest_bit)
  106. {
  107. u32 r;
  108. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  109. *idlest_reg = (__force void __iomem *)r;
  110. *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
  111. }
  112. const struct clkops clkops_omap3430es2_hsotgusb_wait = {
  113. .enable = omap2_dflt_clk_enable,
  114. .disable = omap2_dflt_clk_disable,
  115. .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
  116. .find_companion = omap2_clk_dflt_find_companion,
  117. };
  118. const struct clkops clkops_noncore_dpll_ops = {
  119. .enable = omap3_noncore_dpll_enable,
  120. .disable = omap3_noncore_dpll_disable,
  121. };
  122. int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
  123. {
  124. /*
  125. * According to the 12-5 CDP code from TI, "Limitation 2.5"
  126. * on 3430ES1 prevents us from changing DPLL multipliers or dividers
  127. * on DPLL4.
  128. */
  129. if (omap_rev() == OMAP3430_REV_ES1_0) {
  130. printk(KERN_ERR "clock: DPLL4 cannot change rate due to "
  131. "silicon 'Limitation 2.5' on 3430ES1.\n");
  132. return -EINVAL;
  133. }
  134. return omap3_noncore_dpll_set_rate(clk, rate);
  135. }
  136. /* Common clock code */
  137. /*
  138. * Set clocks for bypass mode for reboot to work.
  139. */
  140. void omap2_clk_prepare_for_reboot(void)
  141. {
  142. /* REVISIT: Not ready for 343x */
  143. #if 0
  144. u32 rate;
  145. if (vclk == NULL || sclk == NULL)
  146. return;
  147. rate = clk_get_rate(sclk);
  148. clk_set_rate(vclk, rate);
  149. #endif
  150. }
  151. void omap3_clk_lock_dpll5(void)
  152. {
  153. struct clk *dpll5_clk;
  154. struct clk *dpll5_m2_clk;
  155. dpll5_clk = clk_get(NULL, "dpll5_ck");
  156. clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
  157. clk_enable(dpll5_clk);
  158. /* Enable autoidle to allow it to enter low power bypass */
  159. omap3_dpll_allow_idle(dpll5_clk);
  160. /* Program dpll5_m2_clk divider for no division */
  161. dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
  162. clk_enable(dpll5_m2_clk);
  163. clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
  164. clk_disable(dpll5_m2_clk);
  165. clk_disable(dpll5_clk);
  166. return;
  167. }
  168. /* REVISIT: Move this init stuff out into clock.c */
  169. /*
  170. * Switch the MPU rate if specified on cmdline.
  171. * We cannot do this early until cmdline is parsed.
  172. */
  173. static int __init omap3xxx_clk_arch_init(void)
  174. {
  175. struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck;
  176. unsigned long osc_sys_rate;
  177. if (!cpu_is_omap34xx())
  178. return 0;
  179. if (!mpurate)
  180. return -EINVAL;
  181. /* XXX test these for success */
  182. dpll1_ck = clk_get(NULL, "dpll1_ck");
  183. arm_fck = clk_get(NULL, "arm_fck");
  184. core_ck = clk_get(NULL, "core_ck");
  185. osc_sys_ck = clk_get(NULL, "osc_sys_ck");
  186. /* REVISIT: not yet ready for 343x */
  187. if (clk_set_rate(dpll1_ck, mpurate))
  188. printk(KERN_ERR "*** Unable to set MPU rate\n");
  189. recalculate_root_clocks();
  190. osc_sys_rate = clk_get_rate(osc_sys_ck);
  191. pr_info("Switched to new clocking rate (Crystal/Core/MPU): "
  192. "%ld.%01ld/%ld/%ld MHz\n",
  193. (osc_sys_rate / 1000000),
  194. ((osc_sys_rate / 100000) % 10),
  195. (clk_get_rate(core_ck) / 1000000),
  196. (clk_get_rate(arm_fck) / 1000000));
  197. calibrate_delay();
  198. return 0;
  199. }
  200. arch_initcall(omap3xxx_clk_arch_init);