1*de778115SLey Foon Tan /* 2*de778115SLey Foon Tan * Copyright (C) 2013-2017 Altera Corporation <www.altera.com> 3*de778115SLey Foon Tan * 4*de778115SLey Foon Tan * SPDX-License-Identifier: GPL-2.0+ 5*de778115SLey Foon Tan */ 6*de778115SLey Foon Tan 7*de778115SLey Foon Tan #include <common.h> 8*de778115SLey Foon Tan #include <asm/io.h> 9*de778115SLey Foon Tan #include <asm/arch/clock_manager.h> 10*de778115SLey Foon Tan #include <wait_bit.h> 11*de778115SLey Foon Tan 12*de778115SLey Foon Tan DECLARE_GLOBAL_DATA_PTR; 13*de778115SLey Foon Tan 14*de778115SLey Foon Tan static const struct socfpga_clock_manager *clock_manager_base = 15*de778115SLey Foon Tan (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS; 16*de778115SLey Foon Tan 17*de778115SLey Foon Tan /* 18*de778115SLey Foon Tan * function to write the bypass register which requires a poll of the 19*de778115SLey Foon Tan * busy bit 20*de778115SLey Foon Tan */ 21*de778115SLey Foon Tan static void cm_write_bypass(u32 val) 22*de778115SLey Foon Tan { 23*de778115SLey Foon Tan writel(val, &clock_manager_base->bypass); 24*de778115SLey Foon Tan cm_wait_for_fsm(); 25*de778115SLey Foon Tan } 26*de778115SLey Foon Tan 27*de778115SLey Foon Tan /* function to write the ctrl register which requires a poll of the busy bit */ 28*de778115SLey Foon Tan static void cm_write_ctrl(u32 val) 29*de778115SLey Foon Tan { 30*de778115SLey Foon Tan writel(val, &clock_manager_base->ctrl); 31*de778115SLey Foon Tan cm_wait_for_fsm(); 32*de778115SLey Foon Tan } 33*de778115SLey Foon Tan 34*de778115SLey Foon Tan /* function to write a clock register that has phase information */ 35*de778115SLey Foon Tan static int cm_write_with_phase(u32 value, u32 reg_address, u32 mask) 36*de778115SLey Foon Tan { 37*de778115SLey Foon Tan int ret; 38*de778115SLey Foon Tan 39*de778115SLey Foon Tan /* poll until phase is zero */ 40*de778115SLey Foon Tan ret = wait_for_bit(__func__, (const u32 *)reg_address, mask, 41*de778115SLey Foon Tan false, 20000, false); 42*de778115SLey Foon Tan if (ret) 43*de778115SLey Foon Tan return ret; 44*de778115SLey Foon Tan 45*de778115SLey Foon Tan writel(value, reg_address); 46*de778115SLey Foon Tan 47*de778115SLey Foon Tan return wait_for_bit(__func__, (const u32 *)reg_address, mask, 48*de778115SLey Foon Tan false, 20000, false); 49*de778115SLey Foon Tan } 50*de778115SLey Foon Tan 51*de778115SLey Foon Tan /* 52*de778115SLey Foon Tan * Setup clocks while making no assumptions about previous state of the clocks. 53*de778115SLey Foon Tan * 54*de778115SLey Foon Tan * Start by being paranoid and gate all sw managed clocks 55*de778115SLey Foon Tan * Put all plls in bypass 56*de778115SLey Foon Tan * Put all plls VCO registers back to reset value (bandgap power down). 57*de778115SLey Foon Tan * Put peripheral and main pll src to reset value to avoid glitch. 58*de778115SLey Foon Tan * Delay 5 us. 59*de778115SLey Foon Tan * Deassert bandgap power down and set numerator and denominator 60*de778115SLey Foon Tan * Start 7 us timer. 61*de778115SLey Foon Tan * set internal dividers 62*de778115SLey Foon Tan * Wait for 7 us timer. 63*de778115SLey Foon Tan * Enable plls 64*de778115SLey Foon Tan * Set external dividers while plls are locking 65*de778115SLey Foon Tan * Wait for pll lock 66*de778115SLey Foon Tan * Assert/deassert outreset all. 67*de778115SLey Foon Tan * Take all pll's out of bypass 68*de778115SLey Foon Tan * Clear safe mode 69*de778115SLey Foon Tan * set source main and peripheral clocks 70*de778115SLey Foon Tan * Ungate clocks 71*de778115SLey Foon Tan */ 72*de778115SLey Foon Tan 73*de778115SLey Foon Tan int cm_basic_init(const struct cm_config * const cfg) 74*de778115SLey Foon Tan { 75*de778115SLey Foon Tan unsigned long end; 76*de778115SLey Foon Tan int ret; 77*de778115SLey Foon Tan 78*de778115SLey Foon Tan /* Start by being paranoid and gate all sw managed clocks */ 79*de778115SLey Foon Tan 80*de778115SLey Foon Tan /* 81*de778115SLey Foon Tan * We need to disable nandclk 82*de778115SLey Foon Tan * and then do another apb access before disabling 83*de778115SLey Foon Tan * gatting off the rest of the periperal clocks. 84*de778115SLey Foon Tan */ 85*de778115SLey Foon Tan writel(~CLKMGR_PERPLLGRP_EN_NANDCLK_MASK & 86*de778115SLey Foon Tan readl(&clock_manager_base->per_pll.en), 87*de778115SLey Foon Tan &clock_manager_base->per_pll.en); 88*de778115SLey Foon Tan 89*de778115SLey Foon Tan /* DO NOT GATE OFF DEBUG CLOCKS & BRIDGE CLOCKS */ 90*de778115SLey Foon Tan writel(CLKMGR_MAINPLLGRP_EN_DBGTIMERCLK_MASK | 91*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_EN_DBGTRACECLK_MASK | 92*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_EN_DBGCLK_MASK | 93*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_EN_DBGATCLK_MASK | 94*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK | 95*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK, 96*de778115SLey Foon Tan &clock_manager_base->main_pll.en); 97*de778115SLey Foon Tan 98*de778115SLey Foon Tan writel(0, &clock_manager_base->sdr_pll.en); 99*de778115SLey Foon Tan 100*de778115SLey Foon Tan /* now we can gate off the rest of the peripheral clocks */ 101*de778115SLey Foon Tan writel(0, &clock_manager_base->per_pll.en); 102*de778115SLey Foon Tan 103*de778115SLey Foon Tan /* Put all plls in bypass */ 104*de778115SLey Foon Tan cm_write_bypass(CLKMGR_BYPASS_PERPLL | CLKMGR_BYPASS_SDRPLL | 105*de778115SLey Foon Tan CLKMGR_BYPASS_MAINPLL); 106*de778115SLey Foon Tan 107*de778115SLey Foon Tan /* Put all plls VCO registers back to reset value. */ 108*de778115SLey Foon Tan writel(CLKMGR_MAINPLLGRP_VCO_RESET_VALUE & 109*de778115SLey Foon Tan ~CLKMGR_MAINPLLGRP_VCO_REGEXTSEL_MASK, 110*de778115SLey Foon Tan &clock_manager_base->main_pll.vco); 111*de778115SLey Foon Tan writel(CLKMGR_PERPLLGRP_VCO_RESET_VALUE & 112*de778115SLey Foon Tan ~CLKMGR_PERPLLGRP_VCO_REGEXTSEL_MASK, 113*de778115SLey Foon Tan &clock_manager_base->per_pll.vco); 114*de778115SLey Foon Tan writel(CLKMGR_SDRPLLGRP_VCO_RESET_VALUE & 115*de778115SLey Foon Tan ~CLKMGR_SDRPLLGRP_VCO_REGEXTSEL_MASK, 116*de778115SLey Foon Tan &clock_manager_base->sdr_pll.vco); 117*de778115SLey Foon Tan 118*de778115SLey Foon Tan /* 119*de778115SLey Foon Tan * The clocks to the flash devices and the L4_MAIN clocks can 120*de778115SLey Foon Tan * glitch when coming out of safe mode if their source values 121*de778115SLey Foon Tan * are different from their reset value. So the trick it to 122*de778115SLey Foon Tan * put them back to their reset state, and change input 123*de778115SLey Foon Tan * after exiting safe mode but before ungating the clocks. 124*de778115SLey Foon Tan */ 125*de778115SLey Foon Tan writel(CLKMGR_PERPLLGRP_SRC_RESET_VALUE, 126*de778115SLey Foon Tan &clock_manager_base->per_pll.src); 127*de778115SLey Foon Tan writel(CLKMGR_MAINPLLGRP_L4SRC_RESET_VALUE, 128*de778115SLey Foon Tan &clock_manager_base->main_pll.l4src); 129*de778115SLey Foon Tan 130*de778115SLey Foon Tan /* read back for the required 5 us delay. */ 131*de778115SLey Foon Tan readl(&clock_manager_base->main_pll.vco); 132*de778115SLey Foon Tan readl(&clock_manager_base->per_pll.vco); 133*de778115SLey Foon Tan readl(&clock_manager_base->sdr_pll.vco); 134*de778115SLey Foon Tan 135*de778115SLey Foon Tan 136*de778115SLey Foon Tan /* 137*de778115SLey Foon Tan * We made sure bgpwr down was assert for 5 us. Now deassert BG PWR DN 138*de778115SLey Foon Tan * with numerator and denominator. 139*de778115SLey Foon Tan */ 140*de778115SLey Foon Tan writel(cfg->main_vco_base, &clock_manager_base->main_pll.vco); 141*de778115SLey Foon Tan writel(cfg->peri_vco_base, &clock_manager_base->per_pll.vco); 142*de778115SLey Foon Tan writel(cfg->sdram_vco_base, &clock_manager_base->sdr_pll.vco); 143*de778115SLey Foon Tan 144*de778115SLey Foon Tan /* 145*de778115SLey Foon Tan * Time starts here. Must wait 7 us from 146*de778115SLey Foon Tan * BGPWRDN_SET(0) to VCO_ENABLE_SET(1). 147*de778115SLey Foon Tan */ 148*de778115SLey Foon Tan end = timer_get_us() + 7; 149*de778115SLey Foon Tan 150*de778115SLey Foon Tan /* main mpu */ 151*de778115SLey Foon Tan writel(cfg->mpuclk, &clock_manager_base->main_pll.mpuclk); 152*de778115SLey Foon Tan 153*de778115SLey Foon Tan /* altera group mpuclk */ 154*de778115SLey Foon Tan writel(cfg->altera_grp_mpuclk, &clock_manager_base->altera.mpuclk); 155*de778115SLey Foon Tan 156*de778115SLey Foon Tan /* main main clock */ 157*de778115SLey Foon Tan writel(cfg->mainclk, &clock_manager_base->main_pll.mainclk); 158*de778115SLey Foon Tan 159*de778115SLey Foon Tan /* main for dbg */ 160*de778115SLey Foon Tan writel(cfg->dbgatclk, &clock_manager_base->main_pll.dbgatclk); 161*de778115SLey Foon Tan 162*de778115SLey Foon Tan /* main for cfgs2fuser0clk */ 163*de778115SLey Foon Tan writel(cfg->cfg2fuser0clk, 164*de778115SLey Foon Tan &clock_manager_base->main_pll.cfgs2fuser0clk); 165*de778115SLey Foon Tan 166*de778115SLey Foon Tan /* Peri emac0 50 MHz default to RMII */ 167*de778115SLey Foon Tan writel(cfg->emac0clk, &clock_manager_base->per_pll.emac0clk); 168*de778115SLey Foon Tan 169*de778115SLey Foon Tan /* Peri emac1 50 MHz default to RMII */ 170*de778115SLey Foon Tan writel(cfg->emac1clk, &clock_manager_base->per_pll.emac1clk); 171*de778115SLey Foon Tan 172*de778115SLey Foon Tan /* Peri QSPI */ 173*de778115SLey Foon Tan writel(cfg->mainqspiclk, &clock_manager_base->main_pll.mainqspiclk); 174*de778115SLey Foon Tan 175*de778115SLey Foon Tan writel(cfg->perqspiclk, &clock_manager_base->per_pll.perqspiclk); 176*de778115SLey Foon Tan 177*de778115SLey Foon Tan /* Peri pernandsdmmcclk */ 178*de778115SLey Foon Tan writel(cfg->mainnandsdmmcclk, 179*de778115SLey Foon Tan &clock_manager_base->main_pll.mainnandsdmmcclk); 180*de778115SLey Foon Tan 181*de778115SLey Foon Tan writel(cfg->pernandsdmmcclk, 182*de778115SLey Foon Tan &clock_manager_base->per_pll.pernandsdmmcclk); 183*de778115SLey Foon Tan 184*de778115SLey Foon Tan /* Peri perbaseclk */ 185*de778115SLey Foon Tan writel(cfg->perbaseclk, &clock_manager_base->per_pll.perbaseclk); 186*de778115SLey Foon Tan 187*de778115SLey Foon Tan /* Peri s2fuser1clk */ 188*de778115SLey Foon Tan writel(cfg->s2fuser1clk, &clock_manager_base->per_pll.s2fuser1clk); 189*de778115SLey Foon Tan 190*de778115SLey Foon Tan /* 7 us must have elapsed before we can enable the VCO */ 191*de778115SLey Foon Tan while (timer_get_us() < end) 192*de778115SLey Foon Tan ; 193*de778115SLey Foon Tan 194*de778115SLey Foon Tan /* Enable vco */ 195*de778115SLey Foon Tan /* main pll vco */ 196*de778115SLey Foon Tan writel(cfg->main_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, 197*de778115SLey Foon Tan &clock_manager_base->main_pll.vco); 198*de778115SLey Foon Tan 199*de778115SLey Foon Tan /* periferal pll */ 200*de778115SLey Foon Tan writel(cfg->peri_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, 201*de778115SLey Foon Tan &clock_manager_base->per_pll.vco); 202*de778115SLey Foon Tan 203*de778115SLey Foon Tan /* sdram pll vco */ 204*de778115SLey Foon Tan writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, 205*de778115SLey Foon Tan &clock_manager_base->sdr_pll.vco); 206*de778115SLey Foon Tan 207*de778115SLey Foon Tan /* L3 MP and L3 SP */ 208*de778115SLey Foon Tan writel(cfg->maindiv, &clock_manager_base->main_pll.maindiv); 209*de778115SLey Foon Tan 210*de778115SLey Foon Tan writel(cfg->dbgdiv, &clock_manager_base->main_pll.dbgdiv); 211*de778115SLey Foon Tan 212*de778115SLey Foon Tan writel(cfg->tracediv, &clock_manager_base->main_pll.tracediv); 213*de778115SLey Foon Tan 214*de778115SLey Foon Tan /* L4 MP, L4 SP, can0, and can1 */ 215*de778115SLey Foon Tan writel(cfg->perdiv, &clock_manager_base->per_pll.div); 216*de778115SLey Foon Tan 217*de778115SLey Foon Tan writel(cfg->gpiodiv, &clock_manager_base->per_pll.gpiodiv); 218*de778115SLey Foon Tan 219*de778115SLey Foon Tan cm_wait_for_lock(LOCKED_MASK); 220*de778115SLey Foon Tan 221*de778115SLey Foon Tan /* write the sdram clock counters before toggling outreset all */ 222*de778115SLey Foon Tan writel(cfg->ddrdqsclk & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK, 223*de778115SLey Foon Tan &clock_manager_base->sdr_pll.ddrdqsclk); 224*de778115SLey Foon Tan 225*de778115SLey Foon Tan writel(cfg->ddr2xdqsclk & CLKMGR_SDRPLLGRP_DDR2XDQSCLK_CNT_MASK, 226*de778115SLey Foon Tan &clock_manager_base->sdr_pll.ddr2xdqsclk); 227*de778115SLey Foon Tan 228*de778115SLey Foon Tan writel(cfg->ddrdqclk & CLKMGR_SDRPLLGRP_DDRDQCLK_CNT_MASK, 229*de778115SLey Foon Tan &clock_manager_base->sdr_pll.ddrdqclk); 230*de778115SLey Foon Tan 231*de778115SLey Foon Tan writel(cfg->s2fuser2clk & CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK, 232*de778115SLey Foon Tan &clock_manager_base->sdr_pll.s2fuser2clk); 233*de778115SLey Foon Tan 234*de778115SLey Foon Tan /* 235*de778115SLey Foon Tan * after locking, but before taking out of bypass 236*de778115SLey Foon Tan * assert/deassert outresetall 237*de778115SLey Foon Tan */ 238*de778115SLey Foon Tan u32 mainvco = readl(&clock_manager_base->main_pll.vco); 239*de778115SLey Foon Tan 240*de778115SLey Foon Tan /* assert main outresetall */ 241*de778115SLey Foon Tan writel(mainvco | CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, 242*de778115SLey Foon Tan &clock_manager_base->main_pll.vco); 243*de778115SLey Foon Tan 244*de778115SLey Foon Tan u32 periphvco = readl(&clock_manager_base->per_pll.vco); 245*de778115SLey Foon Tan 246*de778115SLey Foon Tan /* assert pheriph outresetall */ 247*de778115SLey Foon Tan writel(periphvco | CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, 248*de778115SLey Foon Tan &clock_manager_base->per_pll.vco); 249*de778115SLey Foon Tan 250*de778115SLey Foon Tan /* assert sdram outresetall */ 251*de778115SLey Foon Tan writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN| 252*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_VCO_OUTRESETALL, 253*de778115SLey Foon Tan &clock_manager_base->sdr_pll.vco); 254*de778115SLey Foon Tan 255*de778115SLey Foon Tan /* deassert main outresetall */ 256*de778115SLey Foon Tan writel(mainvco & ~CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, 257*de778115SLey Foon Tan &clock_manager_base->main_pll.vco); 258*de778115SLey Foon Tan 259*de778115SLey Foon Tan /* deassert pheriph outresetall */ 260*de778115SLey Foon Tan writel(periphvco & ~CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, 261*de778115SLey Foon Tan &clock_manager_base->per_pll.vco); 262*de778115SLey Foon Tan 263*de778115SLey Foon Tan /* deassert sdram outresetall */ 264*de778115SLey Foon Tan writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, 265*de778115SLey Foon Tan &clock_manager_base->sdr_pll.vco); 266*de778115SLey Foon Tan 267*de778115SLey Foon Tan /* 268*de778115SLey Foon Tan * now that we've toggled outreset all, all the clocks 269*de778115SLey Foon Tan * are aligned nicely; so we can change any phase. 270*de778115SLey Foon Tan */ 271*de778115SLey Foon Tan ret = cm_write_with_phase(cfg->ddrdqsclk, 272*de778115SLey Foon Tan (u32)&clock_manager_base->sdr_pll.ddrdqsclk, 273*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_DDRDQSCLK_PHASE_MASK); 274*de778115SLey Foon Tan if (ret) 275*de778115SLey Foon Tan return ret; 276*de778115SLey Foon Tan 277*de778115SLey Foon Tan /* SDRAM DDR2XDQSCLK */ 278*de778115SLey Foon Tan ret = cm_write_with_phase(cfg->ddr2xdqsclk, 279*de778115SLey Foon Tan (u32)&clock_manager_base->sdr_pll.ddr2xdqsclk, 280*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_DDR2XDQSCLK_PHASE_MASK); 281*de778115SLey Foon Tan if (ret) 282*de778115SLey Foon Tan return ret; 283*de778115SLey Foon Tan 284*de778115SLey Foon Tan ret = cm_write_with_phase(cfg->ddrdqclk, 285*de778115SLey Foon Tan (u32)&clock_manager_base->sdr_pll.ddrdqclk, 286*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_DDRDQCLK_PHASE_MASK); 287*de778115SLey Foon Tan if (ret) 288*de778115SLey Foon Tan return ret; 289*de778115SLey Foon Tan 290*de778115SLey Foon Tan ret = cm_write_with_phase(cfg->s2fuser2clk, 291*de778115SLey Foon Tan (u32)&clock_manager_base->sdr_pll.s2fuser2clk, 292*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK); 293*de778115SLey Foon Tan if (ret) 294*de778115SLey Foon Tan return ret; 295*de778115SLey Foon Tan 296*de778115SLey Foon Tan /* Take all three PLLs out of bypass when safe mode is cleared. */ 297*de778115SLey Foon Tan cm_write_bypass(0); 298*de778115SLey Foon Tan 299*de778115SLey Foon Tan /* clear safe mode */ 300*de778115SLey Foon Tan cm_write_ctrl(readl(&clock_manager_base->ctrl) | CLKMGR_CTRL_SAFEMODE); 301*de778115SLey Foon Tan 302*de778115SLey Foon Tan /* 303*de778115SLey Foon Tan * now that safe mode is clear with clocks gated 304*de778115SLey Foon Tan * it safe to change the source mux for the flashes the the L4_MAIN 305*de778115SLey Foon Tan */ 306*de778115SLey Foon Tan writel(cfg->persrc, &clock_manager_base->per_pll.src); 307*de778115SLey Foon Tan writel(cfg->l4src, &clock_manager_base->main_pll.l4src); 308*de778115SLey Foon Tan 309*de778115SLey Foon Tan /* Now ungate non-hw-managed clocks */ 310*de778115SLey Foon Tan writel(~0, &clock_manager_base->main_pll.en); 311*de778115SLey Foon Tan writel(~0, &clock_manager_base->per_pll.en); 312*de778115SLey Foon Tan writel(~0, &clock_manager_base->sdr_pll.en); 313*de778115SLey Foon Tan 314*de778115SLey Foon Tan /* Clear the loss of lock bits (write 1 to clear) */ 315*de778115SLey Foon Tan writel(CLKMGR_INTER_SDRPLLLOST_MASK | CLKMGR_INTER_PERPLLLOST_MASK | 316*de778115SLey Foon Tan CLKMGR_INTER_MAINPLLLOST_MASK, 317*de778115SLey Foon Tan &clock_manager_base->inter); 318*de778115SLey Foon Tan 319*de778115SLey Foon Tan return 0; 320*de778115SLey Foon Tan } 321*de778115SLey Foon Tan 322*de778115SLey Foon Tan static unsigned int cm_get_main_vco_clk_hz(void) 323*de778115SLey Foon Tan { 324*de778115SLey Foon Tan u32 reg, clock; 325*de778115SLey Foon Tan 326*de778115SLey Foon Tan /* get the main VCO clock */ 327*de778115SLey Foon Tan reg = readl(&clock_manager_base->main_pll.vco); 328*de778115SLey Foon Tan clock = cm_get_osc_clk_hz(1); 329*de778115SLey Foon Tan clock /= ((reg & CLKMGR_MAINPLLGRP_VCO_DENOM_MASK) >> 330*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_VCO_DENOM_OFFSET) + 1; 331*de778115SLey Foon Tan clock *= ((reg & CLKMGR_MAINPLLGRP_VCO_NUMER_MASK) >> 332*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_VCO_NUMER_OFFSET) + 1; 333*de778115SLey Foon Tan 334*de778115SLey Foon Tan return clock; 335*de778115SLey Foon Tan } 336*de778115SLey Foon Tan 337*de778115SLey Foon Tan static unsigned int cm_get_per_vco_clk_hz(void) 338*de778115SLey Foon Tan { 339*de778115SLey Foon Tan u32 reg, clock = 0; 340*de778115SLey Foon Tan 341*de778115SLey Foon Tan /* identify PER PLL clock source */ 342*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.vco); 343*de778115SLey Foon Tan reg = (reg & CLKMGR_PERPLLGRP_VCO_SSRC_MASK) >> 344*de778115SLey Foon Tan CLKMGR_PERPLLGRP_VCO_SSRC_OFFSET; 345*de778115SLey Foon Tan if (reg == CLKMGR_VCO_SSRC_EOSC1) 346*de778115SLey Foon Tan clock = cm_get_osc_clk_hz(1); 347*de778115SLey Foon Tan else if (reg == CLKMGR_VCO_SSRC_EOSC2) 348*de778115SLey Foon Tan clock = cm_get_osc_clk_hz(2); 349*de778115SLey Foon Tan else if (reg == CLKMGR_VCO_SSRC_F2S) 350*de778115SLey Foon Tan clock = cm_get_f2s_per_ref_clk_hz(); 351*de778115SLey Foon Tan 352*de778115SLey Foon Tan /* get the PER VCO clock */ 353*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.vco); 354*de778115SLey Foon Tan clock /= ((reg & CLKMGR_PERPLLGRP_VCO_DENOM_MASK) >> 355*de778115SLey Foon Tan CLKMGR_PERPLLGRP_VCO_DENOM_OFFSET) + 1; 356*de778115SLey Foon Tan clock *= ((reg & CLKMGR_PERPLLGRP_VCO_NUMER_MASK) >> 357*de778115SLey Foon Tan CLKMGR_PERPLLGRP_VCO_NUMER_OFFSET) + 1; 358*de778115SLey Foon Tan 359*de778115SLey Foon Tan return clock; 360*de778115SLey Foon Tan } 361*de778115SLey Foon Tan 362*de778115SLey Foon Tan unsigned long cm_get_mpu_clk_hz(void) 363*de778115SLey Foon Tan { 364*de778115SLey Foon Tan u32 reg, clock; 365*de778115SLey Foon Tan 366*de778115SLey Foon Tan clock = cm_get_main_vco_clk_hz(); 367*de778115SLey Foon Tan 368*de778115SLey Foon Tan /* get the MPU clock */ 369*de778115SLey Foon Tan reg = readl(&clock_manager_base->altera.mpuclk); 370*de778115SLey Foon Tan clock /= (reg + 1); 371*de778115SLey Foon Tan reg = readl(&clock_manager_base->main_pll.mpuclk); 372*de778115SLey Foon Tan clock /= (reg + 1); 373*de778115SLey Foon Tan return clock; 374*de778115SLey Foon Tan } 375*de778115SLey Foon Tan 376*de778115SLey Foon Tan unsigned long cm_get_sdram_clk_hz(void) 377*de778115SLey Foon Tan { 378*de778115SLey Foon Tan u32 reg, clock = 0; 379*de778115SLey Foon Tan 380*de778115SLey Foon Tan /* identify SDRAM PLL clock source */ 381*de778115SLey Foon Tan reg = readl(&clock_manager_base->sdr_pll.vco); 382*de778115SLey Foon Tan reg = (reg & CLKMGR_SDRPLLGRP_VCO_SSRC_MASK) >> 383*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_VCO_SSRC_OFFSET; 384*de778115SLey Foon Tan if (reg == CLKMGR_VCO_SSRC_EOSC1) 385*de778115SLey Foon Tan clock = cm_get_osc_clk_hz(1); 386*de778115SLey Foon Tan else if (reg == CLKMGR_VCO_SSRC_EOSC2) 387*de778115SLey Foon Tan clock = cm_get_osc_clk_hz(2); 388*de778115SLey Foon Tan else if (reg == CLKMGR_VCO_SSRC_F2S) 389*de778115SLey Foon Tan clock = cm_get_f2s_sdr_ref_clk_hz(); 390*de778115SLey Foon Tan 391*de778115SLey Foon Tan /* get the SDRAM VCO clock */ 392*de778115SLey Foon Tan reg = readl(&clock_manager_base->sdr_pll.vco); 393*de778115SLey Foon Tan clock /= ((reg & CLKMGR_SDRPLLGRP_VCO_DENOM_MASK) >> 394*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_VCO_DENOM_OFFSET) + 1; 395*de778115SLey Foon Tan clock *= ((reg & CLKMGR_SDRPLLGRP_VCO_NUMER_MASK) >> 396*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_VCO_NUMER_OFFSET) + 1; 397*de778115SLey Foon Tan 398*de778115SLey Foon Tan /* get the SDRAM (DDR_DQS) clock */ 399*de778115SLey Foon Tan reg = readl(&clock_manager_base->sdr_pll.ddrdqsclk); 400*de778115SLey Foon Tan reg = (reg & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK) >> 401*de778115SLey Foon Tan CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_OFFSET; 402*de778115SLey Foon Tan clock /= (reg + 1); 403*de778115SLey Foon Tan 404*de778115SLey Foon Tan return clock; 405*de778115SLey Foon Tan } 406*de778115SLey Foon Tan 407*de778115SLey Foon Tan unsigned int cm_get_l4_sp_clk_hz(void) 408*de778115SLey Foon Tan { 409*de778115SLey Foon Tan u32 reg, clock = 0; 410*de778115SLey Foon Tan 411*de778115SLey Foon Tan /* identify the source of L4 SP clock */ 412*de778115SLey Foon Tan reg = readl(&clock_manager_base->main_pll.l4src); 413*de778115SLey Foon Tan reg = (reg & CLKMGR_MAINPLLGRP_L4SRC_L4SP) >> 414*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_L4SRC_L4SP_OFFSET; 415*de778115SLey Foon Tan 416*de778115SLey Foon Tan if (reg == CLKMGR_L4_SP_CLK_SRC_MAINPLL) { 417*de778115SLey Foon Tan clock = cm_get_main_vco_clk_hz(); 418*de778115SLey Foon Tan 419*de778115SLey Foon Tan /* get the clock prior L4 SP divider (main clk) */ 420*de778115SLey Foon Tan reg = readl(&clock_manager_base->altera.mainclk); 421*de778115SLey Foon Tan clock /= (reg + 1); 422*de778115SLey Foon Tan reg = readl(&clock_manager_base->main_pll.mainclk); 423*de778115SLey Foon Tan clock /= (reg + 1); 424*de778115SLey Foon Tan } else if (reg == CLKMGR_L4_SP_CLK_SRC_PERPLL) { 425*de778115SLey Foon Tan clock = cm_get_per_vco_clk_hz(); 426*de778115SLey Foon Tan 427*de778115SLey Foon Tan /* get the clock prior L4 SP divider (periph_base_clk) */ 428*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.perbaseclk); 429*de778115SLey Foon Tan clock /= (reg + 1); 430*de778115SLey Foon Tan } 431*de778115SLey Foon Tan 432*de778115SLey Foon Tan /* get the L4 SP clock which supplied to UART */ 433*de778115SLey Foon Tan reg = readl(&clock_manager_base->main_pll.maindiv); 434*de778115SLey Foon Tan reg = (reg & CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_MASK) >> 435*de778115SLey Foon Tan CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_OFFSET; 436*de778115SLey Foon Tan clock = clock / (1 << reg); 437*de778115SLey Foon Tan 438*de778115SLey Foon Tan return clock; 439*de778115SLey Foon Tan } 440*de778115SLey Foon Tan 441*de778115SLey Foon Tan unsigned int cm_get_mmc_controller_clk_hz(void) 442*de778115SLey Foon Tan { 443*de778115SLey Foon Tan u32 reg, clock = 0; 444*de778115SLey Foon Tan 445*de778115SLey Foon Tan /* identify the source of MMC clock */ 446*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.src); 447*de778115SLey Foon Tan reg = (reg & CLKMGR_PERPLLGRP_SRC_SDMMC_MASK) >> 448*de778115SLey Foon Tan CLKMGR_PERPLLGRP_SRC_SDMMC_OFFSET; 449*de778115SLey Foon Tan 450*de778115SLey Foon Tan if (reg == CLKMGR_SDMMC_CLK_SRC_F2S) { 451*de778115SLey Foon Tan clock = cm_get_f2s_per_ref_clk_hz(); 452*de778115SLey Foon Tan } else if (reg == CLKMGR_SDMMC_CLK_SRC_MAIN) { 453*de778115SLey Foon Tan clock = cm_get_main_vco_clk_hz(); 454*de778115SLey Foon Tan 455*de778115SLey Foon Tan /* get the SDMMC clock */ 456*de778115SLey Foon Tan reg = readl(&clock_manager_base->main_pll.mainnandsdmmcclk); 457*de778115SLey Foon Tan clock /= (reg + 1); 458*de778115SLey Foon Tan } else if (reg == CLKMGR_SDMMC_CLK_SRC_PER) { 459*de778115SLey Foon Tan clock = cm_get_per_vco_clk_hz(); 460*de778115SLey Foon Tan 461*de778115SLey Foon Tan /* get the SDMMC clock */ 462*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.pernandsdmmcclk); 463*de778115SLey Foon Tan clock /= (reg + 1); 464*de778115SLey Foon Tan } 465*de778115SLey Foon Tan 466*de778115SLey Foon Tan /* further divide by 4 as we have fixed divider at wrapper */ 467*de778115SLey Foon Tan clock /= 4; 468*de778115SLey Foon Tan return clock; 469*de778115SLey Foon Tan } 470*de778115SLey Foon Tan 471*de778115SLey Foon Tan unsigned int cm_get_qspi_controller_clk_hz(void) 472*de778115SLey Foon Tan { 473*de778115SLey Foon Tan u32 reg, clock = 0; 474*de778115SLey Foon Tan 475*de778115SLey Foon Tan /* identify the source of QSPI clock */ 476*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.src); 477*de778115SLey Foon Tan reg = (reg & CLKMGR_PERPLLGRP_SRC_QSPI_MASK) >> 478*de778115SLey Foon Tan CLKMGR_PERPLLGRP_SRC_QSPI_OFFSET; 479*de778115SLey Foon Tan 480*de778115SLey Foon Tan if (reg == CLKMGR_QSPI_CLK_SRC_F2S) { 481*de778115SLey Foon Tan clock = cm_get_f2s_per_ref_clk_hz(); 482*de778115SLey Foon Tan } else if (reg == CLKMGR_QSPI_CLK_SRC_MAIN) { 483*de778115SLey Foon Tan clock = cm_get_main_vco_clk_hz(); 484*de778115SLey Foon Tan 485*de778115SLey Foon Tan /* get the qspi clock */ 486*de778115SLey Foon Tan reg = readl(&clock_manager_base->main_pll.mainqspiclk); 487*de778115SLey Foon Tan clock /= (reg + 1); 488*de778115SLey Foon Tan } else if (reg == CLKMGR_QSPI_CLK_SRC_PER) { 489*de778115SLey Foon Tan clock = cm_get_per_vco_clk_hz(); 490*de778115SLey Foon Tan 491*de778115SLey Foon Tan /* get the qspi clock */ 492*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.perqspiclk); 493*de778115SLey Foon Tan clock /= (reg + 1); 494*de778115SLey Foon Tan } 495*de778115SLey Foon Tan 496*de778115SLey Foon Tan return clock; 497*de778115SLey Foon Tan } 498*de778115SLey Foon Tan 499*de778115SLey Foon Tan unsigned int cm_get_spi_controller_clk_hz(void) 500*de778115SLey Foon Tan { 501*de778115SLey Foon Tan u32 reg, clock = 0; 502*de778115SLey Foon Tan 503*de778115SLey Foon Tan clock = cm_get_per_vco_clk_hz(); 504*de778115SLey Foon Tan 505*de778115SLey Foon Tan /* get the clock prior L4 SP divider (periph_base_clk) */ 506*de778115SLey Foon Tan reg = readl(&clock_manager_base->per_pll.perbaseclk); 507*de778115SLey Foon Tan clock /= (reg + 1); 508*de778115SLey Foon Tan 509*de778115SLey Foon Tan return clock; 510*de778115SLey Foon Tan } 511*de778115SLey Foon Tan 512*de778115SLey Foon Tan void cm_print_clock_quick_summary(void) 513*de778115SLey Foon Tan { 514*de778115SLey Foon Tan printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000); 515*de778115SLey Foon Tan printf("DDR %10ld kHz\n", cm_get_sdram_clk_hz() / 1000); 516*de778115SLey Foon Tan printf("EOSC1 %8d kHz\n", cm_get_osc_clk_hz(1) / 1000); 517*de778115SLey Foon Tan printf("EOSC2 %8d kHz\n", cm_get_osc_clk_hz(2) / 1000); 518*de778115SLey Foon Tan printf("F2S_SDR_REF %8d kHz\n", cm_get_f2s_sdr_ref_clk_hz() / 1000); 519*de778115SLey Foon Tan printf("F2S_PER_REF %8d kHz\n", cm_get_f2s_per_ref_clk_hz() / 1000); 520*de778115SLey Foon Tan printf("MMC %8d kHz\n", cm_get_mmc_controller_clk_hz() / 1000); 521*de778115SLey Foon Tan printf("QSPI %8d kHz\n", cm_get_qspi_controller_clk_hz() / 1000); 522*de778115SLey Foon Tan printf("UART %8d kHz\n", cm_get_l4_sp_clk_hz() / 1000); 523*de778115SLey Foon Tan printf("SPI %8d kHz\n", cm_get_spi_controller_clk_hz() / 1000); 524*de778115SLey Foon Tan } 525