diff mbox series

[U-Boot,03/14] arm: socfpga: stratix10: Add Clock Manager driver for Stratix10 SoC

Message ID 1505812951-25088-4-git-send-email-chin.liang.see@intel.com
State Superseded
Delegated to: Marek Vasut
Headers show
Series Enable Stratix10 SoC support | expand

Commit Message

See, Chin Liang Sept. 19, 2017, 9:22 a.m. UTC
From: Chin Liang See <chin.liang.see@intel.com>

Add Clock Manager driver support for Stratix SoC

Signed-off-by: Chin Liang See <chin.liang.see@intel.com>
---
 arch/arm/mach-socfpga/Makefile                     |   4 +
 arch/arm/mach-socfpga/clock_manager.c              |   4 +-
 arch/arm/mach-socfpga/clock_manager_s10.c          | 359 +++++++++++++++++++++
 arch/arm/mach-socfpga/include/mach/clock_manager.h |   2 +
 .../mach-socfpga/include/mach/clock_manager_s10.h  | 202 ++++++++++++
 arch/arm/mach-socfpga/include/mach/handoff_s10.h   |  29 ++
 arch/arm/mach-socfpga/wrap_pll_config_s10.c        |  46 +++
 7 files changed, 644 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

Comments

Dinh Nguyen Sept. 26, 2017, 10:04 p.m. UTC | #1
On Tue, Sep 19, 2017 at 4:22 AM,  <chin.liang.see@intel.com> wrote:
> From: Chin Liang See <chin.liang.see@intel.com>
>
> Add Clock Manager driver support for Stratix SoC
>
> Signed-off-by: Chin Liang See <chin.liang.see@intel.com>
> ---
>  arch/arm/mach-socfpga/Makefile                     |   4 +
>  arch/arm/mach-socfpga/clock_manager.c              |   4 +-
>  arch/arm/mach-socfpga/clock_manager_s10.c          | 359 +++++++++++++++++++++
>  arch/arm/mach-socfpga/include/mach/clock_manager.h |   2 +
>  .../mach-socfpga/include/mach/clock_manager_s10.h  | 202 ++++++++++++
>  arch/arm/mach-socfpga/include/mach/handoff_s10.h   |  29 ++
>  arch/arm/mach-socfpga/wrap_pll_config_s10.c        |  46 +++
>  7 files changed, 644 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..a9f9b07
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/clock_manager_s10.c
> @@ -0,0 +1,359 @@
> +/*
> + * 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();
> +}

Add a new line..

> +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.
> + *

Remove extra line

> + */
> +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 */
> +       /* calculate the vcocalib value */

Move the above comment to where vcocalib is getting calculated, or remove.

> +       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 = 200 / (6 + mdiv) / refclkdiv;

Where are these values, 200 and 6 coming from? Should they be a #define?

> +       hscnt = (mdiv + 6) * mscnt / refclkdiv - 9;

Same for 6 and 9 here...

> +       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 = 200 / (6 + mdiv) / refclkdiv;
> +       hscnt = (mdiv + 6) * mscnt / refclkdiv - 9;
> +       vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
> +                  ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
> +                  CLKMGR_VCOCALIB_MSCNT_OFFSET);

Same comments as above...

> +
> +       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. We will a large
> +        * dividers value then final value as requested by hardware behaviour

Can you update this comment? I don't understand what "We will a large" means.

> +        */
> +       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);
> +
> +       /* get the fref */

Useless comment...

> +       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;
> +       }
> +
> +       /* get the refdiv */

same..

> +       refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
> +                 CLKMGR_PLLGLOB_REFCLKDIV_MASK;
> +
> +       /* get the mdiv */

same...

> +       reg = readl(&clock_manager_base->main_pll.fdbck);
> +       mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
> +
> +       vco = fref / refdiv;
> +       vco = vco * (6 + mdiv);

Why 6? Define?

