diff mbox series

[v6,09/17] clk: sifive: fu540-prci: Add clock initialization for SPL

Message ID 20200329170538.25449-10-pragnesh.patel@sifive.com
State Superseded
Delegated to: Andes
Headers show
Series RISC-V SiFive FU540 support SPL | expand

Commit Message

Pragnesh Patel March 29, 2020, 5:05 p.m. UTC
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(+)

Comments

Jagan Teki April 6, 2020, 7:35 p.m. UTC | #1
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.
Bin Meng April 20, 2020, 9 a.m. UTC | #2
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
Pragnesh Patel April 24, 2020, 10:08 a.m. UTC | #3
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
Bin Meng April 24, 2020, 1 p.m. UTC | #4
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
Pragnesh Patel April 24, 2020, 1:34 p.m. UTC | #5
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
Bin Meng April 24, 2020, 1:55 p.m. UTC | #6
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
Pragnesh Patel April 24, 2020, 4:27 p.m. UTC | #7
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
Bin Meng April 25, 2020, 1:32 a.m. UTC | #8
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
Pragnesh Patel April 26, 2020, 10 a.m. UTC | #9
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.
Bin Meng April 27, 2020, 1:24 a.m. UTC | #10
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
Pragnesh Patel April 28, 2020, 1:56 p.m. UTC | #11
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 mbox series

Patch

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