1 /* 2 * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <common/debug.h> 9 #include <drivers/delay_timer.h> 10 #include <errno.h> 11 #include <lib/mmio.h> 12 13 #include "agilex_clock_manager.h" 14 #include "agilex_system_manager.h" 15 #include "socfpga_handoff.h" 16 17 18 uint32_t wait_pll_lock(void) 19 { 20 uint32_t data; 21 uint32_t count = 0; 22 23 do { 24 data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT); 25 count++; 26 if (count >= 1000) 27 return -ETIMEDOUT; 28 29 } while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) || 30 (CLKMGR_STAT_PERPLLLOCKED(data) == 0)); 31 return 0; 32 } 33 34 uint32_t wait_fsm(void) 35 { 36 uint32_t data; 37 uint32_t count = 0; 38 39 do { 40 data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT); 41 count++; 42 if (count >= 1000) 43 return -ETIMEDOUT; 44 45 } while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY); 46 47 return 0; 48 } 49 50 uint32_t pll_source_sync_config(uint32_t pll_mem_offset, uint32_t data) 51 { 52 uint32_t val = 0; 53 uint32_t count = 0; 54 uint32_t req_status = 0; 55 56 val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ | 57 (data << CLKMGR_MEM_WDAT_OFFSET) | CLKMGR_MEM_ADDR); 58 mmio_write_32(pll_mem_offset, val); 59 60 do { 61 req_status = mmio_read_32(pll_mem_offset); 62 count++; 63 } while ((req_status & CLKMGR_MEM_REQ) && (count < 10)); 64 65 if (count >= 100) 66 return -ETIMEDOUT; 67 68 return 0; 69 } 70 71 uint32_t pll_source_sync_read(uint32_t pll_mem_offset) 72 { 73 uint32_t val = 0; 74 uint32_t rdata = 0; 75 uint32_t count = 0; 76 uint32_t req_status = 0; 77 78 val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR); 79 mmio_write_32(pll_mem_offset, val); 80 81 do { 82 req_status = mmio_read_32(pll_mem_offset); 83 count++; 84 } while ((req_status & CLKMGR_MEM_REQ) && (count < 10)); 85 86 if (count >= 100) 87 return -ETIMEDOUT; 88 89 rdata = mmio_read_32(pll_mem_offset + 0x4); 90 INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata); 91 92 return rdata; 93 } 94 95 void config_clkmgr_handoff(handoff *hoff_ptr) 96 { 97 uint32_t mdiv, mscnt, hscnt; 98 uint32_t drefclk_div, refclk_div, rdata; 99 100 /* Set clock maanger into boot mode before running configuration */ 101 mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_CTRL, 102 CLKMGR_CTRL_BOOTMODE_SET_MSK); 103 /* Bypass all mainpllgrp's clocks */ 104 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7); 105 wait_fsm(); 106 107 /* Bypass all perpllgrp's clocks */ 108 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0x7f); 109 wait_fsm(); 110 111 /* Put both PLL in reset and power down */ 112 mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, 113 CLKMGR_PLLGLOB_PD_SET_MSK | 114 CLKMGR_PLLGLOB_RST_SET_MSK); 115 mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, 116 CLKMGR_PLLGLOB_PD_SET_MSK | 117 CLKMGR_PLLGLOB_RST_SET_MSK); 118 119 /* Setup main PLL dividers */ 120 mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->main_pll_pllm); 121 122 drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV( 123 hoff_ptr->main_pll_pllglob); 124 refclk_div = CLKMGR_PLLGLOB_REFCLKDIV( 125 hoff_ptr->main_pll_pllglob); 126 127 mscnt = 100 / (mdiv * BIT(drefclk_div)); 128 if (!mscnt) 129 mscnt = 1; 130 hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4; 131 132 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, 133 hoff_ptr->main_pll_pllglob & 134 ~CLKMGR_PLLGLOB_RST_SET_MSK); 135 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK, 136 hoff_ptr->main_pll_fdbck); 137 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB, 138 CLKMGR_VCOCALIB_HSCNT_SET(hscnt) | 139 CLKMGR_VCOCALIB_MSCNT_SET(mscnt)); 140 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0, 141 hoff_ptr->main_pll_pllc0); 142 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1, 143 hoff_ptr->main_pll_pllc1); 144 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC2, 145 hoff_ptr->main_pll_pllc2); 146 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC3, 147 hoff_ptr->main_pll_pllc3); 148 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM, 149 hoff_ptr->main_pll_pllm); 150 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MPUCLK, 151 hoff_ptr->main_pll_mpuclk); 152 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK, 153 hoff_ptr->main_pll_nocclk); 154 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV, 155 hoff_ptr->main_pll_nocdiv); 156 157 /* Setup peripheral PLL dividers */ 158 mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->per_pll_pllm); 159 160 drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV( 161 hoff_ptr->per_pll_pllglob); 162 refclk_div = CLKMGR_PLLGLOB_REFCLKDIV( 163 hoff_ptr->per_pll_pllglob); 164 165 166 mscnt = 100 / (mdiv * BIT(drefclk_div)); 167 if (!mscnt) 168 mscnt = 1; 169 hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4; 170 171 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, 172 hoff_ptr->per_pll_pllglob & 173 ~CLKMGR_PLLGLOB_RST_SET_MSK); 174 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK, 175 hoff_ptr->per_pll_fdbck); 176 177 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB, 178 CLKMGR_VCOCALIB_HSCNT_SET(hscnt) | 179 CLKMGR_VCOCALIB_MSCNT_SET(mscnt)); 180 181 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0, 182 hoff_ptr->per_pll_pllc0); 183 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1, 184 hoff_ptr->per_pll_pllc1); 185 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC2, 186 hoff_ptr->per_pll_pllc2); 187 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC3, 188 hoff_ptr->per_pll_pllc3); 189 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM, 190 hoff_ptr->per_pll_pllm); 191 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL, 192 hoff_ptr->per_pll_emacctl); 193 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV, 194 hoff_ptr->per_pll_gpiodiv); 195 196 /* Take both PLL out of reset and power up */ 197 mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, 198 CLKMGR_PLLGLOB_PD_SET_MSK | 199 CLKMGR_PLLGLOB_RST_SET_MSK); 200 mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, 201 CLKMGR_PLLGLOB_PD_SET_MSK | 202 CLKMGR_PLLGLOB_RST_SET_MSK); 203 204 rdata = pll_source_sync_read(CLKMGR_MAINPLL + 205 CLKMGR_MAINPLL_MEM); 206 pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM, 207 rdata | 0x80); 208 209 rdata = pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM); 210 pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM, 211 rdata | 0x80); 212 213 wait_pll_lock(); 214 215 /*Configure Ping Pong counters in altera group */ 216 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR, 217 hoff_ptr->alt_emacactr); 218 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACBCTR, 219 hoff_ptr->alt_emacbctr); 220 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACPTPCTR, 221 hoff_ptr->alt_emacptpctr); 222 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_GPIODBCTR, 223 hoff_ptr->alt_gpiodbctr); 224 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR, 225 hoff_ptr->alt_sdmmcctr); 226 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER0CTR, 227 hoff_ptr->alt_s2fuser0ctr); 228 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER1CTR, 229 hoff_ptr->alt_s2fuser1ctr); 230 mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_PSIREFCTR, 231 hoff_ptr->alt_psirefctr); 232 233 /* Clear lost lock bypass mode */ 234 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_LOSTLOCK, 0x1); 235 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_LOSTLOCK, 0x1); 236 237 mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB, 238 CLKMGR_CLR_LOSTLOCK_BYPASS); 239 240 mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB, 241 CLKMGR_CLR_LOSTLOCK_BYPASS); 242 243 /* Take all PLLs out of bypass */ 244 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0); 245 wait_fsm(); 246 247 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0); 248 wait_fsm(); 249 250 /* Clear loss lock interrupt status register that */ 251 /* might be set during configuration */ 252 mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR, 253 CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK | 254 CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK); 255 256 /* Take all ping pong counters out of reset */ 257 mmio_clrbits_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EXTCNTRST, 258 CLKMGR_ALTERA_EXTCNTRST_RESET); 259 260 /* Set safe mode / out of boot mode */ 261 mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_CTRL, 262 CLKMGR_CTRL_BOOTMODE_SET_MSK); 263 wait_fsm(); 264 265 /* Enable mainpllgrp's software-managed clock */ 266 mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN, 267 CLKMGR_MAINPLL_EN_RESET); 268 mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN, 269 CLKMGR_PERPLL_EN_RESET); 270 271 /* Pass clock source frequency into scratch register */ 272 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1), 273 hoff_ptr->hps_osc_clk_h); 274 mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2), 275 hoff_ptr->fpga_clk_hz); 276 } 277 278 /* Extract reference clock from platform clock source */ 279 uint32_t get_ref_clk(uint32_t pllglob) 280 { 281 uint32_t arefclkdiv, ref_clk; 282 uint32_t scr_reg; 283 284 switch (CLKMGR_PSRC(pllglob)) { 285 case CLKMGR_PLLGLOB_PSRC_EOSC1: 286 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1); 287 ref_clk = mmio_read_32(scr_reg); 288 break; 289 case CLKMGR_PLLGLOB_PSRC_INTOSC: 290 ref_clk = CLKMGR_INTOSC_HZ; 291 break; 292 case CLKMGR_PLLGLOB_PSRC_F2S: 293 scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2); 294 ref_clk = mmio_read_32(scr_reg); 295 break; 296 default: 297 ref_clk = 0; 298 assert(0); 299 break; 300 } 301 302 arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob); 303 ref_clk /= arefclkdiv; 304 305 return ref_clk; 306 } 307 308 /* Calculate clock frequency based on parameter */ 309 uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc) 310 { 311 uint32_t clk_psrc, mdiv, ref_clk; 312 uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg; 313 314 clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg); 315 316 switch (CLKMGR_PSRC(clk_psrc)) { 317 case CLKMGR_PSRC_MAIN: 318 pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM; 319 pllc_reg = CLKMGR_MAINPLL + main_pllc; 320 pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB; 321 break; 322 case CLKMGR_PSRC_PER: 323 pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM; 324 pllc_reg = CLKMGR_PERPLL + per_pllc; 325 pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB; 326 break; 327 default: 328 return 0; 329 } 330 331 ref_clk = get_ref_clk(mmio_read_32(pllglob_reg)); 332 mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg)); 333 ref_clk *= mdiv; 334 335 pllc_div = mmio_read_32(pllc_reg) & 0x7ff; 336 337 return ref_clk / pllc_div; 338 } 339 340 /* Return L3 interconnect clock */ 341 uint32_t get_l3_clk(void) 342 { 343 uint32_t l3_clk; 344 345 l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1, 346 CLKMGR_PERPLL_PLLC1); 347 return l3_clk; 348 } 349 350 /* Calculate clock frequency to be used for watchdog timer */ 351 uint32_t get_wdt_clk(void) 352 { 353 uint32_t l3_clk, l4_sys_clk; 354 355 l3_clk = get_l3_clk(); 356 l4_sys_clk = l3_clk / 4; 357 358 return l4_sys_clk; 359 } 360 361 /* Calculate clock frequency to be used for UART driver */ 362 uint32_t get_uart_clk(void) 363 { 364 uint32_t data32, l3_clk, l4_sp_clk; 365 366 l3_clk = get_l3_clk(); 367 368 data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV); 369 data32 = (data32 >> 16) & 0x3; 370 371 l4_sp_clk = l3_clk >> data32; 372 373 return l4_sp_clk; 374 } 375 376 /* Calculate clock frequency to be used for SDMMC driver */ 377 uint32_t get_mmc_clk(void) 378 { 379 uint32_t data32, mmc_clk; 380 381 mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR, 382 CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3); 383 384 data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR); 385 data32 = (data32 & 0x7ff) + 1; 386 mmc_clk = (mmc_clk / data32) / 4; 387 388 return mmc_clk; 389 } 390 391 /* Return MPU clock */ 392 uint32_t get_mpu_clk(void) 393 { 394 uint32_t mpu_clk; 395 396 mpu_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC0, 397 CLKMGR_PERPLL_PLLC0); 398 return mpu_clk; 399 } 400 401 /* Get cpu freq clock */ 402 uint32_t get_cpu_clk(void) 403 { 404 uint32_t cpu_clk; 405 406 cpu_clk = get_mpu_clk()/PLAT_HZ_CONVERT_TO_MHZ; 407 408 return cpu_clk; 409 } 410