[U-Boot] [PATCH v2 02/14] arm: socfpga: stratix10: Add Clock Manager driver for Stratix10 SoC
Dinh Nguyen
dinh.linux at gmail.com
Tue Oct 10 20:23:39 UTC 2017
On Thu, Oct 5, 2017 at 8:07 AM, <chin.liang.see at intel.com> wrote:
> From: Chin Liang See <chin.liang.see at intel.com>
>
> Add Clock Manager driver support for Stratix SoC
>
> Signed-off-by: Chin Liang See <chin.liang.see at intel.com>
> --
> Changes in v2
> - Declared defines for constant value used
> - Fixed spacing and comments
> ---
> arch/arm/mach-socfpga/Makefile | 4 +
> arch/arm/mach-socfpga/clock_manager.c | 4 +-
> arch/arm/mach-socfpga/clock_manager_s10.c | 355 +++++++++++++++++++++
> arch/arm/mach-socfpga/include/mach/clock_manager.h | 2 +
> .../mach-socfpga/include/mach/clock_manager_s10.h | 210 ++++++++++++
> arch/arm/mach-socfpga/include/mach/handoff_s10.h | 29 ++
> arch/arm/mach-socfpga/wrap_pll_config_s10.c | 44 +++
> 7 files changed, 646 insertions(+), 2 deletions(-)
> create mode 100644 arch/arm/mach-socfpga/clock_manager_s10.c
> create mode 100644 arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
> create mode 100644 arch/arm/mach-socfpga/include/mach/handoff_s10.h
> create mode 100644 arch/arm/mach-socfpga/wrap_pll_config_s10.c
>
> diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
> index 286bfef..e5f9dd7 100644
> --- a/arch/arm/mach-socfpga/Makefile
> +++ b/arch/arm/mach-socfpga/Makefile
> @@ -30,6 +30,10 @@ obj-y += pinmux_arria10.o
> obj-y += reset_manager_arria10.o
> endif
>
> +ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
> +obj-y += clock_manager_s10.o
> +obj-y += wrap_pll_config_s10.o
> +endif
> ifdef CONFIG_SPL_BUILD
> obj-y += spl.o
> ifdef CONFIG_TARGET_SOCFPGA_GEN5
> diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c
> index cb6ae03..f9450a4 100644
> --- a/arch/arm/mach-socfpga/clock_manager.c
> +++ b/arch/arm/mach-socfpga/clock_manager.c
> @@ -21,7 +21,7 @@ void cm_wait_for_lock(u32 mask)
> do {
> #if defined(CONFIG_TARGET_SOCFPGA_GEN5)
> inter_val = readl(&clock_manager_base->inter) & mask;
> -#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
> +#else
> inter_val = readl(&clock_manager_base->stat) & mask;
> #endif
> /* Wait for stable lock */
> @@ -52,7 +52,7 @@ int set_cpu_clk_info(void)
>
> #if defined(CONFIG_TARGET_SOCFPGA_GEN5)
> gd->bd->bi_ddr_freq = cm_get_sdram_clk_hz() / 1000000;
> -#elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
> +#else
> gd->bd->bi_ddr_freq = 0;
> #endif
>
> diff --git a/arch/arm/mach-socfpga/clock_manager_s10.c b/arch/arm/mach-socfpga/clock_manager_s10.c
> new file mode 100644
> index 0000000..cfb6708
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/clock_manager_s10.c
> @@ -0,0 +1,355 @@
> +/*
> + * Copyright (C) 2016-2017 Intel Corporation <www.intel.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock_manager.h>
> +#include <asm/arch/handoff_s10.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +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_mainpll(uint32_t val)
> +{
> + writel(val, &clock_manager_base->main_pll.bypass);
> + cm_wait_for_fsm();
> +}
> +
> +static void cm_write_bypass_perpll(uint32_t val)
> +{
> + writel(val, &clock_manager_base->per_pll.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();
> +}
> +
> +/*
> + * Setup clocks while making no assumptions about previous state of the clocks.
> + */
> +void cm_basic_init(const struct cm_config * const cfg)
> +{
> + uint32_t mdiv, refclkdiv, mscnt, hscnt, vcocalib;
> +
> + if (cfg == 0)
> + return;
> +
> + /* Put all plls in bypass */
> + cm_write_bypass_mainpll(CLKMGR_BYPASS_MAINPLL_ALL);
> + cm_write_bypass_perpll(CLKMGR_BYPASS_PERPLL_ALL);
> +
> + /* setup main PLL dividers where calculate the vcocalib value */
> + mdiv = (cfg->main_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
> + CLKMGR_FDBCK_MDIV_MASK;
> + refclkdiv = (cfg->main_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
> + CLKMGR_PLLGLOB_REFCLKDIV_MASK;
> + mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
> + hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
> + CLKMGR_HSCNT_CONST;
> + vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
> + ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
> + CLKMGR_VCOCALIB_MSCNT_OFFSET);
> +
> + writel((cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
> + ~CLKMGR_PLLGLOB_RST_MASK),
> + &clock_manager_base->main_pll.pllglob);
> + writel(cfg->main_pll_fdbck, &clock_manager_base->main_pll.fdbck);
> + writel(vcocalib, &clock_manager_base->main_pll.vcocalib);
> + writel(cfg->main_pll_pllc0, &clock_manager_base->main_pll.pllc0);
> + writel(cfg->main_pll_pllc1, &clock_manager_base->main_pll.pllc1);
> + writel(cfg->main_pll_nocdiv, &clock_manager_base->main_pll.nocdiv);
> +
> + /* setup peripheral PLL dividers */
> + /* calculate the vcocalib value */
> + mdiv = (cfg->per_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
> + CLKMGR_FDBCK_MDIV_MASK;
> + refclkdiv = (cfg->per_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
> + CLKMGR_PLLGLOB_REFCLKDIV_MASK;
> + mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
> + hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
> + CLKMGR_HSCNT_CONST;
> + vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
> + ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
> + CLKMGR_VCOCALIB_MSCNT_OFFSET);
> +
> + writel((cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
> + ~CLKMGR_PLLGLOB_RST_MASK),
> + &clock_manager_base->per_pll.pllglob);
> + writel(cfg->per_pll_fdbck, &clock_manager_base->per_pll.fdbck);
> + writel(vcocalib, &clock_manager_base->per_pll.vcocalib);
> + writel(cfg->per_pll_pllc0, &clock_manager_base->per_pll.pllc0);
> + writel(cfg->per_pll_pllc1, &clock_manager_base->per_pll.pllc1);
> + writel(cfg->per_pll_emacctl, &clock_manager_base->per_pll.emacctl);
> + writel(cfg->per_pll_gpiodiv, &clock_manager_base->per_pll.gpiodiv);
> +
> + /* Take both PLL out of reset and power up */
> + setbits_le32(&clock_manager_base->main_pll.pllglob,
> + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
> + setbits_le32(&clock_manager_base->per_pll.pllglob,
> + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
> +
> +#define LOCKED_MASK \
> + (CLKMGR_STAT_MAINPLL_LOCKED | \
> + CLKMGR_STAT_PERPLL_LOCKED)
> +
> + cm_wait_for_lock(LOCKED_MASK);
> +
> + /*
> + * Dividers for C2 to C9 only init after PLLs are lock. As dividers
> + * only take effect upon value change, we shall set a maximum value as
> + * default value.
> + */
> + writel(0xff, &clock_manager_base->main_pll.mpuclk);
> + writel(0xff, &clock_manager_base->main_pll.nocclk);
> + writel(0xff, &clock_manager_base->main_pll.cntr2clk);
> + writel(0xff, &clock_manager_base->main_pll.cntr3clk);
> + writel(0xff, &clock_manager_base->main_pll.cntr4clk);
> + writel(0xff, &clock_manager_base->main_pll.cntr5clk);
> + writel(0xff, &clock_manager_base->main_pll.cntr6clk);
> + writel(0xff, &clock_manager_base->main_pll.cntr7clk);
> + writel(0xff, &clock_manager_base->main_pll.cntr8clk);
> + writel(0xff, &clock_manager_base->main_pll.cntr9clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr2clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr3clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr4clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr5clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr6clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr7clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr8clk);
> + writel(0xff, &clock_manager_base->per_pll.cntr9clk);
> +
> + writel(cfg->main_pll_mpuclk, &clock_manager_base->main_pll.mpuclk);
> + writel(cfg->main_pll_nocclk, &clock_manager_base->main_pll.nocclk);
> + writel(cfg->main_pll_cntr2clk, &clock_manager_base->main_pll.cntr2clk);
> + writel(cfg->main_pll_cntr3clk, &clock_manager_base->main_pll.cntr3clk);
> + writel(cfg->main_pll_cntr4clk, &clock_manager_base->main_pll.cntr4clk);
> + writel(cfg->main_pll_cntr5clk, &clock_manager_base->main_pll.cntr5clk);
> + writel(cfg->main_pll_cntr6clk, &clock_manager_base->main_pll.cntr6clk);
> + writel(cfg->main_pll_cntr7clk, &clock_manager_base->main_pll.cntr7clk);
> + writel(cfg->main_pll_cntr8clk, &clock_manager_base->main_pll.cntr8clk);
> + writel(cfg->main_pll_cntr9clk, &clock_manager_base->main_pll.cntr9clk);
> + writel(cfg->per_pll_cntr2clk, &clock_manager_base->per_pll.cntr2clk);
> + writel(cfg->per_pll_cntr3clk, &clock_manager_base->per_pll.cntr3clk);
> + writel(cfg->per_pll_cntr4clk, &clock_manager_base->per_pll.cntr4clk);
> + writel(cfg->per_pll_cntr5clk, &clock_manager_base->per_pll.cntr5clk);
> + writel(cfg->per_pll_cntr6clk, &clock_manager_base->per_pll.cntr6clk);
> + writel(cfg->per_pll_cntr7clk, &clock_manager_base->per_pll.cntr7clk);
> + writel(cfg->per_pll_cntr8clk, &clock_manager_base->per_pll.cntr8clk);
> + writel(cfg->per_pll_cntr9clk, &clock_manager_base->per_pll.cntr9clk);
> +
> + /* Take all PLLs out of bypass */
> + cm_write_bypass_mainpll(0);
> + cm_write_bypass_perpll(0);
> +
> + /* clear safe mode / out of boot mode */
> + cm_write_ctrl(readl(&clock_manager_base->ctrl)
> + & ~(CLKMGR_CTRL_SAFEMODE));
> +
> + /* Now ungate non-hw-managed clocks */
> + writel(~0, &clock_manager_base->main_pll.en);
> + writel(~0, &clock_manager_base->per_pll.en);
> +
> + /* Clear the loss of lock bits (write 1 to clear) */
> + writel(CLKMGR_INTER_PERPLLLOST_MASK | CLKMGR_INTER_MAINPLLLOST_MASK,
> + &clock_manager_base->intrclr);
> +}
> +
> +static unsigned long cm_get_main_vco_clk_hz(void)
> +{
> + unsigned long fref, refdiv, mdiv, reg, vco;
> +
> + reg = readl(&clock_manager_base->main_pll.pllglob);
> +
> + fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
> + CLKMGR_PLLGLOB_VCO_PSRC_MASK;
> + switch (fref) {
> + case CLKMGR_VCO_PSRC_EOSC1:
> + fref = cm_get_osc_clk_hz(0);
> + break;
> + case CLKMGR_VCO_PSRC_INTOSC:
> + fref = cm_get_intosc_clk_hz();
> + break;
> + case CLKMGR_VCO_PSRC_F2S:
> + fref = cm_get_fpga_clk_hz();
> + break;
> + }
> +
> + refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
> + CLKMGR_PLLGLOB_REFCLKDIV_MASK;
> +
> + reg = readl(&clock_manager_base->main_pll.fdbck);
> + mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
> +
> + vco = fref / refdiv;
> + vco = vco * (CLKMGR_MDIV_CONST + mdiv);
> + return vco;
> +}
> +
> +static unsigned long cm_get_per_vco_clk_hz(void)
> +{
> + unsigned long fref, refdiv, mdiv, reg, vco;
> +
> + reg = readl(&clock_manager_base->per_pll.pllglob);
> +
> + fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
> + CLKMGR_PLLGLOB_VCO_PSRC_MASK;
> + switch (fref) {
> + case CLKMGR_VCO_PSRC_EOSC1:
> + fref = cm_get_osc_clk_hz(0);
> + break;
> + case CLKMGR_VCO_PSRC_INTOSC:
> + fref = cm_get_intosc_clk_hz();
> + break;
> + case CLKMGR_VCO_PSRC_F2S:
> + fref = cm_get_fpga_clk_hz();
> + break;
> + }
> +
> + refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
> + CLKMGR_PLLGLOB_REFCLKDIV_MASK;
> +
> + reg = readl(&clock_manager_base->per_pll.fdbck);
> + mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
> +
> + vco = fref / refdiv;
> + vco = vco * (CLKMGR_MDIV_CONST + mdiv);
> + return vco;
> +}
> +
> +unsigned long cm_get_mpu_clk_hz(void)
> +{
> + unsigned long clock = readl(&clock_manager_base->main_pll.mpuclk);
> + clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
> +
> + switch (clock) {
> + case CLKMGR_CLKSRC_MAIN:
> + clock = cm_get_main_vco_clk_hz();
> + clock /= (readl(&clock_manager_base->main_pll.pllc0) &
> + CLKMGR_PLLC0_DIV_MASK);
> + break;
> +
> + case CLKMGR_CLKSRC_PER:
> + clock = cm_get_per_vco_clk_hz();
> + clock /= (readl(&clock_manager_base->per_pll.pllc0) &
> + CLKMGR_CLKCNT_MSK);
> + break;
> +
> + case CLKMGR_CLKSRC_OSC1:
> + clock = cm_get_osc_clk_hz(0);
> + break;
> +
> + case CLKMGR_CLKSRC_INTOSC:
> + clock = cm_get_intosc_clk_hz();
> + break;
> +
> + case CLKMGR_CLKSRC_FPGA:
> + clock = cm_get_fpga_clk_hz();
> + break;
> + }
> +
> + clock /= 1 + (readl(&clock_manager_base->main_pll.mpuclk) &
> + CLKMGR_CLKCNT_MSK);
> + return clock;
> +}
> +
> +unsigned int cm_get_l3_main_clk_hz(void)
> +{
> + uint32_t clock = readl(&clock_manager_base->main_pll.nocclk);
> + clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
> +
> + switch (clock) {
> + case CLKMGR_CLKSRC_MAIN:
> + clock = cm_get_main_vco_clk_hz();
> + clock /= (readl(&clock_manager_base->main_pll.pllc1) &
> + CLKMGR_PLLC0_DIV_MASK);
> + break;
> +
> + case CLKMGR_CLKSRC_PER:
> + clock = cm_get_per_vco_clk_hz();
> + clock /= (readl(&clock_manager_base->per_pll.pllc1) &
> + CLKMGR_CLKCNT_MSK);
> + break;
> +
> + case CLKMGR_CLKSRC_OSC1:
> + clock = cm_get_osc_clk_hz(0);
> + break;
> +
> + case CLKMGR_CLKSRC_INTOSC:
> + clock = cm_get_intosc_clk_hz();
> + break;
> +
> + case CLKMGR_CLKSRC_FPGA:
> + clock = cm_get_fpga_clk_hz();
> + break;
> + }
> +
> + clock /= 1 + (readl(&clock_manager_base->main_pll.nocclk) &
> + CLKMGR_CLKCNT_MSK);
> + return clock;
> +}
> +
> +unsigned int cm_get_mmc_controller_clk_hz(void)
> +{
> + uint32_t clock = readl(&clock_manager_base->per_pll.cntr6clk);
> + clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
> +
> + switch (clock) {
> + case CLKMGR_CLKSRC_MAIN:
> + clock = cm_get_l3_main_clk_hz();
> + clock /= 1 + (readl(&clock_manager_base->main_pll.cntr6clk) &
> + CLKMGR_CLKCNT_MSK);
> + break;
> +
> + case CLKMGR_CLKSRC_PER:
> + clock = cm_get_l3_main_clk_hz();
> + clock /= 1 + (readl(&clock_manager_base->per_pll.cntr6clk) &
> + CLKMGR_CLKCNT_MSK);
> + break;
> +
> + case CLKMGR_CLKSRC_OSC1:
> + clock = cm_get_osc_clk_hz(0);
> + break;
> +
> + case CLKMGR_CLKSRC_INTOSC:
> + clock = cm_get_intosc_clk_hz();
> + break;
> +
> + case CLKMGR_CLKSRC_FPGA:
> + clock = cm_get_fpga_clk_hz();
> + break;
> + }
> + return clock / 4;
> +}
> +
> +unsigned int cm_get_l4_sp_clk_hz(void)
> +{
> + uint32_t clock = cm_get_l3_main_clk_hz();
> +
> + clock /= (1 << ((readl(&clock_manager_base->main_pll.nocdiv) >>
> + CLKMGR_NOCDIV_L4SPCLK_OFFSET) & CLKMGR_CLKCNT_MSK));
> + return clock;
> +}
> +
> +void cm_print_clock_quick_summary(void)
> +{
> + printf("MPU %d kHz\n", (u32)(cm_get_mpu_clk_hz() / 1000));
> + printf("L3 main %d kHz\n", cm_get_l3_main_clk_hz() / 1000);
> + printf("Main VCO %d kHz\n", (u32)(cm_get_main_vco_clk_hz() / 1000));
> + printf("Per VCO %d kHz\n", (u32)(cm_get_per_vco_clk_hz() / 1000));
> + printf("EOSC1 %d kHz\n", cm_get_osc_clk_hz(0) / 1000);
> + printf("HPS MMC %d kHz\n", cm_get_mmc_controller_clk_hz() / 1000);
> + printf("UART %d kHz\n", cm_get_l4_sp_clk_hz() / 1000);
> +}
> diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h
> index 4c6b1f8..ddf814f 100644
> --- a/arch/arm/mach-socfpga/include/mach/clock_manager.h
> +++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h
> @@ -17,6 +17,8 @@ void cm_print_clock_quick_summary(void);
> #include <asm/arch/clock_manager_gen5.h>
> #elif defined(CONFIG_TARGET_SOCFPGA_ARRIA10)
> #include <asm/arch/clock_manager_arria10.h>
> +#elif defined(CONFIG_TARGET_SOCFPGA_STRATIX10)
> +#include <asm/arch/clock_manager_s10.h>
> #endif
>
> #endif /* _CLOCK_MANAGER_H_ */
> diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
> new file mode 100644
> index 0000000..831cf2c
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
> @@ -0,0 +1,210 @@
> +/*
> + * Copyright (C) 2016-2017 Intel Corporation <www.intel.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#ifndef _CLOCK_MANAGER_S10_
> +#define _CLOCK_MANAGER_S10_
> +
> +/* 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);
> +const unsigned int cm_get_intosc_clk_hz(void);
> +const unsigned int cm_get_fpga_clk_hz(void);
> +
> +#define CLKMGR_EOSC1_HZ 25000000
> +#define CLKMGR_INTOSC_HZ 460000000
> +#define CLKMGR_FPGA_CLK_HZ 50000000
> +
> +/* Clock configuration accessors */
> +const struct cm_config * const cm_get_default_config(void);
> +
> +struct cm_config {
> + /* main group */
> + uint32_t main_pll_mpuclk;
> + uint32_t main_pll_nocclk;
> + uint32_t main_pll_cntr2clk;
> + uint32_t main_pll_cntr3clk;
> + uint32_t main_pll_cntr4clk;
> + uint32_t main_pll_cntr5clk;
> + uint32_t main_pll_cntr6clk;
> + uint32_t main_pll_cntr7clk;
> + uint32_t main_pll_cntr8clk;
> + uint32_t main_pll_cntr9clk;
> + uint32_t main_pll_nocdiv;
> + uint32_t main_pll_pllglob;
> + uint32_t main_pll_fdbck;
> + uint32_t main_pll_pllc0;
> + uint32_t main_pll_pllc1;
> + uint32_t spare;
> +
> + /* peripheral group */
> + uint32_t per_pll_cntr2clk;
> + uint32_t per_pll_cntr3clk;
> + uint32_t per_pll_cntr4clk;
> + uint32_t per_pll_cntr5clk;
> + uint32_t per_pll_cntr6clk;
> + uint32_t per_pll_cntr7clk;
> + uint32_t per_pll_cntr8clk;
> + uint32_t per_pll_cntr9clk;
> + uint32_t per_pll_emacctl;
> + uint32_t per_pll_gpiodiv;
> + uint32_t per_pll_pllglob;
> + uint32_t per_pll_fdbck;
> + uint32_t per_pll_pllc0;
> + uint32_t per_pll_pllc1;
> +
> + /* incoming clock */
> + uint32_t hps_osc_clk_hz;
> + uint32_t fpga_clk_hz;
> +};
> +
> +void cm_basic_init(const struct cm_config * const cfg);
> +
> +struct socfpga_clock_manager_main_pll {
> + u32 en;
> + u32 ens;
> + u32 enr;
> + u32 bypass;
> + u32 bypasss;
> + u32 bypassr;
> + u32 mpuclk;
> + u32 nocclk;
> + u32 cntr2clk;
> + u32 cntr3clk;
> + u32 cntr4clk;
> + u32 cntr5clk;
> + u32 cntr6clk;
> + u32 cntr7clk;
> + u32 cntr8clk;
> + u32 cntr9clk;
> + u32 nocdiv;
> + u32 pllglob;
> + u32 fdbck;
> + u32 mem;
> + u32 memstat;
> + u32 pllc0;
> + u32 pllc1;
> + u32 vcocalib;
> + u32 _pad_0x90_0xA0[5];
> +};
> +
> +struct socfpga_clock_manager_per_pll {
> + u32 en;
> + u32 ens;
> + u32 enr;
> + u32 bypass;
> + u32 bypasss;
> + u32 bypassr;
> + u32 cntr2clk;
> + u32 cntr3clk;
> + u32 cntr4clk;
> + u32 cntr5clk;
> + u32 cntr6clk;
> + u32 cntr7clk;
> + u32 cntr8clk;
> + u32 cntr9clk;
> + u32 emacctl;
> + u32 gpiodiv;
> + u32 pllglob;
> + u32 fdbck;
> + u32 mem;
> + u32 memstat;
> + u32 pllc0;
> + u32 pllc1;
> + u32 vcocalib;
> + u32 _pad_0x100_0x124[10];
> +};
> +
> +struct socfpga_clock_manager {
> + u32 ctrl;
> + u32 stat;
> + u32 testioctrl;
> + u32 intrgen;
> + u32 intrmsk;
> + u32 intrclr;
> + u32 intrsts;
> + u32 intrstk;
> + u32 intrraw;
> + u32 _pad_0x24_0x2c[3];
> + struct socfpga_clock_manager_main_pll main_pll;
> + struct socfpga_clock_manager_per_pll per_pll;
> +};
> +
> +#define CLKMGR_CTRL_SAFEMODE (1 << 0)
> +#define CLKMGR_BYPASS_MAINPLL_ALL 0x00000007
> +#define CLKMGR_BYPASS_PERPLL_ALL 0x0000007f
> +
> +#define CLKMGR_INTER_MAINPLLLOCKED_MASK 0x00000001
> +#define CLKMGR_INTER_PERPLLLOCKED_MASK 0x00000002
> +#define CLKMGR_INTER_MAINPLLLOST_MASK 0x00000004
> +#define CLKMGR_INTER_PERPLLLOST_MASK 0x00000008
> +#define CLKMGR_STAT_BUSY (1 << 0)
> +#define CLKMGR_STAT_MAINPLL_LOCKED (1 << 8)
> +#define CLKMGR_STAT_PERPLL_LOCKED (1 << 9)
> +
> +#define CLKMGR_PLLGLOB_PD_MASK 0x00000001
> +#define CLKMGR_PLLGLOB_RST_MASK 0x00000002
> +#define CLKMGR_PLLGLOB_VCO_PSRC_MASK 0X3
> +#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET 16
> +#define CLKMGR_VCO_PSRC_EOSC1 0
> +#define CLKMGR_VCO_PSRC_INTOSC 1
> +#define CLKMGR_VCO_PSRC_F2S 2
> +#define CLKMGR_PLLGLOB_REFCLKDIV_MASK 0X3f
> +#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET 8
> +
> +#define CLKMGR_CLKSRC_MASK 0x7
> +#define CLKMGR_CLKSRC_OFFSET 16
> +#define CLKMGR_CLKSRC_MAIN 0
> +#define CLKMGR_CLKSRC_PER 1
> +#define CLKMGR_CLKSRC_OSC1 2
> +#define CLKMGR_CLKSRC_INTOSC 3
> +#define CLKMGR_CLKSRC_FPGA 4
> +#define CLKMGR_CLKCNT_MSK 0x7ff
> +
> +#define CLKMGR_FDBCK_MDIV_MASK 0xff
> +#define CLKMGR_FDBCK_MDIV_OFFSET 24
> +
> +#define CLKMGR_PLLC0_DIV_MASK 0xff
> +#define CLKMGR_PLLC1_DIV_MASK 0xff
> +#define CLKMGR_PLLC0_EN_OFFSET 27
> +#define CLKMGR_PLLC1_EN_OFFSET 24
> +
> +#define CLKMGR_NOCDIV_L4MAIN_OFFSET 0
> +#define CLKMGR_NOCDIV_L4MPCLK_OFFSET 8
> +#define CLKMGR_NOCDIV_L4SPCLK_OFFSET 16
> +#define CLKMGR_NOCDIV_CSATCLK_OFFSET 24
> +#define CLKMGR_NOCDIV_CSTRACECLK_OFFSET 26
> +#define CLKMGR_NOCDIV_CSPDBGCLK_OFFSET 28
> +
> +#define CLKMGR_NOCDIV_L4SPCLK_MASK 0X3
> +#define CLKMGR_NOCDIV_DIV1 0
> +#define CLKMGR_NOCDIV_DIV2 1
> +#define CLKMGR_NOCDIV_DIV4 2
> +#define CLKMGR_NOCDIV_DIV8 3
> +#define CLKMGR_CSPDBGCLK_DIV1 0
> +#define CLKMGR_CSPDBGCLK_DIV4 1
> +
> +#define CLKMGR_MSCNT_CONST 200
> +#define CLKMGR_MDIV_CONST 6
> +#define CLKMGR_HSCNT_CONST 9
> +
> +#define CLKMGR_VCOCALIB_MSCNT_MASK 0xff
> +#define CLKMGR_VCOCALIB_MSCNT_OFFSET 9
> +#define CLKMGR_VCOCALIB_HSCNT_MASK 0xff
> +
> +#define CLKMGR_EMACCTL_EMAC0SEL_OFFSET 26
> +#define CLKMGR_EMACCTL_EMAC1SEL_OFFSET 27
> +#define CLKMGR_EMACCTL_EMAC2SEL_OFFSET 28
> +
> +#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK 0x00000020
> +
> +#endif /* _CLOCK_MANAGER_S10_ */
> diff --git a/arch/arm/mach-socfpga/include/mach/handoff_s10.h b/arch/arm/mach-socfpga/include/mach/handoff_s10.h
> new file mode 100644
> index 0000000..d4b89ac
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/include/mach/handoff_s10.h
> @@ -0,0 +1,29 @@
> +/*
> + * Copyright (C) 2017 Intel Corporation <www.intel.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#ifndef _HANDOFF_S10_H_
> +#define _HANDOFF_S10_H_
> +
> +/*
> + * Offset for HW handoff from Quartus tools
> + */
> +#define CONFIG_HANDOFF_BASE 0xFFE3F000
> +#define CONFIG_HANDOFF_MUX (CONFIG_HANDOFF_BASE + 0x10)
> +#define CONFIG_HANDOFF_IOCTL (CONFIG_HANDOFF_BASE + 0x1A0)
> +#define CONFIG_HANDOFF_FPGA (CONFIG_HANDOFF_BASE + 0x330)
> +#define CONFIG_HANODFF_DELAY (CONFIG_HANDOFF_BASE + 0x3F0)
> +#define CONFIG_HANDOFF_CLOCK (CONFIG_HANDOFF_BASE + 0x580)
> +#define CONFIG_HANDOFF_MISC (CONFIG_HANDOFF_BASE + 0x610)
> +#define CONFIG_HANDOFF_MAGIC_MUX 0x504D5558
> +#define CONFIG_HANDOFF_MAGIC_IOCTL 0x494F4354
> +#define CONFIG_HANDOFF_MAGIC_FPGA 0x46504741
> +#define CONFIG_HANDOFF_MAGIC_DELAY 0x444C4159
> +#define CONFIG_HANDOFF_MAGIC_CLOCK 0x434C4B53
> +#define CONFIG_HANDOFF_MAGIC_MISC 0x4D495343
> +#define CONFIG_HANDOFF_OFFSET_LENGTH 0x4
> +#define CONFIG_HANDOFF_OFFSET_DATA 0x10
> +
> +#endif /* _HANDOFF_S10_H_ */
> diff --git a/arch/arm/mach-socfpga/wrap_pll_config_s10.c b/arch/arm/mach-socfpga/wrap_pll_config_s10.c
> new file mode 100644
> index 0000000..3f19534
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/wrap_pll_config_s10.c
> @@ -0,0 +1,44 @@
> +/*
> + * Copyright (C) 2016-2017 Intel Corporation <www.intel.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0
> + */
> +
> +#include <common.h>
> +#include <asm/arch/clock_manager.h>
> +#include <asm/io.h>
> +#include <asm/arch/handoff_s10.h>
> +
> +const struct cm_config * const cm_get_default_config(void)
> +{
> + struct cm_config *cm_handoff_cfg = (struct cm_config *)
> + (CONFIG_HANDOFF_CLOCK + CONFIG_HANDOFF_OFFSET_DATA);
> + u32 *conversion = (u32 *)cm_handoff_cfg;
> + u32 i;
> +
> + if (swab32(readl(CONFIG_HANDOFF_CLOCK)) == CONFIG_HANDOFF_MAGIC_CLOCK) {
> + writel(swab32(readl(CONFIG_HANDOFF_CLOCK)),
> + CONFIG_HANDOFF_CLOCK);
> + for (i = 0; i < (sizeof(*cm_handoff_cfg) / sizeof(u32)); i++)
> + conversion[i] = swab32(conversion[i]);
> + return cm_handoff_cfg;
> + } else if (readl(CONFIG_HANDOFF_CLOCK) == CONFIG_HANDOFF_MAGIC_CLOCK) {
> + return cm_handoff_cfg;
> + } else
the above code doesn't really read well. Can you do something like this?
handoff_clk = readl(CONFIG_HANDOFF_CLOCK);
if (swab32(handoff_clk) == CONFIG_HANDOFF_MAGIC_CLOCK) {
writel(swab32(handoff_clk);
for...
} else if (handoff_clk == CONFIG_HANDOFF_MAGIC_CLOCK)
return cm_handoff_cfg;
return 0;
> + return 0;
> +}
> +
> +const unsigned int cm_get_osc_clk_hz(const int osc)
What's "osc" used for?
Dinh
More information about the U-Boot
mailing list