[U-Boot] [PATCH 08/10] arm: socfpga: arria10: Added drivers for Arria10 clock manager

From: Tien Fong Chee tien.fong.chee@intel.com
The drivers is restructured such common functions, gen5 functions, and arria10 functions are moved to clock_manager.c, cock_manager_gen5 and clock_manager_arria10 respectively.
Signed-off-by: Tien Fong Chee tien.fong.chee@intel.com Cc: Marek Vasut marex@denx.de Cc: Dinh Nguyen dinguyen@kernel.org Cc: Chin Liang See chin.liang.see@intel.com Cc: Tien Fong skywindctf@gmail.com --- arch/arm/mach-socfpga/Makefile | 6 +- arch/arm/mach-socfpga/clock_manager.c | 754 +++++++--------- arch/arm/mach-socfpga/clock_manager_arria10.c | 954 ++++++++++++++++++++ arch/arm/mach-socfpga/clock_manager_gen5.c | 342 +++++++ arch/arm/mach-socfpga/include/mach/clock_manager.h | 360 ++++++-- 5 files changed, 1910 insertions(+), 506 deletions(-) create mode 100644 arch/arm/mach-socfpga/clock_manager_arria10.c create mode 100644 arch/arm/mach-socfpga/clock_manager_gen5.c
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index f8b529e..71cf31c 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -9,9 +9,11 @@
obj-y += misc.o timer.o reset_manager.o system_manager.o clock_manager.o \ fpga_manager.o board.o -obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += reset_manager_arria10.o misc_arria10.o +obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += reset_manager_arria10.o misc_arria10.o \ + clock_manager_arria10.o obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += scan_manager.o wrap_pll_config.o \ - reset_manager_gen5.o misc_gen5.o + reset_manager_gen5.o misc_gen5.o \ + clock_manager_gen5.o
ifdef CONFIG_SPL_BUILD obj-y += spl.o diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c index aa71636..fe82c39 100644 --- a/arch/arm/mach-socfpga/clock_manager.c +++ b/arch/arm/mach-socfpga/clock_manager.c @@ -1,422 +1,293 @@ /* - * Copyright (C) 2013 Altera Corporation <www.altera.com> + * Copyright (C) 2013-2016 Intel Corporation <www.intel.com> * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0 */
#include <common.h> #include <asm/io.h> #include <asm/arch/clock_manager.h> +#include <fdtdec.h>
DECLARE_GLOBAL_DATA_PTR;
+/* Function prototypes */ +/* Common prototypes */ +unsigned int cm_get_l4_sp_clk_hz(void); +unsigned int cm_get_qspi_controller_clk_hz(void); +unsigned int cm_get_mmc_controller_clk_hz(void); +unsigned int cm_get_spi_controller_clk_hz(void); +static void cm_print_clock_quick_summary(void); +int do_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +void cm_wait_for_lock(uint32_t mask); +void cm_wait_for_fsm(void); +unsigned int cm_get_main_vco_clk_hz(void); +unsigned int cm_get_per_vco_clk_hz(void); +unsigned long cm_get_mpu_clk_hz(void); + static const struct socfpga_clock_manager *clock_manager_base = (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
-static void cm_wait_for_lock(uint32_t mask) +/* Common functions */ +int set_cpu_clk_info(void) { - register uint32_t inter_val; - uint32_t retry = 0; - do { - inter_val = readl(&clock_manager_base->inter) & mask; - if (inter_val == mask) - retry++; - else - retry = 0; - if (retry >= 10) - break; - } while (1); -} + /* Calculate the clock frequencies required for drivers */ + cm_get_l4_sp_clk_hz(); + cm_get_mmc_controller_clk_hz();
-/* function to poll in the fsm busy bit */ -static void cm_wait_for_fsm(void) -{ - while (readl(&clock_manager_base->stat) & CLKMGR_STAT_BUSY) - ; -} + gd->bd->bi_arm_freq = cm_get_mpu_clk_hz() / 1000000; + gd->bd->bi_dsp_freq = 0;
-/* - * function to write the bypass register which requires a poll of the - * busy bit - */ -static void cm_write_bypass(uint32_t val) -{ - writel(val, &clock_manager_base->bypass); - cm_wait_for_fsm(); -} +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + gd->bd->bi_ddr_freq = cm_get_sdram_clk_hz() / 1000000; +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + gd->bd->bi_ddr_freq = 0; +#endif
-/* function to write the ctrl register which requires a poll of the busy bit */ -static void cm_write_ctrl(uint32_t val) -{ - writel(val, &clock_manager_base->ctrl); - cm_wait_for_fsm(); + return 0; }
-/* function to write a clock register that has phase information */ -static void cm_write_with_phase(uint32_t value, - uint32_t reg_address, uint32_t mask) +unsigned int cm_get_spi_controller_clk_hz(void) { - /* poll until phase is zero */ - while (readl(reg_address) & mask) - ; + uint32_t clock = 0;
- writel(value, reg_address); +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + uint32_t reg; + clock = cm_get_per_vco_clk_hz();
- while (readl(reg_address) & mask) - ; -} + /* get the clock prior L4 SP divider (periph_base_clk) */ + reg = readl(&clock_manager_base->per_pll.perbaseclk); + clock /= (reg + 1); +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + clock = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB); +#endif
-/* - * Setup clocks while making no assumptions about previous state of the clocks. - * - * Start by being paranoid and gate all sw managed clocks - * Put all plls in bypass - * Put all plls VCO registers back to reset value (bandgap power down). - * Put peripheral and main pll src to reset value to avoid glitch. - * Delay 5 us. - * Deassert bandgap power down and set numerator and denominator - * Start 7 us timer. - * set internal dividers - * Wait for 7 us timer. - * Enable plls - * Set external dividers while plls are locking - * Wait for pll lock - * Assert/deassert outreset all. - * Take all pll's out of bypass - * Clear safe mode - * set source main and peripheral clocks - * Ungate clocks - */ + return clock; +}
-void cm_basic_init(const struct cm_config * const cfg) +unsigned int cm_get_qspi_controller_clk_hz(void) { - unsigned long end; - - /* Start by being paranoid and gate all sw managed clocks */ - - /* - * We need to disable nandclk - * and then do another apb access before disabling - * gatting off the rest of the periperal clocks. - */ - writel(~CLKMGR_PERPLLGRP_EN_NANDCLK_MASK & - readl(&clock_manager_base->per_pll.en), - &clock_manager_base->per_pll.en); - - /* DO NOT GATE OFF DEBUG CLOCKS & BRIDGE CLOCKS */ - writel(CLKMGR_MAINPLLGRP_EN_DBGTIMERCLK_MASK | - CLKMGR_MAINPLLGRP_EN_DBGTRACECLK_MASK | - CLKMGR_MAINPLLGRP_EN_DBGCLK_MASK | - CLKMGR_MAINPLLGRP_EN_DBGATCLK_MASK | - CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK | - CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK, - &clock_manager_base->main_pll.en); - - writel(0, &clock_manager_base->sdr_pll.en); - - /* now we can gate off the rest of the peripheral clocks */ - writel(0, &clock_manager_base->per_pll.en); - - /* Put all plls in bypass */ - cm_write_bypass(CLKMGR_BYPASS_PERPLL | CLKMGR_BYPASS_SDRPLL | - CLKMGR_BYPASS_MAINPLL); - - /* Put all plls VCO registers back to reset value. */ - writel(CLKMGR_MAINPLLGRP_VCO_RESET_VALUE & - ~CLKMGR_MAINPLLGRP_VCO_REGEXTSEL_MASK, - &clock_manager_base->main_pll.vco); - writel(CLKMGR_PERPLLGRP_VCO_RESET_VALUE & - ~CLKMGR_PERPLLGRP_VCO_REGEXTSEL_MASK, - &clock_manager_base->per_pll.vco); - writel(CLKMGR_SDRPLLGRP_VCO_RESET_VALUE & - ~CLKMGR_SDRPLLGRP_VCO_REGEXTSEL_MASK, - &clock_manager_base->sdr_pll.vco); - - /* - * The clocks to the flash devices and the L4_MAIN clocks can - * glitch when coming out of safe mode if their source values - * are different from their reset value. So the trick it to - * put them back to their reset state, and change input - * after exiting safe mode but before ungating the clocks. - */ - writel(CLKMGR_PERPLLGRP_SRC_RESET_VALUE, - &clock_manager_base->per_pll.src); - writel(CLKMGR_MAINPLLGRP_L4SRC_RESET_VALUE, - &clock_manager_base->main_pll.l4src); - - /* read back for the required 5 us delay. */ - readl(&clock_manager_base->main_pll.vco); - readl(&clock_manager_base->per_pll.vco); - readl(&clock_manager_base->sdr_pll.vco); - - - /* - * We made sure bgpwr down was assert for 5 us. Now deassert BG PWR DN - * with numerator and denominator. - */ - writel(cfg->main_vco_base, &clock_manager_base->main_pll.vco); - writel(cfg->peri_vco_base, &clock_manager_base->per_pll.vco); - writel(cfg->sdram_vco_base, &clock_manager_base->sdr_pll.vco); - - /* - * Time starts here. Must wait 7 us from - * BGPWRDN_SET(0) to VCO_ENABLE_SET(1). - */ - end = timer_get_us() + 7; - - /* main mpu */ - writel(cfg->mpuclk, &clock_manager_base->main_pll.mpuclk); - - /* main main clock */ - writel(cfg->mainclk, &clock_manager_base->main_pll.mainclk); - - /* main for dbg */ - writel(cfg->dbgatclk, &clock_manager_base->main_pll.dbgatclk); - - /* main for cfgs2fuser0clk */ - writel(cfg->cfg2fuser0clk, - &clock_manager_base->main_pll.cfgs2fuser0clk); - - /* Peri emac0 50 MHz default to RMII */ - writel(cfg->emac0clk, &clock_manager_base->per_pll.emac0clk); - - /* Peri emac1 50 MHz default to RMII */ - writel(cfg->emac1clk, &clock_manager_base->per_pll.emac1clk); - - /* Peri QSPI */ - writel(cfg->mainqspiclk, &clock_manager_base->main_pll.mainqspiclk); - - writel(cfg->perqspiclk, &clock_manager_base->per_pll.perqspiclk); - - /* Peri pernandsdmmcclk */ - writel(cfg->mainnandsdmmcclk, - &clock_manager_base->main_pll.mainnandsdmmcclk); - - writel(cfg->pernandsdmmcclk, - &clock_manager_base->per_pll.pernandsdmmcclk); - - /* Peri perbaseclk */ - writel(cfg->perbaseclk, &clock_manager_base->per_pll.perbaseclk); - - /* Peri s2fuser1clk */ - writel(cfg->s2fuser1clk, &clock_manager_base->per_pll.s2fuser1clk); - - /* 7 us must have elapsed before we can enable the VCO */ - while (timer_get_us() < end) - ; - - /* Enable vco */ - /* main pll vco */ - writel(cfg->main_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, - &clock_manager_base->main_pll.vco); + uint32_t clock = 0;
- /* periferal pll */ - writel(cfg->peri_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, - &clock_manager_base->per_pll.vco); - - /* sdram pll vco */ - writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, - &clock_manager_base->sdr_pll.vco); - - /* L3 MP and L3 SP */ - writel(cfg->maindiv, &clock_manager_base->main_pll.maindiv); - - writel(cfg->dbgdiv, &clock_manager_base->main_pll.dbgdiv); - - writel(cfg->tracediv, &clock_manager_base->main_pll.tracediv); - - /* L4 MP, L4 SP, can0, and can1 */ - writel(cfg->perdiv, &clock_manager_base->per_pll.div); - - writel(cfg->gpiodiv, &clock_manager_base->per_pll.gpiodiv); - -#define LOCKED_MASK \ - (CLKMGR_INTER_SDRPLLLOCKED_MASK | \ - CLKMGR_INTER_PERPLLLOCKED_MASK | \ - CLKMGR_INTER_MAINPLLLOCKED_MASK) - - cm_wait_for_lock(LOCKED_MASK); - - /* write the sdram clock counters before toggling outreset all */ - writel(cfg->ddrdqsclk & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK, - &clock_manager_base->sdr_pll.ddrdqsclk); +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + uint32_t reg; + /* identify the source of QSPI clock */ + reg = readl(&clock_manager_base->per_pll.src); + reg = (reg & CLKMGR_PERPLLGRP_SRC_QSPI_MASK) >> + CLKMGR_PERPLLGRP_SRC_QSPI_OFFSET;
- writel(cfg->ddr2xdqsclk & CLKMGR_SDRPLLGRP_DDR2XDQSCLK_CNT_MASK, - &clock_manager_base->sdr_pll.ddr2xdqsclk); + if (reg == CLKMGR_QSPI_CLK_SRC_F2S) { + clock = cm_get_f2s_per_ref_clk_hz(); + } else if (reg == CLKMGR_QSPI_CLK_SRC_MAIN) { + clock = cm_get_main_vco_clk_hz();
- writel(cfg->ddrdqclk & CLKMGR_SDRPLLGRP_DDRDQCLK_CNT_MASK, - &clock_manager_base->sdr_pll.ddrdqclk); + /* get the qspi clock */ + reg = readl(&clock_manager_base->main_pll.mainqspiclk); + clock /= (reg + 1); + } else if (reg == CLKMGR_QSPI_CLK_SRC_PER) { + clock = cm_get_per_vco_clk_hz();
- writel(cfg->s2fuser2clk & CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK, - &clock_manager_base->sdr_pll.s2fuser2clk); + /* get the qspi clock */ + reg = readl(&clock_manager_base->per_pll.perqspiclk); + clock /= (reg + 1); + } +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + clock = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB); +#endif
- /* - * after locking, but before taking out of bypass - * assert/deassert outresetall - */ - uint32_t mainvco = readl(&clock_manager_base->main_pll.vco); + return clock; +}
- /* assert main outresetall */ - writel(mainvco | CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, - &clock_manager_base->main_pll.vco); +void cm_wait_for_lock(uint32_t mask) +{ + register uint32_t inter_val; + uint32_t retry = 0; + do { +#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + inter_val = readl(&clock_manager_base->stat) & mask; +#elif defined(CONFIG_TARGET_SOCFPGA_GEN5) + inter_val = readl(&clock_manager_base->inter) & mask; +#endif + /* Wait for stable lock */ + if (inter_val == mask) + retry++; + else + retry = 0; + if (retry >= 10) + break; + } while (1); +}
- uint32_t periphvco = readl(&clock_manager_base->per_pll.vco); +unsigned long cm_get_mpu_clk_hz(void) +{ + uint32_t reg, clk_hz; +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + clk_hz = cm_get_main_vco_clk_hz();
- /* assert pheriph outresetall */ - writel(periphvco | CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, - &clock_manager_base->per_pll.vco); + /* get the MPU clock */ + reg = readl(&clock_manager_base->altera.mpuclk); + clk_hz /= (reg + 1); + reg = readl(&clock_manager_base->main_pll.mpuclk); + clk_hz /= (reg + 1); +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + uint32_t clk_src, mainmpuclk_reg;
- /* assert sdram outresetall */ - writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN| - CLKMGR_SDRPLLGRP_VCO_OUTRESETALL, - &clock_manager_base->sdr_pll.vco); + mainmpuclk_reg = readl(&clock_manager_base->main_pll.mpuclk);
- /* deassert main outresetall */ - writel(mainvco & ~CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, - &clock_manager_base->main_pll.vco); + clk_src = (mainmpuclk_reg >> CLKMGR_MAINPLL_MPUCLK_SRC_LSB) & + CLKMGR_MAINPLL_MPUCLK_SRC_MSK;
- /* deassert pheriph outresetall */ - writel(periphvco & ~CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, - &clock_manager_base->per_pll.vco); + reg = readl(&clock_manager_base->altera.mpuclk); + /* Check MPU clock source: main, periph, osc1, intosc or f2s? */ + switch (clk_src) { + case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN: + clk_hz = cm_get_main_vco_clk_hz(); + clk_hz /= ((reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + + 1); + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_PERI: + clk_hz = cm_get_per_vco_clk_hz(); + clk_hz /= (((reg >> CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) & + CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1); + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1: + clk_hz = eosc1_hz; + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC: + clk_hz = cb_intosc_hz; + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA: + clk_hz = f2s_free_hz; + break; + default: + printf("cm_get_mpu_clk_hz invalid clk_src %d\n", clk_src); + return 0; + }
- /* deassert sdram outresetall */ - writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, - &clock_manager_base->sdr_pll.vco); + clk_hz /= ((mainmpuclk_reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1); +#endif
- /* - * now that we've toggled outreset all, all the clocks - * are aligned nicely; so we can change any phase. - */ - cm_write_with_phase(cfg->ddrdqsclk, - (uint32_t)&clock_manager_base->sdr_pll.ddrdqsclk, - CLKMGR_SDRPLLGRP_DDRDQSCLK_PHASE_MASK); + return clk_hz; +}
- /* SDRAM DDR2XDQSCLK */ - cm_write_with_phase(cfg->ddr2xdqsclk, - (uint32_t)&clock_manager_base->sdr_pll.ddr2xdqsclk, - CLKMGR_SDRPLLGRP_DDR2XDQSCLK_PHASE_MASK); +unsigned int cm_get_per_vco_clk_hz(void) +{ + uint32_t src_hz = 0; + uint32_t clk_src = 0; + uint32_t numer = 0; + uint32_t denom = 0; + uint32_t vco = 0;
- cm_write_with_phase(cfg->ddrdqclk, - (uint32_t)&clock_manager_base->sdr_pll.ddrdqclk, - CLKMGR_SDRPLLGRP_DDRDQCLK_PHASE_MASK); +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + /* identify PER PLL clock source */ + clk_src = readl(&clock_manager_base->per_pll.vco); + clk_src = (clk_src & CLKMGR_PERPLLGRP_VCO_SSRC_MASK) >> + CLKMGR_PERPLLGRP_VCO_SSRC_OFFSET; + if (clk_src == CLKMGR_VCO_SSRC_EOSC1) + src_hz = cm_get_osc_clk_hz(1); + else if (clk_src == CLKMGR_VCO_SSRC_EOSC2) + src_hz = cm_get_osc_clk_hz(2); + else if (clk_src == CLKMGR_VCO_SSRC_F2S) + src_hz = cm_get_f2s_per_ref_clk_hz();
- cm_write_with_phase(cfg->s2fuser2clk, - (uint32_t)&clock_manager_base->sdr_pll.s2fuser2clk, - CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK); + /* get the PER VCO clock */ + vco = readl(&clock_manager_base->per_pll.vco); + + numer = (vco & CLKMGR_PERPLLGRP_VCO_NUMER_MASK) >> + CLKMGR_PERPLLGRP_VCO_NUMER_OFFSET; + + denom = (vco & CLKMGR_PERPLLGRP_VCO_DENOM_MASK) >> + CLKMGR_PERPLLGRP_VCO_DENOM_OFFSET; + +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + clk_src = readl(&clock_manager_base->per_pll.vco0); + + clk_src = (clk_src >> CLKMGR_PERPLL_VCO0_PSRC_LSB) & + CLKMGR_PERPLL_VCO0_PSRC_MSK; + + if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_EOSC) { + src_hz = eosc1_hz; + } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC) { + src_hz = cb_intosc_hz; + } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_F2S) { + src_hz = f2s_free_hz; + } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_MAIN) { + src_hz = cm_get_main_vco_clk_hz(); + src_hz /= (readl + (&clock_manager_base->main_pll.cntr15clk) & + CLKMGR_MAINPLL_CNTRCLK_MSK) + 1; + } else { + printf("cm_get_per_vco_clk_hz invalid clk_src %d\n", clk_src); + return 0; + }
- /* Take all three PLLs out of bypass when safe mode is cleared. */ - cm_write_bypass(0); + vco = readl(&clock_manager_base->per_pll.vco1);
- /* clear safe mode */ - cm_write_ctrl(readl(&clock_manager_base->ctrl) | CLKMGR_CTRL_SAFEMODE); + numer = vco & CLKMGR_PERPLL_VCO1_NUMER_MSK;
- /* - * now that safe mode is clear with clocks gated - * it safe to change the source mux for the flashes the the L4_MAIN - */ - writel(cfg->persrc, &clock_manager_base->per_pll.src); - writel(cfg->l4src, &clock_manager_base->main_pll.l4src); + denom = (vco >> CLKMGR_PERPLL_VCO1_DENOM_LSB) & + CLKMGR_PERPLL_VCO1_DENOM_MSK; +#endif
- /* Now ungate non-hw-managed clocks */ - writel(~0, &clock_manager_base->main_pll.en); - writel(~0, &clock_manager_base->per_pll.en); - writel(~0, &clock_manager_base->sdr_pll.en); + vco = src_hz; + vco /= (1 + denom); + vco *= (1 + numer);
- /* Clear the loss of lock bits (write 1 to clear) */ - writel(CLKMGR_INTER_SDRPLLLOST_MASK | CLKMGR_INTER_PERPLLLOST_MASK | - CLKMGR_INTER_MAINPLLLOST_MASK, - &clock_manager_base->inter); + return vco; }
-static unsigned int cm_get_main_vco_clk_hz(void) +unsigned int cm_get_main_vco_clk_hz(void) { - uint32_t reg, clock; + uint32_t src_hz, numer, denom, vco;
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5) /* get the main VCO clock */ - reg = readl(&clock_manager_base->main_pll.vco); - clock = cm_get_osc_clk_hz(1); - clock /= ((reg & CLKMGR_MAINPLLGRP_VCO_DENOM_MASK) >> - CLKMGR_MAINPLLGRP_VCO_DENOM_OFFSET) + 1; - clock *= ((reg & CLKMGR_MAINPLLGRP_VCO_NUMER_MASK) >> - CLKMGR_MAINPLLGRP_VCO_NUMER_OFFSET) + 1; - - return clock; -} - -static unsigned int cm_get_per_vco_clk_hz(void) -{ - uint32_t reg, clock = 0; - - /* identify PER PLL clock source */ - reg = readl(&clock_manager_base->per_pll.vco); - reg = (reg & CLKMGR_PERPLLGRP_VCO_SSRC_MASK) >> - CLKMGR_PERPLLGRP_VCO_SSRC_OFFSET; - if (reg == CLKMGR_VCO_SSRC_EOSC1) - clock = cm_get_osc_clk_hz(1); - else if (reg == CLKMGR_VCO_SSRC_EOSC2) - clock = cm_get_osc_clk_hz(2); - else if (reg == CLKMGR_VCO_SSRC_F2S) - clock = cm_get_f2s_per_ref_clk_hz(); - - /* get the PER VCO clock */ - reg = readl(&clock_manager_base->per_pll.vco); - clock /= ((reg & CLKMGR_PERPLLGRP_VCO_DENOM_MASK) >> - CLKMGR_PERPLLGRP_VCO_DENOM_OFFSET) + 1; - clock *= ((reg & CLKMGR_PERPLLGRP_VCO_NUMER_MASK) >> - CLKMGR_PERPLLGRP_VCO_NUMER_OFFSET) + 1; - - return clock; -} + vco = readl(&clock_manager_base->main_pll.vco); + + numer = ((vco & CLKMGR_MAINPLLGRP_VCO_NUMER_MASK) >> + CLKMGR_MAINPLLGRP_VCO_NUMER_OFFSET); + denom = ((vco & CLKMGR_MAINPLLGRP_VCO_DENOM_MASK) >> + CLKMGR_MAINPLLGRP_VCO_DENOM_OFFSET); + + src_hz = cm_get_osc_clk_hz(1); +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + uint32_t clk_src = readl(&clock_manager_base->main_pll.vco0); + + clk_src = (clk_src >> CLKMGR_MAINPLL_VCO0_PSRC_LSB) & + CLKMGR_MAINPLL_VCO0_PSRC_MSK; + + if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_EOSC) { + src_hz = eosc1_hz; + } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC) { + src_hz = cb_intosc_hz; + } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_F2S) { + src_hz = f2s_free_hz; + } else { + printf("cm_get_main_vco_clk_hz invalid clk_src %d\n", clk_src); + return 0; + }
-unsigned long cm_get_mpu_clk_hz(void) -{ - uint32_t reg, clock; + vco = readl(&clock_manager_base->main_pll.vco1);
- clock = cm_get_main_vco_clk_hz(); + numer = vco & CLKMGR_MAINPLL_VCO1_NUMER_MSK;
- /* get the MPU clock */ - reg = readl(&clock_manager_base->altera.mpuclk); - clock /= (reg + 1); - reg = readl(&clock_manager_base->main_pll.mpuclk); - clock /= (reg + 1); - return clock; -} + denom = (vco >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) & + CLKMGR_MAINPLL_VCO1_DENOM_MSK; +#endif
-unsigned long cm_get_sdram_clk_hz(void) -{ - uint32_t reg, clock = 0; - - /* identify SDRAM PLL clock source */ - reg = readl(&clock_manager_base->sdr_pll.vco); - reg = (reg & CLKMGR_SDRPLLGRP_VCO_SSRC_MASK) >> - CLKMGR_SDRPLLGRP_VCO_SSRC_OFFSET; - if (reg == CLKMGR_VCO_SSRC_EOSC1) - clock = cm_get_osc_clk_hz(1); - else if (reg == CLKMGR_VCO_SSRC_EOSC2) - clock = cm_get_osc_clk_hz(2); - else if (reg == CLKMGR_VCO_SSRC_F2S) - clock = cm_get_f2s_sdr_ref_clk_hz(); - - /* get the SDRAM VCO clock */ - reg = readl(&clock_manager_base->sdr_pll.vco); - clock /= ((reg & CLKMGR_SDRPLLGRP_VCO_DENOM_MASK) >> - CLKMGR_SDRPLLGRP_VCO_DENOM_OFFSET) + 1; - clock *= ((reg & CLKMGR_SDRPLLGRP_VCO_NUMER_MASK) >> - CLKMGR_SDRPLLGRP_VCO_NUMER_OFFSET) + 1; - - /* get the SDRAM (DDR_DQS) clock */ - reg = readl(&clock_manager_base->sdr_pll.ddrdqsclk); - reg = (reg & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK) >> - CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_OFFSET; - clock /= (reg + 1); + vco = src_hz; + vco /= (1 + denom); + vco *= (1 + numer);
- return clock; + return vco; }
unsigned int cm_get_l4_sp_clk_hz(void) { - uint32_t reg, clock = 0; + uint32_t clock = 0;
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + uint32_t reg; /* identify the source of L4 SP clock */ reg = readl(&clock_manager_base->main_pll.l4src); reg = (reg & CLKMGR_MAINPLLGRP_L4SRC_L4SP) >> @@ -443,106 +314,117 @@ unsigned int cm_get_l4_sp_clk_hz(void) reg = (reg & CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_MASK) >> CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_OFFSET; clock = clock / (1 << reg); - +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + clock = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB); +#endif return clock; }
-unsigned int cm_get_mmc_controller_clk_hz(void) +/* function to poll in the fsm busy bit */ +void cm_wait_for_fsm(void) { - uint32_t reg, clock = 0; - - /* identify the source of MMC clock */ - reg = readl(&clock_manager_base->per_pll.src); - reg = (reg & CLKMGR_PERPLLGRP_SRC_SDMMC_MASK) >> - CLKMGR_PERPLLGRP_SRC_SDMMC_OFFSET; - - if (reg == CLKMGR_SDMMC_CLK_SRC_F2S) { - clock = cm_get_f2s_per_ref_clk_hz(); - } else if (reg == CLKMGR_SDMMC_CLK_SRC_MAIN) { - clock = cm_get_main_vco_clk_hz(); - - /* get the SDMMC clock */ - reg = readl(&clock_manager_base->main_pll.mainnandsdmmcclk); - clock /= (reg + 1); - } else if (reg == CLKMGR_SDMMC_CLK_SRC_PER) { - clock = cm_get_per_vco_clk_hz(); - - /* get the SDMMC clock */ - reg = readl(&clock_manager_base->per_pll.pernandsdmmcclk); - clock /= (reg + 1); - } - - /* further divide by 4 as we have fixed divider at wrapper */ - clock /= 4; - return clock; + while (readl(&clock_manager_base->stat) & + CLKMGR_CLKMGR_STAT_BUSY_SET_MSK); }
-unsigned int cm_get_qspi_controller_clk_hz(void) +unsigned int cm_get_mmc_controller_clk_hz(void) { - uint32_t reg, clock = 0; - - /* identify the source of QSPI clock */ - reg = readl(&clock_manager_base->per_pll.src); - reg = (reg & CLKMGR_PERPLLGRP_SRC_QSPI_MASK) >> - CLKMGR_PERPLLGRP_SRC_QSPI_OFFSET; + uint32_t clk_hz = 0; + uint32_t clk_input = 0; + +#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + clk_input = readl(&clock_manager_base->per_pll.cntr6clk); + clk_input = (clk_input >> CLKMGR_PERPLL_CNTR6CLK_SRC_LSB) & + CLKMGR_PERPLLGRP_SRC_MSK; +#elif defined(CONFIG_TARGET_SOCFPGA_GEN5) + clk_input = readl(&clock_manager_base->per_pll.src); + clk_input = (clk_input & CLKMGR_PERPLLGRP_SRC_SDMMC_MASK) >> + CLKMGR_PERPLLGRP_SRC_SDMMC_OFFSET; +#endif + + switch (clk_input) { +#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + case CLKMGR_PERPLLGRP_SRC_MAIN: + clk_hz = cm_get_main_vco_clk_hz(); + clk_hz /= 1 + + (readl + (&clock_manager_base->main_pll.cntr6clk) & + CLKMGR_MAINPLL_CNTRCLK_MSK); + break; + + case CLKMGR_PERPLLGRP_SRC_PERI: + clk_hz = cm_get_per_vco_clk_hz(); + clk_hz /= 1 + (readl + (&clock_manager_base->per_pll.cntr6clk) & + CLKMGR_PERPLL_CNTRCLK_MSK); + break; + + case CLKMGR_PERPLLGRP_SRC_OSC1: + clk_hz = eosc1_hz; + break; + + case CLKMGR_PERPLLGRP_SRC_INTOSC: + clk_hz = cb_intosc_hz; + break; + + case CLKMGR_PERPLLGRP_SRC_FPGA: + clk_hz = f2s_free_hz; + break; +#elif defined(CONFIG_TARGET_SOCFPGA_GEN5) + case CLKMGR_SDMMC_CLK_SRC_F2S: + clk_hz = cm_get_f2s_per_ref_clk_hz(); + break; + + case CLKMGR_SDMMC_CLK_SRC_MAIN: + clk_hz = cm_get_main_vco_clk_hz();
- if (reg == CLKMGR_QSPI_CLK_SRC_F2S) { - clock = cm_get_f2s_per_ref_clk_hz(); - } else if (reg == CLKMGR_QSPI_CLK_SRC_MAIN) { - clock = cm_get_main_vco_clk_hz(); + /* get the SDMMC clock */ + clk_input = + readl(&clock_manager_base->main_pll.mainnandsdmmcclk); + clk_hz /= (clk_input + 1); + break;
- /* get the qspi clock */ - reg = readl(&clock_manager_base->main_pll.mainqspiclk); - clock /= (reg + 1); - } else if (reg == CLKMGR_QSPI_CLK_SRC_PER) { - clock = cm_get_per_vco_clk_hz(); + case CLKMGR_SDMMC_CLK_SRC_PER: + clk_hz = cm_get_per_vco_clk_hz();
- /* get the qspi clock */ - reg = readl(&clock_manager_base->per_pll.perqspiclk); - clock /= (reg + 1); + /* get the SDMMC clock */ + clk_input = + readl(&clock_manager_base->per_pll.pernandsdmmcclk); + clk_hz /= (clk_input + 1); + break; +#endif } - - return clock; -} - -unsigned int cm_get_spi_controller_clk_hz(void) -{ - uint32_t reg, clock = 0; - - clock = cm_get_per_vco_clk_hz(); - - /* get the clock prior L4 SP divider (periph_base_clk) */ - reg = readl(&clock_manager_base->per_pll.perbaseclk); - clock /= (reg + 1); - - return clock; + return clk_hz/4; }
static void cm_print_clock_quick_summary(void) { printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000); + printf("MMC %8d kHz\n", cm_get_mmc_controller_clk_hz() / 1000); + printf("QSPI %8d kHz\n", + cm_get_qspi_controller_clk_hz() / 1000); + printf("SPI %8d kHz\n", cm_get_spi_controller_clk_hz() / 1000); +#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + printf("EOSC1 %8d kHz\n", eosc1_hz / 1000); + printf("cb_intosc %8d kHz\n", cb_intosc_hz / 1000); + printf("f2s_free %8d kHz\n", f2s_free_hz / 1000); + printf("Main VCO %8d kHz\n", cm_get_main_vco_clk_hz()/1000); + printf("NOC %8d kHz\n", cm_get_noc_clk_hz()/1000); + printf("L4 Main %8d kHz\n", + cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB)/1000); + printf("L4 MP %8d kHz\n", + cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB)/1000); + printf("L4 SP %8d kHz\n", + cm_get_l4_sp_clk_hz()/1000); + printf("L4 sys free %8d kHz\n", cm_l4_sys_free_clk_hz/1000); +#elif defined(CONFIG_TARGET_SOCFPGA_GEN5) printf("DDR %10ld kHz\n", cm_get_sdram_clk_hz() / 1000); printf("EOSC1 %8d kHz\n", cm_get_osc_clk_hz(1) / 1000); printf("EOSC2 %8d kHz\n", cm_get_osc_clk_hz(2) / 1000); printf("F2S_SDR_REF %8d kHz\n", cm_get_f2s_sdr_ref_clk_hz() / 1000); printf("F2S_PER_REF %8d kHz\n", cm_get_f2s_per_ref_clk_hz() / 1000); - printf("MMC %8d kHz\n", cm_get_mmc_controller_clk_hz() / 1000); - printf("QSPI %8d kHz\n", cm_get_qspi_controller_clk_hz() / 1000); printf("UART %8d kHz\n", cm_get_l4_sp_clk_hz() / 1000); - printf("SPI %8d kHz\n", cm_get_spi_controller_clk_hz() / 1000); -} - -int set_cpu_clk_info(void) -{ - /* Calculate the clock frequencies required for drivers */ - cm_get_l4_sp_clk_hz(); - cm_get_mmc_controller_clk_hz(); - - gd->bd->bi_arm_freq = cm_get_mpu_clk_hz() / 1000000; - gd->bd->bi_dsp_freq = 0; - gd->bd->bi_ddr_freq = cm_get_sdram_clk_hz() / 1000000; - - return 0; +#endif }
int do_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) diff --git a/arch/arm/mach-socfpga/clock_manager_arria10.c b/arch/arm/mach-socfpga/clock_manager_arria10.c new file mode 100644 index 0000000..93165b4 --- /dev/null +++ b/arch/arm/mach-socfpga/clock_manager_arria10.c @@ -0,0 +1,954 @@ +/* + * Copyright (C) 2016, Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock_manager.h> +#include <fdtdec.h> + +DECLARE_GLOBAL_DATA_PTR; + +int cm_basic_init(const void* blob); +uint32_t eosc1_hz; +uint32_t cb_intosc_hz; +uint32_t f2s_free_hz; +unsigned int cm_l4_main_clk_hz; +unsigned int cm_l4_sp_clk_hz; +unsigned int cm_l4_mp_clk_hz; +unsigned int cm_l4_sys_free_clk_hz; + +struct strtopu32 { + const char *str; + uint32_t *p; +}; + +struct mainpll_cfg { + uint32_t vco0_psrc; + uint32_t vco1_denom; + uint32_t vco1_numer; + uint32_t mpuclk; + uint32_t mpuclk_cnt; + uint32_t mpuclk_src; + uint32_t nocclk; + uint32_t nocclk_cnt; + uint32_t nocclk_src; + uint32_t cntr2clk_cnt; + uint32_t cntr3clk_cnt; + uint32_t cntr4clk_cnt; + uint32_t cntr5clk_cnt; + uint32_t cntr6clk_cnt; + uint32_t cntr7clk_cnt; + uint32_t cntr7clk_src; + uint32_t cntr8clk_cnt; + uint32_t cntr9clk_cnt; + uint32_t cntr9clk_src; + uint32_t cntr15clk_cnt; + uint32_t nocdiv_l4mainclk; + uint32_t nocdiv_l4mpclk; + uint32_t nocdiv_l4spclk; + uint32_t nocdiv_csatclk; + uint32_t nocdiv_cstraceclk; + uint32_t nocdiv_cspdbclk; +}; + +struct perpll_cfg { + uint32_t vco0_psrc; + uint32_t vco1_denom; + uint32_t vco1_numer; + uint32_t cntr2clk_cnt; + uint32_t cntr2clk_src; + uint32_t cntr3clk_cnt; + uint32_t cntr3clk_src; + uint32_t cntr4clk_cnt; + uint32_t cntr4clk_src; + uint32_t cntr5clk_cnt; + uint32_t cntr5clk_src; + uint32_t cntr6clk_cnt; + uint32_t cntr6clk_src; + uint32_t cntr7clk_cnt; + uint32_t cntr8clk_cnt; + uint32_t cntr8clk_src; + uint32_t cntr9clk_cnt; + uint32_t emacctl_emac0sel; + uint32_t emacctl_emac1sel; + uint32_t emacctl_emac2sel; + uint32_t gpiodiv_gpiodbclk; +}; + +struct alteragrp_cfg { + uint32_t nocclk; + uint32_t mpuclk; +}; + +unsigned int cm_get_noc_clk_hz(void); +unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift); +static int of_to_struct(const void *blob, int node, int cfg__len, void *cfg); +static int of_get_input_clks(const void *blob, int node, void *cfg); +static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg, struct alteragrp_cfg *altrgrp_cfg); +static unsigned int cm_calc_handoff_main_vco_clk_hz( + struct mainpll_cfg *main_cfg); +static unsigned int cm_calc_handoff_periph_vco_clk_hz( + struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg); +static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg); +static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg); +static int cm_is_pll_ramp_required(int main0periph1, + struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg); +static unsigned int cm_calc_safe_pll_numer(int main0periph1, + struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg, + unsigned int safe_hz); +static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg, unsigned int pll_ramp_main_hz); +static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg, unsigned int pll_ramp_periph_hz); +static int cm_full_cfg(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg); + +static const struct socfpga_clock_manager *clock_manager_base = + (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS; + +void cm_use_intosc(void) +{ + setbits_le32(&clock_manager_base->ctrl, + CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK); +} + +unsigned int cm_get_noc_clk_hz(void) +{ + unsigned int clk_src, dividor, nocclk, src_hz; + + nocclk = readl(&clock_manager_base->main_pll.nocclk); + clk_src = (nocclk >> CLKMGR_MAINPLL_NOCCLK_SRC_LSB) & + CLKMGR_MAINPLL_NOCCLK_SRC_MSK; + + dividor = 1 + (nocclk & CLKMGR_MAINPLL_NOCDIV_MSK); + + if (clk_src == CLKMGR_PERPLLGRP_SRC_MAIN) { + src_hz = cm_get_main_vco_clk_hz(); + src_hz /= 1 + + (readl(SOCFPGA_CLKMGR_ADDRESS+CLKMGR_MAINPLL_NOC_CLK_OFFSET)& + CLKMGR_MAINPLL_NOCCLK_CNT_MSK); + } else if (clk_src == CLKMGR_PERPLLGRP_SRC_PERI) { + src_hz = cm_get_per_vco_clk_hz(); + src_hz /= 1 + + ((readl(SOCFPGA_CLKMGR_ADDRESS+CLKMGR_MAINPLL_NOC_CLK_OFFSET)>> + CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB)& + CLKMGR_MAINPLL_NOCCLK_CNT_MSK); + } else if (clk_src == CLKMGR_PERPLLGRP_SRC_OSC1) { + src_hz = eosc1_hz; + } else if (clk_src == CLKMGR_PERPLLGRP_SRC_INTOSC) { + src_hz = cb_intosc_hz; + } else if (clk_src == CLKMGR_PERPLLGRP_SRC_FPGA) { + src_hz = f2s_free_hz; + } else { + src_hz = 0; + } + return src_hz/dividor; +} + +unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift) +{ + unsigned int dividor2 = 1 << + ((readl(&clock_manager_base->main_pll.nocdiv) >> + nocdivshift) & CLKMGR_MAINPLL_NOCDIV_MSK); + + return cm_get_noc_clk_hz()/dividor2; +} + +int of_to_struct(const void *blob, int node, int cfg_len, void *cfg) +{ + if (fdtdec_get_int_array(blob, node, "altr,of_reg_value", + (u32*)cfg, cfg_len)) { + /* could not find required property */ + return 100; + } + + return 0; +} + +static int of_get_input_clks(const void *blob, int node, void *cfg) +{ + if (fdtdec_get_int_array(blob, node, "clock-frequency", + (u32*)cfg, 1)) { + /* could not find required property */ + return 100; + } + + return 0; +} + +int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg, struct alteragrp_cfg *altrgrp_cfg) +{ + int node, child, len; + const char *node_name; + + node = fdtdec_next_compatible(blob, 0, COMPAT_ALTERA_SOCFPGA_CLK); + + if (node < 0) + return 1; + + child = fdt_first_subnode(blob, node); + + if (child < 0) + return 2; + + child = fdt_first_subnode(blob, child); + + if (child < 0) + return 3; + + node_name = fdt_get_name(blob, child, &len); + + while (node_name) { + if (!strcmp(node_name, "osc1")) { + if (of_get_input_clks(blob, child, &eosc1_hz)) + return 101; + } else if (!strcmp(node_name, "cb_intosc_ls_clk")) { + if (of_get_input_clks(blob, child, &cb_intosc_hz)) + return 102; + } else if (!strcmp(node_name, "f2s_free_clk")) { + if (of_get_input_clks(blob, child, &f2s_free_hz)) + return 103; + } else if (!strcmp(node_name, "main_pll")) { + if (of_to_struct(blob, child, sizeof(*main_cfg)/sizeof(uint32_t), + main_cfg)) + return 104; + } else if (!strcmp(node_name, "periph_pll")) { + if (of_to_struct(blob, child, sizeof(*per_cfg)/sizeof(uint32_t), + per_cfg)) + return 105; + } else if (!strcmp(node_name, "altera")) { + if (of_to_struct(blob, child, + sizeof(*altrgrp_cfg)/sizeof(uint32_t), altrgrp_cfg)) + return 106; + + main_cfg->mpuclk = altrgrp_cfg->mpuclk; + main_cfg->nocclk = altrgrp_cfg->nocclk; + } + child = fdt_next_subnode(blob, child); + + if (child < 0) + break; + + node_name = fdt_get_name(blob, child, &len); + } + + return 0; +} + +/* calculate the intended main VCO frequency based on handoff */ +static unsigned int cm_calc_handoff_main_vco_clk_hz + (struct mainpll_cfg *main_cfg) +{ + unsigned int clk_hz; + + /* Check main VCO clock source: eosc, intosc or f2s? */ + switch (main_cfg->vco0_psrc) { + case CLKMGR_MAINPLL_VCO0_PSRC_EOSC: + clk_hz = eosc1_hz; + break; + case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC: + clk_hz = cb_intosc_hz; + break; + case CLKMGR_MAINPLL_VCO0_PSRC_F2S: + clk_hz = f2s_free_hz; + break; + default: + return 0; + } + + /* calculate the VCO frequency */ + clk_hz /= (1 + main_cfg->vco1_denom); + clk_hz *= (1 + main_cfg->vco1_numer); + + return clk_hz; +} + +/* calculate the intended periph VCO frequency based on handoff */ +static unsigned int cm_calc_handoff_periph_vco_clk_hz + (struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg) +{ + unsigned int clk_hz; + + /* Check periph VCO clock source: eosc, intosc, f2s or mainpll? */ + switch (per_cfg->vco0_psrc) { + case CLKMGR_PERPLL_VCO0_PSRC_EOSC: + clk_hz = eosc1_hz; + break; + case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC: + clk_hz = cb_intosc_hz; + break; + case CLKMGR_PERPLL_VCO0_PSRC_F2S: + clk_hz = f2s_free_hz; + break; + case CLKMGR_PERPLL_VCO0_PSRC_MAIN: + clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg); + clk_hz /= main_cfg->cntr15clk_cnt; + break; + default: + return 0; + } + + /* calculate the VCO frequency */ + clk_hz /= (1 + per_cfg->vco1_denom); + clk_hz *= (1 + per_cfg->vco1_numer); + + return clk_hz; +} + +/* calculate the intended MPU clock frequency based on handoff */ +static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg) +{ + unsigned int clk_hz; + + /* Check MPU clock source: main, periph, osc1, intosc or f2s? */ + switch (main_cfg->mpuclk_src) { + case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN: + clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg); + clk_hz /= ((main_cfg->mpuclk & CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + + 1); + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_PERI: + clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg); + clk_hz /= (((main_cfg->mpuclk >> + CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) & + CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1); + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1: + clk_hz = eosc1_hz; + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC: + clk_hz = cb_intosc_hz; + break; + case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA: + clk_hz = f2s_free_hz; + break; + default: + return 0; + } + + clk_hz /= (main_cfg->mpuclk_cnt + 1); + return clk_hz; +} + +/* calculate the intended NOC clock frequency based on handoff */ +static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg) +{ + unsigned int clk_hz; + + /* Check MPU clock source: main, periph, osc1, intosc or f2s? */ + switch (main_cfg->nocclk_src) { + case CLKMGR_MAINPLL_NOCCLK_SRC_MAIN: + clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg); + clk_hz /= ((main_cfg->nocclk & CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + + 1); + break; + case CLKMGR_MAINPLL_NOCCLK_SRC_PERI: + clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg); + clk_hz /= (((main_cfg->nocclk >> + CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) & + CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1); + break; + case CLKMGR_MAINPLL_NOCCLK_SRC_OSC1: + clk_hz = eosc1_hz; + break; + case CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC: + clk_hz = cb_intosc_hz; + break; + case CLKMGR_MAINPLL_NOCCLK_SRC_FPGA: + clk_hz = f2s_free_hz; + break; + default: + return 0; + } + + clk_hz /= (main_cfg->nocclk_cnt + 1); + return clk_hz; +} + +/* return 1 if PLL ramp is required */ +static int cm_is_pll_ramp_required(int main0periph1, + struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg) +{ + + /* Check for main PLL */ + if (main0periph1 == 0) { + /* + * PLL ramp is not required if both MPU clock and NOC clock are + * not sourced from main PLL + */ + if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_MAIN && + main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) + return 0; + + /* + * PLL ramp is required if MPU clock is sourced from main PLL + * and MPU clock is over 900MHz (as advised by HW team) + */ + if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN && + (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) > + CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ)) + return 1; + + /* + * PLL ramp is required if NOC clock is sourced from main PLL + * and NOC clock is over 300MHz (as advised by HW team) + */ + if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN && + (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) > + CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ)) + return 2; + + } else if (main0periph1 == 1) { + /* + * PLL ramp is not required if both MPU clock and NOC clock are + * not sourced from periph PLL + */ + if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_PERI && + main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_PERI) + return 0; + + /* + * PLL ramp is required if MPU clock are source from periph PLL + * and MPU clock is over 900MHz (as advised by HW team) + */ + if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI && + (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) > + CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ)) + return 1; + + /* + * PLL ramp is required if NOC clock are source from periph PLL + * and NOC clock is over 300MHz (as advised by HW team) + */ + if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI && + (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) > + CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ)) + return 2; + } + return 0; +} + +/* + * Calculate the new PLL numerator which is based on existing DTS hand off and + * intended safe frequency (safe_hz). Note that PLL ramp is only modifying the + * numerator while maintaining denominator as denominator will influence the + * jitter condition. Please refer A10 HPS TRM for the jitter guide. Note final + * value for numerator is minus with 1 to cater our register value + * representation. + */ +static unsigned int cm_calc_safe_pll_numer(int main0periph1, + struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg, + unsigned int safe_hz) +{ + unsigned int clk_hz = 0; + + /* Check for main PLL */ + if (main0periph1 == 0) { + /* Check main VCO clock source: eosc, intosc or f2s? */ + switch (main_cfg->vco0_psrc) { + case CLKMGR_MAINPLL_VCO0_PSRC_EOSC: + clk_hz = eosc1_hz; + break; + case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC: + clk_hz = cb_intosc_hz; + break; + case CLKMGR_MAINPLL_VCO0_PSRC_F2S: + clk_hz = f2s_free_hz; + break; + default: + return 0; + } + /* Applicable if MPU clock is from main PLL */ + if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) { + /* calculate the safe numer value */ + clk_hz = (safe_hz / clk_hz) * + (main_cfg->mpuclk_cnt + 1) * + ((main_cfg->mpuclk & + CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1) * + (1 + main_cfg->vco1_denom) - 1; + } + /* Reach here if MPU clk not from main PLL but NOC clk is */ + else if (main_cfg->nocclk_src == + CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) { + /* calculate the safe numer value */ + clk_hz = (safe_hz / clk_hz) * + (main_cfg->nocclk_cnt + 1) * + ((main_cfg->nocclk & + CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1) * + (1 + main_cfg->vco1_denom) - 1; + } else + clk_hz = 0; + + } else if (main0periph1 == 1) { + /* Check periph VCO clock source: eosc, intosc, f2s, mainpll */ + switch (per_cfg->vco0_psrc) { + case CLKMGR_PERPLL_VCO0_PSRC_EOSC: + clk_hz = eosc1_hz; + break; + case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC: + clk_hz = cb_intosc_hz; + break; + case CLKMGR_PERPLL_VCO0_PSRC_F2S: + clk_hz = f2s_free_hz; + break; + case CLKMGR_PERPLL_VCO0_PSRC_MAIN: + clk_hz = cm_calc_handoff_main_vco_clk_hz( + main_cfg); + clk_hz /= main_cfg->cntr15clk_cnt; + break; + default: + return 0; + } + /* Applicable if MPU clock is from periph PLL */ + if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) { + /* calculate the safe numer value */ + clk_hz = (safe_hz / clk_hz) * + (main_cfg->mpuclk_cnt + 1) * + (((main_cfg->mpuclk >> + CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) & + CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1) * + (1 + per_cfg->vco1_denom) - 1; + } + /* Reach here if MPU clk not from periph PLL but NOC clk is */ + else if (main_cfg->nocclk_src == + CLKMGR_MAINPLL_NOCCLK_SRC_PERI) { + /* calculate the safe numer value */ + clk_hz = (safe_hz / clk_hz) * + (main_cfg->nocclk_cnt + 1) * + (((main_cfg->nocclk >> + CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) & + CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1) * + (1 + per_cfg->vco1_denom) - 1; + } else + clk_hz = 0; + } + return clk_hz; +} + +/* ramping the main PLL to final value */ +static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg, + unsigned int pll_ramp_main_hz) +{ + unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0; + + /* find out the increment value */ + if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) { + clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ; + clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg); + } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) { + clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ; + clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg); + } + /* execute the ramping here */ + for (clk_hz = pll_ramp_main_hz + clk_incr_hz; + clk_hz < clk_final_hz; clk_hz += clk_incr_hz) { + writel((main_cfg->vco1_denom << + CLKMGR_MAINPLL_VCO1_DENOM_LSB) | + cm_calc_safe_pll_numer(0, main_cfg, per_cfg, clk_hz), + &clock_manager_base->main_pll.vco1); + udelay(1000); + cm_wait_for_lock(LOCKED_MASK); + } + writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) | + main_cfg->vco1_numer, + &clock_manager_base->main_pll.vco1); + udelay(1000); + cm_wait_for_lock(LOCKED_MASK); +} + +/* ramping the periph PLL to final value */ +static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg, + struct perpll_cfg *per_cfg, + unsigned int pll_ramp_periph_hz) +{ + unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0; + + /* find out the increment value */ + if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) { + clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ; + clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg); + } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) { + clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ; + clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg); + } + /* execute the ramping here */ + for (clk_hz = pll_ramp_periph_hz + clk_incr_hz; + clk_hz < clk_final_hz; clk_hz += clk_incr_hz) { + writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) | + cm_calc_safe_pll_numer(1, main_cfg, per_cfg, clk_hz), + &clock_manager_base->per_pll.vco1); + udelay(1000); + cm_wait_for_lock(LOCKED_MASK); + } + writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) | + per_cfg->vco1_numer, + &clock_manager_base->per_pll.vco1); + udelay(1000); + cm_wait_for_lock(LOCKED_MASK); +} + +/* + * Setup clocks while making no assumptions of the + * previous state of the clocks. + * + * Start by being paranoid and gate all sw managed clocks + * + * Put all plls in bypass + * + * Put all plls VCO registers back to reset value (bgpwr dwn). + * + * Put peripheral and main pll src to reset value to avoid glitch. + * + * Delay 5 us. + * + * Deassert bg pwr dn and set numerator and denominator + * + * Start 7 us timer. + * + * set internal dividers + * + * Wait for 7 us timer. + * + * Enable plls + * + * Set external dividers while plls are locking + * + * Wait for pll lock + * + * Assert/deassert outreset all. + * + * Take all pll's out of bypass + * + * Clear safe mode + * + * set source main and peripheral clocks + * + * Ungate clocks + */ + +static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg) +{ + unsigned int pll_ramp_main_hz = 0, pll_ramp_periph_hz = 0, + ramp_required; + + /* gate off all mainpll clock excpet HW managed clock */ + writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK | + CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK, + &clock_manager_base->main_pll.enr); + + /* now we can gate off the rest of the peripheral clocks */ + writel(0, &clock_manager_base->per_pll.en); + + /* Put all plls in external bypass */ + writel(CLKMGR_MAINPLL_BYPASS_RESET, + &clock_manager_base->main_pll.bypasss); + writel(CLKMGR_PERPLL_BYPASS_RESET, + &clock_manager_base->per_pll.bypasss); + + /* + * Put all plls VCO registers back to reset value. + * Some code might have messed with them. At same time set the + * desired clock source + */ + writel(CLKMGR_MAINPLL_VCO0_RESET | + CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK | + (main_cfg->vco0_psrc << + CLKMGR_MAINPLL_VCO0_PSRC_LSB), + &clock_manager_base->main_pll.vco0); + + writel(CLKMGR_PERPLL_VCO0_RESET | + CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK | + (per_cfg->vco0_psrc << + CLKMGR_PERPLL_VCO0_PSRC_LSB), + &clock_manager_base->per_pll.vco0); + + writel(CLKMGR_MAINPLL_VCO1_RESET, + &clock_manager_base->main_pll.vco1); + writel(CLKMGR_PERPLL_VCO1_RESET, + &clock_manager_base->per_pll.vco1); + + /* clear the interrupt register status register */ + writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK | + CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK | + CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK | + CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK | + CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK | + CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK | + CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK | + CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK, + &clock_manager_base->intr); + + /* Program VCO �Numerator� and �Denominator� for main PLL */ + ramp_required = cm_is_pll_ramp_required(0, main_cfg, per_cfg); + if (ramp_required) { + /* set main PLL to safe starting threshold frequency */ + if (ramp_required == 1) + pll_ramp_main_hz = CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ; + else if (ramp_required == 2) + pll_ramp_main_hz = CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ; + + writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) | + cm_calc_safe_pll_numer(0, main_cfg, per_cfg, + pll_ramp_main_hz), + &clock_manager_base->main_pll.vco1); + } else + writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) | + main_cfg->vco1_numer, + &clock_manager_base->main_pll.vco1); + + /* Program VCO �Numerator� and �Denominator� for periph PLL */ + ramp_required = cm_is_pll_ramp_required(1, main_cfg, per_cfg); + if (ramp_required) { + /* set periph PLL to safe starting threshold frequency */ + if (ramp_required == 1) + pll_ramp_periph_hz = + CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ; + else if (ramp_required == 2) + pll_ramp_periph_hz = + CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ; + + writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) | + cm_calc_safe_pll_numer(1, main_cfg, per_cfg, + pll_ramp_periph_hz), + &clock_manager_base->per_pll.vco1); + } else + writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) | + per_cfg->vco1_numer, + &clock_manager_base->per_pll.vco1); + + /* Wait for at least 5 us */ + udelay(5); + + /* Now deassert BGPWRDN and PWRDN */ + clrbits_le32(&clock_manager_base->main_pll.vco0, + CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK | + CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK); + clrbits_le32(&clock_manager_base->per_pll.vco0, + CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK | + CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK); + + /* Wait for at least 7 us */ + udelay(7); + + /* enable the VCO and disable the external regulator to PLL */ + writel((readl(&clock_manager_base->main_pll.vco0) & + ~CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK) | + CLKMGR_MAINPLL_VCO0_EN_SET_MSK, + &clock_manager_base->main_pll.vco0); + writel((readl(&clock_manager_base->per_pll.vco0) & + ~CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK) | + CLKMGR_PERPLL_VCO0_EN_SET_MSK, + &clock_manager_base->per_pll.vco0); + + /* setup all the main PLL counter and clock source */ + writel(main_cfg->nocclk, + SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOC_CLK_OFFSET); + writel(main_cfg->mpuclk, + SOCFPGA_CLKMGR_ADDRESS + CLKMGR_ALTERAGRP_MPU_CLK_OFFSET); + + /* main_emaca_clk divider */ + writel(main_cfg->cntr2clk_cnt, + &clock_manager_base->main_pll.cntr2clk); + /* main_emacb_clk divider */ + writel(main_cfg->cntr3clk_cnt, + &clock_manager_base->main_pll.cntr3clk); + /* main_emac_ptp_clk divider */ + writel(main_cfg->cntr4clk_cnt, + &clock_manager_base->main_pll.cntr4clk); + /* main_gpio_db_clk divider */ + writel(main_cfg->cntr5clk_cnt, + &clock_manager_base->main_pll.cntr5clk); + /* main_sdmmc_clk divider */ + writel(main_cfg->cntr6clk_cnt, + &clock_manager_base->main_pll.cntr6clk); + /* main_s2f_user0_clk divider */ + writel(main_cfg->cntr7clk_cnt | + (main_cfg->cntr7clk_src << + CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB), + &clock_manager_base->main_pll.cntr7clk); + /* main_s2f_user1_clk divider */ + writel(main_cfg->cntr8clk_cnt, + &clock_manager_base->main_pll.cntr8clk); + /* main_hmc_pll_clk divider */ + writel(main_cfg->cntr9clk_cnt | + (main_cfg->cntr9clk_src << + CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB), + &clock_manager_base->main_pll.cntr9clk); + /* main_periph_ref_clk divider */ + writel(main_cfg->cntr15clk_cnt, + &clock_manager_base->main_pll.cntr15clk); + + /* setup all the peripheral PLL counter and clock source */ + /* peri_emaca_clk divider */ + writel(per_cfg->cntr2clk_cnt | + (per_cfg->cntr2clk_src << CLKMGR_PERPLL_CNTR2CLK_SRC_LSB), + &clock_manager_base->per_pll.cntr2clk); + /* peri_emacb_clk divider */ + writel(per_cfg->cntr3clk_cnt | + (per_cfg->cntr3clk_src << CLKMGR_PERPLL_CNTR3CLK_SRC_LSB), + &clock_manager_base->per_pll.cntr3clk); + /* peri_emac_ptp_clk divider */ + writel(per_cfg->cntr4clk_cnt | + (per_cfg->cntr4clk_src << CLKMGR_PERPLL_CNTR4CLK_SRC_LSB), + &clock_manager_base->per_pll.cntr4clk); + /* peri_gpio_db_clk divider */ + writel(per_cfg->cntr5clk_cnt | + (per_cfg->cntr5clk_src << CLKMGR_PERPLL_CNTR5CLK_SRC_LSB), + &clock_manager_base->per_pll.cntr5clk); + /* peri_sdmmc_clk divider */ + writel(per_cfg->cntr6clk_cnt | + (per_cfg->cntr6clk_src << CLKMGR_PERPLL_CNTR6CLK_SRC_LSB), + &clock_manager_base->per_pll.cntr6clk); + /* peri_s2f_user0_clk divider */ + writel(per_cfg->cntr7clk_cnt, + &clock_manager_base->per_pll.cntr7clk); + /* peri_s2f_user1_clk divider */ + writel(per_cfg->cntr8clk_cnt | + (per_cfg->cntr8clk_src << CLKMGR_PERPLL_CNTR8CLK_SRC_LSB), + &clock_manager_base->per_pll.cntr8clk); + /* peri_hmc_pll_clk divider */ + writel(per_cfg->cntr9clk_cnt, + &clock_manager_base->per_pll.cntr9clk); + + /* setup all the external PLL counter */ + /* mpu wrapper / external divider */ + writel(main_cfg->mpuclk_cnt | + (main_cfg->mpuclk_src << + CLKMGR_MAINPLL_MPUCLK_SRC_LSB), + &clock_manager_base->main_pll.mpuclk); + /* NOC wrapper / external divider */ + writel(main_cfg->nocclk_cnt | + (main_cfg->nocclk_src << CLKMGR_MAINPLL_NOCCLK_SRC_LSB), + &clock_manager_base->main_pll.nocclk); + /* NOC subclock divider such as l4 */ + writel(main_cfg->nocdiv_l4mainclk | + (main_cfg->nocdiv_l4mpclk << + CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) | + (main_cfg->nocdiv_l4spclk << + CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB) | + (main_cfg->nocdiv_csatclk << + CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB) | + (main_cfg->nocdiv_cstraceclk << + CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB) | + (main_cfg->nocdiv_cspdbclk << + CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB), + &clock_manager_base->main_pll.nocdiv); + /* gpio_db external divider */ + writel(per_cfg->gpiodiv_gpiodbclk, + &clock_manager_base->per_pll.gpiodiv); + + /* setup the EMAC clock mux select */ + writel((per_cfg->emacctl_emac0sel << + CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB) | + (per_cfg->emacctl_emac1sel << + CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB) | + (per_cfg->emacctl_emac2sel << + CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB), + &clock_manager_base->per_pll.emacctl); + + /* at this stage, check for PLL lock status */ + cm_wait_for_lock(LOCKED_MASK); + + /* + * after locking, but before taking out of bypass, + * assert/deassert outresetall + */ + /* assert mainpll outresetall */ + setbits_le32(&clock_manager_base->main_pll.vco0, + CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK); + /* assert perpll outresetall */ + setbits_le32(&clock_manager_base->per_pll.vco0, + CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK); + /* de-assert mainpll outresetall */ + clrbits_le32(&clock_manager_base->main_pll.vco0, + CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK); + /* de-assert perpll outresetall */ + clrbits_le32(&clock_manager_base->per_pll.vco0, + CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK); + + /* Take all PLLs out of bypass when boot mode is cleared. */ + /* release mainpll from bypass */ + writel(CLKMGR_MAINPLL_BYPASS_RESET, + &clock_manager_base->main_pll.bypassr); + /* wait till Clock Manager is not busy */ + cm_wait_for_fsm(); + + /* release perpll from bypass */ + writel(CLKMGR_PERPLL_BYPASS_RESET, + &clock_manager_base->per_pll.bypassr); + /* wait till Clock Manager is not busy */ + cm_wait_for_fsm(); + + /* clear boot mode */ + clrbits_le32(&clock_manager_base->ctrl, + CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK); + /* wait till Clock Manager is not busy */ + cm_wait_for_fsm(); + + /* At here, we need to ramp to final value if needed */ + if (pll_ramp_main_hz != 0) + cm_pll_ramp_main(main_cfg, per_cfg, pll_ramp_main_hz); + if (pll_ramp_periph_hz != 0) + cm_pll_ramp_periph(main_cfg, per_cfg, pll_ramp_periph_hz); + + /* Now ungate non-hw-managed clocks */ + writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK | + CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK, + &clock_manager_base->main_pll.ens); + writel(CLKMGR_PERPLL_EN_RESET, + &clock_manager_base->per_pll.ens); + + /* Clear the loss lock and slip bits as they might set during + clock reconfiguration */ + writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK | + CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK | + CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK | + CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK | + CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK | + CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK, + &clock_manager_base->intr); + + return 0; +} + +int cm_basic_init(const void *blob) +{ + struct mainpll_cfg main_cfg; + struct perpll_cfg per_cfg; + struct alteragrp_cfg altrgrp_cfg; + int rval; + + /* initialize to zero for use case of optional node */ + memset(&main_cfg, 0, sizeof(main_cfg)); + memset(&per_cfg, 0, sizeof(per_cfg)); + memset(&altrgrp_cfg, 0, sizeof(altrgrp_cfg)); + + if (of_get_clk_cfg(blob, &main_cfg, &per_cfg, &altrgrp_cfg)) { + return 1; + } + + rval = cm_full_cfg(&main_cfg, &per_cfg); + + cm_l4_main_clk_hz = + cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB); + + cm_l4_mp_clk_hz = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB); + + cm_l4_sp_clk_hz = cm_get_l4_sp_clk_hz(); + + cm_l4_sys_free_clk_hz = cm_get_noc_clk_hz()/4; + + return rval; +} diff --git a/arch/arm/mach-socfpga/clock_manager_gen5.c b/arch/arm/mach-socfpga/clock_manager_gen5.c new file mode 100644 index 0000000..f4bb02b --- /dev/null +++ b/arch/arm/mach-socfpga/clock_manager_gen5.c @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2016, Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock_manager.h> + +DECLARE_GLOBAL_DATA_PTR; + +const unsigned int cm_get_osc_clk_hz(const int osc); +const unsigned int cm_get_f2s_per_ref_clk_hz(void); +const unsigned int cm_get_f2s_sdr_ref_clk_hz(void); +static void cm_write_bypass(uint32_t val); +static void cm_write_ctrl(uint32_t val); +static void cm_write_with_phase(uint32_t value, + uint32_t reg_address, uint32_t mask); +unsigned long cm_get_sdram_clk_hz(void); +int set_cpu_clk_info(void); + +static const struct socfpga_clock_manager *clock_manager_base = + (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS; + +/* + * function to write the bypass register which requires a poll of the + * busy bit + */ +static void cm_write_bypass(uint32_t val) +{ + writel(val, &clock_manager_base->bypass); + cm_wait_for_fsm(); +} + +/* function to write the ctrl register which requires a poll of the busy bit */ +static void cm_write_ctrl(uint32_t val) +{ + writel(val, &clock_manager_base->ctrl); + cm_wait_for_fsm(); +} + +/* function to write a clock register that has phase information */ +static void cm_write_with_phase(uint32_t value, + uint32_t reg_address, uint32_t mask) +{ + /* poll until phase is zero */ + while (readl(reg_address) & mask) + ; + + writel(value, reg_address); + + while (readl(reg_address) & mask) + ; +} + +/* + * Setup clocks while making no assumptions about previous state of the clocks. + * + * Start by being paranoid and gate all sw managed clocks + * Put all plls in bypass + * Put all plls VCO registers back to reset value (bandgap power down). + * Put peripheral and main pll src to reset value to avoid glitch. + * Delay 5 us. + * Deassert bandgap power down and set numerator and denominator + * Start 7 us timer. + * set internal dividers + * Wait for 7 us timer. + * Enable plls + * Set external dividers while plls are locking + * Wait for pll lock + * Assert/deassert outreset all. + * Take all pll's out of bypass + * Clear safe mode + * set source main and peripheral clocks + * Ungate clocks + */ +void cm_basic_init(const struct cm_config * const cfg) +{ + unsigned long end; + + /* Start by being paranoid and gate all sw managed clocks */ + + /* + * We need to disable nandclk + * and then do another apb access before disabling + * gatting off the rest of the periperal clocks. + */ + writel(~CLKMGR_PERPLLGRP_EN_NANDCLK_MASK & + readl(&clock_manager_base->per_pll.en), + &clock_manager_base->per_pll.en); + + /* DO NOT GATE OFF DEBUG CLOCKS & BRIDGE CLOCKS */ + writel(CLKMGR_MAINPLLGRP_EN_DBGTIMERCLK_MASK | + CLKMGR_MAINPLLGRP_EN_DBGTRACECLK_MASK | + CLKMGR_MAINPLLGRP_EN_DBGCLK_MASK | + CLKMGR_MAINPLLGRP_EN_DBGATCLK_MASK | + CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK | + CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK, + &clock_manager_base->main_pll.en); + + writel(0, &clock_manager_base->sdr_pll.en); + + /* now we can gate off the rest of the peripheral clocks */ + writel(0, &clock_manager_base->per_pll.en); + + /* Put all plls in bypass */ + cm_write_bypass(CLKMGR_BYPASS_PERPLL | CLKMGR_BYPASS_SDRPLL | + CLKMGR_BYPASS_MAINPLL); + + /* Put all plls VCO registers back to reset value. */ + writel(CLKMGR_MAINPLLGRP_VCO_RESET_VALUE & + ~CLKMGR_MAINPLLGRP_VCO_REGEXTSEL_MASK, + &clock_manager_base->main_pll.vco); + writel(CLKMGR_PERPLLGRP_VCO_RESET_VALUE & + ~CLKMGR_PERPLLGRP_VCO_REGEXTSEL_MASK, + &clock_manager_base->per_pll.vco); + writel(CLKMGR_SDRPLLGRP_VCO_RESET_VALUE & + ~CLKMGR_SDRPLLGRP_VCO_REGEXTSEL_MASK, + &clock_manager_base->sdr_pll.vco); + + /* + * The clocks to the flash devices and the L4_MAIN clocks can + * glitch when coming out of safe mode if their source values + * are different from their reset value. So the trick it to + * put them back to their reset state, and change input + * after exiting safe mode but before ungating the clocks. + */ + writel(CLKMGR_PERPLLGRP_SRC_RESET_VALUE, + &clock_manager_base->per_pll.src); + writel(CLKMGR_MAINPLLGRP_L4SRC_RESET_VALUE, + &clock_manager_base->main_pll.l4src); + + /* read back for the required 5 us delay. */ + readl(&clock_manager_base->main_pll.vco); + readl(&clock_manager_base->per_pll.vco); + readl(&clock_manager_base->sdr_pll.vco); + + + /* + * We made sure bgpwr down was assert for 5 us. Now deassert BG PWR DN + * with numerator and denominator. + */ + writel(cfg->main_vco_base, &clock_manager_base->main_pll.vco); + writel(cfg->peri_vco_base, &clock_manager_base->per_pll.vco); + writel(cfg->sdram_vco_base, &clock_manager_base->sdr_pll.vco); + + /* + * Time starts here. Must wait 7 us from + * BGPWRDN_SET(0) to VCO_ENABLE_SET(1). + */ + end = timer_get_us() + 7; + + /* main mpu */ + writel(cfg->mpuclk, &clock_manager_base->main_pll.mpuclk); + + /* main main clock */ + writel(cfg->mainclk, &clock_manager_base->main_pll.mainclk); + + /* main for dbg */ + writel(cfg->dbgatclk, &clock_manager_base->main_pll.dbgatclk); + + /* main for cfgs2fuser0clk */ + writel(cfg->cfg2fuser0clk, + &clock_manager_base->main_pll.cfgs2fuser0clk); + + /* Peri emac0 50 MHz default to RMII */ + writel(cfg->emac0clk, &clock_manager_base->per_pll.emac0clk); + + /* Peri emac1 50 MHz default to RMII */ + writel(cfg->emac1clk, &clock_manager_base->per_pll.emac1clk); + + /* Peri QSPI */ + writel(cfg->mainqspiclk, &clock_manager_base->main_pll.mainqspiclk); + + writel(cfg->perqspiclk, &clock_manager_base->per_pll.perqspiclk); + + /* Peri pernandsdmmcclk */ + writel(cfg->mainnandsdmmcclk, + &clock_manager_base->main_pll.mainnandsdmmcclk); + + writel(cfg->pernandsdmmcclk, + &clock_manager_base->per_pll.pernandsdmmcclk); + + /* Peri perbaseclk */ + writel(cfg->perbaseclk, &clock_manager_base->per_pll.perbaseclk); + + /* Peri s2fuser1clk */ + writel(cfg->s2fuser1clk, &clock_manager_base->per_pll.s2fuser1clk); + + /* 7 us must have elapsed before we can enable the VCO */ + while (timer_get_us() < end) + ; + + /* Enable vco */ + /* main pll vco */ + writel(cfg->main_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, + &clock_manager_base->main_pll.vco); + + /* periferal pll */ + writel(cfg->peri_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, + &clock_manager_base->per_pll.vco); + + /* sdram pll vco */ + writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, + &clock_manager_base->sdr_pll.vco); + + /* L3 MP and L3 SP */ + writel(cfg->maindiv, &clock_manager_base->main_pll.maindiv); + + writel(cfg->dbgdiv, &clock_manager_base->main_pll.dbgdiv); + + writel(cfg->tracediv, &clock_manager_base->main_pll.tracediv); + + /* L4 MP, L4 SP, can0, and can1 */ + writel(cfg->perdiv, &clock_manager_base->per_pll.div); + + writel(cfg->gpiodiv, &clock_manager_base->per_pll.gpiodiv); + + cm_wait_for_lock(LOCKED_MASK); + + /* write the sdram clock counters before toggling outreset all */ + writel(cfg->ddrdqsclk & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK, + &clock_manager_base->sdr_pll.ddrdqsclk); + + writel(cfg->ddr2xdqsclk & CLKMGR_SDRPLLGRP_DDR2XDQSCLK_CNT_MASK, + &clock_manager_base->sdr_pll.ddr2xdqsclk); + + writel(cfg->ddrdqclk & CLKMGR_SDRPLLGRP_DDRDQCLK_CNT_MASK, + &clock_manager_base->sdr_pll.ddrdqclk); + + writel(cfg->s2fuser2clk & CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK, + &clock_manager_base->sdr_pll.s2fuser2clk); + + /* + * after locking, but before taking out of bypass + * assert/deassert outresetall + */ + uint32_t mainvco = readl(&clock_manager_base->main_pll.vco); + + /* assert main outresetall */ + writel(mainvco | CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->main_pll.vco); + + uint32_t periphvco = readl(&clock_manager_base->per_pll.vco); + + /* assert pheriph outresetall */ + writel(periphvco | CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->per_pll.vco); + + /* assert sdram outresetall */ + writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN| + CLKMGR_SDRPLLGRP_VCO_OUTRESETALL, + &clock_manager_base->sdr_pll.vco); + + /* deassert main outresetall */ + writel(mainvco & ~CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->main_pll.vco); + + /* deassert pheriph outresetall */ + writel(periphvco & ~CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK, + &clock_manager_base->per_pll.vco); + + /* deassert sdram outresetall */ + writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN, + &clock_manager_base->sdr_pll.vco); + + /* + * now that we've toggled outreset all, all the clocks + * are aligned nicely; so we can change any phase. + */ + cm_write_with_phase(cfg->ddrdqsclk, + (uint32_t)&clock_manager_base->sdr_pll.ddrdqsclk, + CLKMGR_SDRPLLGRP_DDRDQSCLK_PHASE_MASK); + + /* SDRAM DDR2XDQSCLK */ + cm_write_with_phase(cfg->ddr2xdqsclk, + (uint32_t)&clock_manager_base->sdr_pll.ddr2xdqsclk, + CLKMGR_SDRPLLGRP_DDR2XDQSCLK_PHASE_MASK); + + cm_write_with_phase(cfg->ddrdqclk, + (uint32_t)&clock_manager_base->sdr_pll.ddrdqclk, + CLKMGR_SDRPLLGRP_DDRDQCLK_PHASE_MASK); + + cm_write_with_phase(cfg->s2fuser2clk, + (uint32_t)&clock_manager_base->sdr_pll.s2fuser2clk, + CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK); + + /* Take all three PLLs out of bypass when safe mode is cleared. */ + cm_write_bypass(0); + + /* clear safe mode */ + cm_write_ctrl(readl(&clock_manager_base->ctrl) | CLKMGR_CTRL_SAFEMODE); + + /* + * now that safe mode is clear with clocks gated + * it safe to change the source mux for the flashes the the L4_MAIN + */ + writel(cfg->persrc, &clock_manager_base->per_pll.src); + writel(cfg->l4src, &clock_manager_base->main_pll.l4src); + + /* Now ungate non-hw-managed clocks */ + writel(~0, &clock_manager_base->main_pll.en); + writel(~0, &clock_manager_base->per_pll.en); + writel(~0, &clock_manager_base->sdr_pll.en); + + /* Clear the loss of lock bits (write 1 to clear) */ + writel(CLKMGR_INTER_SDRPLLLOST_MASK | CLKMGR_INTER_PERPLLLOST_MASK | + CLKMGR_INTER_MAINPLLLOST_MASK, + &clock_manager_base->inter); +} + +unsigned long cm_get_sdram_clk_hz(void) +{ + uint32_t reg, clock = 0; + + /* identify SDRAM PLL clock source */ + reg = readl(&clock_manager_base->sdr_pll.vco); + reg = (reg & CLKMGR_SDRPLLGRP_VCO_SSRC_MASK) >> + CLKMGR_SDRPLLGRP_VCO_SSRC_OFFSET; + if (reg == CLKMGR_VCO_SSRC_EOSC1) + clock = cm_get_osc_clk_hz(1); + else if (reg == CLKMGR_VCO_SSRC_EOSC2) + clock = cm_get_osc_clk_hz(2); + else if (reg == CLKMGR_VCO_SSRC_F2S) + clock = cm_get_f2s_sdr_ref_clk_hz(); + + /* get the SDRAM VCO clock */ + reg = readl(&clock_manager_base->sdr_pll.vco); + clock /= ((reg & CLKMGR_SDRPLLGRP_VCO_DENOM_MASK) >> + CLKMGR_SDRPLLGRP_VCO_DENOM_OFFSET) + 1; + clock *= ((reg & CLKMGR_SDRPLLGRP_VCO_NUMER_MASK) >> + CLKMGR_SDRPLLGRP_VCO_NUMER_OFFSET) + 1; + + /* get the SDRAM (DDR_DQS) clock */ + reg = readl(&clock_manager_base->sdr_pll.ddrdqsclk); + reg = (reg & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK) >> + CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_OFFSET; + clock /= (reg + 1); + + return clock; +} diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h index 2675951..aa401dc 100644 --- a/arch/arm/mach-socfpga/include/mach/clock_manager.h +++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h @@ -1,28 +1,16 @@ /* - * Copyright (C) 2013 Altera Corporation <www.altera.com> + * Copyright (C) 2013-2016 Altera Corporation <www.altera.com> * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0 */
#ifndef _CLOCK_MANAGER_H_ #define _CLOCK_MANAGER_H_
#ifndef __ASSEMBLER__ -/* Clock speed accessors */ -unsigned long cm_get_mpu_clk_hz(void); -unsigned long cm_get_sdram_clk_hz(void); -unsigned int cm_get_l4_sp_clk_hz(void); -unsigned int cm_get_mmc_controller_clk_hz(void); -unsigned int cm_get_qspi_controller_clk_hz(void); -unsigned int cm_get_spi_controller_clk_hz(void); -const unsigned int cm_get_osc_clk_hz(const int osc); -const unsigned int cm_get_f2s_per_ref_clk_hz(void); -const unsigned int cm_get_f2s_sdr_ref_clk_hz(void); - -/* Clock configuration accessors */ -const struct cm_config * const cm_get_default_config(void); -#endif +#include <linux/types.h>
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5) struct cm_config { /* main group */ uint32_t main_vco_base; @@ -57,74 +45,196 @@ struct cm_config { uint32_t s2fuser2clk; };
-void cm_basic_init(const struct cm_config * const cfg); +struct socfpga_clock_manager_sdr_pll { + volatile uint32_t vco; + volatile uint32_t ctrl; + volatile uint32_t ddrdqsclk; + volatile uint32_t ddr2xdqsclk; + volatile uint32_t ddrdqclk; + volatile uint32_t s2fuser2clk; + volatile uint32_t en; + volatile uint32_t stat; +}; +#endif + +/* Common prototypes */ +extern unsigned int cm_get_l4_sp_clk_hz(void); +extern unsigned int cm_get_qspi_controller_clk_hz(void); +extern unsigned int cm_get_mmc_controller_clk_hz(void); +extern unsigned int cm_get_spi_controller_clk_hz(void); +extern void cm_use_intosc(void); +extern void cm_wait_for_lock(uint32_t mask); +extern void cm_wait_for_fsm(void); +extern unsigned int cm_get_main_vco_clk_hz(void); +extern unsigned int cm_get_per_vco_clk_hz(void); +extern unsigned long cm_get_mpu_clk_hz(void); +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) +/* Clock speed accessors */ +extern const unsigned int cm_get_osc_clk_hz(const int osc); +extern const unsigned int cm_get_f2s_per_ref_clk_hz(void); +extern const unsigned int cm_get_f2s_sdr_ref_clk_hz(void); +extern void cm_basic_init(const struct cm_config * const cfg); +extern unsigned long cm_get_sdram_clk_hz(void); +/* Clock configuration accessors */ +extern const struct cm_config * const cm_get_default_config(void); +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) +extern unsigned int cm_get_noc_clk_hz(void); +extern unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift); +extern int cm_basic_init(const void* blob); +extern unsigned int cm_l4_main_clk_hz; +extern unsigned int cm_l4_sp_clk_hz; +extern unsigned int cm_l4_mp_clk_hz; +extern unsigned int cm_l4_sys_free_clk_hz; +extern uint32_t eosc1_hz; +extern uint32_t cb_intosc_hz; +extern uint32_t f2s_free_hz; +#endif +#endif
struct socfpga_clock_manager_main_pll { - u32 vco; - u32 misc; - u32 mpuclk; - u32 mainclk; - u32 dbgatclk; - u32 mainqspiclk; - u32 mainnandsdmmcclk; - u32 cfgs2fuser0clk; - u32 en; - u32 maindiv; - u32 dbgdiv; - u32 tracediv; - u32 l4src; - u32 stat; - u32 _pad_0x38_0x40[2]; +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + volatile uint32_t vco; + volatile uint32_t misc; + volatile uint32_t mpuclk; + volatile uint32_t mainclk; + volatile uint32_t dbgatclk; + volatile uint32_t mainqspiclk; + volatile uint32_t mainnandsdmmcclk; + volatile uint32_t cfgs2fuser0clk; + volatile uint32_t en; + volatile uint32_t maindiv; + volatile uint32_t dbgdiv; + volatile uint32_t tracediv; + volatile uint32_t l4src; + volatile uint32_t stat; + volatile uint32_t _pad_0x38_0x40[2]; +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + uint32_t vco0; + uint32_t vco1; + uint32_t en; + uint32_t ens; + uint32_t enr; + uint32_t bypass; + uint32_t bypasss; + uint32_t bypassr; + uint32_t mpuclk; + uint32_t nocclk; + uint32_t cntr2clk; + uint32_t cntr3clk; + uint32_t cntr4clk; + uint32_t cntr5clk; + uint32_t cntr6clk; + uint32_t cntr7clk; + uint32_t cntr8clk; + uint32_t cntr9clk; + uint32_t pad_0x48_0x5b[5]; + uint32_t cntr15clk; + uint32_t outrst; + uint32_t outrststat; + uint32_t nocdiv; + uint32_t pad_0x6c_0x80[5]; +#endif };
struct socfpga_clock_manager_per_pll { - u32 vco; - u32 misc; - u32 emac0clk; - u32 emac1clk; - u32 perqspiclk; - u32 pernandsdmmcclk; - u32 perbaseclk; - u32 s2fuser1clk; - u32 en; - u32 div; - u32 gpiodiv; - u32 src; - u32 stat; - u32 _pad_0x34_0x40[3]; -}; - -struct socfpga_clock_manager_sdr_pll { - u32 vco; - u32 ctrl; - u32 ddrdqsclk; - u32 ddr2xdqsclk; - u32 ddrdqclk; - u32 s2fuser2clk; - u32 en; - u32 stat; +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + volatile uint32_t vco; + volatile uint32_t misc; + volatile uint32_t emac0clk; + volatile uint32_t emac1clk; + volatile uint32_t perqspiclk; + volatile uint32_t pernandsdmmcclk; + volatile uint32_t perbaseclk; + volatile uint32_t s2fuser1clk; + volatile uint32_t en; + volatile uint32_t div; + volatile uint32_t gpiodiv; + volatile uint32_t src; + volatile uint32_t stat; + volatile uint32_t _pad_0x34_0x40[3]; +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + volatile uint32_t vco0; + volatile uint32_t vco1; + volatile uint32_t en; + volatile uint32_t ens; + volatile uint32_t enr; + volatile uint32_t bypass; + volatile uint32_t bypasss; + volatile uint32_t bypassr; + volatile uint32_t pad_0x20_0x27[2]; + volatile uint32_t cntr2clk; + volatile uint32_t cntr3clk; + volatile uint32_t cntr4clk; + volatile uint32_t cntr5clk; + volatile uint32_t cntr6clk; + volatile uint32_t cntr7clk; + volatile uint32_t cntr8clk; + volatile uint32_t cntr9clk; + volatile uint32_t pad_0x48_0x5f[6]; + volatile uint32_t outrst; + volatile uint32_t outrststat; + volatile uint32_t emacctl; + volatile uint32_t gpiodiv; + volatile uint32_t pad_0x70_0x80[4]; +#endif };
struct socfpga_clock_manager_altera { - u32 mpuclk; - u32 mainclk; + volatile uint32_t mpuclk; +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + volatile uint32_t mainclk; +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + volatile uint32_t nocclk; + volatile uint32_t mainmisc0; + volatile uint32_t mainmisc1; + volatile uint32_t perimisc0; + volatile uint32_t perimisc1; +#endif };
struct socfpga_clock_manager { - u32 ctrl; - u32 bypass; - u32 inter; - u32 intren; - u32 dbctrl; - u32 stat; - u32 _pad_0x18_0x3f[10]; +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) + volatile uint32_t ctrl; + volatile uint32_t bypass; + volatile uint32_t inter; + volatile uint32_t intren; + volatile uint32_t dbctrl; + volatile uint32_t stat; + volatile uint32_t _pad_0x18_0x3f[10]; struct socfpga_clock_manager_main_pll main_pll; struct socfpga_clock_manager_per_pll per_pll; struct socfpga_clock_manager_sdr_pll sdr_pll; struct socfpga_clock_manager_altera altera; - u32 _pad_0xe8_0x200[70]; + volatile uint32_t _pad_0xe8_0x200[70]; +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) + /* clkmgr */ + volatile uint32_t ctrl; + volatile uint32_t intr; + volatile uint32_t intrs; + volatile uint32_t intrr; + volatile uint32_t intren; + volatile uint32_t intrens; + volatile uint32_t intrenr; + volatile uint32_t stat; + volatile uint32_t testioctrl; + volatile uint32_t _pad_0x24_0x40[7]; + /* mainpllgrp */ + struct socfpga_clock_manager_main_pll main_pll; + /* perpllgrp */ + struct socfpga_clock_manager_per_pll per_pll; + struct socfpga_clock_manager_altera altera; +#endif };
+/* Common mask */ +#define CLKMGR_CLKMGR_STAT_BUSY_SET_MSK 0x00000001 + +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) +#define LOCKED_MASK \ + (CLKMGR_INTER_SDRPLLLOCKED_MASK | \ + CLKMGR_INTER_PERPLLLOCKED_MASK | \ + CLKMGR_INTER_MAINPLLLOCKED_MASK) + #define CLKMGR_CTRL_SAFEMODE (1 << 0) #define CLKMGR_CTRL_SAFEMODE_OFFSET 0
@@ -310,5 +420,119 @@ struct socfpga_clock_manager { #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK 0x000001ff #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_OFFSET 9 #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK 0x00000e00 - +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) +#define CLKMGR_ALTERAGRP_MPU_CLK_OFFSET 0x140 +#define CLKMGR_MAINPLL_NOC_CLK_OFFSET 0x144 +#define LOCKED_MASK \ + (CLKMGR_CLKMGR_STAT_MAINPLLLOCKED_SET_MSK | \ + CLKMGR_CLKMGR_STAT_PERPLLLOCKED_SET_MSK) + +/* value */ +#define CLKMGR_MAINPLL_BYPASS_RESET 0x0000003f +#define CLKMGR_PERPLL_BYPASS_RESET 0x000000ff +#define CLKMGR_MAINPLL_VCO0_RESET 0x00010053 +#define CLKMGR_MAINPLL_VCO1_RESET 0x00010001 +#define CLKMGR_PERPLL_VCO0_RESET 0x00010053 +#define CLKMGR_PERPLL_VCO1_RESET 0x00010001 +#define CLKMGR_MAINPLL_VCO0_PSRC_EOSC 0x0 +#define CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC 0x1 +#define CLKMGR_MAINPLL_VCO0_PSRC_F2S 0x2 +#define CLKMGR_PERPLL_VCO0_PSRC_EOSC 0x0 +#define CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC 0x1 +#define CLKMGR_PERPLL_VCO0_PSRC_F2S 0x2 +#define CLKMGR_PERPLL_VCO0_PSRC_MAIN 0x3 + +/* mask */ +#define CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK 0x00000040 +#define CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK 0x00000080 +#define CLKMGR_CLKMGR_STAT_MAINPLLLOCKED_SET_MSK 0x00000100 +#define CLKMGR_CLKMGR_STAT_PERPLLLOCKED_SET_MSK 0x00000200 +#define CLKMGR_CLKMGR_STAT_BOOTCLKSRC_SET_MSK 0x00020000 +#define CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK 0x00000001 +#define CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK 0x00000002 +#define CLKMGR_MAINPLL_VCO0_EN_SET_MSK 0x00000004 +#define CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK 0x00000008 +#define CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK 0x00000010 +#define CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK 0x00000001 +#define CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK 0x00000002 +#define CLKMGR_PERPLL_VCO0_EN_SET_MSK 0x00000004 +#define CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK 0x00000008 +#define CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK 0x00000010 +#define CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK 0x00000800 +#define CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK 0x00000400 +#define CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK 0x00000200 +#define CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK 0x00000100 +#define CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK 0x00000008 +#define CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK 0x00000004 +#define CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK 0x00000001 +#define CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK 0x00000002 +#define CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK 0x00000001 +#define CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK 0x00000300 +#define CLKMGR_PERPLL_EN_RESET 0x00000f7f +#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK 0x00000020 +#define CLKMGR_MAINPLL_VCO0_PSRC_MSK 0x00000003 +#define CLKMGR_MAINPLL_VCO1_NUMER_MSK 0x00001fff +#define CLKMGR_MAINPLL_VCO1_DENOM_MSK 0x0000003f +#define CLKMGR_MAINPLL_CNTRCLK_MSK 0x000003ff +#define CLKMGR_PERPLL_VCO0_PSRC_MSK 0x00000003 +#define CLKMGR_PERPLL_VCO1_NUMER_MSK 0x00001fff +#define CLKMGR_PERPLL_VCO1_DENOM_MSK 0x0000003f +#define CLKMGR_PERPLL_CNTRCLK_MSK 0x000003ff +#define CLKMGR_MAINPLL_MPUCLK_SRC_MSK 0x00000007 +#define CLKMGR_MAINPLL_MPUCLK_CNT_MSK 0x000003ff +#define CLKMGR_MAINPLL_MPUCLK_SRC_MAIN 0 +#define CLKMGR_MAINPLL_MPUCLK_SRC_PERI 1 +#define CLKMGR_MAINPLL_MPUCLK_SRC_OSC1 2 +#define CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC 3 +#define CLKMGR_MAINPLL_MPUCLK_SRC_FPGA 4 +#define CLKMGR_MAINPLL_NOCDIV_MSK 0x00000003 +#define CLKMGR_MAINPLL_NOCCLK_CNT_MSK 0x000003ff +#define CLKMGR_MAINPLL_NOCCLK_SRC_MSK 0x00000007 +#define CLKMGR_MAINPLL_NOCCLK_SRC_MAIN 0 +#define CLKMGR_MAINPLL_NOCCLK_SRC_PERI 1 +#define CLKMGR_MAINPLL_NOCCLK_SRC_OSC1 2 +#define CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC 3 +#define CLKMGR_MAINPLL_NOCCLK_SRC_FPGA 4 + +#define CLKMGR_PERPLLGRP_SRC_MSK 0x00000007 +#define CLKMGR_PERPLLGRP_SRC_MAIN 0 +#define CLKMGR_PERPLLGRP_SRC_PERI 1 +#define CLKMGR_PERPLLGRP_SRC_OSC1 2 +#define CLKMGR_PERPLLGRP_SRC_INTOSC 3 +#define CLKMGR_PERPLLGRP_SRC_FPGA 4 + +/* bit shifting macro */ +#define CLKMGR_MAINPLL_VCO0_PSRC_LSB 8 +#define CLKMGR_PERPLL_VCO0_PSRC_LSB 8 +#define CLKMGR_MAINPLL_VCO1_DENOM_LSB 16 +#define CLKMGR_PERPLL_VCO1_DENOM_LSB 16 +#define CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB 16 +#define CLKMGR_MAINPLL_NOCCLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB 0 +#define CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB 8 +#define CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB 16 +#define CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB 24 +#define CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB 26 +#define CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB 28 +#define CLKMGR_MAINPLL_MPUCLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB 16 +#define CLKMGR_MAINPLL_NOCCLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR2CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR3CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR4CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR5CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR6CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR8CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB 26 +#define CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB 27 +#define CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB 28 + +/* PLL ramping work around */ +#define CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ 900000000 +#define CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ 300000000 +#define CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ 100000000 +#define CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ 33000000 +#endif #endif /* _CLOCK_MANAGER_H_ */

On Sel, 2016-12-06 at 16:10 +0800, Chee Tien Fong wrote:
From: Tien Fong Chee tien.fong.chee@intel.com
The drivers is restructured such common functions, gen5 functions, and arria10 functions are moved to clock_manager.c, cock_manager_gen5 and clock_manager_arria10 respectively.
Signed-off-by: Tien Fong Chee tien.fong.chee@intel.com Cc: Marek Vasut marex@denx.de Cc: Dinh Nguyen dinguyen@kernel.org Cc: Chin Liang See chin.liang.see@intel.com Cc: Tien Fong skywindctf@gmail.com
arch/arm/mach-socfpga/Makefile | 6 +- arch/arm/mach-socfpga/clock_manager.c | 754 +++++++---
arch/arm/mach-socfpga/clock_manager_arria10.c | 954 ++++++++++++++++++++ arch/arm/mach-socfpga/clock_manager_gen5.c | 342 +++++++ arch/arm/mach-socfpga/include/mach/clock_manager.h | 360 ++++++-- 5 files changed, 1910 insertions(+), 506 deletions(-) create mode 100644 arch/arm/mach-socfpga/clock_manager_arria10.c create mode 100644 arch/arm/mach-socfpga/clock_manager_gen5.c
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach- socfpga/Makefile index f8b529e..71cf31c 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -9,9 +9,11 @@
Any comments on this patch before i start the version 2?
obj-y += misc.o timer.o reset_manager.o system_manager.o clock_manager.o \ fpga_manager.o board.o -obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += reset_manager_arria10.o misc_arria10.o +obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += reset_manager_arria10.o misc_arria10.o \
clock_manager_arria10.o
obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += scan_manager.o wrap_pll_config.o \
reset_manager_gen5.o misc_gen5.o
reset_manager_gen5.o misc_gen5.o \
clock_manager_gen5.o
ifdef CONFIG_SPL_BUILD obj-y += spl.o diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach- socfpga/clock_manager.c index aa71636..fe82c39 100644 --- a/arch/arm/mach-socfpga/clock_manager.c +++ b/arch/arm/mach-socfpga/clock_manager.c @@ -1,422 +1,293 @@ /*
- * Copyright (C) 2013 Altera Corporation <www.altera.com>
- * Copyright (C) 2013-2016 Intel Corporation <www.intel.com>
*
- SPDX-License-Identifier: GPL-2.0+
- SPDX-License-Identifier: GPL-2.0
*/ #include <common.h> #include <asm/io.h> #include <asm/arch/clock_manager.h> +#include <fdtdec.h> DECLARE_GLOBAL_DATA_PTR; +/* Function prototypes */ +/* Common prototypes */ +unsigned int cm_get_l4_sp_clk_hz(void); +unsigned int cm_get_qspi_controller_clk_hz(void); +unsigned int cm_get_mmc_controller_clk_hz(void); +unsigned int cm_get_spi_controller_clk_hz(void); +static void cm_print_clock_quick_summary(void); +int do_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +void cm_wait_for_lock(uint32_t mask); +void cm_wait_for_fsm(void); +unsigned int cm_get_main_vco_clk_hz(void); +unsigned int cm_get_per_vco_clk_hz(void); +unsigned long cm_get_mpu_clk_hz(void);
static const struct socfpga_clock_manager *clock_manager_base = (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS; -static void cm_wait_for_lock(uint32_t mask) +/* Common functions */ +int set_cpu_clk_info(void) {
- register uint32_t inter_val;
- uint32_t retry = 0;
- do {
inter_val = readl(&clock_manager_base->inter) &
mask;
if (inter_val == mask)
retry++;
else
retry = 0;
if (retry >= 10)
break;
- } while (1);
-}
- /* Calculate the clock frequencies required for drivers */
- cm_get_l4_sp_clk_hz();
- cm_get_mmc_controller_clk_hz();
-/* function to poll in the fsm busy bit */ -static void cm_wait_for_fsm(void) -{
- while (readl(&clock_manager_base->stat) & CLKMGR_STAT_BUSY)
;
-}
- gd->bd->bi_arm_freq = cm_get_mpu_clk_hz() / 1000000;
- gd->bd->bi_dsp_freq = 0;
-/*
- function to write the bypass register which requires a poll of
the
- busy bit
- */
-static void cm_write_bypass(uint32_t val) -{
- writel(val, &clock_manager_base->bypass);
- cm_wait_for_fsm();
-} +#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- gd->bd->bi_ddr_freq = cm_get_sdram_clk_hz() / 1000000;
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- gd->bd->bi_ddr_freq = 0;
+#endif -/* function to write the ctrl register which requires a poll of the busy bit */ -static void cm_write_ctrl(uint32_t val) -{
- writel(val, &clock_manager_base->ctrl);
- cm_wait_for_fsm();
- return 0;
} -/* function to write a clock register that has phase information */ -static void cm_write_with_phase(uint32_t value,
uint32_t reg_address, uint32_t mask)
+unsigned int cm_get_spi_controller_clk_hz(void) {
- /* poll until phase is zero */
- while (readl(reg_address) & mask)
;
- uint32_t clock = 0;
- writel(value, reg_address);
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- uint32_t reg;
- clock = cm_get_per_vco_clk_hz();
- while (readl(reg_address) & mask)
;
-}
- /* get the clock prior L4 SP divider (periph_base_clk) */
- reg = readl(&clock_manager_base->per_pll.perbaseclk);
- clock /= (reg + 1);
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- clock = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB);
+#endif -/*
- Setup clocks while making no assumptions about previous state of
the clocks.
- Start by being paranoid and gate all sw managed clocks
- Put all plls in bypass
- Put all plls VCO registers back to reset value (bandgap power
down).
- Put peripheral and main pll src to reset value to avoid glitch.
- Delay 5 us.
- Deassert bandgap power down and set numerator and denominator
- Start 7 us timer.
- set internal dividers
- Wait for 7 us timer.
- Enable plls
- Set external dividers while plls are locking
- Wait for pll lock
- Assert/deassert outreset all.
- Take all pll's out of bypass
- Clear safe mode
- set source main and peripheral clocks
- Ungate clocks
- */
- return clock;
+} -void cm_basic_init(const struct cm_config * const cfg) +unsigned int cm_get_qspi_controller_clk_hz(void) {
- unsigned long end;
- /* Start by being paranoid and gate all sw managed clocks */
- /*
- * We need to disable nandclk
- * and then do another apb access before disabling
- * gatting off the rest of the periperal clocks.
- */
- writel(~CLKMGR_PERPLLGRP_EN_NANDCLK_MASK &
readl(&clock_manager_base->per_pll.en),
&clock_manager_base->per_pll.en);
- /* DO NOT GATE OFF DEBUG CLOCKS & BRIDGE CLOCKS */
- writel(CLKMGR_MAINPLLGRP_EN_DBGTIMERCLK_MASK |
CLKMGR_MAINPLLGRP_EN_DBGTRACECLK_MASK |
CLKMGR_MAINPLLGRP_EN_DBGCLK_MASK |
CLKMGR_MAINPLLGRP_EN_DBGATCLK_MASK |
CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK |
CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK,
&clock_manager_base->main_pll.en);
- writel(0, &clock_manager_base->sdr_pll.en);
- /* now we can gate off the rest of the peripheral clocks */
- writel(0, &clock_manager_base->per_pll.en);
- /* Put all plls in bypass */
- cm_write_bypass(CLKMGR_BYPASS_PERPLL | CLKMGR_BYPASS_SDRPLL
|
CLKMGR_BYPASS_MAINPLL);
- /* Put all plls VCO registers back to reset value. */
- writel(CLKMGR_MAINPLLGRP_VCO_RESET_VALUE &
- ~CLKMGR_MAINPLLGRP_VCO_REGEXTSEL_MASK,
- &clock_manager_base->main_pll.vco);
- writel(CLKMGR_PERPLLGRP_VCO_RESET_VALUE &
- ~CLKMGR_PERPLLGRP_VCO_REGEXTSEL_MASK,
- &clock_manager_base->per_pll.vco);
- writel(CLKMGR_SDRPLLGRP_VCO_RESET_VALUE &
- ~CLKMGR_SDRPLLGRP_VCO_REGEXTSEL_MASK,
- &clock_manager_base->sdr_pll.vco);
- /*
- * The clocks to the flash devices and the L4_MAIN clocks
can
- * glitch when coming out of safe mode if their source
values
- * are different from their reset value. So the trick it to
- * put them back to their reset state, and change input
- * after exiting safe mode but before ungating the clocks.
- */
- writel(CLKMGR_PERPLLGRP_SRC_RESET_VALUE,
- &clock_manager_base->per_pll.src);
- writel(CLKMGR_MAINPLLGRP_L4SRC_RESET_VALUE,
- &clock_manager_base->main_pll.l4src);
- /* read back for the required 5 us delay. */
- readl(&clock_manager_base->main_pll.vco);
- readl(&clock_manager_base->per_pll.vco);
- readl(&clock_manager_base->sdr_pll.vco);
- /*
- * We made sure bgpwr down was assert for 5 us. Now deassert
BG PWR DN
- * with numerator and denominator.
- */
- writel(cfg->main_vco_base, &clock_manager_base-
main_pll.vco);
- writel(cfg->peri_vco_base, &clock_manager_base-
per_pll.vco);
- writel(cfg->sdram_vco_base, &clock_manager_base-
sdr_pll.vco);
- /*
- * Time starts here. Must wait 7 us from
- * BGPWRDN_SET(0) to VCO_ENABLE_SET(1).
- */
- end = timer_get_us() + 7;
- /* main mpu */
- writel(cfg->mpuclk, &clock_manager_base->main_pll.mpuclk);
- /* main main clock */
- writel(cfg->mainclk, &clock_manager_base->main_pll.mainclk);
- /* main for dbg */
- writel(cfg->dbgatclk, &clock_manager_base-
main_pll.dbgatclk);
- /* main for cfgs2fuser0clk */
- writel(cfg->cfg2fuser0clk,
- &clock_manager_base->main_pll.cfgs2fuser0clk);
- /* Peri emac0 50 MHz default to RMII */
- writel(cfg->emac0clk, &clock_manager_base-
per_pll.emac0clk);
- /* Peri emac1 50 MHz default to RMII */
- writel(cfg->emac1clk, &clock_manager_base-
per_pll.emac1clk);
- /* Peri QSPI */
- writel(cfg->mainqspiclk, &clock_manager_base-
main_pll.mainqspiclk);
- writel(cfg->perqspiclk, &clock_manager_base-
per_pll.perqspiclk);
- /* Peri pernandsdmmcclk */
- writel(cfg->mainnandsdmmcclk,
- &clock_manager_base->main_pll.mainnandsdmmcclk);
- writel(cfg->pernandsdmmcclk,
- &clock_manager_base->per_pll.pernandsdmmcclk);
- /* Peri perbaseclk */
- writel(cfg->perbaseclk, &clock_manager_base-
per_pll.perbaseclk);
- /* Peri s2fuser1clk */
- writel(cfg->s2fuser1clk, &clock_manager_base-
per_pll.s2fuser1clk);
- /* 7 us must have elapsed before we can enable the VCO */
- while (timer_get_us() < end)
;
- /* Enable vco */
- /* main pll vco */
- writel(cfg->main_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->main_pll.vco);
- uint32_t clock = 0;
- /* periferal pll */
- writel(cfg->peri_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->per_pll.vco);
- /* sdram pll vco */
- writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->sdr_pll.vco);
- /* L3 MP and L3 SP */
- writel(cfg->maindiv, &clock_manager_base->main_pll.maindiv);
- writel(cfg->dbgdiv, &clock_manager_base->main_pll.dbgdiv);
- writel(cfg->tracediv, &clock_manager_base-
main_pll.tracediv);
- /* L4 MP, L4 SP, can0, and can1 */
- writel(cfg->perdiv, &clock_manager_base->per_pll.div);
- writel(cfg->gpiodiv, &clock_manager_base->per_pll.gpiodiv);
-#define LOCKED_MASK \
- (CLKMGR_INTER_SDRPLLLOCKED_MASK | \
- CLKMGR_INTER_PERPLLLOCKED_MASK | \
- CLKMGR_INTER_MAINPLLLOCKED_MASK)
- cm_wait_for_lock(LOCKED_MASK);
- /* write the sdram clock counters before toggling outreset
all */
- writel(cfg->ddrdqsclk & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK,
- &clock_manager_base->sdr_pll.ddrdqsclk);
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- uint32_t reg;
- /* identify the source of QSPI clock */
- reg = readl(&clock_manager_base->per_pll.src);
- reg = (reg & CLKMGR_PERPLLGRP_SRC_QSPI_MASK) >>
- CLKMGR_PERPLLGRP_SRC_QSPI_OFFSET;
- writel(cfg->ddr2xdqsclk &
CLKMGR_SDRPLLGRP_DDR2XDQSCLK_CNT_MASK,
- &clock_manager_base->sdr_pll.ddr2xdqsclk);
- if (reg == CLKMGR_QSPI_CLK_SRC_F2S) {
clock = cm_get_f2s_per_ref_clk_hz();
- } else if (reg == CLKMGR_QSPI_CLK_SRC_MAIN) {
clock = cm_get_main_vco_clk_hz();
- writel(cfg->ddrdqclk & CLKMGR_SDRPLLGRP_DDRDQCLK_CNT_MASK,
- &clock_manager_base->sdr_pll.ddrdqclk);
/* get the qspi clock */
reg = readl(&clock_manager_base-
main_pll.mainqspiclk);
clock /= (reg + 1);
- } else if (reg == CLKMGR_QSPI_CLK_SRC_PER) {
clock = cm_get_per_vco_clk_hz();
- writel(cfg->s2fuser2clk &
CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK,
- &clock_manager_base->sdr_pll.s2fuser2clk);
/* get the qspi clock */
reg = readl(&clock_manager_base-
per_pll.perqspiclk);
clock /= (reg + 1);
- }
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- clock =
cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB); +#endif
- /*
- * after locking, but before taking out of bypass
- * assert/deassert outresetall
- */
- uint32_t mainvco = readl(&clock_manager_base->main_pll.vco);
- return clock;
+}
- /* assert main outresetall */
- writel(mainvco | CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->main_pll.vco);
+void cm_wait_for_lock(uint32_t mask) +{
- register uint32_t inter_val;
- uint32_t retry = 0;
- do {
+#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
inter_val = readl(&clock_manager_base->stat) & mask;
+#elif defined(CONFIG_TARGET_SOCFPGA_GEN5)
inter_val = readl(&clock_manager_base->inter) &
mask; +#endif
/* Wait for stable lock */
if (inter_val == mask)
retry++;
else
retry = 0;
if (retry >= 10)
break;
- } while (1);
+}
- uint32_t periphvco = readl(&clock_manager_base-
per_pll.vco);
+unsigned long cm_get_mpu_clk_hz(void) +{
- uint32_t reg, clk_hz;
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- clk_hz = cm_get_main_vco_clk_hz();
- /* assert pheriph outresetall */
- writel(periphvco | CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->per_pll.vco);
- /* get the MPU clock */
- reg = readl(&clock_manager_base->altera.mpuclk);
- clk_hz /= (reg + 1);
- reg = readl(&clock_manager_base->main_pll.mpuclk);
- clk_hz /= (reg + 1);
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- uint32_t clk_src, mainmpuclk_reg;
- /* assert sdram outresetall */
- writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN|
CLKMGR_SDRPLLGRP_VCO_OUTRESETALL,
&clock_manager_base->sdr_pll.vco);
- mainmpuclk_reg = readl(&clock_manager_base-
main_pll.mpuclk);
- /* deassert main outresetall */
- writel(mainvco & ~CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->main_pll.vco);
- clk_src = (mainmpuclk_reg >> CLKMGR_MAINPLL_MPUCLK_SRC_LSB)
&
CLKMGR_MAINPLL_MPUCLK_SRC_MSK;
- /* deassert pheriph outresetall */
- writel(periphvco & ~CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->per_pll.vco);
- reg = readl(&clock_manager_base->altera.mpuclk);
- /* Check MPU clock source: main, periph, osc1, intosc or
f2s? */
- switch (clk_src) {
- case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
clk_hz = cm_get_main_vco_clk_hz();
clk_hz /= ((reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK)
+ 1);
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
clk_hz = cm_get_per_vco_clk_hz();
clk_hz /= (((reg >>
CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1);
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
clk_hz = eosc1_hz;
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
clk_hz = cb_intosc_hz;
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
clk_hz = f2s_free_hz;
break;
- default:
printf("cm_get_mpu_clk_hz invalid clk_src %d\n",
clk_src);
return 0;
- }
- /* deassert sdram outresetall */
- writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->sdr_pll.vco);
- clk_hz /= ((mainmpuclk_reg & CLKMGR_MAINPLL_MPUCLK_CNT_MSK)
- 1);
+#endif
- /*
- * now that we've toggled outreset all, all the clocks
- * are aligned nicely; so we can change any phase.
- */
- cm_write_with_phase(cfg->ddrdqsclk,
(uint32_t)&clock_manager_base-
sdr_pll.ddrdqsclk,
CLKMGR_SDRPLLGRP_DDRDQSCLK_PHASE_MASK);
- return clk_hz;
+}
- /* SDRAM DDR2XDQSCLK */
- cm_write_with_phase(cfg->ddr2xdqsclk,
(uint32_t)&clock_manager_base-
sdr_pll.ddr2xdqsclk,
CLKMGR_SDRPLLGRP_DDR2XDQSCLK_PHASE_MASK)
; +unsigned int cm_get_per_vco_clk_hz(void) +{
- uint32_t src_hz = 0;
- uint32_t clk_src = 0;
- uint32_t numer = 0;
- uint32_t denom = 0;
- uint32_t vco = 0;
- cm_write_with_phase(cfg->ddrdqclk,
(uint32_t)&clock_manager_base-
sdr_pll.ddrdqclk,
CLKMGR_SDRPLLGRP_DDRDQCLK_PHASE_MASK);
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- /* identify PER PLL clock source */
- clk_src = readl(&clock_manager_base->per_pll.vco);
- clk_src = (clk_src & CLKMGR_PERPLLGRP_VCO_SSRC_MASK) >>
- CLKMGR_PERPLLGRP_VCO_SSRC_OFFSET;
- if (clk_src == CLKMGR_VCO_SSRC_EOSC1)
src_hz = cm_get_osc_clk_hz(1);
- else if (clk_src == CLKMGR_VCO_SSRC_EOSC2)
src_hz = cm_get_osc_clk_hz(2);
- else if (clk_src == CLKMGR_VCO_SSRC_F2S)
src_hz = cm_get_f2s_per_ref_clk_hz();
- cm_write_with_phase(cfg->s2fuser2clk,
(uint32_t)&clock_manager_base-
sdr_pll.s2fuser2clk,
CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK)
;
- /* get the PER VCO clock */
- vco = readl(&clock_manager_base->per_pll.vco);
- numer = (vco & CLKMGR_PERPLLGRP_VCO_NUMER_MASK) >>
CLKMGR_PERPLLGRP_VCO_NUMER_OFFSET;
- denom = (vco & CLKMGR_PERPLLGRP_VCO_DENOM_MASK) >>
CLKMGR_PERPLLGRP_VCO_DENOM_OFFSET;
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- clk_src = readl(&clock_manager_base->per_pll.vco0);
- clk_src = (clk_src >> CLKMGR_PERPLL_VCO0_PSRC_LSB) &
CLKMGR_PERPLL_VCO0_PSRC_MSK;
- if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_EOSC) {
src_hz = eosc1_hz;
- } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC) {
src_hz = cb_intosc_hz;
- } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_F2S) {
src_hz = f2s_free_hz;
- } else if (clk_src == CLKMGR_PERPLL_VCO0_PSRC_MAIN) {
src_hz = cm_get_main_vco_clk_hz();
src_hz /= (readl
(&clock_manager_base->main_pll.cntr15clk) &
CLKMGR_MAINPLL_CNTRCLK_MSK) + 1;
- } else {
printf("cm_get_per_vco_clk_hz invalid clk_src %d\n",
clk_src);
return 0;
- }
- /* Take all three PLLs out of bypass when safe mode is
cleared. */
- cm_write_bypass(0);
- vco = readl(&clock_manager_base->per_pll.vco1);
- /* clear safe mode */
- cm_write_ctrl(readl(&clock_manager_base->ctrl) |
CLKMGR_CTRL_SAFEMODE);
- numer = vco & CLKMGR_PERPLL_VCO1_NUMER_MSK;
- /*
- * now that safe mode is clear with clocks gated
- * it safe to change the source mux for the flashes the the
L4_MAIN
- */
- writel(cfg->persrc, &clock_manager_base->per_pll.src);
- writel(cfg->l4src, &clock_manager_base->main_pll.l4src);
- denom = (vco >> CLKMGR_PERPLL_VCO1_DENOM_LSB) &
CLKMGR_PERPLL_VCO1_DENOM_MSK;
+#endif
- /* Now ungate non-hw-managed clocks */
- writel(~0, &clock_manager_base->main_pll.en);
- writel(~0, &clock_manager_base->per_pll.en);
- writel(~0, &clock_manager_base->sdr_pll.en);
- vco = src_hz;
- vco /= (1 + denom);
- vco *= (1 + numer);
- /* Clear the loss of lock bits (write 1 to clear) */
- writel(CLKMGR_INTER_SDRPLLLOST_MASK |
CLKMGR_INTER_PERPLLLOST_MASK |
- CLKMGR_INTER_MAINPLLLOST_MASK,
- &clock_manager_base->inter);
- return vco;
} -static unsigned int cm_get_main_vco_clk_hz(void) +unsigned int cm_get_main_vco_clk_hz(void) {
- uint32_t reg, clock;
- uint32_t src_hz, numer, denom, vco;
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5) /* get the main VCO clock */
- reg = readl(&clock_manager_base->main_pll.vco);
- clock = cm_get_osc_clk_hz(1);
- clock /= ((reg & CLKMGR_MAINPLLGRP_VCO_DENOM_MASK) >>
CLKMGR_MAINPLLGRP_VCO_DENOM_OFFSET) + 1;
- clock *= ((reg & CLKMGR_MAINPLLGRP_VCO_NUMER_MASK) >>
CLKMGR_MAINPLLGRP_VCO_NUMER_OFFSET) + 1;
- return clock;
-}
-static unsigned int cm_get_per_vco_clk_hz(void) -{
- uint32_t reg, clock = 0;
- /* identify PER PLL clock source */
- reg = readl(&clock_manager_base->per_pll.vco);
- reg = (reg & CLKMGR_PERPLLGRP_VCO_SSRC_MASK) >>
- CLKMGR_PERPLLGRP_VCO_SSRC_OFFSET;
- if (reg == CLKMGR_VCO_SSRC_EOSC1)
clock = cm_get_osc_clk_hz(1);
- else if (reg == CLKMGR_VCO_SSRC_EOSC2)
clock = cm_get_osc_clk_hz(2);
- else if (reg == CLKMGR_VCO_SSRC_F2S)
clock = cm_get_f2s_per_ref_clk_hz();
- /* get the PER VCO clock */
- reg = readl(&clock_manager_base->per_pll.vco);
- clock /= ((reg & CLKMGR_PERPLLGRP_VCO_DENOM_MASK) >>
CLKMGR_PERPLLGRP_VCO_DENOM_OFFSET) + 1;
- clock *= ((reg & CLKMGR_PERPLLGRP_VCO_NUMER_MASK) >>
CLKMGR_PERPLLGRP_VCO_NUMER_OFFSET) + 1;
- return clock;
-}
- vco = readl(&clock_manager_base->main_pll.vco);
- numer = ((vco & CLKMGR_MAINPLLGRP_VCO_NUMER_MASK) >>
CLKMGR_MAINPLLGRP_VCO_NUMER_OFFSET);
- denom = ((vco & CLKMGR_MAINPLLGRP_VCO_DENOM_MASK) >>
CLKMGR_MAINPLLGRP_VCO_DENOM_OFFSET);
- src_hz = cm_get_osc_clk_hz(1);
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- uint32_t clk_src = readl(&clock_manager_base-
main_pll.vco0);
- clk_src = (clk_src >> CLKMGR_MAINPLL_VCO0_PSRC_LSB) &
CLKMGR_MAINPLL_VCO0_PSRC_MSK;
- if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_EOSC) {
src_hz = eosc1_hz;
- } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC) {
src_hz = cb_intosc_hz;
- } else if (clk_src == CLKMGR_MAINPLL_VCO0_PSRC_F2S) {
src_hz = f2s_free_hz;
- } else {
printf("cm_get_main_vco_clk_hz invalid clk_src
%d\n", clk_src);
return 0;
- }
-unsigned long cm_get_mpu_clk_hz(void) -{
- uint32_t reg, clock;
- vco = readl(&clock_manager_base->main_pll.vco1);
- clock = cm_get_main_vco_clk_hz();
- numer = vco & CLKMGR_MAINPLL_VCO1_NUMER_MSK;
- /* get the MPU clock */
- reg = readl(&clock_manager_base->altera.mpuclk);
- clock /= (reg + 1);
- reg = readl(&clock_manager_base->main_pll.mpuclk);
- clock /= (reg + 1);
- return clock;
-}
- denom = (vco >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) &
CLKMGR_MAINPLL_VCO1_DENOM_MSK;
+#endif -unsigned long cm_get_sdram_clk_hz(void) -{
- uint32_t reg, clock = 0;
- /* identify SDRAM PLL clock source */
- reg = readl(&clock_manager_base->sdr_pll.vco);
- reg = (reg & CLKMGR_SDRPLLGRP_VCO_SSRC_MASK) >>
- CLKMGR_SDRPLLGRP_VCO_SSRC_OFFSET;
- if (reg == CLKMGR_VCO_SSRC_EOSC1)
clock = cm_get_osc_clk_hz(1);
- else if (reg == CLKMGR_VCO_SSRC_EOSC2)
clock = cm_get_osc_clk_hz(2);
- else if (reg == CLKMGR_VCO_SSRC_F2S)
clock = cm_get_f2s_sdr_ref_clk_hz();
- /* get the SDRAM VCO clock */
- reg = readl(&clock_manager_base->sdr_pll.vco);
- clock /= ((reg & CLKMGR_SDRPLLGRP_VCO_DENOM_MASK) >>
CLKMGR_SDRPLLGRP_VCO_DENOM_OFFSET) + 1;
- clock *= ((reg & CLKMGR_SDRPLLGRP_VCO_NUMER_MASK) >>
CLKMGR_SDRPLLGRP_VCO_NUMER_OFFSET) + 1;
- /* get the SDRAM (DDR_DQS) clock */
- reg = readl(&clock_manager_base->sdr_pll.ddrdqsclk);
- reg = (reg & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK) >>
- CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_OFFSET;
- clock /= (reg + 1);
- vco = src_hz;
- vco /= (1 + denom);
- vco *= (1 + numer);
- return clock;
- return vco;
} unsigned int cm_get_l4_sp_clk_hz(void) {
- uint32_t reg, clock = 0;
- uint32_t clock = 0;
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- uint32_t reg;
/* identify the source of L4 SP clock */ reg = readl(&clock_manager_base->main_pll.l4src); reg = (reg & CLKMGR_MAINPLLGRP_L4SRC_L4SP) >> @@ -443,106 +314,117 @@ unsigned int cm_get_l4_sp_clk_hz(void) reg = (reg & CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_MASK) >> CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_OFFSET; clock = clock / (1 << reg);
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- clock = cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB);
+#endif return clock; } -unsigned int cm_get_mmc_controller_clk_hz(void) +/* function to poll in the fsm busy bit */ +void cm_wait_for_fsm(void) {
- uint32_t reg, clock = 0;
- /* identify the source of MMC clock */
- reg = readl(&clock_manager_base->per_pll.src);
- reg = (reg & CLKMGR_PERPLLGRP_SRC_SDMMC_MASK) >>
- CLKMGR_PERPLLGRP_SRC_SDMMC_OFFSET;
- if (reg == CLKMGR_SDMMC_CLK_SRC_F2S) {
clock = cm_get_f2s_per_ref_clk_hz();
- } else if (reg == CLKMGR_SDMMC_CLK_SRC_MAIN) {
clock = cm_get_main_vco_clk_hz();
/* get the SDMMC clock */
reg = readl(&clock_manager_base-
main_pll.mainnandsdmmcclk);
clock /= (reg + 1);
- } else if (reg == CLKMGR_SDMMC_CLK_SRC_PER) {
clock = cm_get_per_vco_clk_hz();
/* get the SDMMC clock */
reg = readl(&clock_manager_base-
per_pll.pernandsdmmcclk);
clock /= (reg + 1);
- }
- /* further divide by 4 as we have fixed divider at wrapper
*/
- clock /= 4;
- return clock;
- while (readl(&clock_manager_base->stat) &
CLKMGR_CLKMGR_STAT_BUSY_SET_MSK);
} -unsigned int cm_get_qspi_controller_clk_hz(void) +unsigned int cm_get_mmc_controller_clk_hz(void) {
- uint32_t reg, clock = 0;
- /* identify the source of QSPI clock */
- reg = readl(&clock_manager_base->per_pll.src);
- reg = (reg & CLKMGR_PERPLLGRP_SRC_QSPI_MASK) >>
- CLKMGR_PERPLLGRP_SRC_QSPI_OFFSET;
- uint32_t clk_hz = 0;
- uint32_t clk_input = 0;
+#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- clk_input = readl(&clock_manager_base->per_pll.cntr6clk);
- clk_input = (clk_input >> CLKMGR_PERPLL_CNTR6CLK_SRC_LSB) &
CLKMGR_PERPLLGRP_SRC_MSK;
+#elif defined(CONFIG_TARGET_SOCFPGA_GEN5)
- clk_input = readl(&clock_manager_base->per_pll.src);
- clk_input = (clk_input & CLKMGR_PERPLLGRP_SRC_SDMMC_MASK) >>
- CLKMGR_PERPLLGRP_SRC_SDMMC_OFFSET;
+#endif
- switch (clk_input) {
+#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- case CLKMGR_PERPLLGRP_SRC_MAIN:
clk_hz = cm_get_main_vco_clk_hz();
clk_hz /= 1 +
(readl
(&clock_manager_base->main_pll.cntr6clk) &
CLKMGR_MAINPLL_CNTRCLK_MSK);
break;
- case CLKMGR_PERPLLGRP_SRC_PERI:
clk_hz = cm_get_per_vco_clk_hz();
clk_hz /= 1 + (readl
(&clock_manager_base->per_pll.cntr6clk) &
CLKMGR_PERPLL_CNTRCLK_MSK);
break;
- case CLKMGR_PERPLLGRP_SRC_OSC1:
clk_hz = eosc1_hz;
break;
- case CLKMGR_PERPLLGRP_SRC_INTOSC:
clk_hz = cb_intosc_hz;
break;
- case CLKMGR_PERPLLGRP_SRC_FPGA:
clk_hz = f2s_free_hz;
break;
+#elif defined(CONFIG_TARGET_SOCFPGA_GEN5)
- case CLKMGR_SDMMC_CLK_SRC_F2S:
clk_hz = cm_get_f2s_per_ref_clk_hz();
break;
- case CLKMGR_SDMMC_CLK_SRC_MAIN:
clk_hz = cm_get_main_vco_clk_hz();
- if (reg == CLKMGR_QSPI_CLK_SRC_F2S) {
clock = cm_get_f2s_per_ref_clk_hz();
- } else if (reg == CLKMGR_QSPI_CLK_SRC_MAIN) {
clock = cm_get_main_vco_clk_hz();
/* get the SDMMC clock */
clk_input =
readl(&clock_manager_base-
main_pll.mainnandsdmmcclk);
clk_hz /= (clk_input + 1);
break;
/* get the qspi clock */
reg = readl(&clock_manager_base-
main_pll.mainqspiclk);
clock /= (reg + 1);
- } else if (reg == CLKMGR_QSPI_CLK_SRC_PER) {
clock = cm_get_per_vco_clk_hz();
- case CLKMGR_SDMMC_CLK_SRC_PER:
clk_hz = cm_get_per_vco_clk_hz();
/* get the qspi clock */
reg = readl(&clock_manager_base-
per_pll.perqspiclk);
clock /= (reg + 1);
/* get the SDMMC clock */
clk_input =
readl(&clock_manager_base-
per_pll.pernandsdmmcclk);
clk_hz /= (clk_input + 1);
break;
+#endif }
- return clock;
-}
-unsigned int cm_get_spi_controller_clk_hz(void) -{
- uint32_t reg, clock = 0;
- clock = cm_get_per_vco_clk_hz();
- /* get the clock prior L4 SP divider (periph_base_clk) */
- reg = readl(&clock_manager_base->per_pll.perbaseclk);
- clock /= (reg + 1);
- return clock;
- return clk_hz/4;
} static void cm_print_clock_quick_summary(void) { printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000);
- printf("MMC %8d kHz\n",
cm_get_mmc_controller_clk_hz() / 1000);
- printf("QSPI %8d kHz\n",
cm_get_qspi_controller_clk_hz() / 1000);
- printf("SPI %8d kHz\n",
cm_get_spi_controller_clk_hz() / 1000); +#if defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- printf("EOSC1 %8d kHz\n", eosc1_hz / 1000);
- printf("cb_intosc %8d kHz\n", cb_intosc_hz / 1000);
- printf("f2s_free %8d kHz\n", f2s_free_hz / 1000);
- printf("Main VCO %8d kHz\n",
cm_get_main_vco_clk_hz()/1000);
- printf("NOC %8d kHz\n", cm_get_noc_clk_hz()/1000);
- printf("L4 Main %8d kHz\n",
- cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB)
/1000);
- printf("L4 MP %8d kHz\n",
- cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB)/1
000);
- printf("L4 SP %8d kHz\n",
- cm_get_l4_sp_clk_hz()/1000);
- printf("L4 sys free %8d kHz\n", cm_l4_sys_free_clk_hz/1000);
+#elif defined(CONFIG_TARGET_SOCFPGA_GEN5) printf("DDR %10ld kHz\n", cm_get_sdram_clk_hz() / 1000); printf("EOSC1 %8d kHz\n", cm_get_osc_clk_hz(1) / 1000); printf("EOSC2 %8d kHz\n", cm_get_osc_clk_hz(2) / 1000); printf("F2S_SDR_REF %8d kHz\n", cm_get_f2s_sdr_ref_clk_hz() / 1000); printf("F2S_PER_REF %8d kHz\n", cm_get_f2s_per_ref_clk_hz() / 1000);
- printf("MMC %8d kHz\n",
cm_get_mmc_controller_clk_hz() / 1000);
- printf("QSPI %8d kHz\n",
cm_get_qspi_controller_clk_hz() / 1000); printf("UART %8d kHz\n", cm_get_l4_sp_clk_hz() / 1000);
- printf("SPI %8d kHz\n",
cm_get_spi_controller_clk_hz() / 1000); -}
-int set_cpu_clk_info(void) -{
- /* Calculate the clock frequencies required for drivers */
- cm_get_l4_sp_clk_hz();
- cm_get_mmc_controller_clk_hz();
- gd->bd->bi_arm_freq = cm_get_mpu_clk_hz() / 1000000;
- gd->bd->bi_dsp_freq = 0;
- gd->bd->bi_ddr_freq = cm_get_sdram_clk_hz() / 1000000;
- return 0;
+#endif } int do_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) diff --git a/arch/arm/mach-socfpga/clock_manager_arria10.c b/arch/arm/mach-socfpga/clock_manager_arria10.c new file mode 100644 index 0000000..93165b4 --- /dev/null +++ b/arch/arm/mach-socfpga/clock_manager_arria10.c @@ -0,0 +1,954 @@ +/*
- Copyright (C) 2016, Intel Corporation
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock_manager.h> +#include <fdtdec.h>
+DECLARE_GLOBAL_DATA_PTR;
+int cm_basic_init(const void* blob); +uint32_t eosc1_hz; +uint32_t cb_intosc_hz; +uint32_t f2s_free_hz; +unsigned int cm_l4_main_clk_hz; +unsigned int cm_l4_sp_clk_hz; +unsigned int cm_l4_mp_clk_hz; +unsigned int cm_l4_sys_free_clk_hz;
+struct strtopu32 {
- const char *str;
- uint32_t *p;
+};
+struct mainpll_cfg {
- uint32_t vco0_psrc;
- uint32_t vco1_denom;
- uint32_t vco1_numer;
- uint32_t mpuclk;
- uint32_t mpuclk_cnt;
- uint32_t mpuclk_src;
- uint32_t nocclk;
- uint32_t nocclk_cnt;
- uint32_t nocclk_src;
- uint32_t cntr2clk_cnt;
- uint32_t cntr3clk_cnt;
- uint32_t cntr4clk_cnt;
- uint32_t cntr5clk_cnt;
- uint32_t cntr6clk_cnt;
- uint32_t cntr7clk_cnt;
- uint32_t cntr7clk_src;
- uint32_t cntr8clk_cnt;
- uint32_t cntr9clk_cnt;
- uint32_t cntr9clk_src;
- uint32_t cntr15clk_cnt;
- uint32_t nocdiv_l4mainclk;
- uint32_t nocdiv_l4mpclk;
- uint32_t nocdiv_l4spclk;
- uint32_t nocdiv_csatclk;
- uint32_t nocdiv_cstraceclk;
- uint32_t nocdiv_cspdbclk;
+};
+struct perpll_cfg {
- uint32_t vco0_psrc;
- uint32_t vco1_denom;
- uint32_t vco1_numer;
- uint32_t cntr2clk_cnt;
- uint32_t cntr2clk_src;
- uint32_t cntr3clk_cnt;
- uint32_t cntr3clk_src;
- uint32_t cntr4clk_cnt;
- uint32_t cntr4clk_src;
- uint32_t cntr5clk_cnt;
- uint32_t cntr5clk_src;
- uint32_t cntr6clk_cnt;
- uint32_t cntr6clk_src;
- uint32_t cntr7clk_cnt;
- uint32_t cntr8clk_cnt;
- uint32_t cntr8clk_src;
- uint32_t cntr9clk_cnt;
- uint32_t emacctl_emac0sel;
- uint32_t emacctl_emac1sel;
- uint32_t emacctl_emac2sel;
- uint32_t gpiodiv_gpiodbclk;
+};
+struct alteragrp_cfg {
- uint32_t nocclk;
- uint32_t mpuclk;
+};
+unsigned int cm_get_noc_clk_hz(void); +unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift); +static int of_to_struct(const void *blob, int node, int cfg__len, void *cfg); +static int of_get_input_clks(const void *blob, int node, void *cfg); +static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg,
- struct perpll_cfg *per_cfg, struct alteragrp_cfg
*altrgrp_cfg); +static unsigned int cm_calc_handoff_main_vco_clk_hz(
- struct mainpll_cfg *main_cfg);
+static unsigned int cm_calc_handoff_periph_vco_clk_hz(
- struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg);
+static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg,
- struct perpll_cfg *per_cfg);
+static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg,
- struct perpll_cfg *per_cfg);
+static int cm_is_pll_ramp_required(int main0periph1,
- struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg);
+static unsigned int cm_calc_safe_pll_numer(int main0periph1,
- struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg,
- unsigned int safe_hz);
+static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg,
- struct perpll_cfg *per_cfg, unsigned int pll_ramp_main_hz);
+static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
- struct perpll_cfg *per_cfg, unsigned int
pll_ramp_periph_hz); +static int cm_full_cfg(struct mainpll_cfg *main_cfg,
- struct perpll_cfg *per_cfg);
+static const struct socfpga_clock_manager *clock_manager_base =
- (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
+void cm_use_intosc(void) +{
- setbits_le32(&clock_manager_base->ctrl,
CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK);
+}
+unsigned int cm_get_noc_clk_hz(void) +{
- unsigned int clk_src, dividor, nocclk, src_hz;
- nocclk = readl(&clock_manager_base->main_pll.nocclk);
- clk_src = (nocclk >> CLKMGR_MAINPLL_NOCCLK_SRC_LSB) &
CLKMGR_MAINPLL_NOCCLK_SRC_MSK;
- dividor = 1 + (nocclk & CLKMGR_MAINPLL_NOCDIV_MSK);
- if (clk_src == CLKMGR_PERPLLGRP_SRC_MAIN) {
src_hz = cm_get_main_vco_clk_hz();
src_hz /= 1 +
(readl(SOCFPGA_CLKMGR_ADDRESS+CLKMGR_MAINPLL_NOC_CLK
_OFFSET)&
CLKMGR_MAINPLL_NOCCLK_CNT_MSK);
- } else if (clk_src == CLKMGR_PERPLLGRP_SRC_PERI) {
src_hz = cm_get_per_vco_clk_hz();
src_hz /= 1 +
((readl(SOCFPGA_CLKMGR_ADDRESS+CLKMGR_MAINPLL_NOC_CL
K_OFFSET)>>
CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB)&
CLKMGR_MAINPLL_NOCCLK_CNT_MSK);
- } else if (clk_src == CLKMGR_PERPLLGRP_SRC_OSC1) {
src_hz = eosc1_hz;
- } else if (clk_src == CLKMGR_PERPLLGRP_SRC_INTOSC) {
src_hz = cb_intosc_hz;
- } else if (clk_src == CLKMGR_PERPLLGRP_SRC_FPGA) {
src_hz = f2s_free_hz;
- } else {
src_hz = 0;
- }
- return src_hz/dividor;
+}
+unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift) +{
- unsigned int dividor2 = 1 <<
((readl(&clock_manager_base->main_pll.nocdiv) >>
nocdivshift) & CLKMGR_MAINPLL_NOCDIV_MSK);
- return cm_get_noc_clk_hz()/dividor2;
+}
+int of_to_struct(const void *blob, int node, int cfg_len, void *cfg) +{
- if (fdtdec_get_int_array(blob, node, "altr,of_reg_value",
(u32*)cfg, cfg_len)) {
/* could not find required property */
return 100;
- }
- return 0;
+}
+static int of_get_input_clks(const void *blob, int node, void *cfg) +{
- if (fdtdec_get_int_array(blob, node, "clock-frequency",
(u32*)cfg, 1)) {
/* could not find required property */
return 100;
- }
- return 0;
+}
+int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg, struct
alteragrp_cfg *altrgrp_cfg) +{
- int node, child, len;
- const char *node_name;
- node = fdtdec_next_compatible(blob, 0,
COMPAT_ALTERA_SOCFPGA_CLK);
- if (node < 0)
return 1;
- child = fdt_first_subnode(blob, node);
- if (child < 0)
return 2;
- child = fdt_first_subnode(blob, child);
- if (child < 0)
return 3;
- node_name = fdt_get_name(blob, child, &len);
- while (node_name) {
if (!strcmp(node_name, "osc1")) {
if (of_get_input_clks(blob, child,
&eosc1_hz))
return 101;
} else if (!strcmp(node_name, "cb_intosc_ls_clk")) {
if (of_get_input_clks(blob, child,
&cb_intosc_hz))
return 102;
} else if (!strcmp(node_name, "f2s_free_clk")) {
if (of_get_input_clks(blob, child,
&f2s_free_hz))
return 103;
} else if (!strcmp(node_name, "main_pll")) {
if (of_to_struct(blob, child,
sizeof(*main_cfg)/sizeof(uint32_t),
main_cfg))
return 104;
} else if (!strcmp(node_name, "periph_pll")) {
if (of_to_struct(blob, child,
sizeof(*per_cfg)/sizeof(uint32_t),
per_cfg))
return 105;
} else if (!strcmp(node_name, "altera")) {
if (of_to_struct(blob, child,
sizeof(*altrgrp_cfg)/sizeof(uint32_t
), altrgrp_cfg))
return 106;
main_cfg->mpuclk = altrgrp_cfg->mpuclk;
main_cfg->nocclk = altrgrp_cfg->nocclk;
}
child = fdt_next_subnode(blob, child);
if (child < 0)
break;
node_name = fdt_get_name(blob, child, &len);
- }
- return 0;
+}
+/* calculate the intended main VCO frequency based on handoff */ +static unsigned int cm_calc_handoff_main_vco_clk_hz
- (struct mainpll_cfg *main_cfg)
+{
- unsigned int clk_hz;
- /* Check main VCO clock source: eosc, intosc or f2s? */
- switch (main_cfg->vco0_psrc) {
- case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
clk_hz = eosc1_hz;
break;
- case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
clk_hz = cb_intosc_hz;
break;
- case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
clk_hz = f2s_free_hz;
break;
- default:
return 0;
- }
- /* calculate the VCO frequency */
- clk_hz /= (1 + main_cfg->vco1_denom);
- clk_hz *= (1 + main_cfg->vco1_numer);
- return clk_hz;
+}
+/* calculate the intended periph VCO frequency based on handoff */ +static unsigned int cm_calc_handoff_periph_vco_clk_hz
- (struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
+{
- unsigned int clk_hz;
- /* Check periph VCO clock source: eosc, intosc, f2s or
mainpll? */
- switch (per_cfg->vco0_psrc) {
- case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
clk_hz = eosc1_hz;
break;
- case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
clk_hz = cb_intosc_hz;
break;
- case CLKMGR_PERPLL_VCO0_PSRC_F2S:
clk_hz = f2s_free_hz;
break;
- case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
clk_hz /= main_cfg->cntr15clk_cnt;
break;
- default:
return 0;
- }
- /* calculate the VCO frequency */
- clk_hz /= (1 + per_cfg->vco1_denom);
- clk_hz *= (1 + per_cfg->vco1_numer);
- return clk_hz;
+}
+/* calculate the intended MPU clock frequency based on handoff */ +static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg)
+{
- unsigned int clk_hz;
- /* Check MPU clock source: main, periph, osc1, intosc or
f2s? */
- switch (main_cfg->mpuclk_src) {
- case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
clk_hz /= ((main_cfg->mpuclk &
CLKMGR_MAINPLL_MPUCLK_CNT_MSK)
+ 1);
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg,
per_cfg);
clk_hz /= (((main_cfg->mpuclk >>
CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1);
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
clk_hz = eosc1_hz;
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
clk_hz = cb_intosc_hz;
break;
- case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
clk_hz = f2s_free_hz;
break;
- default:
return 0;
- }
- clk_hz /= (main_cfg->mpuclk_cnt + 1);
- return clk_hz;
+}
+/* calculate the intended NOC clock frequency based on handoff */ +static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg)
+{
- unsigned int clk_hz;
- /* Check MPU clock source: main, periph, osc1, intosc or
f2s? */
- switch (main_cfg->nocclk_src) {
- case CLKMGR_MAINPLL_NOCCLK_SRC_MAIN:
clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
clk_hz /= ((main_cfg->nocclk &
CLKMGR_MAINPLL_NOCCLK_CNT_MSK)
+ 1);
break;
- case CLKMGR_MAINPLL_NOCCLK_SRC_PERI:
clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg,
per_cfg);
clk_hz /= (((main_cfg->nocclk >>
CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) &
CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1);
break;
- case CLKMGR_MAINPLL_NOCCLK_SRC_OSC1:
clk_hz = eosc1_hz;
break;
- case CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC:
clk_hz = cb_intosc_hz;
break;
- case CLKMGR_MAINPLL_NOCCLK_SRC_FPGA:
clk_hz = f2s_free_hz;
break;
- default:
return 0;
- }
- clk_hz /= (main_cfg->nocclk_cnt + 1);
- return clk_hz;
+}
+/* return 1 if PLL ramp is required */ +static int cm_is_pll_ramp_required(int main0periph1,
struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg)
+{
- /* Check for main PLL */
- if (main0periph1 == 0) {
/*
* PLL ramp is not required if both MPU clock and
NOC clock are
* not sourced from main PLL
*/
if (main_cfg->mpuclk_src !=
CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
main_cfg->nocclk_src !=
CLKMGR_MAINPLL_NOCCLK_SRC_MAIN)
return 0;
/*
* PLL ramp is required if MPU clock is sourced from
main PLL
* and MPU clock is over 900MHz (as advised by HW
team)
*/
if (main_cfg->mpuclk_src ==
CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
(cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
return 1;
/*
* PLL ramp is required if NOC clock is sourced from
main PLL
* and NOC clock is over 300MHz (as advised by HW
team)
*/
if (main_cfg->nocclk_src ==
CLKMGR_MAINPLL_NOCCLK_SRC_MAIN &&
(cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
return 2;
- } else if (main0periph1 == 1) {
/*
* PLL ramp is not required if both MPU clock and
NOC clock are
* not sourced from periph PLL
*/
if (main_cfg->mpuclk_src !=
CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
main_cfg->nocclk_src !=
CLKMGR_MAINPLL_NOCCLK_SRC_PERI)
return 0;
/*
* PLL ramp is required if MPU clock are source from
periph PLL
* and MPU clock is over 900MHz (as advised by HW
team)
*/
if (main_cfg->mpuclk_src ==
CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
(cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
return 1;
/*
* PLL ramp is required if NOC clock are source from
periph PLL
* and NOC clock is over 300MHz (as advised by HW
team)
*/
if (main_cfg->nocclk_src ==
CLKMGR_MAINPLL_NOCCLK_SRC_PERI &&
(cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
return 2;
- }
- return 0;
+}
+/*
- Calculate the new PLL numerator which is based on existing DTS
hand off and
- intended safe frequency (safe_hz). Note that PLL ramp is only
modifying the
- numerator while maintaining denominator as denominator will
influence the
- jitter condition. Please refer A10 HPS TRM for the jitter guide.
Note final
- value for numerator is minus with 1 to cater our register value
- representation.
- */
+static unsigned int cm_calc_safe_pll_numer(int main0periph1,
struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg,
unsigned int safe_hz)
+{
- unsigned int clk_hz = 0;
- /* Check for main PLL */
- if (main0periph1 == 0) {
/* Check main VCO clock source: eosc, intosc or f2s?
*/
switch (main_cfg->vco0_psrc) {
case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
clk_hz = eosc1_hz;
break;
case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
clk_hz = cb_intosc_hz;
break;
case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
clk_hz = f2s_free_hz;
break;
default:
return 0;
}
/* Applicable if MPU clock is from main PLL */
if (main_cfg->mpuclk_src ==
CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
/* calculate the safe numer value */
clk_hz = (safe_hz / clk_hz) *
(main_cfg->mpuclk_cnt + 1) *
((main_cfg->mpuclk &
CLKMGR_MAINPLL_MPUCLK_CNT_MSK) +
(1 + main_cfg->vco1_denom) - 1;
}
/* Reach here if MPU clk not from main PLL but NOC
clk is */
else if (main_cfg->nocclk_src ==
CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
/* calculate the safe numer value */
clk_hz = (safe_hz / clk_hz) *
(main_cfg->nocclk_cnt + 1) *
((main_cfg->nocclk &
CLKMGR_MAINPLL_NOCCLK_CNT_MSK) +
(1 + main_cfg->vco1_denom) - 1;
} else
clk_hz = 0;
- } else if (main0periph1 == 1) {
/* Check periph VCO clock source: eosc, intosc, f2s,
mainpll */
switch (per_cfg->vco0_psrc) {
case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
clk_hz = eosc1_hz;
break;
case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
clk_hz = cb_intosc_hz;
break;
case CLKMGR_PERPLL_VCO0_PSRC_F2S:
clk_hz = f2s_free_hz;
break;
case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
clk_hz = cm_calc_handoff_main_vco_clk_hz(
main_cfg);
clk_hz /= main_cfg->cntr15clk_cnt;
break;
default:
return 0;
}
/* Applicable if MPU clock is from periph PLL */
if (main_cfg->mpuclk_src ==
CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
/* calculate the safe numer value */
clk_hz = (safe_hz / clk_hz) *
(main_cfg->mpuclk_cnt + 1) *
(((main_cfg->mpuclk >>
CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB)
&
CLKMGR_MAINPLL_MPUCLK_CNT_MSK) +
(1 + per_cfg->vco1_denom) - 1;
}
/* Reach here if MPU clk not from periph PLL but NOC
clk is */
else if (main_cfg->nocclk_src ==
CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
/* calculate the safe numer value */
clk_hz = (safe_hz / clk_hz) *
(main_cfg->nocclk_cnt + 1) *
(((main_cfg->nocclk >>
CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB)
&
CLKMGR_MAINPLL_NOCCLK_CNT_MSK) +
(1 + per_cfg->vco1_denom) - 1;
} else
clk_hz = 0;
- }
- return clk_hz;
+}
+/* ramping the main PLL to final value */ +static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg,
unsigned int pll_ramp_main_hz)
+{
- unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
- /* find out the increment value */
- if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN)
{
clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg,
per_cfg);
- } else if (main_cfg->nocclk_src ==
CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg,
per_cfg);
- }
- /* execute the ramping here */
- for (clk_hz = pll_ramp_main_hz + clk_incr_hz;
- clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
writel((main_cfg->vco1_denom <<
CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
cm_calc_safe_pll_numer(0, main_cfg, per_cfg,
clk_hz),
&clock_manager_base->main_pll.vco1);
udelay(1000);
cm_wait_for_lock(LOCKED_MASK);
- }
- writel((main_cfg->vco1_denom <<
CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
main_cfg->vco1_numer,
&clock_manager_base->main_pll.vco1);
- udelay(1000);
- cm_wait_for_lock(LOCKED_MASK);
+}
+/* ramping the periph PLL to final value */ +static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
struct perpll_cfg *per_cfg,
unsigned int pll_ramp_periph_hz)
+{
- unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
- /* find out the increment value */
- if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI)
{
clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg,
per_cfg);
- } else if (main_cfg->nocclk_src ==
CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg,
per_cfg);
- }
- /* execute the ramping here */
- for (clk_hz = pll_ramp_periph_hz + clk_incr_hz;
- clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
writel((per_cfg->vco1_denom <<
CLKMGR_PERPLL_VCO1_DENOM_LSB) |
cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
clk_hz),
&clock_manager_base->per_pll.vco1);
udelay(1000);
cm_wait_for_lock(LOCKED_MASK);
- }
- writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB)
|
per_cfg->vco1_numer,
&clock_manager_base->per_pll.vco1);
- udelay(1000);
- cm_wait_for_lock(LOCKED_MASK);
+}
+/*
- Setup clocks while making no assumptions of the
- previous state of the clocks.
- Start by being paranoid and gate all sw managed clocks
- Put all plls in bypass
- Put all plls VCO registers back to reset value (bgpwr dwn).
- Put peripheral and main pll src to reset value to avoid glitch.
- Delay 5 us.
- Deassert bg pwr dn and set numerator and denominator
- Start 7 us timer.
- set internal dividers
- Wait for 7 us timer.
- Enable plls
- Set external dividers while plls are locking
- Wait for pll lock
- Assert/deassert outreset all.
- Take all pll's out of bypass
- Clear safe mode
- set source main and peripheral clocks
- Ungate clocks
- */
+static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg) +{
- unsigned int pll_ramp_main_hz = 0, pll_ramp_periph_hz = 0,
ramp_required;
- /* gate off all mainpll clock excpet HW managed clock */
- writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
&clock_manager_base->main_pll.enr);
- /* now we can gate off the rest of the peripheral clocks */
- writel(0, &clock_manager_base->per_pll.en);
- /* Put all plls in external bypass */
- writel(CLKMGR_MAINPLL_BYPASS_RESET,
&clock_manager_base->main_pll.bypasss);
- writel(CLKMGR_PERPLL_BYPASS_RESET,
&clock_manager_base->per_pll.bypasss);
- /*
- * Put all plls VCO registers back to reset value.
- * Some code might have messed with them. At same time set
the
- * desired clock source
- */
- writel(CLKMGR_MAINPLL_VCO0_RESET |
CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK |
(main_cfg->vco0_psrc <<
CLKMGR_MAINPLL_VCO0_PSRC_LSB),
&clock_manager_base->main_pll.vco0);
- writel(CLKMGR_PERPLL_VCO0_RESET |
CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK |
(per_cfg->vco0_psrc <<
CLKMGR_PERPLL_VCO0_PSRC_LSB),
&clock_manager_base->per_pll.vco0);
- writel(CLKMGR_MAINPLL_VCO1_RESET,
&clock_manager_base->main_pll.vco1);
- writel(CLKMGR_PERPLL_VCO1_RESET,
&clock_manager_base->per_pll.vco1);
- /* clear the interrupt register status register */
- writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK |
CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK |
CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK,
&clock_manager_base->intr);
- /* Program VCO �Numerator� and �Denominator� for main PLL */
- ramp_required = cm_is_pll_ramp_required(0, main_cfg,
per_cfg);
- if (ramp_required) {
/* set main PLL to safe starting threshold frequency
*/
if (ramp_required == 1)
pll_ramp_main_hz =
CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
else if (ramp_required == 2)
pll_ramp_main_hz =
CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
writel((main_cfg->vco1_denom <<
CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
cm_calc_safe_pll_numer(0, main_cfg, per_cfg,
pll_ramp_main_hz),
&clock_manager_base->main_pll.vco1);
- } else
writel((main_cfg->vco1_denom <<
CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
main_cfg->vco1_numer,
&clock_manager_base->main_pll.vco1);
- /* Program VCO �Numerator� and �Denominator� for periph PLL
*/
- ramp_required = cm_is_pll_ramp_required(1, main_cfg,
per_cfg);
- if (ramp_required) {
/* set periph PLL to safe starting threshold
frequency */
if (ramp_required == 1)
pll_ramp_periph_hz =
CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
else if (ramp_required == 2)
pll_ramp_periph_hz =
CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
writel((per_cfg->vco1_denom <<
CLKMGR_PERPLL_VCO1_DENOM_LSB) |
cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
pll_ramp_periph_hz),
&clock_manager_base->per_pll.vco1);
- } else
writel((per_cfg->vco1_denom <<
CLKMGR_PERPLL_VCO1_DENOM_LSB) |
per_cfg->vco1_numer,
&clock_manager_base->per_pll.vco1);
- /* Wait for at least 5 us */
- udelay(5);
- /* Now deassert BGPWRDN and PWRDN */
- clrbits_le32(&clock_manager_base->main_pll.vco0,
CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK |
CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK);
- clrbits_le32(&clock_manager_base->per_pll.vco0,
CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK |
CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK);
- /* Wait for at least 7 us */
- udelay(7);
- /* enable the VCO and disable the external regulator to PLL
*/
- writel((readl(&clock_manager_base->main_pll.vco0) &
~CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK) |
CLKMGR_MAINPLL_VCO0_EN_SET_MSK,
&clock_manager_base->main_pll.vco0);
- writel((readl(&clock_manager_base->per_pll.vco0) &
~CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK) |
CLKMGR_PERPLL_VCO0_EN_SET_MSK,
&clock_manager_base->per_pll.vco0);
- /* setup all the main PLL counter and clock source */
- writel(main_cfg->nocclk,
- SOCFPGA_CLKMGR_ADDRESS +
CLKMGR_MAINPLL_NOC_CLK_OFFSET);
- writel(main_cfg->mpuclk,
- SOCFPGA_CLKMGR_ADDRESS +
CLKMGR_ALTERAGRP_MPU_CLK_OFFSET);
- /* main_emaca_clk divider */
- writel(main_cfg->cntr2clk_cnt,
&clock_manager_base->main_pll.cntr2clk);
- /* main_emacb_clk divider */
- writel(main_cfg->cntr3clk_cnt,
&clock_manager_base->main_pll.cntr3clk);
- /* main_emac_ptp_clk divider */
- writel(main_cfg->cntr4clk_cnt,
&clock_manager_base->main_pll.cntr4clk);
- /* main_gpio_db_clk divider */
- writel(main_cfg->cntr5clk_cnt,
&clock_manager_base->main_pll.cntr5clk);
- /* main_sdmmc_clk divider */
- writel(main_cfg->cntr6clk_cnt,
&clock_manager_base->main_pll.cntr6clk);
- /* main_s2f_user0_clk divider */
- writel(main_cfg->cntr7clk_cnt |
(main_cfg->cntr7clk_src <<
CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB),
&clock_manager_base->main_pll.cntr7clk);
- /* main_s2f_user1_clk divider */
- writel(main_cfg->cntr8clk_cnt,
&clock_manager_base->main_pll.cntr8clk);
- /* main_hmc_pll_clk divider */
- writel(main_cfg->cntr9clk_cnt |
(main_cfg->cntr9clk_src <<
CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB),
&clock_manager_base->main_pll.cntr9clk);
- /* main_periph_ref_clk divider */
- writel(main_cfg->cntr15clk_cnt,
&clock_manager_base->main_pll.cntr15clk);
- /* setup all the peripheral PLL counter and clock source */
- /* peri_emaca_clk divider */
- writel(per_cfg->cntr2clk_cnt |
(per_cfg->cntr2clk_src <<
CLKMGR_PERPLL_CNTR2CLK_SRC_LSB),
&clock_manager_base->per_pll.cntr2clk);
- /* peri_emacb_clk divider */
- writel(per_cfg->cntr3clk_cnt |
(per_cfg->cntr3clk_src <<
CLKMGR_PERPLL_CNTR3CLK_SRC_LSB),
&clock_manager_base->per_pll.cntr3clk);
- /* peri_emac_ptp_clk divider */
- writel(per_cfg->cntr4clk_cnt |
(per_cfg->cntr4clk_src <<
CLKMGR_PERPLL_CNTR4CLK_SRC_LSB),
&clock_manager_base->per_pll.cntr4clk);
- /* peri_gpio_db_clk divider */
- writel(per_cfg->cntr5clk_cnt |
(per_cfg->cntr5clk_src <<
CLKMGR_PERPLL_CNTR5CLK_SRC_LSB),
&clock_manager_base->per_pll.cntr5clk);
- /* peri_sdmmc_clk divider */
- writel(per_cfg->cntr6clk_cnt |
(per_cfg->cntr6clk_src <<
CLKMGR_PERPLL_CNTR6CLK_SRC_LSB),
&clock_manager_base->per_pll.cntr6clk);
- /* peri_s2f_user0_clk divider */
- writel(per_cfg->cntr7clk_cnt,
&clock_manager_base->per_pll.cntr7clk);
- /* peri_s2f_user1_clk divider */
- writel(per_cfg->cntr8clk_cnt |
(per_cfg->cntr8clk_src <<
CLKMGR_PERPLL_CNTR8CLK_SRC_LSB),
&clock_manager_base->per_pll.cntr8clk);
- /* peri_hmc_pll_clk divider */
- writel(per_cfg->cntr9clk_cnt,
&clock_manager_base->per_pll.cntr9clk);
- /* setup all the external PLL counter */
- /* mpu wrapper / external divider */
- writel(main_cfg->mpuclk_cnt |
(main_cfg->mpuclk_src <<
CLKMGR_MAINPLL_MPUCLK_SRC_LSB),
&clock_manager_base->main_pll.mpuclk);
- /* NOC wrapper / external divider */
- writel(main_cfg->nocclk_cnt |
(main_cfg->nocclk_src <<
CLKMGR_MAINPLL_NOCCLK_SRC_LSB),
&clock_manager_base->main_pll.nocclk);
- /* NOC subclock divider such as l4 */
- writel(main_cfg->nocdiv_l4mainclk |
(main_cfg->nocdiv_l4mpclk <<
CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) |
(main_cfg->nocdiv_l4spclk <<
CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB) |
(main_cfg->nocdiv_csatclk <<
CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB) |
(main_cfg->nocdiv_cstraceclk <<
CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB) |
(main_cfg->nocdiv_cspdbclk <<
CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB),
&clock_manager_base->main_pll.nocdiv);
- /* gpio_db external divider */
- writel(per_cfg->gpiodiv_gpiodbclk,
&clock_manager_base->per_pll.gpiodiv);
- /* setup the EMAC clock mux select */
- writel((per_cfg->emacctl_emac0sel <<
CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB) |
(per_cfg->emacctl_emac1sel <<
CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB) |
(per_cfg->emacctl_emac2sel <<
CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB),
&clock_manager_base->per_pll.emacctl);
- /* at this stage, check for PLL lock status */
- cm_wait_for_lock(LOCKED_MASK);
- /*
- * after locking, but before taking out of bypass,
- * assert/deassert outresetall
- */
- /* assert mainpll outresetall */
- setbits_le32(&clock_manager_base->main_pll.vco0,
CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
- /* assert perpll outresetall */
- setbits_le32(&clock_manager_base->per_pll.vco0,
CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
- /* de-assert mainpll outresetall */
- clrbits_le32(&clock_manager_base->main_pll.vco0,
CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
- /* de-assert perpll outresetall */
- clrbits_le32(&clock_manager_base->per_pll.vco0,
CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
- /* Take all PLLs out of bypass when boot mode is cleared. */
- /* release mainpll from bypass */
- writel(CLKMGR_MAINPLL_BYPASS_RESET,
&clock_manager_base->main_pll.bypassr);
- /* wait till Clock Manager is not busy */
- cm_wait_for_fsm();
- /* release perpll from bypass */
- writel(CLKMGR_PERPLL_BYPASS_RESET,
&clock_manager_base->per_pll.bypassr);
- /* wait till Clock Manager is not busy */
- cm_wait_for_fsm();
- /* clear boot mode */
- clrbits_le32(&clock_manager_base->ctrl,
CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK);
- /* wait till Clock Manager is not busy */
- cm_wait_for_fsm();
- /* At here, we need to ramp to final value if needed */
- if (pll_ramp_main_hz != 0)
cm_pll_ramp_main(main_cfg, per_cfg,
pll_ramp_main_hz);
- if (pll_ramp_periph_hz != 0)
cm_pll_ramp_periph(main_cfg, per_cfg,
pll_ramp_periph_hz);
- /* Now ungate non-hw-managed clocks */
- writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
&clock_manager_base->main_pll.ens);
- writel(CLKMGR_PERPLL_EN_RESET,
&clock_manager_base->per_pll.ens);
- /* Clear the loss lock and slip bits as they might set
during
- clock reconfiguration */
- writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK,
&clock_manager_base->intr);
- return 0;
+}
+int cm_basic_init(const void *blob) +{
- struct mainpll_cfg main_cfg;
- struct perpll_cfg per_cfg;
- struct alteragrp_cfg altrgrp_cfg;
- int rval;
- /* initialize to zero for use case of optional node */
- memset(&main_cfg, 0, sizeof(main_cfg));
- memset(&per_cfg, 0, sizeof(per_cfg));
- memset(&altrgrp_cfg, 0, sizeof(altrgrp_cfg));
- if (of_get_clk_cfg(blob, &main_cfg, &per_cfg, &altrgrp_cfg))
{
return 1;
- }
- rval = cm_full_cfg(&main_cfg, &per_cfg);
- cm_l4_main_clk_hz =
cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB
);
- cm_l4_mp_clk_hz =
cm_get_l4_noc_hz(CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB);
- cm_l4_sp_clk_hz = cm_get_l4_sp_clk_hz();
- cm_l4_sys_free_clk_hz = cm_get_noc_clk_hz()/4;
- return rval;
+} diff --git a/arch/arm/mach-socfpga/clock_manager_gen5.c b/arch/arm/mach-socfpga/clock_manager_gen5.c new file mode 100644 index 0000000..f4bb02b --- /dev/null +++ b/arch/arm/mach-socfpga/clock_manager_gen5.c @@ -0,0 +1,342 @@ +/*
- Copyright (C) 2016, Intel Corporation
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock_manager.h>
+DECLARE_GLOBAL_DATA_PTR;
+const unsigned int cm_get_osc_clk_hz(const int osc); +const unsigned int cm_get_f2s_per_ref_clk_hz(void); +const unsigned int cm_get_f2s_sdr_ref_clk_hz(void); +static void cm_write_bypass(uint32_t val); +static void cm_write_ctrl(uint32_t val); +static void cm_write_with_phase(uint32_t value,
- uint32_t reg_address, uint32_t mask);
+unsigned long cm_get_sdram_clk_hz(void); +int set_cpu_clk_info(void);
+static const struct socfpga_clock_manager *clock_manager_base =
- (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
+/*
- function to write the bypass register which requires a poll of
the
- busy bit
- */
+static void cm_write_bypass(uint32_t val) +{
- writel(val, &clock_manager_base->bypass);
- cm_wait_for_fsm();
+}
+/* function to write the ctrl register which requires a poll of the busy bit */ +static void cm_write_ctrl(uint32_t val) +{
- writel(val, &clock_manager_base->ctrl);
- cm_wait_for_fsm();
+}
+/* function to write a clock register that has phase information */ +static void cm_write_with_phase(uint32_t value,
uint32_t reg_address, uint32_t mask)
+{
- /* poll until phase is zero */
- while (readl(reg_address) & mask)
;
- writel(value, reg_address);
- while (readl(reg_address) & mask)
;
+}
+/*
- Setup clocks while making no assumptions about previous state of
the clocks.
- Start by being paranoid and gate all sw managed clocks
- Put all plls in bypass
- Put all plls VCO registers back to reset value (bandgap power
down).
- Put peripheral and main pll src to reset value to avoid glitch.
- Delay 5 us.
- Deassert bandgap power down and set numerator and denominator
- Start 7 us timer.
- set internal dividers
- Wait for 7 us timer.
- Enable plls
- Set external dividers while plls are locking
- Wait for pll lock
- Assert/deassert outreset all.
- Take all pll's out of bypass
- Clear safe mode
- set source main and peripheral clocks
- Ungate clocks
- */
+void cm_basic_init(const struct cm_config * const cfg) +{
- unsigned long end;
- /* Start by being paranoid and gate all sw managed clocks */
- /*
- * We need to disable nandclk
- * and then do another apb access before disabling
- * gatting off the rest of the periperal clocks.
- */
- writel(~CLKMGR_PERPLLGRP_EN_NANDCLK_MASK &
readl(&clock_manager_base->per_pll.en),
&clock_manager_base->per_pll.en);
- /* DO NOT GATE OFF DEBUG CLOCKS & BRIDGE CLOCKS */
- writel(CLKMGR_MAINPLLGRP_EN_DBGTIMERCLK_MASK |
CLKMGR_MAINPLLGRP_EN_DBGTRACECLK_MASK |
CLKMGR_MAINPLLGRP_EN_DBGCLK_MASK |
CLKMGR_MAINPLLGRP_EN_DBGATCLK_MASK |
CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK |
CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK,
&clock_manager_base->main_pll.en);
- writel(0, &clock_manager_base->sdr_pll.en);
- /* now we can gate off the rest of the peripheral clocks */
- writel(0, &clock_manager_base->per_pll.en);
- /* Put all plls in bypass */
- cm_write_bypass(CLKMGR_BYPASS_PERPLL | CLKMGR_BYPASS_SDRPLL
|
CLKMGR_BYPASS_MAINPLL);
- /* Put all plls VCO registers back to reset value. */
- writel(CLKMGR_MAINPLLGRP_VCO_RESET_VALUE &
- ~CLKMGR_MAINPLLGRP_VCO_REGEXTSEL_MASK,
- &clock_manager_base->main_pll.vco);
- writel(CLKMGR_PERPLLGRP_VCO_RESET_VALUE &
- ~CLKMGR_PERPLLGRP_VCO_REGEXTSEL_MASK,
- &clock_manager_base->per_pll.vco);
- writel(CLKMGR_SDRPLLGRP_VCO_RESET_VALUE &
- ~CLKMGR_SDRPLLGRP_VCO_REGEXTSEL_MASK,
- &clock_manager_base->sdr_pll.vco);
- /*
- * The clocks to the flash devices and the L4_MAIN clocks
can
- * glitch when coming out of safe mode if their source
values
- * are different from their reset value. So the trick it to
- * put them back to their reset state, and change input
- * after exiting safe mode but before ungating the clocks.
- */
- writel(CLKMGR_PERPLLGRP_SRC_RESET_VALUE,
- &clock_manager_base->per_pll.src);
- writel(CLKMGR_MAINPLLGRP_L4SRC_RESET_VALUE,
- &clock_manager_base->main_pll.l4src);
- /* read back for the required 5 us delay. */
- readl(&clock_manager_base->main_pll.vco);
- readl(&clock_manager_base->per_pll.vco);
- readl(&clock_manager_base->sdr_pll.vco);
- /*
- * We made sure bgpwr down was assert for 5 us. Now deassert
BG PWR DN
- * with numerator and denominator.
- */
- writel(cfg->main_vco_base, &clock_manager_base-
main_pll.vco);
- writel(cfg->peri_vco_base, &clock_manager_base-
per_pll.vco);
- writel(cfg->sdram_vco_base, &clock_manager_base-
sdr_pll.vco);
- /*
- * Time starts here. Must wait 7 us from
- * BGPWRDN_SET(0) to VCO_ENABLE_SET(1).
- */
- end = timer_get_us() + 7;
- /* main mpu */
- writel(cfg->mpuclk, &clock_manager_base->main_pll.mpuclk);
- /* main main clock */
- writel(cfg->mainclk, &clock_manager_base->main_pll.mainclk);
- /* main for dbg */
- writel(cfg->dbgatclk, &clock_manager_base-
main_pll.dbgatclk);
- /* main for cfgs2fuser0clk */
- writel(cfg->cfg2fuser0clk,
- &clock_manager_base->main_pll.cfgs2fuser0clk);
- /* Peri emac0 50 MHz default to RMII */
- writel(cfg->emac0clk, &clock_manager_base-
per_pll.emac0clk);
- /* Peri emac1 50 MHz default to RMII */
- writel(cfg->emac1clk, &clock_manager_base-
per_pll.emac1clk);
- /* Peri QSPI */
- writel(cfg->mainqspiclk, &clock_manager_base-
main_pll.mainqspiclk);
- writel(cfg->perqspiclk, &clock_manager_base-
per_pll.perqspiclk);
- /* Peri pernandsdmmcclk */
- writel(cfg->mainnandsdmmcclk,
- &clock_manager_base->main_pll.mainnandsdmmcclk);
- writel(cfg->pernandsdmmcclk,
- &clock_manager_base->per_pll.pernandsdmmcclk);
- /* Peri perbaseclk */
- writel(cfg->perbaseclk, &clock_manager_base-
per_pll.perbaseclk);
- /* Peri s2fuser1clk */
- writel(cfg->s2fuser1clk, &clock_manager_base-
per_pll.s2fuser1clk);
- /* 7 us must have elapsed before we can enable the VCO */
- while (timer_get_us() < end)
;
- /* Enable vco */
- /* main pll vco */
- writel(cfg->main_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->main_pll.vco);
- /* periferal pll */
- writel(cfg->peri_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->per_pll.vco);
- /* sdram pll vco */
- writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->sdr_pll.vco);
- /* L3 MP and L3 SP */
- writel(cfg->maindiv, &clock_manager_base->main_pll.maindiv);
- writel(cfg->dbgdiv, &clock_manager_base->main_pll.dbgdiv);
- writel(cfg->tracediv, &clock_manager_base-
main_pll.tracediv);
- /* L4 MP, L4 SP, can0, and can1 */
- writel(cfg->perdiv, &clock_manager_base->per_pll.div);
- writel(cfg->gpiodiv, &clock_manager_base->per_pll.gpiodiv);
- cm_wait_for_lock(LOCKED_MASK);
- /* write the sdram clock counters before toggling outreset
all */
- writel(cfg->ddrdqsclk & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK,
- &clock_manager_base->sdr_pll.ddrdqsclk);
- writel(cfg->ddr2xdqsclk &
CLKMGR_SDRPLLGRP_DDR2XDQSCLK_CNT_MASK,
- &clock_manager_base->sdr_pll.ddr2xdqsclk);
- writel(cfg->ddrdqclk & CLKMGR_SDRPLLGRP_DDRDQCLK_CNT_MASK,
- &clock_manager_base->sdr_pll.ddrdqclk);
- writel(cfg->s2fuser2clk &
CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK,
- &clock_manager_base->sdr_pll.s2fuser2clk);
- /*
- * after locking, but before taking out of bypass
- * assert/deassert outresetall
- */
- uint32_t mainvco = readl(&clock_manager_base->main_pll.vco);
- /* assert main outresetall */
- writel(mainvco | CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->main_pll.vco);
- uint32_t periphvco = readl(&clock_manager_base-
per_pll.vco);
- /* assert pheriph outresetall */
- writel(periphvco | CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->per_pll.vco);
- /* assert sdram outresetall */
- writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN|
CLKMGR_SDRPLLGRP_VCO_OUTRESETALL,
&clock_manager_base->sdr_pll.vco);
- /* deassert main outresetall */
- writel(mainvco & ~CLKMGR_MAINPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->main_pll.vco);
- /* deassert pheriph outresetall */
- writel(periphvco & ~CLKMGR_PERPLLGRP_VCO_OUTRESETALL_MASK,
- &clock_manager_base->per_pll.vco);
- /* deassert sdram outresetall */
- writel(cfg->sdram_vco_base | CLKMGR_MAINPLLGRP_VCO_EN,
- &clock_manager_base->sdr_pll.vco);
- /*
- * now that we've toggled outreset all, all the clocks
- * are aligned nicely; so we can change any phase.
- */
- cm_write_with_phase(cfg->ddrdqsclk,
(uint32_t)&clock_manager_base-
sdr_pll.ddrdqsclk,
CLKMGR_SDRPLLGRP_DDRDQSCLK_PHASE_MASK);
- /* SDRAM DDR2XDQSCLK */
- cm_write_with_phase(cfg->ddr2xdqsclk,
(uint32_t)&clock_manager_base-
sdr_pll.ddr2xdqsclk,
CLKMGR_SDRPLLGRP_DDR2XDQSCLK_PHASE_MASK)
;
- cm_write_with_phase(cfg->ddrdqclk,
(uint32_t)&clock_manager_base-
sdr_pll.ddrdqclk,
CLKMGR_SDRPLLGRP_DDRDQCLK_PHASE_MASK);
- cm_write_with_phase(cfg->s2fuser2clk,
(uint32_t)&clock_manager_base-
sdr_pll.s2fuser2clk,
CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK)
;
- /* Take all three PLLs out of bypass when safe mode is
cleared. */
- cm_write_bypass(0);
- /* clear safe mode */
- cm_write_ctrl(readl(&clock_manager_base->ctrl) |
CLKMGR_CTRL_SAFEMODE);
- /*
- * now that safe mode is clear with clocks gated
- * it safe to change the source mux for the flashes the the
L4_MAIN
- */
- writel(cfg->persrc, &clock_manager_base->per_pll.src);
- writel(cfg->l4src, &clock_manager_base->main_pll.l4src);
- /* Now ungate non-hw-managed clocks */
- writel(~0, &clock_manager_base->main_pll.en);
- writel(~0, &clock_manager_base->per_pll.en);
- writel(~0, &clock_manager_base->sdr_pll.en);
- /* Clear the loss of lock bits (write 1 to clear) */
- writel(CLKMGR_INTER_SDRPLLLOST_MASK |
CLKMGR_INTER_PERPLLLOST_MASK |
- CLKMGR_INTER_MAINPLLLOST_MASK,
- &clock_manager_base->inter);
+}
+unsigned long cm_get_sdram_clk_hz(void) +{
- uint32_t reg, clock = 0;
- /* identify SDRAM PLL clock source */
- reg = readl(&clock_manager_base->sdr_pll.vco);
- reg = (reg & CLKMGR_SDRPLLGRP_VCO_SSRC_MASK) >>
- CLKMGR_SDRPLLGRP_VCO_SSRC_OFFSET;
- if (reg == CLKMGR_VCO_SSRC_EOSC1)
clock = cm_get_osc_clk_hz(1);
- else if (reg == CLKMGR_VCO_SSRC_EOSC2)
clock = cm_get_osc_clk_hz(2);
- else if (reg == CLKMGR_VCO_SSRC_F2S)
clock = cm_get_f2s_sdr_ref_clk_hz();
- /* get the SDRAM VCO clock */
- reg = readl(&clock_manager_base->sdr_pll.vco);
- clock /= ((reg & CLKMGR_SDRPLLGRP_VCO_DENOM_MASK) >>
CLKMGR_SDRPLLGRP_VCO_DENOM_OFFSET) + 1;
- clock *= ((reg & CLKMGR_SDRPLLGRP_VCO_NUMER_MASK) >>
CLKMGR_SDRPLLGRP_VCO_NUMER_OFFSET) + 1;
- /* get the SDRAM (DDR_DQS) clock */
- reg = readl(&clock_manager_base->sdr_pll.ddrdqsclk);
- reg = (reg & CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_MASK) >>
- CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_OFFSET;
- clock /= (reg + 1);
- return clock;
+} diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h index 2675951..aa401dc 100644 --- a/arch/arm/mach-socfpga/include/mach/clock_manager.h +++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h @@ -1,28 +1,16 @@ /*
- * Copyright (C) 2013 Altera Corporation <www.altera.com>
- * Copyright (C) 2013-2016 Altera Corporation <www.altera.com>
*
- SPDX-License-Identifier: GPL-2.0+
- SPDX-License-Identifier: GPL-2.0
*/ #ifndef _CLOCK_MANAGER_H_ #define _CLOCK_MANAGER_H_ #ifndef __ASSEMBLER__ -/* Clock speed accessors */ -unsigned long cm_get_mpu_clk_hz(void); -unsigned long cm_get_sdram_clk_hz(void); -unsigned int cm_get_l4_sp_clk_hz(void); -unsigned int cm_get_mmc_controller_clk_hz(void); -unsigned int cm_get_qspi_controller_clk_hz(void); -unsigned int cm_get_spi_controller_clk_hz(void); -const unsigned int cm_get_osc_clk_hz(const int osc); -const unsigned int cm_get_f2s_per_ref_clk_hz(void); -const unsigned int cm_get_f2s_sdr_ref_clk_hz(void);
-/* Clock configuration accessors */ -const struct cm_config * const cm_get_default_config(void); -#endif +#include <linux/types.h> +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) struct cm_config { /* main group */ uint32_t main_vco_base; @@ -57,74 +45,196 @@ struct cm_config { uint32_t s2fuser2clk; }; -void cm_basic_init(const struct cm_config * const cfg); +struct socfpga_clock_manager_sdr_pll {
- volatile uint32_t vco;
- volatile uint32_t ctrl;
- volatile uint32_t ddrdqsclk;
- volatile uint32_t ddr2xdqsclk;
- volatile uint32_t ddrdqclk;
- volatile uint32_t s2fuser2clk;
- volatile uint32_t en;
- volatile uint32_t stat;
+}; +#endif
+/* Common prototypes */ +extern unsigned int cm_get_l4_sp_clk_hz(void); +extern unsigned int cm_get_qspi_controller_clk_hz(void); +extern unsigned int cm_get_mmc_controller_clk_hz(void); +extern unsigned int cm_get_spi_controller_clk_hz(void); +extern void cm_use_intosc(void); +extern void cm_wait_for_lock(uint32_t mask); +extern void cm_wait_for_fsm(void); +extern unsigned int cm_get_main_vco_clk_hz(void); +extern unsigned int cm_get_per_vco_clk_hz(void); +extern unsigned long cm_get_mpu_clk_hz(void); +#if defined(CONFIG_TARGET_SOCFPGA_GEN5) +/* Clock speed accessors */ +extern const unsigned int cm_get_osc_clk_hz(const int osc); +extern const unsigned int cm_get_f2s_per_ref_clk_hz(void); +extern const unsigned int cm_get_f2s_sdr_ref_clk_hz(void); +extern void cm_basic_init(const struct cm_config * const cfg); +extern unsigned long cm_get_sdram_clk_hz(void); +/* Clock configuration accessors */ +extern const struct cm_config * const cm_get_default_config(void); +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) +extern unsigned int cm_get_noc_clk_hz(void); +extern unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift); +extern int cm_basic_init(const void* blob); +extern unsigned int cm_l4_main_clk_hz; +extern unsigned int cm_l4_sp_clk_hz; +extern unsigned int cm_l4_mp_clk_hz; +extern unsigned int cm_l4_sys_free_clk_hz; +extern uint32_t eosc1_hz; +extern uint32_t cb_intosc_hz; +extern uint32_t f2s_free_hz; +#endif +#endif struct socfpga_clock_manager_main_pll {
- u32 vco;
- u32 misc;
- u32 mpuclk;
- u32 mainclk;
- u32 dbgatclk;
- u32 mainqspiclk;
- u32 mainnandsdmmcclk;
- u32 cfgs2fuser0clk;
- u32 en;
- u32 maindiv;
- u32 dbgdiv;
- u32 tracediv;
- u32 l4src;
- u32 stat;
- u32 _pad_0x38_0x40[2];
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- volatile uint32_t vco;
- volatile uint32_t misc;
- volatile uint32_t mpuclk;
- volatile uint32_t mainclk;
- volatile uint32_t dbgatclk;
- volatile uint32_t mainqspiclk;
- volatile uint32_t mainnandsdmmcclk;
- volatile uint32_t cfgs2fuser0clk;
- volatile uint32_t en;
- volatile uint32_t maindiv;
- volatile uint32_t dbgdiv;
- volatile uint32_t tracediv;
- volatile uint32_t l4src;
- volatile uint32_t stat;
- volatile uint32_t _pad_0x38_0x40[2];
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- uint32_t vco0;
- uint32_t vco1;
- uint32_t en;
- uint32_t ens;
- uint32_t enr;
- uint32_t bypass;
- uint32_t bypasss;
- uint32_t bypassr;
- uint32_t mpuclk;
- uint32_t nocclk;
- uint32_t cntr2clk;
- uint32_t cntr3clk;
- uint32_t cntr4clk;
- uint32_t cntr5clk;
- uint32_t cntr6clk;
- uint32_t cntr7clk;
- uint32_t cntr8clk;
- uint32_t cntr9clk;
- uint32_t pad_0x48_0x5b[5];
- uint32_t cntr15clk;
- uint32_t outrst;
- uint32_t outrststat;
- uint32_t nocdiv;
- uint32_t pad_0x6c_0x80[5];
+#endif }; struct socfpga_clock_manager_per_pll {
- u32 vco;
- u32 misc;
- u32 emac0clk;
- u32 emac1clk;
- u32 perqspiclk;
- u32 pernandsdmmcclk;
- u32 perbaseclk;
- u32 s2fuser1clk;
- u32 en;
- u32 div;
- u32 gpiodiv;
- u32 src;
- u32 stat;
- u32 _pad_0x34_0x40[3];
-};
-struct socfpga_clock_manager_sdr_pll {
- u32 vco;
- u32 ctrl;
- u32 ddrdqsclk;
- u32 ddr2xdqsclk;
- u32 ddrdqclk;
- u32 s2fuser2clk;
- u32 en;
- u32 stat;
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- volatile uint32_t vco;
- volatile uint32_t misc;
- volatile uint32_t emac0clk;
- volatile uint32_t emac1clk;
- volatile uint32_t perqspiclk;
- volatile uint32_t pernandsdmmcclk;
- volatile uint32_t perbaseclk;
- volatile uint32_t s2fuser1clk;
- volatile uint32_t en;
- volatile uint32_t div;
- volatile uint32_t gpiodiv;
- volatile uint32_t src;
- volatile uint32_t stat;
- volatile uint32_t _pad_0x34_0x40[3];
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- volatile uint32_t vco0;
- volatile uint32_t vco1;
- volatile uint32_t en;
- volatile uint32_t ens;
- volatile uint32_t enr;
- volatile uint32_t bypass;
- volatile uint32_t bypasss;
- volatile uint32_t bypassr;
- volatile uint32_t pad_0x20_0x27[2];
- volatile uint32_t cntr2clk;
- volatile uint32_t cntr3clk;
- volatile uint32_t cntr4clk;
- volatile uint32_t cntr5clk;
- volatile uint32_t cntr6clk;
- volatile uint32_t cntr7clk;
- volatile uint32_t cntr8clk;
- volatile uint32_t cntr9clk;
- volatile uint32_t pad_0x48_0x5f[6];
- volatile uint32_t outrst;
- volatile uint32_t outrststat;
- volatile uint32_t emacctl;
- volatile uint32_t gpiodiv;
- volatile uint32_t pad_0x70_0x80[4];
+#endif }; struct socfpga_clock_manager_altera {
- u32 mpuclk;
- u32 mainclk;
- volatile uint32_t mpuclk;
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- volatile uint32_t mainclk;
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- volatile uint32_t nocclk;
- volatile uint32_t mainmisc0;
- volatile uint32_t mainmisc1;
- volatile uint32_t perimisc0;
- volatile uint32_t perimisc1;
+#endif }; struct socfpga_clock_manager {
- u32 ctrl;
- u32 bypass;
- u32 inter;
- u32 intren;
- u32 dbctrl;
- u32 stat;
- u32 _pad_0x18_0x3f[10];
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
- volatile uint32_t ctrl;
- volatile uint32_t bypass;
- volatile uint32_t inter;
- volatile uint32_t intren;
- volatile uint32_t dbctrl;
- volatile uint32_t stat;
- volatile uint32_t _pad_0x18_0x3f[10];
struct socfpga_clock_manager_main_pll main_pll; struct socfpga_clock_manager_per_pll per_pll; struct socfpga_clock_manager_sdr_pll sdr_pll; struct socfpga_clock_manager_altera altera;
- u32 _pad_0xe8_0x200[70];
- volatile uint32_t _pad_0xe8_0x200[70];
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
- /* clkmgr */
- volatile uint32_t ctrl;
- volatile uint32_t intr;
- volatile uint32_t intrs;
- volatile uint32_t intrr;
- volatile uint32_t intren;
- volatile uint32_t intrens;
- volatile uint32_t intrenr;
- volatile uint32_t stat;
- volatile uint32_t testioctrl;
- volatile uint32_t _pad_0x24_0x40[7];
- /* mainpllgrp */
- struct socfpga_clock_manager_main_pll main_pll;
- /* perpllgrp */
- struct socfpga_clock_manager_per_pll per_pll;
- struct socfpga_clock_manager_altera altera;
+#endif }; +/* Common mask */ +#define CLKMGR_CLKMGR_STAT_BUSY_SET_MSK 0x000 00001
+#if defined(CONFIG_TARGET_SOCFPGA_GEN5) +#define LOCKED_MASK \
- (CLKMGR_INTER_SDRPLLLOCKED_MASK | \
- CLKMGR_INTER_PERPLLLOCKED_MASK | \
- CLKMGR_INTER_MAINPLLLOCKED_MASK)
#define CLKMGR_CTRL_SAFEMODE (1 << 0) #define CLKMGR_CTRL_SAFEMODE_OFFSET 0 @@ -310,5 +420,119 @@ struct socfpga_clock_manager { #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_CNT_MASK 0x00000 1ff #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_OFFSET 9 #define CLKMGR_SDRPLLGRP_S2FUSER2CLK_PHASE_MASK 0x000 00e00
+#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10) +#define CLKMGR_ALTERAGRP_MPU_CLK_OFFSET 0x140 +#define CLKMGR_MAINPLL_NOC_CLK_OFFSET 0x144 +#define LOCKED_MASK \
- (CLKMGR_CLKMGR_STAT_MAINPLLLOCKED_SET_MSK | \
- CLKMGR_CLKMGR_STAT_PERPLLLOCKED_SET_MSK)
+/* value */ +#define CLKMGR_MAINPLL_BYPASS_RESET 0x0000003 f +#define CLKMGR_PERPLL_BYPASS_RESET 0x000000ff +#define CLKMGR_MAINPLL_VCO0_RESET 0x00010053 +#define CLKMGR_MAINPLL_VCO1_RESET 0x00010001 +#define CLKMGR_PERPLL_VCO0_RESET 0x00010053 +#define CLKMGR_PERPLL_VCO1_RESET 0x00010001 +#define CLKMGR_MAINPLL_VCO0_PSRC_EOSC 0x0 +#define CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC 0x1 +#define CLKMGR_MAINPLL_VCO0_PSRC_F2S 0x2 +#define CLKMGR_PERPLL_VCO0_PSRC_EOSC 0x0 +#define CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC 0x1 +#define CLKMGR_PERPLL_VCO0_PSRC_F2S 0x2 +#define CLKMGR_PERPLL_VCO0_PSRC_MAIN 0x3
+/* mask */ +#define CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK 0x000 00040 +#define CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK 0x00000080 +#define CLKMGR_CLKMGR_STAT_MAINPLLLOCKED_SET_MSK 0x00000100 +#define CLKMGR_CLKMGR_STAT_PERPLLLOCKED_SET_MSK 0x000 00200 +#define CLKMGR_CLKMGR_STAT_BOOTCLKSRC_SET_MSK 0x00020 000 +#define CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK 0x0000000 1 +#define CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK 0x00000002 +#define CLKMGR_MAINPLL_VCO0_EN_SET_MSK 0x0000 0004 +#define CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK 0x00000 008 +#define CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK 0x00000 010 +#define CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK 0x00000001 +#define CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK 0x00000002 +#define CLKMGR_PERPLL_VCO0_EN_SET_MSK 0x00000 004 +#define CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK 0x000000 08 +#define CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK 0x000000 10 +#define CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK 0x000 00800 +#define CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK 0x00000400 +#define CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK 0x000 00200 +#define CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK 0x00000100 +#define CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK 0x00000 008 +#define CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK 0x0000 0004 +#define CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK 0x00000001 +#define CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK 0x00000002 +#define CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK 0x00000001 +#define CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK 0x00000300 +#define CLKMGR_PERPLL_EN_RESET 0x0000 0f7f +#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK 0x00000020 +#define CLKMGR_MAINPLL_VCO0_PSRC_MSK 0x000000 03 +#define CLKMGR_MAINPLL_VCO1_NUMER_MSK 0x00001 fff +#define CLKMGR_MAINPLL_VCO1_DENOM_MSK 0x00000 03f +#define CLKMGR_MAINPLL_CNTRCLK_MSK 0x000003ff +#define CLKMGR_PERPLL_VCO0_PSRC_MSK 0x0000000 3 +#define CLKMGR_PERPLL_VCO1_NUMER_MSK 0x00001f ff +#define CLKMGR_PERPLL_VCO1_DENOM_MSK 0x000000 3f +#define CLKMGR_PERPLL_CNTRCLK_MSK 0x000003ff +#define CLKMGR_MAINPLL_MPUCLK_SRC_MSK 0x00000 007 +#define CLKMGR_MAINPLL_MPUCLK_CNT_MSK 0x00000 3ff +#define CLKMGR_MAINPLL_MPUCLK_SRC_MAIN 0 +#define CLKMGR_MAINPLL_MPUCLK_SRC_PERI 1 +#define CLKMGR_MAINPLL_MPUCLK_SRC_OSC1 2 +#define CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC 3 +#define CLKMGR_MAINPLL_MPUCLK_SRC_FPGA 4 +#define CLKMGR_MAINPLL_NOCDIV_MSK 0x00000003 +#define CLKMGR_MAINPLL_NOCCLK_CNT_MSK 0x00000 3ff +#define CLKMGR_MAINPLL_NOCCLK_SRC_MSK 0x00000 007 +#define CLKMGR_MAINPLL_NOCCLK_SRC_MAIN 0 +#define CLKMGR_MAINPLL_NOCCLK_SRC_PERI 1 +#define CLKMGR_MAINPLL_NOCCLK_SRC_OSC1 2 +#define CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC 3 +#define CLKMGR_MAINPLL_NOCCLK_SRC_FPGA 4
+#define CLKMGR_PERPLLGRP_SRC_MSK 0x00000007 +#define CLKMGR_PERPLLGRP_SRC_MAIN 0 +#define CLKMGR_PERPLLGRP_SRC_PERI 1 +#define CLKMGR_PERPLLGRP_SRC_OSC1 2 +#define CLKMGR_PERPLLGRP_SRC_INTOSC 3 +#define CLKMGR_PERPLLGRP_SRC_FPGA 4
+/* bit shifting macro */ +#define CLKMGR_MAINPLL_VCO0_PSRC_LSB 8 +#define CLKMGR_PERPLL_VCO0_PSRC_LSB 8 +#define CLKMGR_MAINPLL_VCO1_DENOM_LSB 16 +#define CLKMGR_PERPLL_VCO1_DENOM_LSB 16 +#define CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB 16 +#define CLKMGR_MAINPLL_NOCCLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_NOCDIV_L4MAINCLK_LSB 0 +#define CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB 8 +#define CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB 16 +#define CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB 24 +#define CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB 26 +#define CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB 28 +#define CLKMGR_MAINPLL_MPUCLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB 16 +#define CLKMGR_MAINPLL_NOCCLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB 16 +#define CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR2CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR3CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR4CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR5CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR6CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_CNTR8CLK_SRC_LSB 16 +#define CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB 26 +#define CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB 27 +#define CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB 28
+/* PLL ramping work around */ +#define CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ 900000000 +#define CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ 300000000 +#define CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ 100000000 +#define CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ 33000000 +#endif #endif /* _CLOCK_MANAGER_H_ */
participants (2)
-
Chee Tien Fong
-
Chee, Tien Fong