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