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