> +       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);
> +
> +       /* get the fref */
> +       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;
> +       }
> +
> +       /* get the refdiv */
> +       refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
> +                 CLKMGR_PLLGLOB_REFCLKDIV_MASK;
> +
> +       /* get the mdiv */
> +       reg = readl(&clock_manager_base->per_pll.fdbck);
> +       mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
> +
> +       vco = fref / refdiv;
> +       vco = vco * (6 + 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;

Need space between '/'.

> +}
> +
> +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..c99ad97
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
> @@ -0,0 +1,202 @@
> +/*
> + * 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);
> +
> +/* 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_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..2a624d5
> --- /dev/null
> +++ b/arch/arm/mach-socfpga/wrap_pll_config_s10.c
> @@ -0,0 +1,46 @@
> +/*
> + * 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
> +               return 0;
> +}
> +
> +const unsigned int cm_get_osc_clk_hz(const int osc)
> +{
> +       return 25000000;

Needs to be a #define

> +}
> +
> +const unsigned int cm_get_intosc_clk_hz(void)
> +{
> +       /* theory maximum internal osc clock */
> +       return 460000000;

Same...

> +}
> +
> +const unsigned int cm_get_fpga_clk_hz(void)
> +{
> +       /* assuming 50MHz */
> +       return 50000000;

Same..

Dinh
See, Chin Liang Sept. 29, 2017, 12:58 p.m. UTC | #2
On Tue, 2017-09-26 at 17:04 -0500, Dinh Nguyen wrote:
> On Tue, Sep 19, 2017 at 4:22 AM,  <chin.liang.see@intel.com> wrote:

> > 

> > From: Chin Liang See <chin.liang.see@intel.com>

> > 

> > Add Clock Manager driver support for Stratix SoC

> > 

> > Signed-off-by: Chin Liang See <chin.liang.see@intel.com>

> > ---

> >  arch/arm/mach-socfpga/Makefile                     |   4 +

> >  arch/arm/mach-socfpga/clock_manager.c              |   4 +-

> >  arch/arm/mach-socfpga/clock_manager_s10.c          | 359

> > +++++++++++++++++++++

> >  arch/arm/mach-socfpga/include/mach/clock_manager.h |   2 +

> >  .../mach-socfpga/include/mach/clock_manager_s10.h  | 202

> > ++++++++++++

> >  arch/arm/mach-socfpga/include/mach/handoff_s10.h   |  29 ++

> >  arch/arm/mach-socfpga/wrap_pll_config_s10.c        |  46 +++

> >  7 files changed, 644 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..a9f9b07

> > --- /dev/null

> > +++ b/arch/arm/mach-socfpga/clock_manager_s10.c

> > @@ -0,0 +1,359 @@

> > +/*

> > + * 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();

> > +}

> Add a new line..

> 

> > 

> > +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.

> > + *

> Remove extra line

> 

> > 

> > + */

> > +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 */

> > +       /* calculate the vcocalib value */

> Move the above comment to where vcocalib is getting calculated, or

> remove.

> 

> > 

> > +       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 = 200 / (6 + mdiv) / refclkdiv;

> Where are these values, 200 and 6 coming from? Should they be a

> #define?

> 


Yes, I can improve the readaibility here.

> > 

> > +       hscnt = (mdiv + 6) * mscnt / refclkdiv - 9;

> Same for 6 and 9 here...

> 

> > 

> > +       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 = 200 / (6 + mdiv) / refclkdiv;

> > +       hscnt = (mdiv + 6) * mscnt / refclkdiv - 9;

> > +       vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |

> > +                  ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<

> > +                  CLKMGR_VCOCALIB_MSCNT_OFFSET);

> Same comments as above...

> 

> > 

> > +

> > +       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. We

> > will a large

> > +        * dividers value then final value as requested by hardware

> > behaviour

> Can you update this comment? I don't understand what "We will a

> large" means.


Let me rephrase to why instead how.

Chin Liang

> 

> > 

> > +        */

> > +       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);

> > +

> > +       /* get the fref */

> Useless comment...

> 

> > 

> > +       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;

> > +       }

> > +

> > +       /* get the refdiv */

> same..

> 

> > 

> > +       refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &

> > +                 CLKMGR_PLLGLOB_REFCLKDIV_MASK;

> > +

> > +       /* get the mdiv */

> same...

