Message ID | 20200329170538.25449-10-pragnesh.patel@sifive.com |
---|---|
State | Superseded |
Delegated to: | Andes |
Headers | show |
Series | RISC-V SiFive FU540 support SPL | expand |
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel <pragnesh.patel@sifive.com> wrote: > > Set corepll, ddrpll and ethernet PLL for u-boot-spl > > Signed-off-by: Pragnesh Patel <pragnesh.patel@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. Jagan.
Hi Jagan, Pragnesh, On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki <jagan@amarulasolutions.com> wrote: > > On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel > <pragnesh.patel@sifive.com> wrote: > > > > Set corepll, ddrpll and ethernet PLL for u-boot-spl > > > > Signed-off-by: Pragnesh Patel <pragnesh.patel@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
Hi Bin, Jagan >-----Original Message----- >From: Bin Meng <bmeng.cn@gmail.com> >Sent: 20 April 2020 14:30 >To: Jagan Teki <jagan@amarulasolutions.com> >Cc: Pragnesh Patel <pragnesh.patel@sifive.com>; U-Boot-Denx <u- >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer Dabbelt ><palmerdabbelt@google.com>; Paul Walmsley <paul.walmsley@sifive.com>; >Troy Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass ><sjg@chromium.org> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for >SPL > >[External Email] Do not click links or attachments unless you recognize the >sender and know the content is safe > >Hi Jagan, Pragnesh, > >On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki <jagan@amarulasolutions.com> >wrote: >> >> On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel >> <pragnesh.patel@sifive.com> wrote: >> > >> > Set corepll, ddrpll and ethernet PLL for u-boot-spl >> > >> > Signed-off-by: Pragnesh Patel <pragnesh.patel@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. 1. ethernet clock is not necessary for SPL but SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled. 2. There is nothing special of this clocks for SPL, we can use this for U-Boot. I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree Do you guys have any suggestion for this ? 3. I am planning to make dm way. Any suggestions are welcome > >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
Hi Pragnesh, On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel <pragnesh.patel@sifive.com> wrote: > > Hi Bin, Jagan > > >-----Original Message----- > >From: Bin Meng <bmeng.cn@gmail.com> > >Sent: 20 April 2020 14:30 > >To: Jagan Teki <jagan@amarulasolutions.com> > >Cc: Pragnesh Patel <pragnesh.patel@sifive.com>; U-Boot-Denx <u- > >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer Dabbelt > ><palmerdabbelt@google.com>; Paul Walmsley <paul.walmsley@sifive.com>; > >Troy Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel > ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen > ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass > ><sjg@chromium.org> > >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for > >SPL > > > >[External Email] Do not click links or attachments unless you recognize the > >sender and know the content is safe > > > >Hi Jagan, Pragnesh, > > > >On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki <jagan@amarulasolutions.com> > >wrote: > >> > >> On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel > >> <pragnesh.patel@sifive.com> wrote: > >> > > >> > Set corepll, ddrpll and ethernet PLL for u-boot-spl > >> > > >> > Signed-off-by: Pragnesh Patel <pragnesh.patel@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. > > 1. ethernet clock is not necessary for SPL but SPL performs ethernet PHY reset > sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled. Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset the PHY ? > > 2. There is nothing special of this clocks for SPL, we can use this for U-Boot. > I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree > Do you guys have any suggestion for this ? > Does the example in http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090-20-seanga2@gmail.com/ help? + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "kendryte,k210", "sifive,rocket0", "riscv"; + reg = <0>; + riscv,isa = "rv64imafdgc"; + mmu-type = "sv39"; + i-cache-block-size = <64>; + i-cache-size = <0x8000>; + d-cache-block-size = <64>; + d-cache-size = <0x8000>; + clocks = <&sysclk K210_CLK_CPU>; You need this patch to get clock in the CPU node. http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090-19-seanga2@gmail.com/ > 3. I am planning to make dm way. > > Any suggestions are welcome > > > > >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
Hi Bin, >-----Original Message----- >From: Bin Meng <bmeng.cn@gmail.com> >Sent: 24 April 2020 18:31 >To: Pragnesh Patel <pragnesh.patel@sifive.com> >Cc: Jagan Teki <jagan@amarulasolutions.com>; U-Boot-Denx <u- >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer Dabbelt ><palmerdabbelt@google.com>; Paul Walmsley <paul.walmsley@sifive.com>; >Troy Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass ><sjg@chromium.org> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for >SPL > >[External Email] Do not click links or attachments unless you recognize the >sender and know the content is safe > >Hi Pragnesh, > >On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel <pragnesh.patel@sifive.com> >wrote: >> >> Hi Bin, Jagan >> >> >-----Original Message----- >> >From: Bin Meng <bmeng.cn@gmail.com> >> >Sent: 20 April 2020 14:30 >> >To: Jagan Teki <jagan@amarulasolutions.com> >> >Cc: Pragnesh Patel <pragnesh.patel@sifive.com>; U-Boot-Denx <u- >> >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer >> >Dabbelt <palmerdabbelt@google.com>; Paul Walmsley >> ><paul.walmsley@sifive.com>; Troy Benjegerdes >> ><troy.benjegerdes@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar >> >Kadam <sagar.kadam@sifive.com>; Rick Chen <rick@andestech.com>; >> >Lukasz Majewski <lukma@denx.de>; Simon Glass <sjg@chromium.org> >> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock >> >initialization for SPL >> > >> >[External Email] Do not click links or attachments unless you >> >recognize the sender and know the content is safe >> > >> >Hi Jagan, Pragnesh, >> > >> >On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki >> ><jagan@amarulasolutions.com> >> >wrote: >> >> >> >> On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel >> >> <pragnesh.patel@sifive.com> wrote: >> >> > >> >> > Set corepll, ddrpll and ethernet PLL for u-boot-spl >> >> > >> >> > Signed-off-by: Pragnesh Patel <pragnesh.patel@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. >> >> 1. ethernet clock is not necessary for SPL but SPL performs ethernet >> PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for >that ethernet clock needs to be enabled. > >Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset >the PHY ? We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI + Linux) ? > >> >> 2. There is nothing special of this clocks for SPL, we can use this for U-Boot. >> I am planning to add this clocks in device tree but I am not sure how >> to add coreclk (corepll) in device tree Do you guys have any suggestion for >this ? >> > >Does the example in >http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- >20-seanga2@gmail.com/ >help? > >+ cpu0: cpu@0 { >+ device_type = "cpu"; >+ compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>; >+ riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size = >+ <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>; d-cache-size >+ = <0x8000>; clocks = <&sysclk K210_CLK_CPU>; > >You need this patch to get clock in the CPU node. > >http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- >19-seanga2@gmail.com/ Thanks, will update this in v7. > >> 3. I am planning to make dm way. >> >> Any suggestions are welcome >> >> > >> >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
Hi Pragnesh, On Fri, Apr 24, 2020 at 9:34 PM Pragnesh Patel <pragnesh.patel@sifive.com> wrote: > > > > Hi Bin, > > >-----Original Message----- > >From: Bin Meng <bmeng.cn@gmail.com> > >Sent: 24 April 2020 18:31 > >To: Pragnesh Patel <pragnesh.patel@sifive.com> > >Cc: Jagan Teki <jagan@amarulasolutions.com>; U-Boot-Denx <u- > >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer Dabbelt > ><palmerdabbelt@google.com>; Paul Walmsley <paul.walmsley@sifive.com>; > >Troy Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel > ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen > ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass > ><sjg@chromium.org> > >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for > >SPL > > > >[External Email] Do not click links or attachments unless you recognize the > >sender and know the content is safe > > > >Hi Pragnesh, > > > >On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel <pragnesh.patel@sifive.com> > >wrote: > >> > >> Hi Bin, Jagan > >> > >> >-----Original Message----- > >> >From: Bin Meng <bmeng.cn@gmail.com> > >> >Sent: 20 April 2020 14:30 > >> >To: Jagan Teki <jagan@amarulasolutions.com> > >> >Cc: Pragnesh Patel <pragnesh.patel@sifive.com>; U-Boot-Denx <u- > >> >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer > >> >Dabbelt <palmerdabbelt@google.com>; Paul Walmsley > >> ><paul.walmsley@sifive.com>; Troy Benjegerdes > >> ><troy.benjegerdes@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar > >> >Kadam <sagar.kadam@sifive.com>; Rick Chen <rick@andestech.com>; > >> >Lukasz Majewski <lukma@denx.de>; Simon Glass <sjg@chromium.org> > >> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock > >> >initialization for SPL > >> > > >> >[External Email] Do not click links or attachments unless you > >> >recognize the sender and know the content is safe > >> > > >> >Hi Jagan, Pragnesh, > >> > > >> >On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki > >> ><jagan@amarulasolutions.com> > >> >wrote: > >> >> > >> >> On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel > >> >> <pragnesh.patel@sifive.com> wrote: > >> >> > > >> >> > Set corepll, ddrpll and ethernet PLL for u-boot-spl > >> >> > > >> >> > Signed-off-by: Pragnesh Patel <pragnesh.patel@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. > >> > >> 1. ethernet clock is not necessary for SPL but SPL performs ethernet > >> PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for > >that ethernet clock needs to be enabled. > > > >Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset > >the PHY ? > > We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI + Linux) ? > I am not sure if that's a desired boot flow. If that's something we want to support, yes we will have to do it in SPL. > > > >> > >> 2. There is nothing special of this clocks for SPL, we can use this for U-Boot. > >> I am planning to add this clocks in device tree but I am not sure how > >> to add coreclk (corepll) in device tree Do you guys have any suggestion for > >this ? > >> > > > >Does the example in > >http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- > >20-seanga2@gmail.com/ > >help? > > > >+ cpu0: cpu@0 { > >+ device_type = "cpu"; > >+ compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>; > >+ riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size = > >+ <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>; d-cache-size > >+ = <0x8000>; clocks = <&sysclk K210_CLK_CPU>; > > > >You need this patch to get clock in the CPU node. > > > >http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- > >19-seanga2@gmail.com/ > > Thanks, will update this in v7. > Regards, Bin
Hi Bin, >-----Original Message----- >From: Bin Meng <bmeng.cn@gmail.com> >Sent: 24 April 2020 19:25 >To: Pragnesh Patel <pragnesh.patel@sifive.com> >Cc: Jagan Teki <jagan@amarulasolutions.com>; U-Boot-Denx <u- >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer Dabbelt ><palmerdabbelt@google.com>; Paul Walmsley <paul.walmsley@sifive.com>; >Troy Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass ><sjg@chromium.org> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for >SPL > >[External Email] Do not click links or attachments unless you recognize the >sender and know the content is safe > >Hi Pragnesh, > >On Fri, Apr 24, 2020 at 9:34 PM Pragnesh Patel <pragnesh.patel@sifive.com> >wrote: >> >> >> >> Hi Bin, >> >> >-----Original Message----- >> >From: Bin Meng <bmeng.cn@gmail.com> >> >Sent: 24 April 2020 18:31 >> >To: Pragnesh Patel <pragnesh.patel@sifive.com> >> >Cc: Jagan Teki <jagan@amarulasolutions.com>; U-Boot-Denx <u- >> >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer >> >Dabbelt <palmerdabbelt@google.com>; Paul Walmsley >> ><paul.walmsley@sifive.com>; Troy Benjegerdes >> ><troy.benjegerdes@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar >> >Kadam <sagar.kadam@sifive.com>; Rick Chen <rick@andestech.com>; >> >Lukasz Majewski <lukma@denx.de>; Simon Glass <sjg@chromium.org> >> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock >> >initialization for SPL >> > >> >[External Email] Do not click links or attachments unless you >> >recognize the sender and know the content is safe >> > >> >Hi Pragnesh, >> > >> >On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel >> ><pragnesh.patel@sifive.com> >> >wrote: >> >> >> >> Hi Bin, Jagan >> >> >> >> >-----Original Message----- >> >> >From: Bin Meng <bmeng.cn@gmail.com> >> >> >Sent: 20 April 2020 14:30 >> >> >To: Jagan Teki <jagan@amarulasolutions.com> >> >> >Cc: Pragnesh Patel <pragnesh.patel@sifive.com>; U-Boot-Denx <u- >> >> >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer >> >> >Dabbelt <palmerdabbelt@google.com>; Paul Walmsley >> >> ><paul.walmsley@sifive.com>; Troy Benjegerdes >> >> ><troy.benjegerdes@sifive.com>; Anup Patel <anup.patel@wdc.com>; >> >> >Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen >> >> ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon >Glass >> >> ><sjg@chromium.org> >> >> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock >> >> >initialization for SPL >> >> > >> >> >[External Email] Do not click links or attachments unless you >> >> >recognize the sender and know the content is safe >> >> > >> >> >Hi Jagan, Pragnesh, >> >> > >> >> >On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki >> >> ><jagan@amarulasolutions.com> >> >> >wrote: >> >> >> >> >> >> On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel >> >> >> <pragnesh.patel@sifive.com> wrote: >> >> >> > >> >> >> > Set corepll, ddrpll and ethernet PLL for u-boot-spl >> >> >> > >> >> >> > Signed-off-by: Pragnesh Patel <pragnesh.patel@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. >> >> >> >> 1. ethernet clock is not necessary for SPL but SPL performs >> >> ethernet PHY reset sequence (board/sifive/fu540/spl.c - >> >> "gem_phy_reset") and for >> >that ethernet clock needs to be enabled. >> > >> >Can we delay that for U-Boot proper to enable PRCI ethernet clock and >> >reset the PHY ? >> >> We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI >+ Linux) ? >> > >I am not sure if that's a desired boot flow. If that's something we want to >support, yes we will have to do it in SPL. > >> > >> >> >> >> 2. There is nothing special of this clocks for SPL, we can use this for U- >Boot. >> >> I am planning to add this clocks in device tree but I am not sure >> >> how to add coreclk (corepll) in device tree Do you guys have any >> >> suggestion for >> >this ? >> >> >> > >> >Does the example in >> >>http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009 >> >0- >> >20-seanga2@gmail.com/ >> >help? >> > >> >+ cpu0: cpu@0 { >> >+ device_type = "cpu"; >> >+ compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>; >> >+ riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size = >> >+ <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>; >> >+ d-cache-size = <0x8000>; clocks = <&sysclk K210_CLK_CPU>; >> > >> >You need this patch to get clock in the CPU node. >> > >> >>http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009 >> >0- >> >19-seanga2@gmail.com/ This patch helps but I also need to do clk_set_rate() for coreclk. static void corepll_init(struct udevice *dev) { ..... 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); } } I think, if "clock-frequency" is provided in dts then it's better to call clk_set_rate() Any suggestions are welcome. >> >> Thanks, will update this in v7. >> > >Regards, >Bin
Hi Pragnesh, On Sat, Apr 25, 2020 at 12:27 AM Pragnesh Patel <pragnesh.patel@sifive.com> wrote: > > Hi Bin, > > >-----Original Message----- > >From: Bin Meng <bmeng.cn@gmail.com> > >Sent: 24 April 2020 19:25 > >To: Pragnesh Patel <pragnesh.patel@sifive.com> > >Cc: Jagan Teki <jagan@amarulasolutions.com>; U-Boot-Denx <u- > >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer Dabbelt > ><palmerdabbelt@google.com>; Paul Walmsley <paul.walmsley@sifive.com>; > >Troy Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel > ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen > ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass > ><sjg@chromium.org> > >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for > >SPL > > > >[External Email] Do not click links or attachments unless you recognize the > >sender and know the content is safe > > > >Hi Pragnesh, > > > >On Fri, Apr 24, 2020 at 9:34 PM Pragnesh Patel <pragnesh.patel@sifive.com> > >wrote: > >> > >> > >> > >> Hi Bin, > >> > >> >-----Original Message----- > >> >From: Bin Meng <bmeng.cn@gmail.com> > >> >Sent: 24 April 2020 18:31 > >> >To: Pragnesh Patel <pragnesh.patel@sifive.com> > >> >Cc: Jagan Teki <jagan@amarulasolutions.com>; U-Boot-Denx <u- > >> >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer > >> >Dabbelt <palmerdabbelt@google.com>; Paul Walmsley > >> ><paul.walmsley@sifive.com>; Troy Benjegerdes > >> ><troy.benjegerdes@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar > >> >Kadam <sagar.kadam@sifive.com>; Rick Chen <rick@andestech.com>; > >> >Lukasz Majewski <lukma@denx.de>; Simon Glass <sjg@chromium.org> > >> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock > >> >initialization for SPL > >> > > >> >[External Email] Do not click links or attachments unless you > >> >recognize the sender and know the content is safe > >> > > >> >Hi Pragnesh, > >> > > >> >On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel > >> ><pragnesh.patel@sifive.com> > >> >wrote: > >> >> > >> >> Hi Bin, Jagan > >> >> > >> >> >-----Original Message----- > >> >> >From: Bin Meng <bmeng.cn@gmail.com> > >> >> >Sent: 20 April 2020 14:30 > >> >> >To: Jagan Teki <jagan@amarulasolutions.com> > >> >> >Cc: Pragnesh Patel <pragnesh.patel@sifive.com>; U-Boot-Denx <u- > >> >> >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; Palmer > >> >> >Dabbelt <palmerdabbelt@google.com>; Paul Walmsley > >> >> ><paul.walmsley@sifive.com>; Troy Benjegerdes > >> >> ><troy.benjegerdes@sifive.com>; Anup Patel <anup.patel@wdc.com>; > >> >> >Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen > >> >> ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon > >Glass > >> >> ><sjg@chromium.org> > >> >> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock > >> >> >initialization for SPL > >> >> > > >> >> >[External Email] Do not click links or attachments unless you > >> >> >recognize the sender and know the content is safe > >> >> > > >> >> >Hi Jagan, Pragnesh, > >> >> > > >> >> >On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki > >> >> ><jagan@amarulasolutions.com> > >> >> >wrote: > >> >> >> > >> >> >> On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel > >> >> >> <pragnesh.patel@sifive.com> wrote: > >> >> >> > > >> >> >> > Set corepll, ddrpll and ethernet PLL for u-boot-spl > >> >> >> > > >> >> >> > Signed-off-by: Pragnesh Patel <pragnesh.patel@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. > >> >> > >> >> 1. ethernet clock is not necessary for SPL but SPL performs > >> >> ethernet PHY reset sequence (board/sifive/fu540/spl.c - > >> >> "gem_phy_reset") and for > >> >that ethernet clock needs to be enabled. > >> > > >> >Can we delay that for U-Boot proper to enable PRCI ethernet clock and > >> >reset the PHY ? > >> > >> We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI > >+ Linux) ? > >> > > > >I am not sure if that's a desired boot flow. If that's something we want to > >support, yes we will have to do it in SPL. > > > >> > > >> >> > >> >> 2. There is nothing special of this clocks for SPL, we can use this for U- > >Boot. > >> >> I am planning to add this clocks in device tree but I am not sure > >> >> how to add coreclk (corepll) in device tree Do you guys have any > >> >> suggestion for > >> >this ? > >> >> > >> > > >> >Does the example in > >> > >>http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009 > >> >0- > >> >20-seanga2@gmail.com/ > >> >help? > >> > > >> >+ cpu0: cpu@0 { > >> >+ device_type = "cpu"; > >> >+ compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>; > >> >+ riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size = > >> >+ <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>; > >> >+ d-cache-size = <0x8000>; clocks = <&sysclk K210_CLK_CPU>; > >> > > >> >You need this patch to get clock in the CPU node. > >> > > >> > >>http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009 > >> >0- > >> >19-seanga2@gmail.com/ > > This patch helps but I also need to do clk_set_rate() for coreclk. > > static void corepll_init(struct udevice *dev) > { > ..... > 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); > } > } > > I think, if "clock-frequency" is provided in dts then it's better to call clk_set_rate() > I think so. > Any suggestions are welcome. Regards, Bin
Hi Jagan, Bin >-----Original Message----- >From: Jagan Teki <jagan@amarulasolutions.com> >Sent: 07 April 2020 01:06 >To: Pragnesh Patel <pragnesh.patel@sifive.com> >Cc: U-Boot-Denx <u-boot@lists.denx.de>; Atish Patra ><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng ><bmeng.cn@gmail.com>; Paul Walmsley <paul.walmsley@sifive.com>; Troy >Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass ><sjg@chromium.org> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for >SPL > >[External Email] Do not click links or attachments unless you recognize the >sender and know the content is safe > >On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel ><pragnesh.patel@sifive.com> wrote: >> >> Set corepll, ddrpll and ethernet PLL for u-boot-spl >> >> Signed-off-by: Pragnesh Patel <pragnesh.patel@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) { Will convert corepll into DM >> + 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"); >> +} With DDR clock DM, DDR clock can be enabled by clk_enable() and set rate with clk_set_rate() but after this DDR clock Reset needs to be released as shown below, /* 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); Do you guys have any suggestion how to Release DDR reset in DM way in SPL or current implementation is fine for DDR clock initialization ? >> + >> +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); >> +} SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled. So I am not planning to make any changes in ethernet_init() in v7 Any suggestions are welcome >> +#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. > >Jagan.
Hi Pragnesh, On Sun, Apr 26, 2020 at 6:00 PM Pragnesh Patel <pragnesh.patel@sifive.com> wrote: > > Hi Jagan, Bin > > >-----Original Message----- > >From: Jagan Teki <jagan@amarulasolutions.com> > >Sent: 07 April 2020 01:06 > >To: Pragnesh Patel <pragnesh.patel@sifive.com> > >Cc: U-Boot-Denx <u-boot@lists.denx.de>; Atish Patra > ><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng > ><bmeng.cn@gmail.com>; Paul Walmsley <paul.walmsley@sifive.com>; Troy > >Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel > ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen > ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass > ><sjg@chromium.org> > >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for > >SPL > > > >[External Email] Do not click links or attachments unless you recognize the > >sender and know the content is safe > > > >On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel > ><pragnesh.patel@sifive.com> wrote: > >> > >> Set corepll, ddrpll and ethernet PLL for u-boot-spl > >> > >> Signed-off-by: Pragnesh Patel <pragnesh.patel@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) { > > Will convert corepll into DM > > >> + 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"); > >> +} > > With DDR clock DM, > DDR clock can be enabled by clk_enable() and set rate with clk_set_rate() but after this > DDR clock Reset needs to be released as shown below, > > /* 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); > > Do you guys have any suggestion how to Release DDR reset in DM way in SPL or current implementation is > fine for DDR clock initialization ? Is it possible to do the DDR reset as part of the clk_enable() for the DDR clock? > > >> + > >> +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); > >> +} > > SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled. > So I am not planning to make any changes in ethernet_init() in v7 > If performing DDR reset is not possible with clk_enable, we can leave that here ... > Any suggestions are welcome > Regards, Bin
Hi Bin, >-----Original Message----- >From: Bin Meng <bmeng.cn@gmail.com> >Sent: 27 April 2020 06:54 >To: Pragnesh Patel <pragnesh.patel@sifive.com> >Cc: Jagan Teki <jagan@amarulasolutions.com>; U-Boot-Denx <u- >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>; >palmerdabbelt@google.com; Paul Walmsley <paul.walmsley@sifive.com>; >Troy Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick Chen ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass ><sjg@chromium.org> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for >SPL > >[External Email] Do not click links or attachments unless you recognize the >sender and know the content is safe > >Hi Pragnesh, > >On Sun, Apr 26, 2020 at 6:00 PM Pragnesh Patel <pragnesh.patel@sifive.com> >wrote: >> >> Hi Jagan, Bin >> >> >-----Original Message----- >> >From: Jagan Teki <jagan@amarulasolutions.com> >> >Sent: 07 April 2020 01:06 >> >To: Pragnesh Patel <pragnesh.patel@sifive.com> >> >Cc: U-Boot-Denx <u-boot@lists.denx.de>; Atish Patra >> ><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng >> ><bmeng.cn@gmail.com>; Paul Walmsley <paul.walmsley@sifive.com>; >Troy >> >Benjegerdes <troy.benjegerdes@sifive.com>; Anup Patel >> ><anup.patel@wdc.com>; Sagar Kadam <sagar.kadam@sifive.com>; Rick >Chen >> ><rick@andestech.com>; Lukasz Majewski <lukma@denx.de>; Simon Glass >> ><sjg@chromium.org> >> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock >> >initialization for SPL >> > >> >[External Email] Do not click links or attachments unless you >> >recognize the sender and know the content is safe >> > >> >On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel >> ><pragnesh.patel@sifive.com> wrote: >> >> >> >> Set corepll, ddrpll and ethernet PLL for u-boot-spl >> >> >> >> Signed-off-by: Pragnesh Patel <pragnesh.patel@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) { >> >> Will convert corepll into DM >> >> >> + 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"); } >> >> With DDR clock DM, >> DDR clock can be enabled by clk_enable() and set rate with >> clk_set_rate() but after this DDR clock Reset needs to be released as >> shown below, >> >> /* 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); >> >> Do you guys have any suggestion how to Release DDR reset in DM way in >> SPL or current implementation is fine for DDR clock initialization ? > >Is it possible to do the DDR reset as part of the clk_enable() for the DDR clock? Yes, I will do DDR release reset adter clk_enable() in v7. > >> >> >> + >> >> +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); >> >> +} >> >> SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - >"gem_phy_reset") and for that ethernet clock needs to be enabled. >> So I am not planning to make any changes in ethernet_init() in v7 >> > >If performing DDR reset is not possible with clk_enable, we can leave that >here ... @Bin Meng I think you misunderstood, I am talking about ethernet_init() not DDR. I am not planning to use DM for ethernet clock because of PHY reset sequence. > >> Any suggestions are welcome >> > >Regards, >Bin
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 + return 0; }
Set corepll, ddrpll and ethernet PLL for u-boot-spl Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com> --- drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)