clock34xx.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * OMAP3-specific clock framework functions
  3. *
  4. * Copyright (C) 2007-2008 Texas Instruments, Inc.
  5. * Copyright (C) 2007-2009 Nokia Corporation
  6. *
  7. * Written by Paul Walmsley
  8. * Testing and integration fixes by 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/module.h>
  19. #include <linux/kernel.h>
  20. #include <linux/device.h>
  21. #include <linux/list.h>
  22. #include <linux/errno.h>
  23. #include <linux/delay.h>
  24. #include <linux/clk.h>
  25. #include <linux/io.h>
  26. #include <linux/limits.h>
  27. #include <linux/bitops.h>
  28. #include <plat/cpu.h>
  29. #include <plat/clock.h>
  30. #include <plat/sram.h>
  31. #include <plat/sdrc.h>
  32. #include <asm/div64.h>
  33. #include <asm/clkdev.h>
  34. #include "clock.h"
  35. #include "clock34xx.h"
  36. #include "sdrc.h"
  37. #include "prm.h"
  38. #include "prm-regbits-34xx.h"
  39. #include "cm.h"
  40. #include "cm-regbits-34xx.h"
  41. /*
  42. * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
  43. * that are sourced by DPLL5, and both of these require this clock
  44. * to be at 120 MHz for proper operation.
  45. */
  46. #define DPLL5_FREQ_FOR_USBHOST 120000000
  47. /* needed by omap3_core_dpll_m2_set_rate() */
  48. struct clk *sdrc_ick_p, *arm_fck_p;
  49. /**
  50. * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
  51. * @clk: struct clk * being enabled
  52. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  53. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  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. {
  63. u32 r;
  64. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  65. *idlest_reg = (__force void __iomem *)r;
  66. *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
  67. }
  68. const struct clkops clkops_omap3430es2_ssi_wait = {
  69. .enable = omap2_dflt_clk_enable,
  70. .disable = omap2_dflt_clk_disable,
  71. .find_idlest = omap3430es2_clk_ssi_find_idlest,
  72. .find_companion = omap2_clk_dflt_find_companion,
  73. };
  74. /**
  75. * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
  76. * @clk: struct clk * being enabled
  77. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  78. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  79. *
  80. * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
  81. * target IDLEST bits. For our purposes, we are concerned with the
  82. * target IDLEST bits, which exist at a different bit position than
  83. * the *CLKEN bit position for these modules (DSS and USBHOST) (The
  84. * default find_idlest code assumes that they are at the same
  85. * position.) No return value.
  86. */
  87. static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
  88. void __iomem **idlest_reg,
  89. u8 *idlest_bit)
  90. {
  91. u32 r;
  92. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  93. *idlest_reg = (__force void __iomem *)r;
  94. /* USBHOST_IDLE has same shift */
  95. *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
  96. }
  97. const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
  98. .enable = omap2_dflt_clk_enable,
  99. .disable = omap2_dflt_clk_disable,
  100. .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
  101. .find_companion = omap2_clk_dflt_find_companion,
  102. };
  103. /**
  104. * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
  105. * @clk: struct clk * being enabled
  106. * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
  107. * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
  108. *
  109. * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
  110. * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
  111. * @idlest_reg and @idlest_bit. No return value.
  112. */
  113. static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
  114. void __iomem **idlest_reg,
  115. u8 *idlest_bit)
  116. {
  117. u32 r;
  118. r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
  119. *idlest_reg = (__force void __iomem *)r;
  120. *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
  121. }
  122. const struct clkops clkops_omap3430es2_hsotgusb_wait = {
  123. .enable = omap2_dflt_clk_enable,
  124. .disable = omap2_dflt_clk_disable,
  125. .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
  126. .find_companion = omap2_clk_dflt_find_companion,
  127. };
  128. const struct clkops clkops_noncore_dpll_ops = {
  129. .enable = omap3_noncore_dpll_enable,
  130. .disable = omap3_noncore_dpll_disable,
  131. };
  132. int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
  133. {
  134. /*
  135. * According to the 12-5 CDP code from TI, "Limitation 2.5"
  136. * on 3430ES1 prevents us from changing DPLL multipliers or dividers
  137. * on DPLL4.
  138. */
  139. if (omap_rev() == OMAP3430_REV_ES1_0) {
  140. printk(KERN_ERR "clock: DPLL4 cannot change rate due to "
  141. "silicon 'Limitation 2.5' on 3430ES1.\n");
  142. return -EINVAL;
  143. }
  144. return omap3_noncore_dpll_set_rate(clk, rate);
  145. }
  146. /* Common clock code */
  147. /*
  148. * As it is structured now, this will prevent an OMAP2/3 multiboot
  149. * kernel from compiling. This will need further attention.
  150. */
  151. #if defined(CONFIG_ARCH_OMAP3)
  152. /*
  153. * Set clocks for bypass mode for reboot to work.
  154. */
  155. void omap2_clk_prepare_for_reboot(void)
  156. {
  157. /* REVISIT: Not ready for 343x */
  158. #if 0
  159. u32 rate;
  160. if (vclk == NULL || sclk == NULL)
  161. return;
  162. rate = clk_get_rate(sclk);
  163. clk_set_rate(vclk, rate);
  164. #endif
  165. }
  166. void omap3_clk_lock_dpll5(void)
  167. {
  168. struct clk *dpll5_clk;
  169. struct clk *dpll5_m2_clk;
  170. dpll5_clk = clk_get(NULL, "dpll5_ck");
  171. clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
  172. clk_enable(dpll5_clk);
  173. /* Enable autoidle to allow it to enter low power bypass */
  174. omap3_dpll_allow_idle(dpll5_clk);
  175. /* Program dpll5_m2_clk divider for no division */
  176. dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
  177. clk_enable(dpll5_m2_clk);
  178. clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
  179. clk_disable(dpll5_m2_clk);
  180. clk_disable(dpll5_clk);
  181. return;
  182. }
  183. /* REVISIT: Move this init stuff out into clock.c */
  184. /*
  185. * Switch the MPU rate if specified on cmdline.
  186. * We cannot do this early until cmdline is parsed.
  187. */
  188. static int __init omap2_clk_arch_init(void)
  189. {
  190. struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck;
  191. unsigned long osc_sys_rate;
  192. if (!mpurate)
  193. return -EINVAL;
  194. /* XXX test these for success */
  195. dpll1_ck = clk_get(NULL, "dpll1_ck");
  196. arm_fck = clk_get(NULL, "arm_fck");
  197. core_ck = clk_get(NULL, "core_ck");
  198. osc_sys_ck = clk_get(NULL, "osc_sys_ck");
  199. /* REVISIT: not yet ready for 343x */
  200. if (clk_set_rate(dpll1_ck, mpurate))
  201. printk(KERN_ERR "*** Unable to set MPU rate\n");
  202. recalculate_root_clocks();
  203. osc_sys_rate = clk_get_rate(osc_sys_ck);
  204. pr_info("Switched to new clocking rate (Crystal/Core/MPU): "
  205. "%ld.%01ld/%ld/%ld MHz\n",
  206. (osc_sys_rate / 1000000),
  207. ((osc_sys_rate / 100000) % 10),
  208. (clk_get_rate(core_ck) / 1000000),
  209. (clk_get_rate(arm_fck) / 1000000));
  210. calibrate_delay();
  211. return 0;
  212. }
  213. arch_initcall(omap2_clk_arch_init);
  214. #endif