> 

> > 

> > +       reg = readl(&clock_manager_base->main_pll.fdbck);

> > +       mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) &

> > CLKMGR_FDBCK_MDIV_MASK;

> > +

> > +       vco = fref / refdiv;

> > +       vco = vco * (6 + mdiv);

> Why 6? Define?

> 

> > 

> > +       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);

> > +

> > +       /* get the fref */

> > +       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;

> > +       }

> > +

> > +       /* get the refdiv */

> > +       refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &

> > +                 CLKMGR_PLLGLOB_REFCLKDIV_MASK;

> > +

> > +       /* get the mdiv */

> > +       reg = readl(&clock_manager_base->per_pll.fdbck);

> > +       mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) &

> > CLKMGR_FDBCK_MDIV_MASK;

> > +

> > +       vco = fref / refdiv;

> > +       vco = vco * (6 + 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;

> Need space between '/'.

> 

> > 

> > +}

> > +

> > +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..c99ad97

> > --- /dev/null

> > +++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h

> > @@ -0,0 +1,202 @@

> > +/*

> > + * 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);

> > +

> > +/* 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_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..2a624d5

> > --- /dev/null

> > +++ b/arch/arm/mach-socfpga/wrap_pll_config_s10.c

> > @@ -0,0 +1,46 @@

> > +/*

> > + * 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

> > +               return 0;

> > +}

> > +

> > +const unsigned int cm_get_osc_clk_hz(const int osc)

> > +{

> > +       return 25000000;

> Needs to be a #define

> 

> > 

> > +}

> > +

> > +const unsigned int cm_get_intosc_clk_hz(void)

> > +{

> > +       /* theory maximum internal osc clock */

> > +       return 460000000;

> Same...

> 

> > 

> > +}

> > +

> > +const unsigned int cm_get_fpga_clk_hz(void)

> > +{

> > +       /* assuming 50MHz */

> > +       return 50000000;

> Same..

> 

> Dinh
diff mbox series

Patch

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..a9f9b07
--- /dev/null
+++ b/arch/arm/mach-socfpga/clock_manager_s10.c
@@ -0,0 +1,359 @@ 
+/*
+ * 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 */
+	/* 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 = 200 / (6 + mdiv) / refclkdiv;
+	hscnt = (mdiv + 6) * mscnt / refclkdiv - 9;
+	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 = 200 / (6 + mdiv) / refclkdiv;
+	hscnt = (mdiv + 6) * mscnt / refclkdiv - 9;
+	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. We will a large
+	 * dividers value then final value as requested by hardware behaviour
+	 */
+	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);
+
+	/* get the fref */
+	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;
+	}
+
+	/* get the refdiv */
+	refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
+		  CLKMGR_PLLGLOB_REFCLKDIV_MASK;
+
+	/* get the mdiv */
+	reg = readl(&clock_manager_base->main_pll.fdbck);
+	mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
+
+	vco = fref / refdiv;
+	vco = vco * (6 + 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);
+
+	/* get the fref */
+	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;
+	}
+
+	/* get the refdiv */
+	refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
+		  CLKMGR_PLLGLOB_REFCLKDIV_MASK;
+
+	/* get the mdiv */
+	reg = readl(&clock_manager_base->per_pll.fdbck);
+	mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
+
+	vco = fref / refdiv;
+	vco = vco * (6 + 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..c99ad97
--- /dev/null
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h
@@ -0,0 +1,202 @@ 
+/*
+ * 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);
+
+/* 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_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..2a624d5
--- /dev/null
+++ b/arch/arm/mach-socfpga/wrap_pll_config_s10.c
@@ -0,0 +1,46 @@ 
+/*
+ * 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
+		return 0;
+}
+
+const unsigned int cm_get_osc_clk_hz(const int osc)
+{
+	return 25000000;
+}
+
+const unsigned int cm_get_intosc_clk_hz(void)
+{
+	/* theory maximum internal osc clock */
+	return 460000000;
+}
+
+const unsigned int cm_get_fpga_clk_hz(void)
+{
+	/* assuming 50MHz */
+	return 50000000;
+}