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