1 /* 2 * clock_am33xx.c 3 * 4 * clocks for AM33XX based boards 5 * 6 * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 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/io.h> 16 17 #define OSC (V_OSCK/1000000) 18 19 struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER; 20 struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP; 21 struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL; 22 struct cm_rtc *const cmrtc = (struct cm_rtc *)CM_RTC; 23 24 const struct dpll_regs dpll_mpu_regs = { 25 .cm_clkmode_dpll = CM_WKUP + 0x88, 26 .cm_idlest_dpll = CM_WKUP + 0x20, 27 .cm_clksel_dpll = CM_WKUP + 0x2C, 28 .cm_div_m2_dpll = CM_WKUP + 0xA8, 29 }; 30 31 const struct dpll_regs dpll_core_regs = { 32 .cm_clkmode_dpll = CM_WKUP + 0x90, 33 .cm_idlest_dpll = CM_WKUP + 0x5C, 34 .cm_clksel_dpll = CM_WKUP + 0x68, 35 .cm_div_m4_dpll = CM_WKUP + 0x80, 36 .cm_div_m5_dpll = CM_WKUP + 0x84, 37 .cm_div_m6_dpll = CM_WKUP + 0xD8, 38 }; 39 40 const struct dpll_regs dpll_per_regs = { 41 .cm_clkmode_dpll = CM_WKUP + 0x8C, 42 .cm_idlest_dpll = CM_WKUP + 0x70, 43 .cm_clksel_dpll = CM_WKUP + 0x9C, 44 .cm_div_m2_dpll = CM_WKUP + 0xAC, 45 }; 46 47 const struct dpll_regs dpll_ddr_regs = { 48 .cm_clkmode_dpll = CM_WKUP + 0x94, 49 .cm_idlest_dpll = CM_WKUP + 0x34, 50 .cm_clksel_dpll = CM_WKUP + 0x40, 51 .cm_div_m2_dpll = CM_WKUP + 0xA0, 52 }; 53 54 struct dpll_params dpll_mpu_opp100 = { 55 CONFIG_SYS_MPUCLK, OSC-1, 1, -1, -1, -1, -1}; 56 const struct dpll_params dpll_core_opp100 = { 57 1000, OSC-1, -1, -1, 10, 8, 4}; 58 const struct dpll_params dpll_mpu = { 59 MPUPLL_M_300, OSC-1, 1, -1, -1, -1, -1}; 60 const struct dpll_params dpll_core = { 61 50, OSC-1, -1, -1, 1, 1, 1}; 62 const struct dpll_params dpll_per = { 63 960, OSC-1, 5, -1, -1, -1, -1}; 64 65 const struct dpll_params *get_dpll_mpu_params(void) 66 { 67 return &dpll_mpu; 68 } 69 70 const struct dpll_params *get_dpll_core_params(void) 71 { 72 return &dpll_core; 73 } 74 75 const struct dpll_params *get_dpll_per_params(void) 76 { 77 return &dpll_per; 78 } 79 80 void setup_clocks_for_console(void) 81 { 82 clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, 83 CD_CLKCTRL_CLKTRCTRL_SW_WKUP << 84 CD_CLKCTRL_CLKTRCTRL_SHIFT); 85 86 clrsetbits_le32(&cmper->l4hsclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK, 87 CD_CLKCTRL_CLKTRCTRL_SW_WKUP << 88 CD_CLKCTRL_CLKTRCTRL_SHIFT); 89 90 clrsetbits_le32(&cmwkup->wkup_uart0ctrl, 91 MODULE_CLKCTRL_MODULEMODE_MASK, 92 MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << 93 MODULE_CLKCTRL_MODULEMODE_SHIFT); 94 clrsetbits_le32(&cmper->uart1clkctrl, 95 MODULE_CLKCTRL_MODULEMODE_MASK, 96 MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << 97 MODULE_CLKCTRL_MODULEMODE_SHIFT); 98 clrsetbits_le32(&cmper->uart2clkctrl, 99 MODULE_CLKCTRL_MODULEMODE_MASK, 100 MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << 101 MODULE_CLKCTRL_MODULEMODE_SHIFT); 102 clrsetbits_le32(&cmper->uart3clkctrl, 103 MODULE_CLKCTRL_MODULEMODE_MASK, 104 MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << 105 MODULE_CLKCTRL_MODULEMODE_SHIFT); 106 clrsetbits_le32(&cmper->uart4clkctrl, 107 MODULE_CLKCTRL_MODULEMODE_MASK, 108 MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << 109 MODULE_CLKCTRL_MODULEMODE_SHIFT); 110 clrsetbits_le32(&cmper->uart5clkctrl, 111 MODULE_CLKCTRL_MODULEMODE_MASK, 112 MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN << 113 MODULE_CLKCTRL_MODULEMODE_SHIFT); 114 } 115 116 void enable_basic_clocks(void) 117 { 118 u32 *const clk_domains[] = { 119 &cmper->l3clkstctrl, 120 &cmper->l4fwclkstctrl, 121 &cmper->l3sclkstctrl, 122 &cmper->l4lsclkstctrl, 123 &cmwkup->wkclkstctrl, 124 &cmper->emiffwclkctrl, 125 &cmrtc->clkstctrl, 126 0 127 }; 128 129 u32 *const clk_modules_explicit_en[] = { 130 &cmper->l3clkctrl, 131 &cmper->l4lsclkctrl, 132 &cmper->l4fwclkctrl, 133 &cmwkup->wkl4wkclkctrl, 134 &cmper->l3instrclkctrl, 135 &cmper->l4hsclkctrl, 136 &cmwkup->wkgpio0clkctrl, 137 &cmwkup->wkctrlclkctrl, 138 &cmper->timer2clkctrl, 139 &cmper->gpmcclkctrl, 140 &cmper->elmclkctrl, 141 &cmper->mmc0clkctrl, 142 &cmper->mmc1clkctrl, 143 &cmwkup->wkup_i2c0ctrl, 144 &cmper->gpio1clkctrl, 145 &cmper->gpio2clkctrl, 146 &cmper->gpio3clkctrl, 147 &cmper->i2c1clkctrl, 148 &cmper->cpgmac0clkctrl, 149 &cmper->spi0clkctrl, 150 &cmrtc->rtcclkctrl, 151 &cmper->usb0clkctrl, 152 &cmper->emiffwclkctrl, 153 &cmper->emifclkctrl, 154 0 155 }; 156 157 do_enable_clocks(clk_domains, clk_modules_explicit_en, 1); 158 159 /* Select the Master osc 24 MHZ as Timer2 clock source */ 160 writel(0x1, &cmdpll->clktimer2clk); 161 } 162 163 /* 164 * Enable Spread Spectrum for the MPU by calculating the required 165 * values and setting the registers accordingly. 166 * @param permille The spreading in permille (10th of a percent) 167 */ 168 void set_mpu_spreadspectrum(int permille) 169 { 170 u32 multiplier_m; 171 u32 predivider_n; 172 u32 cm_clksel_dpll_mpu; 173 u32 cm_clkmode_dpll_mpu; 174 u32 ref_clock; 175 u32 pll_bandwidth; 176 u32 mod_freq_divider; 177 u32 exponent; 178 u32 mantissa; 179 u32 delta_m_step; 180 181 printf("Enabling Spread Spectrum of %d permille for MPU\n", 182 permille); 183 184 /* Read PLL parameter m and n */ 185 cm_clksel_dpll_mpu = readl(&cmwkup->clkseldpllmpu); 186 multiplier_m = (cm_clksel_dpll_mpu >> 8) & 0x3FF; 187 predivider_n = cm_clksel_dpll_mpu & 0x7F; 188 189 /* 190 * Calculate reference clock (clock after pre-divider), 191 * its max. PLL bandwidth, 192 * and resulting mod_freq_divider 193 */ 194 ref_clock = V_OSCK / (predivider_n + 1); 195 pll_bandwidth = ref_clock / 70; 196 mod_freq_divider = ref_clock / (4 * pll_bandwidth); 197 198 /* Calculate Mantissa/Exponent */ 199 exponent = 0; 200 mantissa = mod_freq_divider; 201 while ((mantissa > 127) && (exponent < 7)) { 202 exponent++; 203 mantissa /= 2; 204 } 205 if (mantissa > 127) 206 mantissa = 127; 207 208 mod_freq_divider = mantissa << exponent; 209 210 /* 211 * Calculate Modulation steps 212 * As we use Downspread only, the spread is twice the value of 213 * permille, so Div2! 214 * As it takes the value in percent, divide by ten! 215 */ 216 delta_m_step = ((u32)((multiplier_m * permille) / 10 / 2)) << 18; 217 delta_m_step /= 100; 218 delta_m_step /= mod_freq_divider; 219 if (delta_m_step > 0xFFFFF) 220 delta_m_step = 0xFFFFF; 221 222 /* Setup Spread Spectrum */ 223 writel(delta_m_step, &cmwkup->sscdeltamstepdllmpu); 224 writel((exponent << 8) | mantissa, &cmwkup->sscmodfreqdivdpllmpu); 225 cm_clkmode_dpll_mpu = readl(&cmwkup->clkmoddpllmpu); 226 /* clear all SSC flags */ 227 cm_clkmode_dpll_mpu &= ~(0xF << CM_CLKMODE_DPLL_SSC_EN_SHIFT); 228 /* enable SSC with Downspread only */ 229 cm_clkmode_dpll_mpu |= CM_CLKMODE_DPLL_SSC_EN_MASK | 230 CM_CLKMODE_DPLL_SSC_DOWNSPREAD_MASK; 231 writel(cm_clkmode_dpll_mpu, &cmwkup->clkmoddpllmpu); 232 while (!(readl(&cmwkup->clkmoddpllmpu) & 0x2000)) 233 ; 234 } 235