From 508791a035ea8e2698c52e1547f77048c49c4391 Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Fri, 18 May 2018 22:05:22 +0800 Subject: [PATCH] arm: socfpga: stratix10: Add clock manager driver for Stratix10 SoC Add Clock Manager driver support for Stratix SoC Signed-off-by: Chin Liang See Signed-off-by: Ley Foon Tan --- arch/arm/mach-socfpga/Makefile | 4 + arch/arm/mach-socfpga/clock_manager.c | 4 +- arch/arm/mach-socfpga/clock_manager_s10.c | 380 ++++++++++++++++++ .../mach-socfpga/include/mach/clock_manager.h | 2 + .../include/mach/clock_manager_s10.h | 210 ++++++++++ .../mach-socfpga/include/mach/handoff_s10.h | 34 ++ arch/arm/mach-socfpga/wrap_pll_config_s10.c | 59 +++ 7 files changed, 691 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 89b4fdf0f7..6ee8ce66e5 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -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 diff --git a/arch/arm/mach-socfpga/clock_manager.c b/arch/arm/mach-socfpga/clock_manager.c index bc2c0f8854..59ede59b59 100644 --- a/arch/arm/mach-socfpga/clock_manager.c +++ b/arch/arm/mach-socfpga/clock_manager.c @@ -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 index 0000000000..3ba2a00c02 --- /dev/null +++ b/arch/arm/mach-socfpga/clock_manager_s10.c @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Intel Corporation + * + */ + +#include +#include +#include +#include +#include + +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); +} diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h index 3ace040d15..dd80e3a767 100644 --- a/arch/arm/mach-socfpga/include/mach/clock_manager.h +++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h @@ -16,6 +16,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 0000000000..24b20de011 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/clock_manager_s10.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2016-2018 Intel Corporation + * + */ + +#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 index 0000000000..ba0f1fd1b2 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/handoff_s10.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2016-2018 Intel Corporation + * + */ + +#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 index 0000000000..7cafc7dcfc --- /dev/null +++ b/arch/arm/mach-socfpga/wrap_pll_config_s10.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Intel Corporation + * + */ + +#include +#include +#include +#include +#include + +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); +} -- 2.25.1