arm: socfpga: stratix10: Add clock manager driver for Stratix10 SoC

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>
This commit is contained in:
Ley Foon Tan 2018-05-18 22:05:22 +08:00 committed by Marek Vasut
parent 641f7470b6
commit 508791a035
7 changed files with 691 additions and 2 deletions

View 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

View 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

View file

@ -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);
}

View 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_ */

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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);
}