Message ID | 1568283065-11023-9-git-send-email-ley.foon.tan@intel.com |
---|---|
State | Superseded |
Delegated to: | Simon Goldschmidt |
Headers | show |
Series | Add Intel Agilex SoC support | expand |
On Thu, Sep 12, 2019 at 12:11 PM Ley Foon Tan <ley.foon.tan@intel.com> wrote: > > Add clock manager driver for Agilex. Provides clock initialization > and get_rate functions. > > Rename stratix10-clock.h to socfpga-soc64-clock.h. > > stratix10-clock.h is from Linux commit ID 89727949ea1e. > > Signed-off-by: Chee Hong Ang <chee.hong.ang@intel.com> > Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com> I would have preferred the handoff data to come from devicetree... Anyway: Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com> > > --- > v4: > - Get address from DT. > > v3: > - Fixed clear PLL's lostlock bypass mode to ensure the clock manager provide glitchless clock > to downstream logic > - Changed CM_REG_CLRBITS(), CM_REG_SETBITS() and CM_REG_CLRSETBITS() macros > argument ordering, to match with clrbits_le32, setbits_le32 and clrsetbits_le32. > - Rename stratix10-clock.h to socfpga-soc64-clock.h. > - Convert struct to defines and move defines to clk-agilex.h > > v2: > - Convert Clock driver to DM > --- > arch/arm/mach-socfpga/misc.c | 4 + > drivers/clk/altera/Makefile | 1 + > drivers/clk/altera/clk-agilex.c | 579 ++++++++++++++++++ > drivers/clk/altera/clk-agilex.h | 237 +++++++ > .../dt-bindings/clock/socfpga-soc64-clock.h | 84 +++ > 5 files changed, 905 insertions(+) > create mode 100644 drivers/clk/altera/clk-agilex.c > create mode 100644 drivers/clk/altera/clk-agilex.h > create mode 100644 include/dt-bindings/clock/socfpga-soc64-clock.h > > diff --git a/arch/arm/mach-socfpga/misc.c b/arch/arm/mach-socfpga/misc.c > index dffd1b2e41..f540606569 100644 > --- a/arch/arm/mach-socfpga/misc.c > +++ b/arch/arm/mach-socfpga/misc.c > @@ -240,7 +240,11 @@ void socfpga_get_manager_addr(void) > if (!socfpga_sysmgr_base) > hang(); > > +#ifdef CONFIG_TARGET_SOCFPGA_AGILEX > + socfpga_clkmgr_base = socfpga_get_base_addr("intel,agilex-clkmgr"); > +#else > socfpga_clkmgr_base = socfpga_get_base_addr("altr,clk-mgr"); > +#endif > if (!socfpga_clkmgr_base) > hang(); > } > diff --git a/drivers/clk/altera/Makefile b/drivers/clk/altera/Makefile > index a3ae8b24b0..96215ad5c4 100644 > --- a/drivers/clk/altera/Makefile > +++ b/drivers/clk/altera/Makefile > @@ -3,4 +3,5 @@ > # Copyright (C) 2018 Marek Vasut <marex@denx.de> > # > > +obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += clk-agilex.o > obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o > diff --git a/drivers/clk/altera/clk-agilex.c b/drivers/clk/altera/clk-agilex.c > new file mode 100644 > index 0000000000..f796016d73 > --- /dev/null > +++ b/drivers/clk/altera/clk-agilex.c > @@ -0,0 +1,579 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2019 Intel Corporation <www.intel.com> > + */ > + > +#include <common.h> > +#include <asm/io.h> > +#include <clk-uclass.h> > +#include <dm.h> > +#include <dm/lists.h> > +#include <dm/util.h> > +#include <dt-bindings/clock/socfpga-soc64-clock.h> > + > +#include <asm/arch/clock_manager.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +struct socfpga_clk_platdata { > + void __iomem *regs; > +}; > + > +/* > + * function to write the bypass register which requires a poll of the > + * busy bit > + */ > +static void clk_write_bypass_mainpll(struct socfpga_clk_platdata *plat, u32 val) > +{ > + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS); > + cm_wait_for_fsm(); > +} > + > +static void clk_write_bypass_perpll(struct socfpga_clk_platdata *plat, u32 val) > +{ > + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS); > + cm_wait_for_fsm(); > +} > + > +/* function to write the ctrl register which requires a poll of the busy bit */ > +static void clk_write_ctrl(struct socfpga_clk_platdata *plat, u32 val) > +{ > + CM_REG_WRITEL(plat, val, CLKMGR_CTRL); > + cm_wait_for_fsm(); > +} > + > +#define MEMBUS_MAINPLL 0 > +#define MEMBUS_PERPLL 1 > +#define MEMBUS_TIMEOUT 1000 > +#define MEMBUS_ADDR_CLKSLICE 0x27 > +#define MEMBUS_CLKSLICE_SYNC_MODE_EN 0x80 > + > +static int membus_wait_for_req(struct socfpga_clk_platdata *plat, u32 pll, > + int timeout) > +{ > + int cnt = 0; > + u32 req_status; > + > + if (pll == MEMBUS_MAINPLL) > + req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM); > + else > + req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM); > + > + while ((cnt < timeout) && (req_status & CLKMGR_MEM_REQ_SET_MSK)) { > + if (pll == MEMBUS_MAINPLL) > + req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM); > + else > + req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM); > + cnt++; > + } > + > + if (cnt >= timeout) > + return -ETIMEDOUT; > + > + return 0; > +} > + > +static int membus_write_pll(struct socfpga_clk_platdata *plat, u32 pll, > + u32 addr_offset, u32 wdat, int timeout) > +{ > + u32 addr; > + u32 val; > + > + addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK); > + > + val = (CLKMGR_MEM_REQ_SET_MSK | CLKMGR_MEM_WR_SET_MSK | > + (wdat << CLKMGR_MEM_WDAT_LSB_OFFSET) | addr); > + > + if (pll == MEMBUS_MAINPLL) > + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM); > + else > + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM); > + > + debug("MEMBUS: Write 0x%08x to addr = 0x%08x\n", wdat, addr); > + > + return membus_wait_for_req(plat, pll, timeout); > +} > + > +static int membus_read_pll(struct socfpga_clk_platdata *plat, u32 pll, > + u32 addr_offset, u32 *rdata, int timeout) > +{ > + u32 addr; > + u32 val; > + > + addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK); > + > + val = ((CLKMGR_MEM_REQ_SET_MSK & ~CLKMGR_MEM_WR_SET_MSK) | addr); > + > + if (pll == MEMBUS_MAINPLL) > + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM); > + else > + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM); > + > + *rdata = 0; > + > + if (membus_wait_for_req(plat, pll, timeout)) > + return -ETIMEDOUT; > + > + if (pll == MEMBUS_MAINPLL) > + *rdata = CM_REG_READL(plat, CLKMGR_MAINPLL_MEMSTAT); > + else > + *rdata = CM_REG_READL(plat, CLKMGR_PERPLL_MEMSTAT); > + > + debug("MEMBUS: Read 0x%08x from addr = 0x%08x\n", *rdata, addr); > + > + return 0; > +} > + > +static u32 calc_vocalib_pll(u32 pllm, u32 pllglob) > +{ > + u32 mdiv, refclkdiv, arefclkdiv, drefclkdiv, mscnt, hscnt, vcocalib; > + > + mdiv = pllm & CLKMGR_PLLM_MDIV_MASK; > + arefclkdiv = (pllglob & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >> > + CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET; > + drefclkdiv = (pllglob & CLKMGR_PLLGLOB_DREFCLKDIV_MASK) >> > + CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET; > + refclkdiv = (pllglob & CLKMGR_PLLGLOB_REFCLKDIV_MASK) >> > + CLKMGR_PLLGLOB_REFCLKDIV_OFFSET; > + mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv)); > + if (!mscnt) > + mscnt = 1; > + hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) - > + CLKMGR_VCOCALIB_HSCNT_CONST; > + vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) | > + ((mscnt << CLKMGR_VCOCALIB_MSCNT_OFFSET) & > + CLKMGR_VCOCALIB_MSCNT_MASK); > + > + /* Dump all the pll calibration settings for debug purposes */ > + debug("mdiv : %d\n", mdiv); > + debug("arefclkdiv : %d\n", arefclkdiv); > + debug("drefclkdiv : %d\n", drefclkdiv); > + debug("refclkdiv : %d\n", refclkdiv); > + debug("mscnt : %d\n", mscnt); > + debug("hscnt : %d\n", hscnt); > + debug("vcocalib : 0x%08x\n", vcocalib); > + > + return vcocalib; > +} > + > +/* > + * Setup clocks while making no assumptions about previous state of the clocks. > + */ > +static void clk_basic_init(struct udevice *dev, > + const struct cm_config * const cfg) > +{ > + struct socfpga_clk_platdata *plat = dev_get_platdata(dev); > + u32 vcocalib; > + u32 rdata; > + > + if (!cfg) > + return; > + > + /* Put both PLLs in bypass */ > + clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL); > + clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL); > + > + /* Put both PLLs in Reset and Power Down */ > + CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLGLOB, > + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); > + CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLGLOB, > + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); > + > + /* setup main PLL dividers where calculate the vcocalib value */ > + vcocalib = calc_vocalib_pll(cfg->main_pll_pllm, cfg->main_pll_pllglob); > + CM_REG_WRITEL(plat, cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK, > + CLKMGR_MAINPLL_PLLGLOB); > + CM_REG_WRITEL(plat, cfg->main_pll_fdbck, CLKMGR_MAINPLL_FDBCK); > + CM_REG_WRITEL(plat, vcocalib, CLKMGR_MAINPLL_VCOCALIB); > + CM_REG_WRITEL(plat, cfg->main_pll_pllc0, CLKMGR_MAINPLL_PLLC0); > + CM_REG_WRITEL(plat, cfg->main_pll_pllc1, CLKMGR_MAINPLL_PLLC1); > + CM_REG_WRITEL(plat, cfg->main_pll_pllc2, CLKMGR_MAINPLL_PLLC2); > + CM_REG_WRITEL(plat, cfg->main_pll_pllc3, CLKMGR_MAINPLL_PLLC3); > + CM_REG_WRITEL(plat, cfg->main_pll_pllm, CLKMGR_MAINPLL_PLLM); > + CM_REG_WRITEL(plat, cfg->main_pll_mpuclk, CLKMGR_MAINPLL_MPUCLK); > + CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK); > + CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV); > + > + /* setup peripheral PLL dividers where calculate the vcocalib value */ > + vcocalib = calc_vocalib_pll(cfg->per_pll_pllm, cfg->per_pll_pllglob); > + CM_REG_WRITEL(plat, cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK, > + CLKMGR_PERPLL_PLLGLOB); > + CM_REG_WRITEL(plat, cfg->per_pll_fdbck, CLKMGR_PERPLL_FDBCK); > + CM_REG_WRITEL(plat, vcocalib, CLKMGR_PERPLL_VCOCALIB); > + CM_REG_WRITEL(plat, cfg->per_pll_pllc0, CLKMGR_PERPLL_PLLC0); > + CM_REG_WRITEL(plat, cfg->per_pll_pllc1, CLKMGR_PERPLL_PLLC1); > + CM_REG_WRITEL(plat, cfg->per_pll_pllc2, CLKMGR_PERPLL_PLLC2); > + CM_REG_WRITEL(plat, cfg->per_pll_pllc3, CLKMGR_PERPLL_PLLC3); > + CM_REG_WRITEL(plat, cfg->per_pll_pllm, CLKMGR_PERPLL_PLLM); > + CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL); > + CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV); > + > + /* Take both PLL out of reset and power up */ > + CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLGLOB, > + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); > + CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLGLOB, > + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); > + > + /* Membus programming to set mainpll and perripll to > + * source synchronous mode > + */ > + membus_read_pll(plat, MEMBUS_MAINPLL, MEMBUS_ADDR_CLKSLICE, &rdata, > + MEMBUS_TIMEOUT); > + membus_write_pll(plat, MEMBUS_MAINPLL, MEMBUS_ADDR_CLKSLICE, > + (rdata | MEMBUS_CLKSLICE_SYNC_MODE_EN), > + MEMBUS_TIMEOUT); > + membus_read_pll(plat, MEMBUS_PERPLL, MEMBUS_ADDR_CLKSLICE, &rdata, > + MEMBUS_TIMEOUT); > + membus_write_pll(plat, MEMBUS_PERPLL, MEMBUS_ADDR_CLKSLICE, > + (rdata | MEMBUS_CLKSLICE_SYNC_MODE_EN), > + MEMBUS_TIMEOUT); > + > + cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK); > + > + /* Configure ping pong counters in altera group */ > + CM_REG_WRITEL(plat, cfg->alt_emacactr, CLKMGR_ALTR_EMACACTR); > + CM_REG_WRITEL(plat, cfg->alt_emacbctr, CLKMGR_ALTR_EMACBCTR); > + CM_REG_WRITEL(plat, cfg->alt_emacptpctr, CLKMGR_ALTR_EMACPTPCTR); > + CM_REG_WRITEL(plat, cfg->alt_gpiodbctr, CLKMGR_ALTR_GPIODBCTR); > + CM_REG_WRITEL(plat, cfg->alt_sdmmcctr, CLKMGR_ALTR_SDMMCCTR); > + CM_REG_WRITEL(plat, cfg->alt_s2fuser0ctr, CLKMGR_ALTR_S2FUSER0CTR); > + CM_REG_WRITEL(plat, cfg->alt_s2fuser1ctr, CLKMGR_ALTR_S2FUSER1CTR); > + CM_REG_WRITEL(plat, cfg->alt_psirefctr, CLKMGR_ALTR_PSIREFCTR); > + > + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK); > + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK); > + > + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) | > + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK, > + CLKMGR_MAINPLL_PLLGLOB); > + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) | > + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK, > + CLKMGR_PERPLL_PLLGLOB); > + > + /* Take all PLLs out of bypass */ > + clk_write_bypass_mainpll(plat, 0); > + clk_write_bypass_perpll(plat, 0); > + > + /* Clear the loss of lock bits (write 1 to clear) */ > + CM_REG_CLRBITS(plat, CLKMGR_INTRCLR, > + CLKMGR_INTER_PERPLLLOST_MASK | > + CLKMGR_INTER_MAINPLLLOST_MASK); > + > + /* Take all ping pong counters out of reset */ > + CM_REG_CLRBITS(plat, CLKMGR_ALTR_EXTCNTRST, > + CLKMGR_ALT_EXTCNTRST_ALLCNTRST); > + > + /* Out of boot mode */ > + clk_write_ctrl(plat, > + CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE); > +} > + > +static u64 clk_get_vco_clk_hz(struct socfpga_clk_platdata *plat, > + u32 pllglob_reg, u32 pllm_reg) > +{ > + u64 fref, arefdiv, mdiv, reg, vco; > + > + reg = CM_REG_READL(plat, pllglob_reg); > + > + fref = (reg & CLKMGR_PLLGLOB_VCO_PSRC_MASK) >> > + CLKMGR_PLLGLOB_VCO_PSRC_OFFSET; > + > + 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; > + } > + > + arefdiv = (reg & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >> > + CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET; > + > + mdiv = CM_REG_READL(plat, pllm_reg) & CLKMGR_PLLM_MDIV_MASK; > + > + vco = fref / arefdiv; > + vco = vco * mdiv; > + > + return vco; > +} > + > +static u64 clk_get_main_vco_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + return clk_get_vco_clk_hz(plat, CLKMGR_MAINPLL_PLLGLOB, > + CLKMGR_MAINPLL_PLLM); > +} > + > +static u64 clk_get_per_vco_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + return clk_get_vco_clk_hz(plat, CLKMGR_PERPLL_PLLGLOB, > + CLKMGR_PERPLL_PLLM); > +} > + > +static u32 clk_get_5_1_clk_src(struct socfpga_clk_platdata *plat, u64 reg) > +{ > + u32 clksrc = CM_REG_READL(plat, reg); > + > + return (clksrc & CLKMGR_CLKSRC_MASK) >> CLKMGR_CLKSRC_OFFSET; > +} > + > +static u64 clk_get_clksrc_hz(struct socfpga_clk_platdata *plat, u32 clksrc_reg, > + u32 main_reg, u32 per_reg) > +{ > + u64 clock; > + u32 clklsrc = clk_get_5_1_clk_src(plat, clksrc_reg); > + > + switch (clklsrc) { > + case CLKMGR_CLKSRC_MAIN: > + clock = clk_get_main_vco_clk_hz(plat); > + clock /= (CM_REG_READL(plat, main_reg) & > + CLKMGR_CLKCNT_MSK); > + break; > + > + case CLKMGR_CLKSRC_PER: > + clock = clk_get_per_vco_clk_hz(plat); > + clock /= (CM_REG_READL(plat, per_reg) & > + 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; > + default: > + return 0; > + } > + > + return clock; > +} > + > +static u64 clk_get_mpu_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + u64 clock = clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_MPUCLK, > + CLKMGR_MAINPLL_PLLC0, > + CLKMGR_PERPLL_PLLC0); > + > + clock /= 1 + (CM_REG_READL(plat, CLKMGR_MAINPLL_MPUCLK) & > + CLKMGR_CLKCNT_MSK); > + > + return clock; > +} > + > +static u32 clk_get_l3_main_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + return clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_NOCCLK, > + CLKMGR_MAINPLL_PLLC1, > + CLKMGR_PERPLL_PLLC1); > +} > + > +static u32 clk_get_l4_main_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + u64 clock = clk_get_l3_main_clk_hz(plat); > + > + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> > + CLKMGR_NOCDIV_L4MAIN_OFFSET) & > + CLKMGR_NOCDIV_DIVIDER_MASK); > + > + return clock; > +} > + > +static u32 clk_get_sdmmc_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + u64 clock = clk_get_clksrc_hz(plat, CLKMGR_ALTR_SDMMCCTR, > + CLKMGR_MAINPLL_PLLC3, > + CLKMGR_PERPLL_PLLC3); > + > + clock /= 1 + (CM_REG_READL(plat, CLKMGR_ALTR_SDMMCCTR) & > + CLKMGR_CLKCNT_MSK); > + > + return clock / 4; > +} > + > +static u32 clk_get_l4_sp_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + u64 clock = clk_get_l3_main_clk_hz(plat); > + > + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> > + CLKMGR_NOCDIV_L4SPCLK_OFFSET) & > + CLKMGR_NOCDIV_DIVIDER_MASK); > + > + return clock; > +} > + > +static u32 clk_get_l4_mp_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + u64 clock = clk_get_l3_main_clk_hz(plat); > + > + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> > + CLKMGR_NOCDIV_L4MPCLK_OFFSET) & > + CLKMGR_NOCDIV_DIVIDER_MASK); > + > + return clock; > +} > + > +static u32 clk_get_l4_sys_free_clk_hz(struct socfpga_clk_platdata *plat) > +{ > + if (CM_REG_READL(plat, CLKMGR_STAT) & CLKMGR_STAT_BOOTMODE) > + return clk_get_l3_main_clk_hz(plat) / 2; > + > + return clk_get_l3_main_clk_hz(plat) / 4; > +} > + > +static u32 clk_get_emac_clk_hz(struct socfpga_clk_platdata *plat, u32 emac_id) > +{ > + bool emacsel_a; > + u32 ctl; > + u32 ctr_reg; > + u32 clock; > + u32 div; > + u32 reg; > + > + /* Get EMAC clock source */ > + ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL); > + if (emac_id == SOCFPGA_SOC64_EMAC0_CLK) > + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET) & > + CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK; > + else if (emac_id == SOCFPGA_SOC64_EMAC1_CLK) > + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET) & > + CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK; > + else if (emac_id == SOCFPGA_SOC64_EMAC2_CLK) > + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET) & > + CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK; > + else > + return 0; > + > + if (ctl) { > + /* EMAC B source */ > + emacsel_a = false; > + ctr_reg = CLKMGR_ALTR_EMACBCTR; > + } else { > + /* EMAC A source */ > + emacsel_a = true; > + ctr_reg = CLKMGR_ALTR_EMACACTR; > + } > + > + reg = CM_REG_READL(plat, ctr_reg); > + clock = (reg & CLKMGR_ALT_EMACCTR_SRC_MASK) > + >> CLKMGR_ALT_EMACCTR_SRC_OFFSET; > + div = (reg & CLKMGR_ALT_EMACCTR_CNT_MASK) > + >> CLKMGR_ALT_EMACCTR_CNT_OFFSET; > + > + switch (clock) { > + case CLKMGR_CLKSRC_MAIN: > + clock = clk_get_main_vco_clk_hz(plat); > + if (emacsel_a) { > + clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC2) & > + CLKMGR_CLKCNT_MSK); > + } else { > + clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC3) & > + CLKMGR_CLKCNT_MSK); > + } > + break; > + > + case CLKMGR_CLKSRC_PER: > + clock = clk_get_per_vco_clk_hz(plat); > + if (emacsel_a) { > + clock /= (CM_REG_READL(plat, CLKMGR_PERPLL_PLLC2) & > + CLKMGR_CLKCNT_MSK); > + } else { > + clock /= (CM_REG_READL(plat, CLKMGR_PERPLL_PLLC3) & > + 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 + div; > + > + return clock; > +} > + > +static ulong socfpga_clk_get_rate(struct clk *clk) > +{ > + struct socfpga_clk_platdata *plat = dev_get_platdata(clk->dev); > + > + switch (clk->id) { > + case SOCFPGA_SOC64_MPU_CLK: > + return clk_get_mpu_clk_hz(plat); > + case SOCFPGA_SOC64_L4_MAIN_CLK: > + return clk_get_l4_main_clk_hz(plat); > + case SOCFPGA_SOC64_L4_SYS_FREE_CLK: > + return clk_get_l4_sys_free_clk_hz(plat); > + case SOCFPGA_SOC64_L4_MP_CLK: > + return clk_get_l4_mp_clk_hz(plat); > + case SOCFPGA_SOC64_L4_SP_CLK: > + return clk_get_l4_sp_clk_hz(plat); > + case SOCFPGA_SOC64_SDMMC_CLK: > + return clk_get_sdmmc_clk_hz(plat); > + case SOCFPGA_SOC64_EMAC0_CLK: > + case SOCFPGA_SOC64_EMAC1_CLK: > + case SOCFPGA_SOC64_EMAC2_CLK: > + return clk_get_emac_clk_hz(plat, clk->id); > + case SOCFPGA_SOC64_USB_CLK: > + return clk_get_l4_mp_clk_hz(plat); > + default: > + return -ENXIO; > + } > +} > + > +static int socfpga_clk_probe(struct udevice *dev) > +{ > + const struct cm_config *cm_default_cfg = cm_get_default_config(); > + > + clk_basic_init(dev, cm_default_cfg); > + > + return 0; > +} > + > +static int socfpga_clk_ofdata_to_platdata(struct udevice *dev) > +{ > + struct socfpga_clk_platdata *plat = dev_get_platdata(dev); > + fdt_addr_t addr; > + > + addr = devfdt_get_addr(dev); > + if (addr == FDT_ADDR_T_NONE) > + return -EINVAL; > + plat->regs = (void __iomem *)addr; > + > + return 0; > +} > + > +static struct clk_ops socfpga_clk_ops = { > + .get_rate = socfpga_clk_get_rate, > +}; > + > +static const struct udevice_id socfpga_clk_match[] = { > + { .compatible = "intel,agilex-clkmgr" }, > + {} > +}; > + > +U_BOOT_DRIVER(socfpga_agilex_clk) = { > + .name = "clk-agilex", > + .id = UCLASS_CLK, > + .of_match = socfpga_clk_match, > + .ops = &socfpga_clk_ops, > + .probe = socfpga_clk_probe, > + .ofdata_to_platdata = socfpga_clk_ofdata_to_platdata, > + .platdata_auto_alloc_size = sizeof(struct socfpga_clk_platdata), > +}; > diff --git a/drivers/clk/altera/clk-agilex.h b/drivers/clk/altera/clk-agilex.h > new file mode 100644 > index 0000000000..3cf2afa006 > --- /dev/null > +++ b/drivers/clk/altera/clk-agilex.h > @@ -0,0 +1,237 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2019 Intel Corporation <www.intel.com> > + */ > + > +#ifndef _CLK_AGILEX_ > +#define _CLK_AGILEX_ > + > +#define CM_REG_READL(plat, reg) \ > + readl(plat->regs + (reg)) > + > +#define CM_REG_WRITEL(plat, data, reg) \ > + writel(data, plat->regs + (reg)) > + > +#define CM_REG_CLRBITS(plat, reg, clear) \ > + clrbits_le32(plat->regs + (reg), (clear)) > + > +#define CM_REG_SETBITS(plat, reg, set) \ > + setbits_le32(plat->regs + (reg), (set)) > + > +struct cm_config { > + /* main group */ > + u32 main_pll_mpuclk; > + u32 main_pll_nocclk; > + u32 main_pll_nocdiv; > + u32 main_pll_pllglob; > + u32 main_pll_fdbck; > + u32 main_pll_pllc0; > + u32 main_pll_pllc1; > + u32 main_pll_pllc2; > + u32 main_pll_pllc3; > + u32 main_pll_pllm; > + > + /* peripheral group */ > + u32 per_pll_emacctl; > + u32 per_pll_gpiodiv; > + u32 per_pll_pllglob; > + u32 per_pll_fdbck; > + u32 per_pll_pllc0; > + u32 per_pll_pllc1; > + u32 per_pll_pllc2; > + u32 per_pll_pllc3; > + u32 per_pll_pllm; > + > + /* altera group */ > + u32 alt_emacactr; > + u32 alt_emacbctr; > + u32 alt_emacptpctr; > + u32 alt_gpiodbctr; > + u32 alt_sdmmcctr; > + u32 alt_s2fuser0ctr; > + u32 alt_s2fuser1ctr; > + u32 alt_psirefctr; > + > + /* incoming clock */ > + u32 hps_osc_clk_hz; > + u32 fpga_clk_hz; > + u32 spare[3]; > +}; > + > +/* Clock Manager registers */ > +#define CLKMGR_CTRL 0 > +#define CLKMGR_STAT 4 > +#define CLKMGR_TESTIOCTRL 8 > +#define CLKMGR_INTRGEN 0x0c > +#define CLKMGR_INTRMSK 0x10 > +#define CLKMGR_INTRCLR 0x14 > +#define CLKMGR_INTRSTS 0x18 > +#define CLKMGR_INTRSTK 0x1c > +#define CLKMGR_INTRRAW 0x20 > + > +/* Clock Manager Main PPL group registers */ > +#define CLKMGR_MAINPLL_EN 0x24 > +#define CLKMGR_MAINPLL_ENS 0x28 > +#define CLKMGR_MAINPLL_ENR 0x2c > +#define CLKMGR_MAINPLL_BYPASS 0x30 > +#define CLKMGR_MAINPLL_BYPASSS 0x34 > +#define CLKMGR_MAINPLL_BYPASSR 0x38 > +#define CLKMGR_MAINPLL_MPUCLK 0x3c > +#define CLKMGR_MAINPLL_NOCCLK 0x40 > +#define CLKMGR_MAINPLL_NOCDIV 0x44 > +#define CLKMGR_MAINPLL_PLLGLOB 0x48 > +#define CLKMGR_MAINPLL_FDBCK 0x4c > +#define CLKMGR_MAINPLL_MEM 0x50 > +#define CLKMGR_MAINPLL_MEMSTAT 0x54 > +#define CLKMGR_MAINPLL_PLLC0 0x58 > +#define CLKMGR_MAINPLL_PLLC1 0x5c > +#define CLKMGR_MAINPLL_VCOCALIB 0x60 > +#define CLKMGR_MAINPLL_PLLC2 0x64 > +#define CLKMGR_MAINPLL_PLLC3 0x68 > +#define CLKMGR_MAINPLL_PLLM 0x6c > +#define CLKMGR_MAINPLL_FHOP 0x70 > +#define CLKMGR_MAINPLL_SSC 0x74 > +#define CLKMGR_MAINPLL_LOSTLOCK 0x78 > + > +/* Clock Manager Peripheral PPL group registers */ > +#define CLKMGR_PERPLL_EN 0x7c > +#define CLKMGR_PERPLL_ENS 0x80 > +#define CLKMGR_PERPLL_ENR 0x84 > +#define CLKMGR_PERPLL_BYPASS 0x88 > +#define CLKMGR_PERPLL_BYPASSS 0x8c > +#define CLKMGR_PERPLL_BYPASSR 0x90 > +#define CLKMGR_PERPLL_EMACCTL 0x94 > +#define CLKMGR_PERPLL_GPIODIV 0x98 > +#define CLKMGR_PERPLL_PLLGLOB 0x9c > +#define CLKMGR_PERPLL_FDBCK 0xa0 > +#define CLKMGR_PERPLL_MEM 0xa4 > +#define CLKMGR_PERPLL_MEMSTAT 0xa8 > +#define CLKMGR_PERPLL_PLLC0 0xac > +#define CLKMGR_PERPLL_PLLC1 0xb0 > +#define CLKMGR_PERPLL_VCOCALIB 0xb4 > +#define CLKMGR_PERPLL_PLLC2 0xb8 > +#define CLKMGR_PERPLL_PLLC3 0xbc > +#define CLKMGR_PERPLL_PLLM 0xc0 > +#define CLKMGR_PERPLL_FHOP 0xc4 > +#define CLKMGR_PERPLL_SSC 0xc8 > +#define CLKMGR_PERPLL_LOSTLOCK 0xcc > + > +/* Clock Manager Altera group registers */ > +#define CLKMGR_ALTR_JTAG 0xd0 > +#define CLKMGR_ALTR_EMACACTR 0xd4 > +#define CLKMGR_ALTR_EMACBCTR 0xd8 > +#define CLKMGR_ALTR_EMACPTPCTR 0xdc > +#define CLKMGR_ALTR_GPIODBCTR 0xe0 > +#define CLKMGR_ALTR_SDMMCCTR 0xe4 > +#define CLKMGR_ALTR_S2FUSER0CTR 0xe8 > +#define CLKMGR_ALTR_S2FUSER1CTR 0xec > +#define CLKMGR_ALTR_PSIREFCTR 0xf0 > +#define CLKMGR_ALTR_EXTCNTRST 0xf4 > + > +#define CLKMGR_CTRL_BOOTMODE BIT(0) > + > +#define CLKMGR_STAT_BUSY BIT(0) > +#define CLKMGR_STAT_MAINPLL_LOCKED BIT(8) > +#define CLKMGR_STAT_MAIN_TRANS BIT(9) > +#define CLKMGR_STAT_PERPLL_LOCKED BIT(16) > +#define CLKMGR_STAT_PERF_TRANS BIT(17) > +#define CLKMGR_STAT_BOOTMODE BIT(24) > +#define CLKMGR_STAT_BOOTCLKSRC BIT(25) > + > +#define CLKMGR_STAT_ALLPLL_LOCKED_MASK \ > + (CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED) > + > +#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_CLKSRC_MASK GENMASK(18, 16) > +#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 GENMASK(10, 0) > + > +#define CLKMGR_BYPASS_MAINPLL_ALL 0x7 > +#define CLKMGR_BYPASS_PERPLL_ALL 0x7f > + > +#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_DIVIDER_MASK 0x3 > + > +#define CLKMGR_PLLGLOB_PD_MASK BIT(0) > +#define CLKMGR_PLLGLOB_RST_MASK BIT(1) > +#define CLKMGR_PLLGLOB_AREFCLKDIV_MASK GENMASK(11, 8) > +#define CLKMGR_PLLGLOB_DREFCLKDIV_MASK GENMASK(13, 12) > +#define CLKMGR_PLLGLOB_REFCLKDIV_MASK GENMASK(13, 8) > +#define CLKMGR_PLLGLOB_MODCLKDIV_MASK GENMASK(24, 27) > +#define CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET 8 > +#define CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET 12 > +#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET 8 > +#define CLKMGR_PLLGLOB_MODCLKDIV_OFFSET 24 > +#define CLKMGR_PLLGLOB_VCO_PSRC_MASK GENMASK(17, 16) > +#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET 16 > +#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK BIT(29) > + > +#define CLKMGR_VCO_PSRC_EOSC1 0 > +#define CLKMGR_VCO_PSRC_INTOSC 1 > +#define CLKMGR_VCO_PSRC_F2S 2 > + > +#define CLKMGR_MEM_REQ_SET_MSK BIT(24) > +#define CLKMGR_MEM_WR_SET_MSK BIT(25) > +#define CLKMGR_MEM_ERR_MSK BIT(26) > +#define CLKMGR_MEM_WDAT_LSB_OFFSET 16 > +#define CLKMGR_MEM_ADDR_MASK GENMASK(15, 0) > +#define CLKMGR_MEM_ADDR_START 0x00004000 > + > +#define CLKMGR_PLLCX_EN_SET_MSK BIT(27) > +#define CLKMGR_PLLCX_MUTE_SET_MSK BIT(28) > + > +#define CLKMGR_VCOCALIB_MSCNT_MASK GENMASK(23, 16) > +#define CLKMGR_VCOCALIB_MSCNT_OFFSET 16 > +#define CLKMGR_VCOCALIB_HSCNT_MASK GENMASK(9, 0) > +#define CLKMGR_VCOCALIB_MSCNT_CONST 100 > +#define CLKMGR_VCOCALIB_HSCNT_CONST 4 > + > +#define CLKMGR_PLLM_MDIV_MASK GENMASK(9, 0) > + > +#define CLKMGR_LOSTLOCK_SET_MASK BIT(0) > + > +#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK BIT(5) > +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET 26 > +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK BIT(26) > +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET 27 > +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK BIT(27) > +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET 28 > +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK BIT(28) > + > +#define CLKMGR_ALT_EMACCTR_SRC_OFFSET 16 > +#define CLKMGR_ALT_EMACCTR_SRC_MASK GENMASK(18, 16) > +#define CLKMGR_ALT_EMACCTR_CNT_OFFSET 0 > +#define CLKMGR_ALT_EMACCTR_CNT_MASK GENMASK(10, 0) > + > +#define CLKMGR_ALT_EXTCNTRST_EMACACNTRST BIT(0) > +#define CLKMGR_ALT_EXTCNTRST_EMACBCNTRST BIT(1) > +#define CLKMGR_ALT_EXTCNTRST_EMACPTPCNTRST BIT(2) > +#define CLKMGR_ALT_EXTCNTRST_GPIODBCNTRST BIT(3) > +#define CLKMGR_ALT_EXTCNTRST_SDMMCCNTRST BIT(4) > +#define CLKMGR_ALT_EXTCNTRST_S2FUSER0CNTRST BIT(5) > +#define CLKMGR_ALT_EXTCNTRST_S2FUSER1CNTRST BIT(6) > +#define CLKMGR_ALT_EXTCNTRST_PSIREFCNTRST BIT(7) > +#define CLKMGR_ALT_EXTCNTRST_ALLCNTRST \ > + (CLKMGR_ALT_EXTCNTRST_EMACACNTRST | \ > + CLKMGR_ALT_EXTCNTRST_EMACBCNTRST | \ > + CLKMGR_ALT_EXTCNTRST_EMACPTPCNTRST | \ > + CLKMGR_ALT_EXTCNTRST_GPIODBCNTRST | \ > + CLKMGR_ALT_EXTCNTRST_SDMMCCNTRST | \ > + CLKMGR_ALT_EXTCNTRST_S2FUSER0CNTRST | \ > + CLKMGR_ALT_EXTCNTRST_S2FUSER1CNTRST | \ > + CLKMGR_ALT_EXTCNTRST_PSIREFCNTRST) > +#endif /* _CLK_AGILEX_ */ > diff --git a/include/dt-bindings/clock/socfpga-soc64-clock.h b/include/dt-bindings/clock/socfpga-soc64-clock.h > new file mode 100644 > index 0000000000..6a05f63676 > --- /dev/null > +++ b/include/dt-bindings/clock/socfpga-soc64-clock.h > @@ -0,0 +1,84 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2017-2019, Intel Corporation > + */ > + > +#ifndef __SOCFPGA_SOC64_CLOCK_H > +#define __SOCFPGA_SOC64_CLOCK_H > + > +/* fixed rate clocks */ > +#define SOCFPGA_SOC64_OSC1 0 > +#define SOCFPGA_SOC64_CB_INTOSC_HS_DIV2_CLK 1 > +#define SOCFPGA_SOC64_CB_INTOSC_LS_CLK 2 > +#define SOCFPGA_SOC64_F2S_FREE_CLK 3 > + > +/* fixed factor clocks */ > +#define SOCFPGA_SOC64_L4_SYS_FREE_CLK 4 > +#define SOCFPGA_SOC64_MPU_PERIPH_CLK 5 > +#define SOCFPGA_SOC64_MPU_L2RAM_CLK 6 > +#define SOCFPGA_SOC64_SDMMC_CIU_CLK 7 > + > +/* PLL clocks */ > +#define SOCFPGA_SOC64_MAIN_PLL_CLK 8 > +#define SOCFPGA_SOC64_PERIPH_PLL_CLK 9 > +#define SOCFPGA_SOC64_BOOT_CLK 10 > + > +/* Periph clocks */ > +#define SOCFPGA_SOC64_MAIN_MPU_BASE_CLK 11 > +#define SOCFPGA_SOC64_MAIN_NOC_BASE_CLK 12 > +#define SOCFPGA_SOC64_MAIN_EMACA_CLK 13 > +#define SOCFPGA_SOC64_MAIN_EMACB_CLK 14 > +#define SOCFPGA_SOC64_MAIN_EMAC_PTP_CLK 15 > +#define SOCFPGA_SOC64_MAIN_GPIO_DB_CLK 16 > +#define SOCFPGA_SOC64_MAIN_SDMMC_CLK 17 > +#define SOCFPGA_SOC64_MAIN_S2F_USR0_CLK 18 > +#define SOCFPGA_SOC64_MAIN_S2F_USR1_CLK 19 > +#define SOCFPGA_SOC64_MAIN_PSI_REF_CLK 20 > + > +#define SOCFPGA_SOC64_PERI_MPU_BASE_CLK 21 > +#define SOCFPGA_SOC64_PERI_NOC_BASE_CLK 22 > +#define SOCFPGA_SOC64_PERI_EMACA_CLK 23 > +#define SOCFPGA_SOC64_PERI_EMACB_CLK 24 > +#define SOCFPGA_SOC64_PERI_EMAC_PTP_CLK 25 > +#define SOCFPGA_SOC64_PERI_GPIO_DB_CLK 26 > +#define SOCFPGA_SOC64_PERI_SDMMC_CLK 27 > +#define SOCFPGA_SOC64_PERI_S2F_USR0_CLK 28 > +#define SOCFPGA_SOC64_PERI_S2F_USR1_CLK 29 > +#define SOCFPGA_SOC64_PERI_PSI_REF_CLK 30 > + > +#define SOCFPGA_SOC64_MPU_FREE_CLK 31 > +#define SOCFPGA_SOC64_NOC_FREE_CLK 32 > +#define SOCFPGA_SOC64_S2F_USR0_CLK 33 > +#define SOCFPGA_SOC64_NOC_CLK 34 > +#define SOCFPGA_SOC64_EMAC_A_FREE_CLK 35 > +#define SOCFPGA_SOC64_EMAC_B_FREE_CLK 36 > +#define SOCFPGA_SOC64_EMAC_PTP_FREE_CLK 37 > +#define SOCFPGA_SOC64_GPIO_DB_FREE_CLK 38 > +#define SOCFPGA_SOC64_SDMMC_FREE_CLK 39 > +#define SOCFPGA_SOC64_S2F_USER1_FREE_CLK 40 > +#define SOCFPGA_SOC64_PSI_REF_FREE_CLK 41 > + > +/* Gate clocks */ > +#define SOCFPGA_SOC64_MPU_CLK 42 > +#define SOCFPGA_SOC64_L4_MAIN_CLK 43 > +#define SOCFPGA_SOC64_L4_MP_CLK 44 > +#define SOCFPGA_SOC64_L4_SP_CLK 45 > +#define SOCFPGA_SOC64_CS_AT_CLK 46 > +#define SOCFPGA_SOC64_CS_TRACE_CLK 47 > +#define SOCFPGA_SOC64_CS_PDBG_CLK 48 > +#define SOCFPGA_SOC64_CS_TIMER_CLK 49 > +#define SOCFPGA_SOC64_S2F_USER0_CLK 50 > +#define SOCFPGA_SOC64_S2F_USER1_CLK 51 > +#define SOCFPGA_SOC64_EMAC0_CLK 52 > +#define SOCFPGA_SOC64_EMAC1_CLK 53 > +#define SOCFPGA_SOC64_EMAC2_CLK 54 > +#define SOCFPGA_SOC64_EMAC_PTP_CLK 55 > +#define SOCFPGA_SOC64_GPIO_DB_CLK 56 > +#define SOCFPGA_SOC64_SDMMC_CLK 57 > +#define SOCFPGA_SOC64_PSI_REF_CLK 58 > +#define SOCFPGA_SOC64_USB_CLK 59 > +#define SOCFPGA_SOC64_SPI_M_CLK 60 > +#define SOCFPGA_SOC64_NAND_CLK 61 > +#define SOCFPGA_SOC64_NUM_CLKS 62 > + > +#endif /* __SOCFPGA_SOC64_CLOCK_H */ > -- > 2.19.0 >
diff --git a/arch/arm/mach-socfpga/misc.c b/arch/arm/mach-socfpga/misc.c index dffd1b2e41..f540606569 100644 --- a/arch/arm/mach-socfpga/misc.c +++ b/arch/arm/mach-socfpga/misc.c @@ -240,7 +240,11 @@ void socfpga_get_manager_addr(void) if (!socfpga_sysmgr_base) hang(); +#ifdef CONFIG_TARGET_SOCFPGA_AGILEX + socfpga_clkmgr_base = socfpga_get_base_addr("intel,agilex-clkmgr"); +#else socfpga_clkmgr_base = socfpga_get_base_addr("altr,clk-mgr"); +#endif if (!socfpga_clkmgr_base) hang(); } diff --git a/drivers/clk/altera/Makefile b/drivers/clk/altera/Makefile index a3ae8b24b0..96215ad5c4 100644 --- a/drivers/clk/altera/Makefile +++ b/drivers/clk/altera/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2018 Marek Vasut <marex@denx.de> # +obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += clk-agilex.o obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o diff --git a/drivers/clk/altera/clk-agilex.c b/drivers/clk/altera/clk-agilex.c new file mode 100644 index 0000000000..f796016d73 --- /dev/null +++ b/drivers/clk/altera/clk-agilex.c @@ -0,0 +1,579 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Intel Corporation <www.intel.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dm/lists.h> +#include <dm/util.h> +#include <dt-bindings/clock/socfpga-soc64-clock.h> + +#include <asm/arch/clock_manager.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct socfpga_clk_platdata { + void __iomem *regs; +}; + +/* + * function to write the bypass register which requires a poll of the + * busy bit + */ +static void clk_write_bypass_mainpll(struct socfpga_clk_platdata *plat, u32 val) +{ + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS); + cm_wait_for_fsm(); +} + +static void clk_write_bypass_perpll(struct socfpga_clk_platdata *plat, u32 val) +{ + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS); + cm_wait_for_fsm(); +} + +/* function to write the ctrl register which requires a poll of the busy bit */ +static void clk_write_ctrl(struct socfpga_clk_platdata *plat, u32 val) +{ + CM_REG_WRITEL(plat, val, CLKMGR_CTRL); + cm_wait_for_fsm(); +} + +#define MEMBUS_MAINPLL 0 +#define MEMBUS_PERPLL 1 +#define MEMBUS_TIMEOUT 1000 +#define MEMBUS_ADDR_CLKSLICE 0x27 +#define MEMBUS_CLKSLICE_SYNC_MODE_EN 0x80 + +static int membus_wait_for_req(struct socfpga_clk_platdata *plat, u32 pll, + int timeout) +{ + int cnt = 0; + u32 req_status; + + if (pll == MEMBUS_MAINPLL) + req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM); + else + req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM); + + while ((cnt < timeout) && (req_status & CLKMGR_MEM_REQ_SET_MSK)) { + if (pll == MEMBUS_MAINPLL) + req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM); + else + req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM); + cnt++; + } + + if (cnt >= timeout) + return -ETIMEDOUT; + + return 0; +} + +static int membus_write_pll(struct socfpga_clk_platdata *plat, u32 pll, + u32 addr_offset, u32 wdat, int timeout) +{ + u32 addr; + u32 val; + + addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK); + + val = (CLKMGR_MEM_REQ_SET_MSK | CLKMGR_MEM_WR_SET_MSK | + (wdat << CLKMGR_MEM_WDAT_LSB_OFFSET) | addr); + + if (pll == MEMBUS_MAINPLL) + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM); + else + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM); + + debug("MEMBUS: Write 0x%08x to addr = 0x%08x\n", wdat, addr); + + return membus_wait_for_req(plat, pll, timeout); +} + +static int membus_read_pll(struct socfpga_clk_platdata *plat, u32 pll, + u32 addr_offset, u32 *rdata, int timeout) +{ + u32 addr; + u32 val; + + addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK); + + val = ((CLKMGR_MEM_REQ_SET_MSK & ~CLKMGR_MEM_WR_SET_MSK) | addr); + + if (pll == MEMBUS_MAINPLL) + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM); + else + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM); + + *rdata = 0; + + if (membus_wait_for_req(plat, pll, timeout)) + return -ETIMEDOUT; + + if (pll == MEMBUS_MAINPLL) + *rdata = CM_REG_READL(plat, CLKMGR_MAINPLL_MEMSTAT); + else + *rdata = CM_REG_READL(plat, CLKMGR_PERPLL_MEMSTAT); + + debug("MEMBUS: Read 0x%08x from addr = 0x%08x\n", *rdata, addr); + + return 0; +} + +static u32 calc_vocalib_pll(u32 pllm, u32 pllglob) +{ + u32 mdiv, refclkdiv, arefclkdiv, drefclkdiv, mscnt, hscnt, vcocalib; + + mdiv = pllm & CLKMGR_PLLM_MDIV_MASK; + arefclkdiv = (pllglob & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET; + drefclkdiv = (pllglob & CLKMGR_PLLGLOB_DREFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET; + refclkdiv = (pllglob & CLKMGR_PLLGLOB_REFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_REFCLKDIV_OFFSET; + mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv)); + if (!mscnt) + mscnt = 1; + hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) - + CLKMGR_VCOCALIB_HSCNT_CONST; + vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) | + ((mscnt << CLKMGR_VCOCALIB_MSCNT_OFFSET) & + CLKMGR_VCOCALIB_MSCNT_MASK); + + /* Dump all the pll calibration settings for debug purposes */ + debug("mdiv : %d\n", mdiv); + debug("arefclkdiv : %d\n", arefclkdiv); + debug("drefclkdiv : %d\n", drefclkdiv); + debug("refclkdiv : %d\n", refclkdiv); + debug("mscnt : %d\n", mscnt); + debug("hscnt : %d\n", hscnt); + debug("vcocalib : 0x%08x\n", vcocalib); + + return vcocalib; +} + +/* + * Setup clocks while making no assumptions about previous state of the clocks. + */ +static void clk_basic_init(struct udevice *dev, + const struct cm_config * const cfg) +{ + struct socfpga_clk_platdata *plat = dev_get_platdata(dev); + u32 vcocalib; + u32 rdata; + + if (!cfg) + return; + + /* Put both PLLs in bypass */ + clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL); + clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL); + + /* Put both PLLs in Reset and Power Down */ + CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + + /* setup main PLL dividers where calculate the vcocalib value */ + vcocalib = calc_vocalib_pll(cfg->main_pll_pllm, cfg->main_pll_pllglob); + CM_REG_WRITEL(plat, cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK, + CLKMGR_MAINPLL_PLLGLOB); + CM_REG_WRITEL(plat, cfg->main_pll_fdbck, CLKMGR_MAINPLL_FDBCK); + CM_REG_WRITEL(plat, vcocalib, CLKMGR_MAINPLL_VCOCALIB); + CM_REG_WRITEL(plat, cfg->main_pll_pllc0, CLKMGR_MAINPLL_PLLC0); + CM_REG_WRITEL(plat, cfg->main_pll_pllc1, CLKMGR_MAINPLL_PLLC1); + CM_REG_WRITEL(plat, cfg->main_pll_pllc2, CLKMGR_MAINPLL_PLLC2); + CM_REG_WRITEL(plat, cfg->main_pll_pllc3, CLKMGR_MAINPLL_PLLC3); + CM_REG_WRITEL(plat, cfg->main_pll_pllm, CLKMGR_MAINPLL_PLLM); + CM_REG_WRITEL(plat, cfg->main_pll_mpuclk, CLKMGR_MAINPLL_MPUCLK); + CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK); + CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV); + + /* setup peripheral PLL dividers where calculate the vcocalib value */ + vcocalib = calc_vocalib_pll(cfg->per_pll_pllm, cfg->per_pll_pllglob); + CM_REG_WRITEL(plat, cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK, + CLKMGR_PERPLL_PLLGLOB); + CM_REG_WRITEL(plat, cfg->per_pll_fdbck, CLKMGR_PERPLL_FDBCK); + CM_REG_WRITEL(plat, vcocalib, CLKMGR_PERPLL_VCOCALIB); + CM_REG_WRITEL(plat, cfg->per_pll_pllc0, CLKMGR_PERPLL_PLLC0); + CM_REG_WRITEL(plat, cfg->per_pll_pllc1, CLKMGR_PERPLL_PLLC1); + CM_REG_WRITEL(plat, cfg->per_pll_pllc2, CLKMGR_PERPLL_PLLC2); + CM_REG_WRITEL(plat, cfg->per_pll_pllc3, CLKMGR_PERPLL_PLLC3); + CM_REG_WRITEL(plat, cfg->per_pll_pllm, CLKMGR_PERPLL_PLLM); + CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL); + CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV); + + /* Take both PLL out of reset and power up */ + CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + + /* Membus programming to set mainpll and perripll to + * source synchronous mode + */ + membus_read_pll(plat, MEMBUS_MAINPLL, MEMBUS_ADDR_CLKSLICE, &rdata, + MEMBUS_TIMEOUT); + membus_write_pll(plat, MEMBUS_MAINPLL, MEMBUS_ADDR_CLKSLICE, + (rdata | MEMBUS_CLKSLICE_SYNC_MODE_EN), + MEMBUS_TIMEOUT); + membus_read_pll(plat, MEMBUS_PERPLL, MEMBUS_ADDR_CLKSLICE, &rdata, + MEMBUS_TIMEOUT); + membus_write_pll(plat, MEMBUS_PERPLL, MEMBUS_ADDR_CLKSLICE, + (rdata | MEMBUS_CLKSLICE_SYNC_MODE_EN), + MEMBUS_TIMEOUT); + + cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK); + + /* Configure ping pong counters in altera group */ + CM_REG_WRITEL(plat, cfg->alt_emacactr, CLKMGR_ALTR_EMACACTR); + CM_REG_WRITEL(plat, cfg->alt_emacbctr, CLKMGR_ALTR_EMACBCTR); + CM_REG_WRITEL(plat, cfg->alt_emacptpctr, CLKMGR_ALTR_EMACPTPCTR); + CM_REG_WRITEL(plat, cfg->alt_gpiodbctr, CLKMGR_ALTR_GPIODBCTR); + CM_REG_WRITEL(plat, cfg->alt_sdmmcctr, CLKMGR_ALTR_SDMMCCTR); + CM_REG_WRITEL(plat, cfg->alt_s2fuser0ctr, CLKMGR_ALTR_S2FUSER0CTR); + CM_REG_WRITEL(plat, cfg->alt_s2fuser1ctr, CLKMGR_ALTR_S2FUSER1CTR); + CM_REG_WRITEL(plat, cfg->alt_psirefctr, CLKMGR_ALTR_PSIREFCTR); + + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK); + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK); + + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) | + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK, + CLKMGR_MAINPLL_PLLGLOB); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) | + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK, + CLKMGR_PERPLL_PLLGLOB); + + /* Take all PLLs out of bypass */ + clk_write_bypass_mainpll(plat, 0); + clk_write_bypass_perpll(plat, 0); + + /* Clear the loss of lock bits (write 1 to clear) */ + CM_REG_CLRBITS(plat, CLKMGR_INTRCLR, + CLKMGR_INTER_PERPLLLOST_MASK | + CLKMGR_INTER_MAINPLLLOST_MASK); + + /* Take all ping pong counters out of reset */ + CM_REG_CLRBITS(plat, CLKMGR_ALTR_EXTCNTRST, + CLKMGR_ALT_EXTCNTRST_ALLCNTRST); + + /* Out of boot mode */ + clk_write_ctrl(plat, + CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE); +} + +static u64 clk_get_vco_clk_hz(struct socfpga_clk_platdata *plat, + u32 pllglob_reg, u32 pllm_reg) +{ + u64 fref, arefdiv, mdiv, reg, vco; + + reg = CM_REG_READL(plat, pllglob_reg); + + fref = (reg & CLKMGR_PLLGLOB_VCO_PSRC_MASK) >> + CLKMGR_PLLGLOB_VCO_PSRC_OFFSET; + + 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; + } + + arefdiv = (reg & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET; + + mdiv = CM_REG_READL(plat, pllm_reg) & CLKMGR_PLLM_MDIV_MASK; + + vco = fref / arefdiv; + vco = vco * mdiv; + + return vco; +} + +static u64 clk_get_main_vco_clk_hz(struct socfpga_clk_platdata *plat) +{ + return clk_get_vco_clk_hz(plat, CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_MAINPLL_PLLM); +} + +static u64 clk_get_per_vco_clk_hz(struct socfpga_clk_platdata *plat) +{ + return clk_get_vco_clk_hz(plat, CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PERPLL_PLLM); +} + +static u32 clk_get_5_1_clk_src(struct socfpga_clk_platdata *plat, u64 reg) +{ + u32 clksrc = CM_REG_READL(plat, reg); + + return (clksrc & CLKMGR_CLKSRC_MASK) >> CLKMGR_CLKSRC_OFFSET; +} + +static u64 clk_get_clksrc_hz(struct socfpga_clk_platdata *plat, u32 clksrc_reg, + u32 main_reg, u32 per_reg) +{ + u64 clock; + u32 clklsrc = clk_get_5_1_clk_src(plat, clksrc_reg); + + switch (clklsrc) { + case CLKMGR_CLKSRC_MAIN: + clock = clk_get_main_vco_clk_hz(plat); + clock /= (CM_REG_READL(plat, main_reg) & + CLKMGR_CLKCNT_MSK); + break; + + case CLKMGR_CLKSRC_PER: + clock = clk_get_per_vco_clk_hz(plat); + clock /= (CM_REG_READL(plat, per_reg) & + 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; + default: + return 0; + } + + return clock; +} + +static u64 clk_get_mpu_clk_hz(struct socfpga_clk_platdata *plat) +{ + u64 clock = clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_MPUCLK, + CLKMGR_MAINPLL_PLLC0, + CLKMGR_PERPLL_PLLC0); + + clock /= 1 + (CM_REG_READL(plat, CLKMGR_MAINPLL_MPUCLK) & + CLKMGR_CLKCNT_MSK); + + return clock; +} + +static u32 clk_get_l3_main_clk_hz(struct socfpga_clk_platdata *plat) +{ + return clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_NOCCLK, + CLKMGR_MAINPLL_PLLC1, + CLKMGR_PERPLL_PLLC1); +} + +static u32 clk_get_l4_main_clk_hz(struct socfpga_clk_platdata *plat) +{ + u64 clock = clk_get_l3_main_clk_hz(plat); + + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> + CLKMGR_NOCDIV_L4MAIN_OFFSET) & + CLKMGR_NOCDIV_DIVIDER_MASK); + + return clock; +} + +static u32 clk_get_sdmmc_clk_hz(struct socfpga_clk_platdata *plat) +{ + u64 clock = clk_get_clksrc_hz(plat, CLKMGR_ALTR_SDMMCCTR, + CLKMGR_MAINPLL_PLLC3, + CLKMGR_PERPLL_PLLC3); + + clock /= 1 + (CM_REG_READL(plat, CLKMGR_ALTR_SDMMCCTR) & + CLKMGR_CLKCNT_MSK); + + return clock / 4; +} + +static u32 clk_get_l4_sp_clk_hz(struct socfpga_clk_platdata *plat) +{ + u64 clock = clk_get_l3_main_clk_hz(plat); + + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> + CLKMGR_NOCDIV_L4SPCLK_OFFSET) & + CLKMGR_NOCDIV_DIVIDER_MASK); + + return clock; +} + +static u32 clk_get_l4_mp_clk_hz(struct socfpga_clk_platdata *plat) +{ + u64 clock = clk_get_l3_main_clk_hz(plat); + + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> + CLKMGR_NOCDIV_L4MPCLK_OFFSET) & + CLKMGR_NOCDIV_DIVIDER_MASK); + + return clock; +} + +static u32 clk_get_l4_sys_free_clk_hz(struct socfpga_clk_platdata *plat) +{ + if (CM_REG_READL(plat, CLKMGR_STAT) & CLKMGR_STAT_BOOTMODE) + return clk_get_l3_main_clk_hz(plat) / 2; + + return clk_get_l3_main_clk_hz(plat) / 4; +} + +static u32 clk_get_emac_clk_hz(struct socfpga_clk_platdata *plat, u32 emac_id) +{ + bool emacsel_a; + u32 ctl; + u32 ctr_reg; + u32 clock; + u32 div; + u32 reg; + + /* Get EMAC clock source */ + ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL); + if (emac_id == SOCFPGA_SOC64_EMAC0_CLK) + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET) & + CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK; + else if (emac_id == SOCFPGA_SOC64_EMAC1_CLK) + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET) & + CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK; + else if (emac_id == SOCFPGA_SOC64_EMAC2_CLK) + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET) & + CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK; + else + return 0; + + if (ctl) { + /* EMAC B source */ + emacsel_a = false; + ctr_reg = CLKMGR_ALTR_EMACBCTR; + } else { + /* EMAC A source */ + emacsel_a = true; + ctr_reg = CLKMGR_ALTR_EMACACTR; + } + + reg = CM_REG_READL(plat, ctr_reg); + clock = (reg & CLKMGR_ALT_EMACCTR_SRC_MASK) + >> CLKMGR_ALT_EMACCTR_SRC_OFFSET; + div = (reg & CLKMGR_ALT_EMACCTR_CNT_MASK) + >> CLKMGR_ALT_EMACCTR_CNT_OFFSET; + + switch (clock) { + case CLKMGR_CLKSRC_MAIN: + clock = clk_get_main_vco_clk_hz(plat); + if (emacsel_a) { + clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC2) & + CLKMGR_CLKCNT_MSK); + } else { + clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC3) & + CLKMGR_CLKCNT_MSK); + } + break; + + case CLKMGR_CLKSRC_PER: + clock = clk_get_per_vco_clk_hz(plat); + if (emacsel_a) { + clock /= (CM_REG_READL(plat, CLKMGR_PERPLL_PLLC2) & + CLKMGR_CLKCNT_MSK); + } else { + clock /= (CM_REG_READL(plat, CLKMGR_PERPLL_PLLC3) & + 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 + div; + + return clock; +} + +static ulong socfpga_clk_get_rate(struct clk *clk) +{ + struct socfpga_clk_platdata *plat = dev_get_platdata(clk->dev); + + switch (clk->id) { + case SOCFPGA_SOC64_MPU_CLK: + return clk_get_mpu_clk_hz(plat); + case SOCFPGA_SOC64_L4_MAIN_CLK: + return clk_get_l4_main_clk_hz(plat); + case SOCFPGA_SOC64_L4_SYS_FREE_CLK: + return clk_get_l4_sys_free_clk_hz(plat); + case SOCFPGA_SOC64_L4_MP_CLK: + return clk_get_l4_mp_clk_hz(plat); + case SOCFPGA_SOC64_L4_SP_CLK: + return clk_get_l4_sp_clk_hz(plat); + case SOCFPGA_SOC64_SDMMC_CLK: + return clk_get_sdmmc_clk_hz(plat); + case SOCFPGA_SOC64_EMAC0_CLK: + case SOCFPGA_SOC64_EMAC1_CLK: + case SOCFPGA_SOC64_EMAC2_CLK: + return clk_get_emac_clk_hz(plat, clk->id); + case SOCFPGA_SOC64_USB_CLK: + return clk_get_l4_mp_clk_hz(plat); + default: + return -ENXIO; + } +} + +static int socfpga_clk_probe(struct udevice *dev) +{ + const struct cm_config *cm_default_cfg = cm_get_default_config(); + + clk_basic_init(dev, cm_default_cfg); + + return 0; +} + +static int socfpga_clk_ofdata_to_platdata(struct udevice *dev) +{ + struct socfpga_clk_platdata *plat = dev_get_platdata(dev); + fdt_addr_t addr; + + addr = devfdt_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + plat->regs = (void __iomem *)addr; + + return 0; +} + +static struct clk_ops socfpga_clk_ops = { + .get_rate = socfpga_clk_get_rate, +}; + +static const struct udevice_id socfpga_clk_match[] = { + { .compatible = "intel,agilex-clkmgr" }, + {} +}; + +U_BOOT_DRIVER(socfpga_agilex_clk) = { + .name = "clk-agilex", + .id = UCLASS_CLK, + .of_match = socfpga_clk_match, + .ops = &socfpga_clk_ops, + .probe = socfpga_clk_probe, + .ofdata_to_platdata = socfpga_clk_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct socfpga_clk_platdata), +}; diff --git a/drivers/clk/altera/clk-agilex.h b/drivers/clk/altera/clk-agilex.h new file mode 100644 index 0000000000..3cf2afa006 --- /dev/null +++ b/drivers/clk/altera/clk-agilex.h @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 Intel Corporation <www.intel.com> + */ + +#ifndef _CLK_AGILEX_ +#define _CLK_AGILEX_ + +#define CM_REG_READL(plat, reg) \ + readl(plat->regs + (reg)) + +#define CM_REG_WRITEL(plat, data, reg) \ + writel(data, plat->regs + (reg)) + +#define CM_REG_CLRBITS(plat, reg, clear) \ + clrbits_le32(plat->regs + (reg), (clear)) + +#define CM_REG_SETBITS(plat, reg, set) \ + setbits_le32(plat->regs + (reg), (set)) + +struct cm_config { + /* main group */ + u32 main_pll_mpuclk; + u32 main_pll_nocclk; + u32 main_pll_nocdiv; + u32 main_pll_pllglob; + u32 main_pll_fdbck; + u32 main_pll_pllc0; + u32 main_pll_pllc1; + u32 main_pll_pllc2; + u32 main_pll_pllc3; + u32 main_pll_pllm; + + /* peripheral group */ + u32 per_pll_emacctl; + u32 per_pll_gpiodiv; + u32 per_pll_pllglob; + u32 per_pll_fdbck; + u32 per_pll_pllc0; + u32 per_pll_pllc1; + u32 per_pll_pllc2; + u32 per_pll_pllc3; + u32 per_pll_pllm; + + /* altera group */ + u32 alt_emacactr; + u32 alt_emacbctr; + u32 alt_emacptpctr; + u32 alt_gpiodbctr; + u32 alt_sdmmcctr; + u32 alt_s2fuser0ctr; + u32 alt_s2fuser1ctr; + u32 alt_psirefctr; + + /* incoming clock */ + u32 hps_osc_clk_hz; + u32 fpga_clk_hz; + u32 spare[3]; +}; + +/* Clock Manager registers */ +#define CLKMGR_CTRL 0 +#define CLKMGR_STAT 4 +#define CLKMGR_TESTIOCTRL 8 +#define CLKMGR_INTRGEN 0x0c +#define CLKMGR_INTRMSK 0x10 +#define CLKMGR_INTRCLR 0x14 +#define CLKMGR_INTRSTS 0x18 +#define CLKMGR_INTRSTK 0x1c +#define CLKMGR_INTRRAW 0x20 + +/* Clock Manager Main PPL group registers */ +#define CLKMGR_MAINPLL_EN 0x24 +#define CLKMGR_MAINPLL_ENS 0x28 +#define CLKMGR_MAINPLL_ENR 0x2c +#define CLKMGR_MAINPLL_BYPASS 0x30 +#define CLKMGR_MAINPLL_BYPASSS 0x34 +#define CLKMGR_MAINPLL_BYPASSR 0x38 +#define CLKMGR_MAINPLL_MPUCLK 0x3c +#define CLKMGR_MAINPLL_NOCCLK 0x40 +#define CLKMGR_MAINPLL_NOCDIV 0x44 +#define CLKMGR_MAINPLL_PLLGLOB 0x48 +#define CLKMGR_MAINPLL_FDBCK 0x4c +#define CLKMGR_MAINPLL_MEM 0x50 +#define CLKMGR_MAINPLL_MEMSTAT 0x54 +#define CLKMGR_MAINPLL_PLLC0 0x58 +#define CLKMGR_MAINPLL_PLLC1 0x5c +#define CLKMGR_MAINPLL_VCOCALIB 0x60 +#define CLKMGR_MAINPLL_PLLC2 0x64 +#define CLKMGR_MAINPLL_PLLC3 0x68 +#define CLKMGR_MAINPLL_PLLM 0x6c +#define CLKMGR_MAINPLL_FHOP 0x70 +#define CLKMGR_MAINPLL_SSC 0x74 +#define CLKMGR_MAINPLL_LOSTLOCK 0x78 + +/* Clock Manager Peripheral PPL group registers */ +#define CLKMGR_PERPLL_EN 0x7c +#define CLKMGR_PERPLL_ENS 0x80 +#define CLKMGR_PERPLL_ENR 0x84 +#define CLKMGR_PERPLL_BYPASS 0x88 +#define CLKMGR_PERPLL_BYPASSS 0x8c +#define CLKMGR_PERPLL_BYPASSR 0x90 +#define CLKMGR_PERPLL_EMACCTL 0x94 +#define CLKMGR_PERPLL_GPIODIV 0x98 +#define CLKMGR_PERPLL_PLLGLOB 0x9c +#define CLKMGR_PERPLL_FDBCK 0xa0 +#define CLKMGR_PERPLL_MEM 0xa4 +#define CLKMGR_PERPLL_MEMSTAT 0xa8 +#define CLKMGR_PERPLL_PLLC0 0xac +#define CLKMGR_PERPLL_PLLC1 0xb0 +#define CLKMGR_PERPLL_VCOCALIB 0xb4 +#define CLKMGR_PERPLL_PLLC2 0xb8 +#define CLKMGR_PERPLL_PLLC3 0xbc +#define CLKMGR_PERPLL_PLLM 0xc0 +#define CLKMGR_PERPLL_FHOP 0xc4 +#define CLKMGR_PERPLL_SSC 0xc8 +#define CLKMGR_PERPLL_LOSTLOCK 0xcc + +/* Clock Manager Altera group registers */ +#define CLKMGR_ALTR_JTAG 0xd0 +#define CLKMGR_ALTR_EMACACTR 0xd4 +#define CLKMGR_ALTR_EMACBCTR 0xd8 +#define CLKMGR_ALTR_EMACPTPCTR 0xdc +#define CLKMGR_ALTR_GPIODBCTR 0xe0 +#define CLKMGR_ALTR_SDMMCCTR 0xe4 +#define CLKMGR_ALTR_S2FUSER0CTR 0xe8 +#define CLKMGR_ALTR_S2FUSER1CTR 0xec +#define CLKMGR_ALTR_PSIREFCTR 0xf0 +#define CLKMGR_ALTR_EXTCNTRST 0xf4 + +#define CLKMGR_CTRL_BOOTMODE BIT(0) + +#define CLKMGR_STAT_BUSY BIT(0) +#define CLKMGR_STAT_MAINPLL_LOCKED BIT(8) +#define CLKMGR_STAT_MAIN_TRANS BIT(9) +#define CLKMGR_STAT_PERPLL_LOCKED BIT(16) +#define CLKMGR_STAT_PERF_TRANS BIT(17) +#define CLKMGR_STAT_BOOTMODE BIT(24) +#define CLKMGR_STAT_BOOTCLKSRC BIT(25) + +#define CLKMGR_STAT_ALLPLL_LOCKED_MASK \ + (CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED) + +#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_CLKSRC_MASK GENMASK(18, 16) +#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 GENMASK(10, 0) + +#define CLKMGR_BYPASS_MAINPLL_ALL 0x7 +#define CLKMGR_BYPASS_PERPLL_ALL 0x7f + +#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_DIVIDER_MASK 0x3 + +#define CLKMGR_PLLGLOB_PD_MASK BIT(0) +#define CLKMGR_PLLGLOB_RST_MASK BIT(1) +#define CLKMGR_PLLGLOB_AREFCLKDIV_MASK GENMASK(11, 8) +#define CLKMGR_PLLGLOB_DREFCLKDIV_MASK GENMASK(13, 12) +#define CLKMGR_PLLGLOB_REFCLKDIV_MASK GENMASK(13, 8) +#define CLKMGR_PLLGLOB_MODCLKDIV_MASK GENMASK(24, 27) +#define CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET 8 +#define CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET 12 +#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET 8 +#define CLKMGR_PLLGLOB_MODCLKDIV_OFFSET 24 +#define CLKMGR_PLLGLOB_VCO_PSRC_MASK GENMASK(17, 16) +#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET 16 +#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK BIT(29) + +#define CLKMGR_VCO_PSRC_EOSC1 0 +#define CLKMGR_VCO_PSRC_INTOSC 1 +#define CLKMGR_VCO_PSRC_F2S 2 + +#define CLKMGR_MEM_REQ_SET_MSK BIT(24) +#define CLKMGR_MEM_WR_SET_MSK BIT(25) +#define CLKMGR_MEM_ERR_MSK BIT(26) +#define CLKMGR_MEM_WDAT_LSB_OFFSET 16 +#define CLKMGR_MEM_ADDR_MASK GENMASK(15, 0) +#define CLKMGR_MEM_ADDR_START 0x00004000 + +#define CLKMGR_PLLCX_EN_SET_MSK BIT(27) +#define CLKMGR_PLLCX_MUTE_SET_MSK BIT(28) + +#define CLKMGR_VCOCALIB_MSCNT_MASK GENMASK(23, 16) +#define CLKMGR_VCOCALIB_MSCNT_OFFSET 16 +#define CLKMGR_VCOCALIB_HSCNT_MASK GENMASK(9, 0) +#define CLKMGR_VCOCALIB_MSCNT_CONST 100 +#define CLKMGR_VCOCALIB_HSCNT_CONST 4 + +#define CLKMGR_PLLM_MDIV_MASK GENMASK(9, 0) + +#define CLKMGR_LOSTLOCK_SET_MASK BIT(0) + +#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK BIT(5) +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET 26 +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK BIT(26) +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET 27 +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK BIT(27) +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET 28 +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK BIT(28) + +#define CLKMGR_ALT_EMACCTR_SRC_OFFSET 16 +#define CLKMGR_ALT_EMACCTR_SRC_MASK GENMASK(18, 16) +#define CLKMGR_ALT_EMACCTR_CNT_OFFSET 0 +#define CLKMGR_ALT_EMACCTR_CNT_MASK GENMASK(10, 0) + +#define CLKMGR_ALT_EXTCNTRST_EMACACNTRST BIT(0) +#define CLKMGR_ALT_EXTCNTRST_EMACBCNTRST BIT(1) +#define CLKMGR_ALT_EXTCNTRST_EMACPTPCNTRST BIT(2) +#define CLKMGR_ALT_EXTCNTRST_GPIODBCNTRST BIT(3) +#define CLKMGR_ALT_EXTCNTRST_SDMMCCNTRST BIT(4) +#define CLKMGR_ALT_EXTCNTRST_S2FUSER0CNTRST BIT(5) +#define CLKMGR_ALT_EXTCNTRST_S2FUSER1CNTRST BIT(6) +#define CLKMGR_ALT_EXTCNTRST_PSIREFCNTRST BIT(7) +#define CLKMGR_ALT_EXTCNTRST_ALLCNTRST \ + (CLKMGR_ALT_EXTCNTRST_EMACACNTRST | \ + CLKMGR_ALT_EXTCNTRST_EMACBCNTRST | \ + CLKMGR_ALT_EXTCNTRST_EMACPTPCNTRST | \ + CLKMGR_ALT_EXTCNTRST_GPIODBCNTRST | \ + CLKMGR_ALT_EXTCNTRST_SDMMCCNTRST | \ + CLKMGR_ALT_EXTCNTRST_S2FUSER0CNTRST | \ + CLKMGR_ALT_EXTCNTRST_S2FUSER1CNTRST | \ + CLKMGR_ALT_EXTCNTRST_PSIREFCNTRST) +#endif /* _CLK_AGILEX_ */ diff --git a/include/dt-bindings/clock/socfpga-soc64-clock.h b/include/dt-bindings/clock/socfpga-soc64-clock.h new file mode 100644 index 0000000000..6a05f63676 --- /dev/null +++ b/include/dt-bindings/clock/socfpga-soc64-clock.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2017-2019, Intel Corporation + */ + +#ifndef __SOCFPGA_SOC64_CLOCK_H +#define __SOCFPGA_SOC64_CLOCK_H + +/* fixed rate clocks */ +#define SOCFPGA_SOC64_OSC1 0 +#define SOCFPGA_SOC64_CB_INTOSC_HS_DIV2_CLK 1 +#define SOCFPGA_SOC64_CB_INTOSC_LS_CLK 2 +#define SOCFPGA_SOC64_F2S_FREE_CLK 3 + +/* fixed factor clocks */ +#define SOCFPGA_SOC64_L4_SYS_FREE_CLK 4 +#define SOCFPGA_SOC64_MPU_PERIPH_CLK 5 +#define SOCFPGA_SOC64_MPU_L2RAM_CLK 6 +#define SOCFPGA_SOC64_SDMMC_CIU_CLK 7 + +/* PLL clocks */ +#define SOCFPGA_SOC64_MAIN_PLL_CLK 8 +#define SOCFPGA_SOC64_PERIPH_PLL_CLK 9 +#define SOCFPGA_SOC64_BOOT_CLK 10 + +/* Periph clocks */ +#define SOCFPGA_SOC64_MAIN_MPU_BASE_CLK 11 +#define SOCFPGA_SOC64_MAIN_NOC_BASE_CLK 12 +#define SOCFPGA_SOC64_MAIN_EMACA_CLK 13 +#define SOCFPGA_SOC64_MAIN_EMACB_CLK 14 +#define SOCFPGA_SOC64_MAIN_EMAC_PTP_CLK 15 +#define SOCFPGA_SOC64_MAIN_GPIO_DB_CLK 16 +#define SOCFPGA_SOC64_MAIN_SDMMC_CLK 17 +#define SOCFPGA_SOC64_MAIN_S2F_USR0_CLK 18 +#define SOCFPGA_SOC64_MAIN_S2F_USR1_CLK 19 +#define SOCFPGA_SOC64_MAIN_PSI_REF_CLK 20 + +#define SOCFPGA_SOC64_PERI_MPU_BASE_CLK 21 +#define SOCFPGA_SOC64_PERI_NOC_BASE_CLK 22 +#define SOCFPGA_SOC64_PERI_EMACA_CLK 23 +#define SOCFPGA_SOC64_PERI_EMACB_CLK 24 +#define SOCFPGA_SOC64_PERI_EMAC_PTP_CLK 25 +#define SOCFPGA_SOC64_PERI_GPIO_DB_CLK 26 +#define SOCFPGA_SOC64_PERI_SDMMC_CLK 27 +#define SOCFPGA_SOC64_PERI_S2F_USR0_CLK 28 +#define SOCFPGA_SOC64_PERI_S2F_USR1_CLK 29 +#define SOCFPGA_SOC64_PERI_PSI_REF_CLK 30 + +#define SOCFPGA_SOC64_MPU_FREE_CLK 31 +#define SOCFPGA_SOC64_NOC_FREE_CLK 32 +#define SOCFPGA_SOC64_S2F_USR0_CLK 33 +#define SOCFPGA_SOC64_NOC_CLK 34 +#define SOCFPGA_SOC64_EMAC_A_FREE_CLK 35 +#define SOCFPGA_SOC64_EMAC_B_FREE_CLK 36 +#define SOCFPGA_SOC64_EMAC_PTP_FREE_CLK 37 +#define SOCFPGA_SOC64_GPIO_DB_FREE_CLK 38 +#define SOCFPGA_SOC64_SDMMC_FREE_CLK 39 +#define SOCFPGA_SOC64_S2F_USER1_FREE_CLK 40 +#define SOCFPGA_SOC64_PSI_REF_FREE_CLK 41 + +/* Gate clocks */ +#define SOCFPGA_SOC64_MPU_CLK 42 +#define SOCFPGA_SOC64_L4_MAIN_CLK 43 +#define SOCFPGA_SOC64_L4_MP_CLK 44 +#define SOCFPGA_SOC64_L4_SP_CLK 45 +#define SOCFPGA_SOC64_CS_AT_CLK 46 +#define SOCFPGA_SOC64_CS_TRACE_CLK 47 +#define SOCFPGA_SOC64_CS_PDBG_CLK 48 +#define SOCFPGA_SOC64_CS_TIMER_CLK 49 +#define SOCFPGA_SOC64_S2F_USER0_CLK 50 +#define SOCFPGA_SOC64_S2F_USER1_CLK 51 +#define SOCFPGA_SOC64_EMAC0_CLK 52 +#define SOCFPGA_SOC64_EMAC1_CLK 53 +#define SOCFPGA_SOC64_EMAC2_CLK 54 +#define SOCFPGA_SOC64_EMAC_PTP_CLK 55 +#define SOCFPGA_SOC64_GPIO_DB_CLK 56 +#define SOCFPGA_SOC64_SDMMC_CLK 57 +#define SOCFPGA_SOC64_PSI_REF_CLK 58 +#define SOCFPGA_SOC64_USB_CLK 59 +#define SOCFPGA_SOC64_SPI_M_CLK 60 +#define SOCFPGA_SOC64_NAND_CLK 61 +#define SOCFPGA_SOC64_NUM_CLKS 62 + +#endif /* __SOCFPGA_SOC64_CLOCK_H */