[PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
Bin Meng
bmeng.cn at gmail.com
Mon Apr 20 11:00:16 CEST 2020
Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki <jagan at amarulasolutions.com> wrote:
>
> On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel
> <pragnesh.patel at sifive.com> wrote:
> >
> > Set corepll, ddrpll and ethernet PLL for u-boot-spl
> >
> > Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
> > ---
> > drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++
> > 1 file changed, 118 insertions(+)
> >
> > diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
> > index e6214cd821..3a73c2c8d1 100644
> > --- a/drivers/clk/sifive/fu540-prci.c
> > +++ b/drivers/clk/sifive/fu540-prci.c
> > @@ -41,6 +41,10 @@
> > #include <linux/clk/analogbits-wrpll-cln28hpc.h>
> > #include <dt-bindings/clock/sifive-fu540-prci.h>
> >
> > +#define DDRCTLPLL_F 55
> > +#define DDRCTLPLL_Q 2
> > +#define MHz 1000000
> > +
> > /*
> > * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
> > * hfclk and rtcclk
> > @@ -152,6 +156,27 @@
> > #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
> > (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
> >
> > +/* PROCMONCFG */
> > +#define PRCI_PROCMONCFG_OFFSET 0xF0
> > +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24
> > +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
> > + (0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
> > +
> > +#define PLL_R(x) \
> > + ((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) & PRCI_DDRPLLCFG0_DIVR_MASK
> > +#define PLL_F(x) \
> > + ((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) & PRCI_DDRPLLCFG0_DIVF_MASK
> > +#define PLL_Q(x) \
> > + ((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) & PRCI_DDRPLLCFG0_DIVQ_MASK
> > +#define PLL_RANGE(x) \
> > + ((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) & PRCI_DDRPLLCFG0_RANGE_MASK
> > +#define PLL_BYPASS(x) \
> > + ((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) & PRCI_DDRPLLCFG0_BYPASS_MASK
> > +#define PLL_FSE(x) \
> > + ((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & PRCI_DDRPLLCFG0_FSE_MASK
> > +#define PLL_LOCK(x) \
> > + ((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) & PRCI_DDRPLLCFG0_LOCK_MASK
> > +
> > /*
> > * Private structures
> > */
> > @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk)
> > return pc->ops->enable_clk(pc, 0);
> > }
> >
> > +#ifdef CONFIG_SPL_BUILD
> > +static void corepll_init(struct udevice *dev)
> > +{
> > + u32 v;
> > + struct clk clock;
> > + struct __prci_data *pd = dev_get_priv(dev);
> > +
> > + v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
> > + v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
> > +
> > + clock.id = PRCI_CLK_COREPLL;
> > +
> > + if (v) {
> > + /* corepll 500 Mhz */
> > + sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
> > + } else {
> > + /* corepll 1 Ghz */
> > + sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
> > + }
> > +
> > + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
> > +}
> > +
> > +static void ddr_init(struct udevice *dev)
> > +{
> > + u32 v;
> > + struct clk clock;
> > + struct __prci_data *pd = dev_get_priv(dev);
> > +
> > + //DDR init
> > + u32 ddrctlmhz =
> > + (PLL_R(0)) |
> > + (PLL_F(DDRCTLPLL_F)) |
> > + (PLL_Q(DDRCTLPLL_Q)) |
> > + (PLL_RANGE(0x4)) |
> > + (PLL_BYPASS(0)) |
> > + (PLL_FSE(1));
> > + __prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
> > +
> > + clock.id = PRCI_CLK_DDRPLL;
> > + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
> > +
> > + /* Release DDR reset */
> > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
> > + v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
> > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
> > +
> > + // HACK to get the '1 full controller clock cycle'.
> > + asm volatile ("fence");
> > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
> > + v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
> > + PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
> > + PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
> > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
> > + // HACK to get the '1 full controller clock cycle'.
> > + asm volatile ("fence");
> > +
> > + /* These take like 16 cycles to actually propagate. We can't go sending
> > + * stuff before they come out of reset. So wait. (TODO: Add a register
> > + * to read the current reset states, or DDR Control device?)
> > + */
> > + for (int i = 0; i < 256; i++)
> > + asm volatile ("nop");
> > +}
> > +
> > +static void ethernet_init(struct udevice *dev)
> > +{
> > + u32 v;
> > + struct clk clock;
> > + struct __prci_data *pd = dev_get_priv(dev);
> > +
> > + /* GEMGXL init */
> > + clock.id = PRCI_CLK_GEMGXLPLL;
> > + sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
> > + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
> > +
> > + /* Release GEMGXL reset */
> > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
> > + v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
> > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
> > +
> > + /* Procmon => core clock */
> > + __prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET,
> > + pd);
> > +}
> > +#endif
> > +
> > static int sifive_fu540_prci_probe(struct udevice *dev)
> > {
> > int i, err;
> > @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice *dev)
> > __prci_wrpll_read_cfg0(pd, pc->pwd);
> > }
> >
> > +#ifdef CONFIG_SPL_BUILD
> > + corepll_init(dev);
> > + ddr_init(dev);
> > + ethernet_init(dev);
> > +#endif
>
> 1. Why would ethernet clocks require for SPL
> 2. Why these clocks are special for SPL, can't we use it for U-Boot proper
> 3. This look like raw clock initialization instead of having in
> conventional dm way. since these are here just to use pd. May be
> reuse the required clock of what u-boot proper using or move them into
> spl code.
I believe Jagan's comments are the same as mine that was mentioned in
previous version:
See https://patchwork.ozlabs.org/project/uboot/patch/20200311070320.21323-10-pragnesh.patel@sifive.com/
Regards,
Bin
More information about the U-Boot
mailing list