arm: socfpga: stratix10: Add clock manager driver for Stratix10 SoC
authorLey Foon Tan <ley.foon.tan@intel.com>
Fri, 18 May 2018 14:05:22 +0000 (22:05 +0800)
committerMarek Vasut <marex@denx.de>
Fri, 18 May 2018 08:30:47 +0000 (10:30 +0200)
Add Clock Manager driver support for Stratix SoC

Signed-off-by: Chin Liang See <chin.liang.see@intel.com>
Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
arch/arm/mach-socfpga/Makefile
arch/arm/mach-socfpga/clock_manager.c
arch/arm/mach-socfpga/clock_manager_s10.c [new file with mode: 0644]
arch/arm/mach-socfpga/include/mach/clock_manager.h
arch/arm/mach-socfpga/include/mach/clock_manager_s10.h [new file with mode: 0644]
arch/arm/mach-socfpga/include/mach/handoff_s10.h [new file with mode: 0644]
arch/arm/mach-socfpga/wrap_pll_config_s10.c [new file with mode: 0644]

index 89b4fdf0f7f80e38101580857979ced68d6765af..6ee8ce66e5d5204964e0d97ad22b5170caf9858b 100644 (file)
@@ -28,6 +28,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
index bc2c0f8854ab8fa409df306c31b74e7e2ad8784a..59ede59b5995e5d48fac2ec3b0b47df8cb938021 100644 (file)
@@ -20,7 +20,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 */
@@ -51,7 +51,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 (file)
index 0000000..3ba2a00
--- /dev/null
@@ -0,0 +1,380 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/arch/handoff_s10.h>
+#include <asm/arch/system_manager.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct socfpga_clock_manager *clock_manager_base =
+       (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
+static const struct socfpga_system_manager *sysmgr_regs =
+               (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
+
+/*
+ * function to write the bypass register which requires a poll of the
+ * busy bit
+ */
+static void cm_write_bypass_mainpll(u32 val)
+{
+       writel(val, &clock_manager_base->main_pll.bypass);
+       cm_wait_for_fsm();
+}
+
+static void cm_write_bypass_perpll(u32 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(u32 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)
+{
+       u32 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();
+               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();
+               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();
+               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)
+{
+       u32 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();
+               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)
+{
+       u32 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();
+               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)
+{
+       u32 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;
+}
+
+unsigned int cm_get_qspi_controller_clk_hz(void)
+{
+       return readl(&sysmgr_regs->boot_scratch_cold0);
+}
+
+unsigned int cm_get_spi_controller_clk_hz(void)
+{
+       u32 clock = cm_get_l3_main_clk_hz();
+
+       clock /= (1 << ((readl(&clock_manager_base->main_pll.nocdiv) >>
+                 CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_CLKCNT_MSK));
+       return clock;
+}
+
+unsigned int cm_get_l4_sys_free_clk_hz(void)
+{
+       return cm_get_l3_main_clk_hz() / 4;
+}
+
+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() / 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);
+}
index 3ace040d156b01c93af4606d6771f505a461b873..dd80e3a76720d323c2341c133b89c78deffa9867 100644 (file)
@@ -16,6 +16,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 (file)
index 0000000..24b20de
--- /dev/null
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ *
+ */
+
+#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(void);
+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 */
+       u32 main_pll_mpuclk;
+       u32 main_pll_nocclk;
+       u32 main_pll_cntr2clk;
+       u32 main_pll_cntr3clk;
+       u32 main_pll_cntr4clk;
+       u32 main_pll_cntr5clk;
+       u32 main_pll_cntr6clk;
+       u32 main_pll_cntr7clk;
+       u32 main_pll_cntr8clk;
+       u32 main_pll_cntr9clk;
+       u32 main_pll_nocdiv;
+       u32 main_pll_pllglob;
+       u32 main_pll_fdbck;
+       u32 main_pll_pllc0;
+       u32 main_pll_pllc1;
+       u32 spare;
+
+       /* peripheral group */
+       u32 per_pll_cntr2clk;
+       u32 per_pll_cntr3clk;
+       u32 per_pll_cntr4clk;
+       u32 per_pll_cntr5clk;
+       u32 per_pll_cntr6clk;
+       u32 per_pll_cntr7clk;
+       u32 per_pll_cntr8clk;
+       u32 per_pll_cntr9clk;
+       u32 per_pll_emacctl;
+       u32 per_pll_gpiodiv;
+       u32 per_pll_pllglob;
+       u32 per_pll_fdbck;
+       u32 per_pll_pllc0;
+       u32 per_pll_pllc1;
+
+       /* incoming clock */
+       u32 hps_osc_clk_hz;
+       u32 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                           BIT(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                               BIT(0)
+#define CLKMGR_STAT_MAINPLL_LOCKED                     BIT(8)
+#define CLKMGR_STAT_PERPLL_LOCKED                      BIT(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 (file)
index 0000000..ba0f1fd
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef _HANDOFF_S10_H_
+#define _HANDOFF_S10_H_
+
+/*
+ * Offset for HW handoff from Quartus tools
+ */
+#define S10_HANDOFF_BASE               0xFFE3F000
+#define S10_HANDOFF_MUX                (S10_HANDOFF_BASE + 0x10)
+#define S10_HANDOFF_IOCTL              (S10_HANDOFF_BASE + 0x1A0)
+#define S10_HANDOFF_FPGA               (S10_HANDOFF_BASE + 0x330)
+#define S10_HANODFF_DELAY              (S10_HANDOFF_BASE + 0x3F0)
+#define S10_HANDOFF_CLOCK              (S10_HANDOFF_BASE + 0x580)
+#define S10_HANDOFF_MISC               (S10_HANDOFF_BASE + 0x610)
+#define S10_HANDOFF_MAGIC_MUX  0x504D5558
+#define S10_HANDOFF_MAGIC_IOCTL        0x494F4354
+#define S10_HANDOFF_MAGIC_FPGA 0x46504741
+#define S10_HANDOFF_MAGIC_DELAY        0x444C4159
+#define S10_HANDOFF_MAGIC_CLOCK        0x434C4B53
+#define S10_HANDOFF_MAGIC_MISC 0x4D495343
+#define S10_HANDOFF_OFFSET_LENGTH      0x4
+#define S10_HANDOFF_OFFSET_DATA        0x10
+
+#define S10_HANDOFF_CLOCK_OSC  (S10_HANDOFF_BASE + 0x608)
+#define S10_HANDOFF_CLOCK_FPGA (S10_HANDOFF_BASE + 0x60C)
+
+#define S10_HANDOFF_SIZE       4096
+
+#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 (file)
index 0000000..7cafc7d
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/io.h>
+#include <asm/arch/handoff_s10.h>
+#include <asm/arch/system_manager.h>
+
+static const struct socfpga_system_manager *sysmgr_regs =
+       (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
+
+const struct cm_config * const cm_get_default_config(void)
+{
+       struct cm_config *cm_handoff_cfg = (struct cm_config *)
+               (S10_HANDOFF_CLOCK + S10_HANDOFF_OFFSET_DATA);
+       u32 *conversion = (u32 *)cm_handoff_cfg;
+       u32 i;
+       u32 handoff_clk = readl(S10_HANDOFF_CLOCK);
+
+       if (swab32(handoff_clk) == S10_HANDOFF_MAGIC_CLOCK) {
+               writel(swab32(handoff_clk), S10_HANDOFF_CLOCK);
+               for (i = 0; i < (sizeof(*cm_handoff_cfg) / sizeof(u32)); i++)
+                       conversion[i] = swab32(conversion[i]);
+               return cm_handoff_cfg;
+       } else if (handoff_clk == S10_HANDOFF_MAGIC_CLOCK) {
+               return cm_handoff_cfg;
+       }
+
+       return NULL;
+}
+
+const unsigned int cm_get_osc_clk_hz(void)
+{
+#ifdef CONFIG_SPL_BUILD
+       u32 clock = readl(S10_HANDOFF_CLOCK_OSC);
+
+       writel(clock, &sysmgr_regs->boot_scratch_cold1);
+#endif
+       return readl(&sysmgr_regs->boot_scratch_cold1);
+}
+
+const unsigned int cm_get_intosc_clk_hz(void)
+{
+       return CLKMGR_INTOSC_HZ;
+}
+
+const unsigned int cm_get_fpga_clk_hz(void)
+{
+#ifdef CONFIG_SPL_BUILD
+       u32 clock = readl(S10_HANDOFF_CLOCK_FPGA);
+
+       writel(clock, &sysmgr_regs->boot_scratch_cold2);
+#endif
+       return readl(&sysmgr_regs->boot_scratch_cold2);
+}