[U-Boot] [PATCH v4 25/28] arm: socfpga: arria10: Added drivers for Arria10 clock manager
Marek Vasut
marex at denx.de
Mon Jan 23 05:18:37 CET 2017
On 01/10/2017 06:20 AM, Chee Tien Fong wrote:
> From: Tien Fong Chee <tien.fong.chee at intel.com>
>
> The drivers is restructured such common functions, gen5 functions, and
> arria10 functions are moved to clock_manager.c, clock_manager_gen5 and
> clock_manager_arria10 respectively.
>
> Signed-off-by: Tien Fong Chee <tien.fong.chee at intel.com>
> Cc: Marek Vasut <marex at denx.de>
> Cc: Dinh Nguyen <dingnuyen at kernel.org>
> Cc: Ching Liang See <chin.liang.see at intel.com>
> Cc: Tien Fong <skywindctf at gmail.com>
> ---
> arch/arm/mach-socfpga/clock_manager.c | 752 +++++++---------
> arch/arm/mach-socfpga/clock_manager_arria10.c | 954 +++++++++++++++++++++
> .../{clock_manager.c => clock_manager_gen5.c} | 240 +-----
> arch/arm/mach-socfpga/include/mach/clock_manager.h | 356 ++++++--
> 4 files changed, 1573 insertions(+), 729 deletions(-)
> create mode 100644 arch/arm/mach-socfpga/clock_manager_arria10.c
> copy arch/arm/mach-socfpga/{clock_manager.c => clock_manager_gen5.c} (62%)
>
> diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c
> index aa71636..d209f7d 100644
> --- a/arch/arm/mach-socfpga/clock_manager.c
> +++ b/arch/arm/mach-socfpga/clock_manager.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (C) 2013 Altera Corporation <www.altera.com>
> + * Copyright (C) 2013-2016 Altera Corporation <www.altera.com>
> *
> * SPDX-License-Identifier: GPL-2.0+
> */
> @@ -7,416 +7,287 @@
> #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;
What ? This cannot work ...
> +#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
You might want to consider separate clock manager for A10 and Gen5 to
avoid the massive ifdeffery.
> -/*
> - * 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.c b/arch/arm/mach-socfpga/clock_manager_gen5.c
> similarity index 62%
> copy from arch/arm/mach-socfpga/clock_manager.c
> copy to arch/arm/mach-socfpga/clock_manager_gen5.c
> index aa71636..f4bb02b 100644
> --- a/arch/arm/mach-socfpga/clock_manager.c
> +++ b/arch/arm/mach-socfpga/clock_manager_gen5.c
> @@ -1,7 +1,7 @@
> /*
> - * Copyright (C) 2013 Altera Corporation <www.altera.com>
> + * Copyright (C) 2016, Intel Corporation
> *
> - * SPDX-License-Identifier: GPL-2.0+
> + * SPDX-License-Identifier: GPL-2.0
> */
>
> #include <common.h>
> @@ -10,31 +10,19 @@
>
> 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;
>
> -static void cm_wait_for_lock(uint32_t mask)
> -{
> - 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);
> -}
> -
> -/* function to poll in the fsm busy bit */
> -static void cm_wait_for_fsm(void)
> -{
> - while (readl(&clock_manager_base->stat) & CLKMGR_STAT_BUSY)
> - ;
> -}
> -
> /*
> * function to write the bypass register which requires a poll of the
> * busy bit
> @@ -87,7 +75,6 @@ static void cm_write_with_phase(uint32_t value,
> * set source main and peripheral clocks
> * Ungate clocks
> */
> -
> void cm_basic_init(const struct cm_config * const cfg)
> {
> unsigned long end;
> @@ -230,11 +217,6 @@ void cm_basic_init(const struct cm_config * const cfg)
>
> 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 */
> @@ -328,60 +310,6 @@ void cm_basic_init(const struct cm_config * const cfg)
> &clock_manager_base->inter);
> }
>
> -static unsigned int cm_get_main_vco_clk_hz(void)
> -{
> - uint32_t reg, clock;
> -
> - /* 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;
> -}
> -
> -unsigned long cm_get_mpu_clk_hz(void)
> -{
> - uint32_t reg, clock;
> -
> - clock = cm_get_main_vco_clk_hz();
> -
> - /* 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;
> -}
> -
> unsigned long cm_get_sdram_clk_hz(void)
> {
> uint32_t reg, clock = 0;
> @@ -412,147 +340,3 @@ unsigned long cm_get_sdram_clk_hz(void)
>
> return clock;
> }
> -
> -unsigned int cm_get_l4_sp_clk_hz(void)
> -{
> - uint32_t reg, clock = 0;
> -
> - /* identify the source of L4 SP clock */
> - reg = readl(&clock_manager_base->main_pll.l4src);
> - reg = (reg & CLKMGR_MAINPLLGRP_L4SRC_L4SP) >>
> - CLKMGR_MAINPLLGRP_L4SRC_L4SP_OFFSET;
> -
> - if (reg == CLKMGR_L4_SP_CLK_SRC_MAINPLL) {
> - clock = cm_get_main_vco_clk_hz();
> -
> - /* get the clock prior L4 SP divider (main clk) */
> - reg = readl(&clock_manager_base->altera.mainclk);
> - clock /= (reg + 1);
> - reg = readl(&clock_manager_base->main_pll.mainclk);
> - clock /= (reg + 1);
> - } else if (reg == CLKMGR_L4_SP_CLK_SRC_PERPLL) {
> - 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);
> - }
> -
> - /* get the L4 SP clock which supplied to UART */
> - reg = readl(&clock_manager_base->main_pll.maindiv);
> - reg = (reg & CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_MASK) >>
> - CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_OFFSET;
> - clock = clock / (1 << reg);
> -
> - return clock;
> -}
> -
> -unsigned int cm_get_mmc_controller_clk_hz(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;
> -}
> -
> -unsigned int cm_get_qspi_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;
> -
> - 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 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();
> -
> - /* get the qspi clock */
> - reg = readl(&clock_manager_base->per_pll.perqspiclk);
> - clock /= (reg + 1);
> - }
> -
> - 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;
> -}
> -
> -static void cm_print_clock_quick_summary(void)
> -{
> - printf("MPU %10ld kHz\n", cm_get_mpu_clk_hz() / 1000);
> - 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;
> -}
> -
> -int do_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> -{
> - cm_print_clock_quick_summary();
> - return 0;
> -}
> -
> -U_BOOT_CMD(
> - clocks, CONFIG_SYS_MAXARGS, 1, do_showclocks,
> - "display clocks",
> - ""
> -);
> diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h
> index 2675951..45943ea 100644
> --- a/arch/arm/mach-socfpga/include/mach/clock_manager.h
> +++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (C) 2013 Altera Corporation <www.altera.com>
> + * Copyright (C) 2013-2016 Altera Corporation <www.altera.com>
> *
> * SPDX-License-Identifier: GPL-2.0+
> */
> @@ -8,21 +8,9 @@
> #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;
> };
>
> +struct socfpga_clock_manager_sdr_pll {
> + uint32_t vco;
> + uint32_t ctrl;
> + uint32_t ddrdqsclk;
> + uint32_t ddr2xdqsclk;
> + uint32_t ddrdqclk;
> + uint32_t s2fuser2clk;
> + uint32_t en;
> + uint32_t stat;
> +};
> +#endif
> +
> +/* 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);
> +void cm_use_intosc(void);
> +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);
> +#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
> +/* Clock speed accessors */
> +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);
> void cm_basic_init(const struct cm_config * const cfg);
> +unsigned long cm_get_sdram_clk_hz(void);
> +/* Clock configuration accessors */
> +const struct cm_config * const cm_get_default_config(void);
> +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
> +unsigned int cm_get_noc_clk_hz(void);
> +unsigned int cm_get_l4_noc_hz(unsigned int nocdivshift);
> +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)
> + uint32_t vco;
> + uint32_t misc;
> + uint32_t mpuclk;
> + uint32_t mainclk;
> + uint32_t dbgatclk;
> + uint32_t mainqspiclk;
> + uint32_t mainnandsdmmcclk;
> + uint32_t cfgs2fuser0clk;
> + uint32_t en;
> + uint32_t maindiv;
> + uint32_t dbgdiv;
> + uint32_t tracediv;
> + uint32_t l4src;
> + uint32_t stat;
> + 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)
> + uint32_t vco;
> + uint32_t misc;
> + uint32_t emac0clk;
> + uint32_t emac1clk;
> + uint32_t perqspiclk;
> + uint32_t pernandsdmmcclk;
> + uint32_t perbaseclk;
> + uint32_t s2fuser1clk;
> + uint32_t en;
> + uint32_t div;
> + uint32_t gpiodiv;
> + uint32_t src;
> + uint32_t stat;
> + uint32_t _pad_0x34_0x40[3];
> +#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 pad_0x20_0x27[2];
> + 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_0x5f[6];
> + uint32_t outrst;
> + uint32_t outrststat;
> + uint32_t emacctl;
> + uint32_t gpiodiv;
> + uint32_t pad_0x70_0x80[4];
> +#endif
> };
>
> struct socfpga_clock_manager_altera {
> - u32 mpuclk;
> - u32 mainclk;
> + uint32_t mpuclk;
> +#if defined(CONFIG_TARGET_SOCFPGA_GEN5)
> + uint32_t mainclk;
> +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
> + uint32_t nocclk;
> + uint32_t mainmisc0;
> + uint32_t mainmisc1;
> + uint32_t perimisc0;
> + 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)
> + uint32_t ctrl;
> + uint32_t bypass;
> + uint32_t inter;
> + uint32_t intren;
> + uint32_t dbctrl;
> + uint32_t stat;
> + 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];
> + uint32_t _pad_0xe8_0x200[70];
> +#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
> + /* clkmgr */
> + uint32_t ctrl;
> + uint32_t intr;
> + uint32_t intrs;
> + uint32_t intrr;
> + uint32_t intren;
> + uint32_t intrens;
> + uint32_t intrenr;
> + uint32_t stat;
> + uint32_t testioctrl;
> + 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_ */
>
--
Best regards,
Marek Vasut
More information about the U-Boot
mailing list