1 /* 2 * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch.h> 8 #include <arch_helpers.h> 9 #include <assert.h> 10 #include <drivers/delay_timer.h> 11 #include <lib/mmio.h> 12 #include <platform_def.h> 13 14 #include "s10_clock_manager.h" 15 #include "socfpga_handoff.h" 16 #include "socfpga_system_manager.h" 17 18 19 void wait_pll_lock(void) 20 { 21 uint32_t data; 22 23 do { 24 data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT); 25 } while ((ALT_CLKMGR_STAT_MAINPLLLOCKED(data) == 0) || 26 (ALT_CLKMGR_STAT_PERPLLLOCKED(data) == 0)); 27 } 28 29 void wait_fsm(void) 30 { 31 uint32_t data; 32 33 do { 34 data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT); 35 } while (ALT_CLKMGR_STAT_BUSY(data) == ALT_CLKMGR_STAT_BUSY_E_BUSY); 36 } 37 38 void config_clkmgr_handoff(handoff *hoff_ptr) 39 { 40 uint32_t m_div, refclk_div, mscnt, hscnt; 41 42 /* Bypass all mainpllgrp's clocks */ 43 mmio_write_32(ALT_CLKMGR_MAINPLL + 44 ALT_CLKMGR_MAINPLL_BYPASS, 45 0x7); 46 wait_fsm(); 47 /* Bypass all perpllgrp's clocks */ 48 mmio_write_32(ALT_CLKMGR_PERPLL + 49 ALT_CLKMGR_PERPLL_BYPASS, 50 0x7f); 51 wait_fsm(); 52 53 /* Setup main PLL dividers */ 54 m_div = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(hoff_ptr->main_pll_fdbck); 55 refclk_div = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV( 56 hoff_ptr->main_pll_pllglob); 57 mscnt = 200 / ((6 + m_div) / refclk_div); 58 hscnt = (m_div + 6) * mscnt / refclk_div - 9; 59 60 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB, 61 hoff_ptr->main_pll_pllglob); 62 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK, 63 hoff_ptr->main_pll_fdbck); 64 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_VCOCALIB, 65 ALT_CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(hscnt) | 66 ALT_CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(mscnt)); 67 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC0, 68 hoff_ptr->main_pll_pllc0); 69 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1, 70 hoff_ptr->main_pll_pllc1); 71 72 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV, 73 hoff_ptr->main_pll_nocdiv); 74 75 /* Setup peripheral PLL dividers */ 76 m_div = ALT_CLKMGR_PERPLL_FDBCK_MDIV(hoff_ptr->per_pll_fdbck); 77 refclk_div = ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV( 78 hoff_ptr->per_pll_pllglob); 79 mscnt = 200 / ((6 + m_div) / refclk_div); 80 hscnt = (m_div + 6) * mscnt / refclk_div - 9; 81 82 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB, 83 hoff_ptr->per_pll_pllglob); 84 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_FDBCK, 85 hoff_ptr->per_pll_fdbck); 86 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_VCOCALIB, 87 ALT_CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(hscnt) | 88 ALT_CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(mscnt)); 89 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC0, 90 hoff_ptr->per_pll_pllc0); 91 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1, 92 hoff_ptr->per_pll_pllc1); 93 94 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_GPIODIV, 95 ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET( 96 hoff_ptr->per_pll_gpiodiv)); 97 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EMACCTL, 98 hoff_ptr->per_pll_emacctl); 99 100 101 /* Take both PLL out of reset and power up */ 102 mmio_setbits_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB, 103 ALT_CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK | 104 ALT_CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK); 105 mmio_setbits_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB, 106 ALT_CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK | 107 ALT_CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK); 108 109 wait_pll_lock(); 110 111 /* Dividers for C2 to C9 only init after PLLs are lock. */ 112 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK, 0xff); 113 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK, 0xff); 114 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK, 0xff); 115 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK, 0xff); 116 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK, 0xff); 117 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK, 0xff); 118 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK, 0xff); 119 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK, 0xff); 120 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK, 0xff); 121 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK, 0xff); 122 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK, 0xff); 123 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK, 0xff); 124 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK, 0xff); 125 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK, 0xff); 126 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK, 0xff); 127 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK, 0xff); 128 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK, 0xff); 129 130 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK, 131 hoff_ptr->main_pll_mpuclk); 132 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK, 133 hoff_ptr->main_pll_nocclk); 134 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK, 135 hoff_ptr->main_pll_cntr2clk); 136 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK, 137 hoff_ptr->main_pll_cntr3clk); 138 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK, 139 hoff_ptr->main_pll_cntr4clk); 140 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK, 141 hoff_ptr->main_pll_cntr5clk); 142 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK, 143 hoff_ptr->main_pll_cntr6clk); 144 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK, 145 hoff_ptr->main_pll_cntr7clk); 146 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK, 147 hoff_ptr->main_pll_cntr8clk); 148 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK, 149 hoff_ptr->main_pll_cntr9clk); 150 151 /* Peripheral PLL Clock Source and Counters/Divider */ 152 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK, 153 hoff_ptr->per_pll_cntr2clk); 154 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK, 155 hoff_ptr->per_pll_cntr3clk); 156 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK, 157 hoff_ptr->per_pll_cntr4clk); 158 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK, 159 hoff_ptr->per_pll_cntr5clk); 160 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK, 161 hoff_ptr->per_pll_cntr6clk); 162 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK, 163 hoff_ptr->per_pll_cntr7clk); 164 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK, 165 hoff_ptr->per_pll_cntr8clk); 166 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR9CLK, 167 hoff_ptr->per_pll_cntr9clk); 168 169 /* Take all PLLs out of bypass */ 170 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_BYPASS, 0); 171 wait_fsm(); 172 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_BYPASS, 0); 173 wait_fsm(); 174 175 /* Set safe mode/ out of boot mode */ 176 mmio_clrbits_32(ALT_CLKMGR + ALT_CLKMGR_CTRL, 177 ALT_CLKMGR_CTRL_BOOTMODE_SET_MSK); 178 wait_fsm(); 179 180 /* 10 Enable mainpllgrp's software-managed clock */ 181 mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_EN, 182 ALT_CLKMGR_MAINPLL_EN_RESET); 183 mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EN, 184 ALT_CLKMGR_PERPLL_EN_RESET); 185 186 /* Clear loss lock interrupt status register that */ 187 /* might be set during configuration */ 188 mmio_write_32(ALT_CLKMGR + ALT_CLKMGR_INTRCLR, 189 ALT_CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK | 190 ALT_CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK); 191 192 /* Pass clock source frequency into scratch register */ 193 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1), 194 hoff_ptr->hps_osc_clk_h); 195 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2), 196 hoff_ptr->fpga_clk_hz); 197 198 } 199 200 /* Extract reference clock from platform clock source */ 201 uint32_t get_ref_clk(uint32_t pllglob) 202 { 203 uint32_t data32, mdiv, refclkdiv, ref_clk; 204 uint32_t scr_reg; 205 206 switch (ALT_CLKMGR_PSRC(pllglob)) { 207 case ALT_CLKMGR_PLLGLOB_PSRC_EOSC1: 208 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1); 209 ref_clk = mmio_read_32(scr_reg); 210 break; 211 case ALT_CLKMGR_PLLGLOB_PSRC_INTOSC: 212 ref_clk = ALT_CLKMGR_INTOSC_HZ; 213 break; 214 case ALT_CLKMGR_PLLGLOB_PSRC_F2S: 215 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2); 216 ref_clk = mmio_read_32(scr_reg); 217 break; 218 default: 219 ref_clk = 0; 220 assert(0); 221 break; 222 } 223 224 refclkdiv = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(pllglob); 225 data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK); 226 mdiv = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(data32); 227 228 ref_clk = (ref_clk / refclkdiv) * (6 + mdiv); 229 230 return ref_clk; 231 } 232 233 /* Calculate clock frequency based on parameter */ 234 uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc) 235 { 236 uint32_t clk_psrc, ref_clk; 237 uint32_t pllc_reg, pllc_div, pllglob_reg; 238 239 clk_psrc = mmio_read_32(ALT_CLKMGR_MAINPLL + psrc_reg); 240 241 switch (ALT_CLKMGR_PSRC(clk_psrc)) { 242 case ALT_CLKMGR_SRC_MAIN: 243 pllc_reg = ALT_CLKMGR_MAINPLL + main_pllc; 244 pllglob_reg = ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB; 245 break; 246 case ALT_CLKMGR_SRC_PER: 247 pllc_reg = ALT_CLKMGR_PERPLL + per_pllc; 248 pllglob_reg = ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB; 249 break; 250 default: 251 return 0; 252 } 253 254 ref_clk = get_ref_clk(mmio_read_32(pllglob_reg)); 255 256 pllc_div = mmio_read_32(pllc_reg) & 0xff; 257 258 if (pllc_div != 0) { 259 ref_clk = (ref_clk / pllc_div) / (clk_psrc + 1); 260 return ref_clk; 261 } else { 262 VERBOSE("PLL DIV is 0\n"); 263 return 0; 264 } 265 } 266 267 /* Calculate L3 interconnect main clock */ 268 uint32_t get_l3_clk(uint32_t ref_clk) 269 { 270 uint32_t noc_base_clk, l3_clk, noc_clk, data32; 271 uint32_t pllc1_reg; 272 273 noc_clk = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK); 274 275 switch (ALT_CLKMGR_PSRC(noc_clk)) { 276 case ALT_CLKMGR_SRC_MAIN: 277 pllc1_reg = ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1; 278 break; 279 case ALT_CLKMGR_SRC_PER: 280 pllc1_reg = ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1; 281 break; 282 default: 283 pllc1_reg = 0; 284 assert(0); 285 break; 286 } 287 288 data32 = mmio_read_32(pllc1_reg); 289 noc_base_clk = ref_clk / (data32 & 0xff); 290 l3_clk = noc_base_clk / (noc_clk + 1); 291 292 return l3_clk; 293 } 294 295 /* Calculate clock frequency to be used for watchdog timer */ 296 uint32_t get_wdt_clk(void) 297 { 298 uint32_t data32, ref_clk, l3_clk, l4_sys_clk; 299 300 data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB); 301 ref_clk = get_ref_clk(data32); 302 303 l3_clk = get_l3_clk(ref_clk); 304 305 l4_sys_clk = l3_clk / 4; 306 307 return l4_sys_clk; 308 } 309 310 /* Calculate clock frequency to be used for UART driver */ 311 uint32_t get_uart_clk(void) 312 { 313 uint32_t data32, ref_clk, l3_clk, l4_sp_clk; 314 315 data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB); 316 ref_clk = get_ref_clk(data32); 317 318 l3_clk = get_l3_clk(ref_clk); 319 320 data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV); 321 data32 = (data32 >> 16) & 0x3; 322 data32 = 1 << data32; 323 324 l4_sp_clk = (l3_clk / data32); 325 326 return l4_sp_clk; 327 } 328 329 /* Calculate clock frequency to be used for SDMMC driver */ 330 uint32_t get_mmc_clk(void) 331 { 332 uint32_t data32, ref_clk, l3_clk, mmc_clk; 333 334 data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB); 335 ref_clk = get_ref_clk(data32); 336 337 l3_clk = get_l3_clk(ref_clk); 338 339 data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK); 340 mmc_clk = (l3_clk / (data32 + 1)) / 4; 341 342 return mmc_clk; 343 } 344 345 /* Return MPU clock */ 346 uint32_t get_mpu_clk(void) 347 { 348 uint32_t mpu_clk; 349 350 mpu_clk = get_clk_freq(ALT_CLKMGR_MAINPLL_NOCCLK, ALT_CLKMGR_MAINPLL_PLLC0, 351 ALT_CLKMGR_PERPLL_PLLC0); 352 353 return mpu_clk; 354 } 355 356 /* Get cpu freq clock */ 357 uint32_t get_cpu_clk(void) 358 { 359 uint32_t data32, ref_clk, cpu_clk; 360 361 data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB); 362 ref_clk = get_ref_clk(data32); 363 364 cpu_clk = get_l3_clk(ref_clk)/PLAT_HZ_CONVERT_TO_MHZ; 365 366 return cpu_clk; 367 } 368 369 /* Return mpu_periph_clk clock frequency */ 370 uint32_t get_mpu_periph_clk(void) 371 { 372 uint32_t mpu_periph_clk = 0; 373 /* mpu_periph_clk is mpu_clk, via a static /4 divider */ 374 mpu_periph_clk = (get_mpu_clk()/4)/PLAT_HZ_CONVERT_TO_MHZ; 375 return mpu_periph_clk; 376 } 377 378 /* Return mpu_periph_clk tick */ 379 unsigned int plat_get_syscnt_freq2(void) 380 { 381 return PLAT_SYS_COUNTER_FREQ_IN_TICKS; 382 } 383