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 <asm/arch/cpu.h> 12 #include <asm/arch/clock.h> 13 #include <asm/arch/hardware.h> 14 #include <asm/arch/sys_proto.h> 15 #include <asm/io.h> 16 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 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 40 static inline void wait_for_lock(const struct dpll_regs *dpll_regs) 41 { 42 if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK, 43 (void *)dpll_regs->cm_idlest_dpll, LDELAY)) { 44 printf("DPLL locking failed for 0x%x\n", 45 dpll_regs->cm_clkmode_dpll); 46 hang(); 47 } 48 } 49 50 static inline void do_bypass_dpll(const struct dpll_regs *dpll_regs) 51 { 52 clrsetbits_le32(dpll_regs->cm_clkmode_dpll, 53 CM_CLKMODE_DPLL_DPLL_EN_MASK, 54 DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT); 55 } 56 57 static inline void wait_for_bypass(const struct dpll_regs *dpll_regs) 58 { 59 if (!wait_on_value(ST_DPLL_CLK_MASK, 0, 60 (void *)dpll_regs->cm_idlest_dpll, LDELAY)) { 61 printf("Bypassing DPLL failed 0x%x\n", 62 dpll_regs->cm_clkmode_dpll); 63 } 64 } 65 66 static void bypass_dpll(const struct dpll_regs *dpll_regs) 67 { 68 do_bypass_dpll(dpll_regs); 69 wait_for_bypass(dpll_regs); 70 } 71 72 void do_setup_dpll(const struct dpll_regs *dpll_regs, 73 const struct dpll_params *params) 74 { 75 u32 temp; 76 77 if (!params) 78 return; 79 80 temp = readl(dpll_regs->cm_clksel_dpll); 81 82 bypass_dpll(dpll_regs); 83 84 /* Set M & N */ 85 temp &= ~CM_CLKSEL_DPLL_M_MASK; 86 temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK; 87 88 temp &= ~CM_CLKSEL_DPLL_N_MASK; 89 temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK; 90 91 writel(temp, dpll_regs->cm_clksel_dpll); 92 93 setup_post_dividers(dpll_regs, params); 94 95 /* Wait till the DPLL locks */ 96 do_lock_dpll(dpll_regs); 97 wait_for_lock(dpll_regs); 98 } 99 100 static void setup_dplls(void) 101 { 102 const struct dpll_params *params; 103 104 params = get_dpll_core_params(); 105 do_setup_dpll(&dpll_core_regs, params); 106 107 params = get_dpll_mpu_params(); 108 do_setup_dpll(&dpll_mpu_regs, params); 109 110 params = get_dpll_per_params(); 111 do_setup_dpll(&dpll_per_regs, params); 112 writel(0x300, &cmwkup->clkdcoldodpllper); 113 114 params = get_dpll_ddr_params(); 115 do_setup_dpll(&dpll_ddr_regs, params); 116 } 117 118 static inline void wait_for_clk_enable(u32 *clkctrl_addr) 119 { 120 u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED; 121 u32 bound = LDELAY; 122 123 while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) || 124 (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) { 125 clkctrl = readl(clkctrl_addr); 126 idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >> 127 MODULE_CLKCTRL_IDLEST_SHIFT; 128 if (--bound == 0) { 129 printf("Clock enable failed for 0x%p idlest 0x%x\n", 130 clkctrl_addr, clkctrl); 131 return; 132 } 133 } 134 } 135 136 static inline void enable_clock_module(u32 *const clkctrl_addr, u32 enable_mode, 137 u32 wait_for_enable) 138 { 139 clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK, 140 enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT); 141 debug("Enable clock module - %p\n", clkctrl_addr); 142 if (wait_for_enable) 143 wait_for_clk_enable(clkctrl_addr); 144 } 145 146 static inline void wait_for_clk_disable(u32 *clkctrl_addr) 147 { 148 u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_FULLY_FUNCTIONAL; 149 u32 bound = LDELAY; 150 151 while ((idlest != MODULE_CLKCTRL_IDLEST_DISABLED)) { 152 clkctrl = readl(clkctrl_addr); 153 idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >> 154 MODULE_CLKCTRL_IDLEST_SHIFT; 155 if (--bound == 0) { 156 printf("Clock disable failed for 0x%p idlest 0x%x\n", 157 clkctrl_addr, clkctrl); 158 return; 159 } 160 } 161 } 162 static inline void disable_clock_module(u32 *const clkctrl_addr, 163 u32 wait_for_disable) 164 { 165 clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK, 166 MODULE_CLKCTRL_MODULEMODE_SW_DISABLE << 167 MODULE_CLKCTRL_MODULEMODE_SHIFT); 168 debug("Disable clock module - %p\n", clkctrl_addr); 169 if (wait_for_disable) 170 wait_for_clk_disable(clkctrl_addr); 171 } 172 173 static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode) 174 { 175 clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK, 176 enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT); 177 debug("Enable clock domain - %p\n", clkctrl_reg); 178 } 179 180 static inline void disable_clock_domain(u32 *const clkctrl_reg) 181 { 182 clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK, 183 CD_CLKCTRL_CLKTRCTRL_SW_SLEEP << 184 CD_CLKCTRL_CLKTRCTRL_SHIFT); 185 debug("Disable clock domain - %p\n", clkctrl_reg); 186 } 187 188 void do_enable_clocks(u32 *const *clk_domains, 189 u32 *const *clk_modules_explicit_en, u8 wait_for_enable) 190 { 191 u32 i, max = 100; 192 193 /* Put the clock domains in SW_WKUP mode */ 194 for (i = 0; (i < max) && clk_domains[i]; i++) { 195 enable_clock_domain(clk_domains[i], 196 CD_CLKCTRL_CLKTRCTRL_SW_WKUP); 197 } 198 199 /* Clock modules that need to be put in SW_EXPLICIT_EN mode */ 200 for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) { 201 enable_clock_module(clk_modules_explicit_en[i], 202 MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN, 203 wait_for_enable); 204 }; 205 } 206 207 void do_disable_clocks(u32 *const *clk_domains, 208 u32 *const *clk_modules_disable, 209 u8 wait_for_disable) 210 { 211 u32 i, max = 100; 212 213 214 /* Clock modules that need to be put in SW_DISABLE */ 215 for (i = 0; (i < max) && clk_modules_disable[i]; i++) 216 disable_clock_module(clk_modules_disable[i], 217 wait_for_disable); 218 219 /* Put the clock domains in SW_SLEEP mode */ 220 for (i = 0; (i < max) && clk_domains[i]; i++) 221 disable_clock_domain(clk_domains[i]); 222 } 223 224 /* 225 * Before scaling up the clocks we need to have the PMIC scale up the 226 * voltages first. This will be dependent on which PMIC is in use 227 * and in some cases we may not be scaling things up at all and thus not 228 * need to do anything here. 229 */ 230 __weak void scale_vcores(void) 231 { 232 } 233 234 void setup_early_clocks(void) 235 { 236 setup_clocks_for_console(); 237 enable_basic_clocks(); 238 timer_init(); 239 } 240 241 void prcm_init(void) 242 { 243 scale_vcores(); 244 setup_dplls(); 245 } 246 247 void rtc_only_prcm_init(void) 248 { 249 const struct dpll_params *params; 250 251 rtc_only_enable_basic_clocks(); 252 253 params = get_dpll_ddr_params(); 254 do_setup_dpll(&dpll_ddr_regs, params); 255 } 256