clock.c 6.6 KB

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