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