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