clock.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * clock.c
  3. *
  4. * Clock initialization for AM33XX boards.
  5. * Derived from OMAP4 boards
  6. *
  7. * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #include <common.h>
  12. #include <asm/arch/cpu.h>
  13. #include <asm/arch/clock.h>
  14. #include <asm/arch/hardware.h>
  15. #include <asm/arch/sys_proto.h>
  16. #include <asm/io.h>
  17. static void setup_post_dividers(const struct dpll_regs *dpll_regs,
  18. const struct dpll_params *params)
  19. {
  20. /* Setup post-dividers */
  21. if (params->m2 >= 0)
  22. writel(params->m2, dpll_regs->cm_div_m2_dpll);
  23. if (params->m3 >= 0)
  24. writel(params->m3, dpll_regs->cm_div_m3_dpll);
  25. if (params->m4 >= 0)
  26. writel(params->m4, dpll_regs->cm_div_m4_dpll);
  27. if (params->m5 >= 0)
  28. writel(params->m5, dpll_regs->cm_div_m5_dpll);
  29. if (params->m6 >= 0)
  30. writel(params->m6, dpll_regs->cm_div_m6_dpll);
  31. }
  32. static inline void do_lock_dpll(const struct dpll_regs *dpll_regs)
  33. {
  34. clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
  35. CM_CLKMODE_DPLL_DPLL_EN_MASK,
  36. DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT);
  37. }
  38. static inline void wait_for_lock(const struct dpll_regs *dpll_regs)
  39. {
  40. if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK,
  41. (void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
  42. printf("DPLL locking failed for 0x%x\n",
  43. dpll_regs->cm_clkmode_dpll);
  44. hang();
  45. }
  46. }
  47. static inline void do_bypass_dpll(const struct dpll_regs *dpll_regs)
  48. {
  49. clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
  50. CM_CLKMODE_DPLL_DPLL_EN_MASK,
  51. DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT);
  52. }
  53. static inline void wait_for_bypass(const struct dpll_regs *dpll_regs)
  54. {
  55. if (!wait_on_value(ST_DPLL_CLK_MASK, 0,
  56. (void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
  57. printf("Bypassing DPLL failed 0x%x\n",
  58. dpll_regs->cm_clkmode_dpll);
  59. }
  60. }
  61. static void bypass_dpll(const struct dpll_regs *dpll_regs)
  62. {
  63. do_bypass_dpll(dpll_regs);
  64. wait_for_bypass(dpll_regs);
  65. }
  66. void do_setup_dpll(const struct dpll_regs *dpll_regs,
  67. const struct dpll_params *params)
  68. {
  69. u32 temp;
  70. if (!params)
  71. return;
  72. temp = readl(dpll_regs->cm_clksel_dpll);
  73. bypass_dpll(dpll_regs);
  74. /* Set M & N */
  75. temp &= ~CM_CLKSEL_DPLL_M_MASK;
  76. temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK;
  77. temp &= ~CM_CLKSEL_DPLL_N_MASK;
  78. temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK;
  79. writel(temp, dpll_regs->cm_clksel_dpll);
  80. setup_post_dividers(dpll_regs, params);
  81. /* Wait till the DPLL locks */
  82. do_lock_dpll(dpll_regs);
  83. wait_for_lock(dpll_regs);
  84. }
  85. static void setup_dplls(void)
  86. {
  87. const struct dpll_params *params;
  88. params = get_dpll_core_params();
  89. do_setup_dpll(&dpll_core_regs, params);
  90. params = get_dpll_mpu_params();
  91. do_setup_dpll(&dpll_mpu_regs, params);
  92. params = get_dpll_per_params();
  93. do_setup_dpll(&dpll_per_regs, params);
  94. writel(0x300, &cmwkup->clkdcoldodpllper);
  95. params = get_dpll_ddr_params();
  96. do_setup_dpll(&dpll_ddr_regs, params);
  97. }
  98. static inline void wait_for_clk_enable(u32 *clkctrl_addr)
  99. {
  100. u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
  101. u32 bound = LDELAY;
  102. while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
  103. (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
  104. clkctrl = readl(clkctrl_addr);
  105. idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
  106. MODULE_CLKCTRL_IDLEST_SHIFT;
  107. if (--bound == 0) {
  108. printf("Clock enable failed for 0x%p idlest 0x%x\n",
  109. clkctrl_addr, clkctrl);
  110. return;
  111. }
  112. }
  113. }
  114. static inline void enable_clock_module(u32 *const clkctrl_addr, u32 enable_mode,
  115. u32 wait_for_enable)
  116. {
  117. clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
  118. enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT);
  119. debug("Enable clock module - %p\n", clkctrl_addr);
  120. if (wait_for_enable)
  121. wait_for_clk_enable(clkctrl_addr);
  122. }
  123. static inline void wait_for_clk_disable(u32 *clkctrl_addr)
  124. {
  125. u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_FULLY_FUNCTIONAL;
  126. u32 bound = LDELAY;
  127. while ((idlest != MODULE_CLKCTRL_IDLEST_DISABLED)) {
  128. clkctrl = readl(clkctrl_addr);
  129. idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
  130. MODULE_CLKCTRL_IDLEST_SHIFT;
  131. if (--bound == 0) {
  132. printf("Clock disable failed for 0x%p idlest 0x%x\n",
  133. clkctrl_addr, clkctrl);
  134. return;
  135. }
  136. }
  137. }
  138. static inline void disable_clock_module(u32 *const clkctrl_addr,
  139. u32 wait_for_disable)
  140. {
  141. clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
  142. MODULE_CLKCTRL_MODULEMODE_SW_DISABLE <<
  143. MODULE_CLKCTRL_MODULEMODE_SHIFT);
  144. debug("Disable clock module - %p\n", clkctrl_addr);
  145. if (wait_for_disable)
  146. wait_for_clk_disable(clkctrl_addr);
  147. }
  148. static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode)
  149. {
  150. clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
  151. enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT);
  152. debug("Enable clock domain - %p\n", clkctrl_reg);
  153. }
  154. static inline void disable_clock_domain(u32 *const clkctrl_reg)
  155. {
  156. clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
  157. CD_CLKCTRL_CLKTRCTRL_SW_SLEEP <<
  158. CD_CLKCTRL_CLKTRCTRL_SHIFT);
  159. debug("Disable clock domain - %p\n", clkctrl_reg);
  160. }
  161. void do_enable_clocks(u32 *const *clk_domains,
  162. u32 *const *clk_modules_explicit_en, u8 wait_for_enable)
  163. {
  164. u32 i, max = 100;
  165. /* Put the clock domains in SW_WKUP mode */
  166. for (i = 0; (i < max) && clk_domains[i]; i++) {
  167. enable_clock_domain(clk_domains[i],
  168. CD_CLKCTRL_CLKTRCTRL_SW_WKUP);
  169. }
  170. /* Clock modules that need to be put in SW_EXPLICIT_EN mode */
  171. for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) {
  172. enable_clock_module(clk_modules_explicit_en[i],
  173. MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN,
  174. wait_for_enable);
  175. };
  176. }
  177. void do_disable_clocks(u32 *const *clk_domains,
  178. u32 *const *clk_modules_disable,
  179. u8 wait_for_disable)
  180. {
  181. u32 i, max = 100;
  182. /* Clock modules that need to be put in SW_DISABLE */
  183. for (i = 0; (i < max) && clk_modules_disable[i]; i++)
  184. disable_clock_module(clk_modules_disable[i],
  185. wait_for_disable);
  186. /* Put the clock domains in SW_SLEEP mode */
  187. for (i = 0; (i < max) && clk_domains[i]; i++)
  188. disable_clock_domain(clk_domains[i]);
  189. }
  190. /*
  191. * Before scaling up the clocks we need to have the PMIC scale up the
  192. * voltages first. This will be dependent on which PMIC is in use
  193. * and in some cases we may not be scaling things up at all and thus not
  194. * need to do anything here.
  195. */
  196. __weak void scale_vcores(void)
  197. {
  198. }
  199. void setup_early_clocks(void)
  200. {
  201. setup_clocks_for_console();
  202. enable_basic_clocks();
  203. timer_init();
  204. }
  205. void prcm_init(void)
  206. {
  207. scale_vcores();
  208. setup_dplls();
  209. }
  210. void rtc_only_prcm_init(void)
  211. {
  212. const struct dpll_params *params;
  213. rtc_only_enable_basic_clocks();
  214. params = get_dpll_ddr_params();
  215. do_setup_dpll(&dpll_ddr_regs, params);
  216. }