clock.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. do_setup_dpll(&dpll_core_regs, &dpll_core);
  89. do_setup_dpll(&dpll_mpu_regs, &dpll_mpu);
  90. do_setup_dpll(&dpll_per_regs, &dpll_per);
  91. writel(0x300, &cmwkup->clkdcoldodpllper);
  92. params = get_dpll_ddr_params();
  93. do_setup_dpll(&dpll_ddr_regs, params);
  94. }
  95. static inline void wait_for_clk_enable(u32 *clkctrl_addr)
  96. {
  97. u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
  98. u32 bound = LDELAY;
  99. while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
  100. (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
  101. clkctrl = readl(clkctrl_addr);
  102. idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
  103. MODULE_CLKCTRL_IDLEST_SHIFT;
  104. if (--bound == 0) {
  105. printf("Clock enable failed for 0x%p idlest 0x%x\n",
  106. clkctrl_addr, clkctrl);
  107. return;
  108. }
  109. }
  110. }
  111. static inline void enable_clock_module(u32 *const clkctrl_addr, u32 enable_mode,
  112. u32 wait_for_enable)
  113. {
  114. clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
  115. enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT);
  116. debug("Enable clock module - %p\n", clkctrl_addr);
  117. if (wait_for_enable)
  118. wait_for_clk_enable(clkctrl_addr);
  119. }
  120. static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode)
  121. {
  122. clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
  123. enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT);
  124. debug("Enable clock domain - %p\n", clkctrl_reg);
  125. }
  126. void do_enable_clocks(u32 *const *clk_domains,
  127. u32 *const *clk_modules_explicit_en, u8 wait_for_enable)
  128. {
  129. u32 i, max = 100;
  130. /* Put the clock domains in SW_WKUP mode */
  131. for (i = 0; (i < max) && clk_domains[i]; i++) {
  132. enable_clock_domain(clk_domains[i],
  133. CD_CLKCTRL_CLKTRCTRL_SW_WKUP);
  134. }
  135. /* Clock modules that need to be put in SW_EXPLICIT_EN mode */
  136. for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) {
  137. enable_clock_module(clk_modules_explicit_en[i],
  138. MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN,
  139. wait_for_enable);
  140. };
  141. }
  142. void prcm_init()
  143. {
  144. enable_basic_clocks();
  145. setup_dplls();
  146. }