diff mbox series

[v7,10/22] clk: sifive: fu540-prci: ddr and ethernet clock initialization in SPL

Message ID 20200502100628.24809-11-pragnesh.patel@sifive.com
State New
Headers show
Series RISC-V SiFive FU540 support SPL | expand

Commit Message

Pragnesh Patel May 2, 2020, 10:06 a.m. UTC
Add ddr clock release reset and ehternet clock initialization for
SPL

Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
---
 drivers/clk/sifive/fu540-prci.c | 87 ++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 6 deletions(-)

Comments

Bin Meng May 2, 2020, 12:28 p.m. UTC | #1
Hi Pragnesh,

On Sat, May 2, 2020 at 6:08 PM Pragnesh Patel <pragnesh.patel at sifive.com> wrote:
>
> Add ddr clock release reset and ehternet clock initialization for
> SPL
>
> Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
> ---
>  drivers/clk/sifive/fu540-prci.c | 87 ++++++++++++++++++++++++++++++---
>  1 file changed, 81 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
> index bf06c3a3bb..1c89bdf242 100644
> --- a/drivers/clk/sifive/fu540-prci.c
> +++ b/drivers/clk/sifive/fu540-prci.c
> @@ -41,6 +41,8 @@
>  #include <linux/clk/analogbits-wrpll-cln28hpc.h>
>  #include <dt-bindings/clock/sifive-fu540-prci.h>
>
> +#define MHz            1000000
> +
>  /*
>   * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
>   *     hfclk and rtcclk
> @@ -152,6 +154,12 @@
>  #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)
> +
>  /*
>   * Private structures
>   */
> @@ -176,6 +184,7 @@ struct __prci_data {
>   * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
>   * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
>   * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
> + * @release_reset: fn ptr to code to release clock reset
>   *
>   * @enable_bypass and @disable_bypass are used for WRPLL instances
>   * that contain a separate external glitchless clock mux downstream
> @@ -187,6 +196,9 @@ struct __prci_wrpll_data {
>         void (*disable_bypass)(struct __prci_data *pd);
>         u8 cfg0_offs;
>         u8 cfg1_offs;
> +#ifdef CONFIG_SPL_BUILD
> +       void (*release_reset)(struct __prci_data *pd);
> +#endif
>  };
>
>  struct __prci_clock;
> @@ -476,6 +488,11 @@ static int sifive_fu540_prci_clock_enable(struct __prci_clock *pc, bool enable)
>
>         if (enable) {
>                 __prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
> +
> +#ifdef CONFIG_SPL_BUILD
> +               if (pwd->release_reset)
> +                       pwd->release_reset(pd);
> +#endif
>         } else {
>                 u32 r;
>
> @@ -495,11 +512,6 @@ static const struct __prci_clock_ops sifive_fu540_prci_wrpll_clk_ops = {
>         .enable_clk = sifive_fu540_prci_clock_enable,
>  };
>
> -static const struct __prci_clock_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
> -       .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
> -       .enable_clk = sifive_fu540_prci_clock_enable,
> -};
> -
>  /* TLCLKSEL clock integration */
>
>  static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(
> @@ -521,6 +533,39 @@ static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
>         .recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
>  };
>
> +#ifdef CONFIG_SPL_BUILD
> +/**
> + * __prci_ddr_release_reset() - Release DDR reset
> + * @pd: struct __prci_data * for the PRCI containing the DDRCLK mux reg
> + *
> + */
> +static void __prci_ddr_release_reset(struct __prci_data *pd)
> +{
> +       u32 v;
> +
> +       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'.

nits: should use /* */

> +       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'.

the same here

> +       asm volatile ("fence");
> +
> +       /* These take like 16 cycles to actually propagate. We can't go sending

nits: wrong multi-line comment format

> +        * stuff before they come out of reset. So wait. (TODO: Add a register
> +        * to read the current reset states, or DDR Control device?)

Is there no register to reflect the reset states?

> +        */
> +       for (int i = 0; i < 256; i++)
> +               asm volatile ("nop");
> +}
> +#endif
> +
>  /*
>   * PRCI integration data for each WRPLL instance
>   */
> @@ -535,6 +580,9 @@ static struct __prci_wrpll_data __prci_corepll_data = {
>  static struct __prci_wrpll_data __prci_ddrpll_data = {
>         .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
>         .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
> +#ifdef CONFIG_SPL_BUILD
> +       .release_reset = __prci_ddr_release_reset,
> +#endif
>  };
>
>  static struct __prci_wrpll_data __prci_gemgxlpll_data = {
> @@ -556,7 +604,7 @@ static struct __prci_clock __prci_init_clocks[] = {
>         [PRCI_CLK_DDRPLL] = {
>                 .name = "ddrpll",
>                 .parent_name = "hfclk",
> -               .ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
> +               .ops = &sifive_fu540_prci_wrpll_clk_ops,
>                 .pwd = &__prci_ddrpll_data,
>         },
>         [PRCI_CLK_GEMGXLPLL] = {
> @@ -662,6 +710,29 @@ static int sifive_fu540_prci_disable(struct clk *clk)
>         return ret;
>  }
>
> +#ifdef CONFIG_SPL_BUILD
> +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;
> @@ -687,6 +758,10 @@ static int sifive_fu540_prci_probe(struct udevice *dev)
>                         __prci_wrpll_read_cfg0(pd, pc->pwd);
>         }
>
> +#ifdef CONFIG_SPL_BUILD
> +       ethernet_init(dev);
> +#endif
> +
>         return 0;
>  }

Regards,
Bin
Pragnesh Patel May 2, 2020, 2:49 p.m. UTC | #2
Hi Bin,

>-----Original Message-----
>From: Bin Meng <bmeng.cn at gmail.com>
>Sent: 02 May 2020 17:58
>To: Pragnesh Patel <pragnesh.patel at sifive.com>
>Cc: U-Boot Mailing List <u-boot at lists.denx.de>; Atish Patra
><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>; Paul
>Walmsley <paul.walmsley at sifive.com>; Jagan Teki
><jagan at amarulasolutions.com>; Troy Benjegerdes
><troy.benjegerdes at sifive.com>; Anup Patel <anup.patel at wdc.com>; Sagar
>Kadam <sagar.kadam at sifive.com>; Rick Chen <rick at andestech.com>; Lukasz
>Majewski <lukma at denx.de>; Anatolij Gustschin <agust at denx.de>; Simon
>Glass <sjg at chromium.org>
>Subject: Re: [PATCH v7 10/22] clk: sifive: fu540-prci: ddr and ethernet clock
>initialization in SPL
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>Hi Pragnesh,
>
>On Sat, May 2, 2020 at 6:08 PM Pragnesh Patel <pragnesh.patel at sifive.com>
>wrote:
>>
>> Add ddr clock release reset and ehternet clock initialization for SPL
>>
>> Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
>> ---
>>  drivers/clk/sifive/fu540-prci.c | 87
>> ++++++++++++++++++++++++++++++---
>>  1 file changed, 81 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/clk/sifive/fu540-prci.c
>> b/drivers/clk/sifive/fu540-prci.c index bf06c3a3bb..1c89bdf242 100644
>> --- a/drivers/clk/sifive/fu540-prci.c
>> +++ b/drivers/clk/sifive/fu540-prci.c
>> @@ -41,6 +41,8 @@
>>  #include <linux/clk/analogbits-wrpll-cln28hpc.h>
>>  #include <dt-bindings/clock/sifive-fu540-prci.h>
>>
>> +#define MHz            1000000
>> +
>>  /*
>>   * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
>expects:
>>   *     hfclk and rtcclk
>> @@ -152,6 +154,12 @@
>>  #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)
>> +
>>  /*
>>   * Private structures
>>   */
>> @@ -176,6 +184,7 @@ struct __prci_data {
>>   * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
>>   * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base
>address
>>   * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI
>> base address
>> + * @release_reset: fn ptr to code to release clock reset
>>   *
>>   * @enable_bypass and @disable_bypass are used for WRPLL instances
>>   * that contain a separate external glitchless clock mux downstream
>> @@ -187,6 +196,9 @@ struct __prci_wrpll_data {
>>         void (*disable_bypass)(struct __prci_data *pd);
>>         u8 cfg0_offs;
>>         u8 cfg1_offs;
>> +#ifdef CONFIG_SPL_BUILD
>> +       void (*release_reset)(struct __prci_data *pd); #endif
>>  };
>>
>>  struct __prci_clock;
>> @@ -476,6 +488,11 @@ static int sifive_fu540_prci_clock_enable(struct
>> __prci_clock *pc, bool enable)
>>
>>         if (enable) {
>>                 __prci_wrpll_write_cfg1(pd, pwd,
>> PRCI_COREPLLCFG1_CKE_MASK);
>> +
>> +#ifdef CONFIG_SPL_BUILD
>> +               if (pwd->release_reset)
>> +                       pwd->release_reset(pd); #endif
>>         } else {
>>                 u32 r;
>>
>> @@ -495,11 +512,6 @@ static const struct __prci_clock_ops
>sifive_fu540_prci_wrpll_clk_ops = {
>>         .enable_clk = sifive_fu540_prci_clock_enable,  };
>>
>> -static const struct __prci_clock_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
>> -       .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
>> -       .enable_clk = sifive_fu540_prci_clock_enable,
>> -};
>> -
>>  /* TLCLKSEL clock integration */
>>
>>  static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(
>> @@ -521,6 +533,39 @@ static const struct __prci_clock_ops
>sifive_fu540_prci_tlclksel_clk_ops = {
>>         .recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
>>  };
>>
>> +#ifdef CONFIG_SPL_BUILD
>> +/**
>> + * __prci_ddr_release_reset() - Release DDR reset
>> + * @pd: struct __prci_data * for the PRCI containing the DDRCLK mux
>> +reg
>> + *
>> + */
>> +static void __prci_ddr_release_reset(struct __prci_data *pd) {
>> +       u32 v;
>> +
>> +       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'.
>
>nits: should use /* */

Will update in v8.

>
>> +       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'.
>
>the same here

Will update in v8.

>
>> +       asm volatile ("fence");
>> +
>> +       /* These take like 16 cycles to actually propagate. We can't
>> + go sending
>
>nits: wrong multi-line comment format

Will update in v8.

>
>> +        * stuff before they come out of reset. So wait. (TODO: Add a register
>> +        * to read the current reset states, or DDR Control device?)
>
>Is there no register to reflect the reset states?

As of now, I don't know about this. This is something copied from FSBL.
Right now, we need to go with TODO.

@Troy Benjegerdes Do you have any idea on this ?

>
>> +        */
>> +       for (int i = 0; i < 256; i++)
>> +               asm volatile ("nop");
>> +}
>> +#endif
>> +
>>  /*
>>   * PRCI integration data for each WRPLL instance
>>   */
>> @@ -535,6 +580,9 @@ static struct __prci_wrpll_data
>> __prci_corepll_data = {  static struct __prci_wrpll_data __prci_ddrpll_data =
>{
>>         .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
>>         .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
>> +#ifdef CONFIG_SPL_BUILD
>> +       .release_reset = __prci_ddr_release_reset, #endif
>>  };
>>
>>  static struct __prci_wrpll_data __prci_gemgxlpll_data = { @@ -556,7
>> +604,7 @@ static struct __prci_clock __prci_init_clocks[] = {
>>         [PRCI_CLK_DDRPLL] = {
>>                 .name = "ddrpll",
>>                 .parent_name = "hfclk",
>> -               .ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
>> +               .ops = &sifive_fu540_prci_wrpll_clk_ops,
>>                 .pwd = &__prci_ddrpll_data,
>>         },
>>         [PRCI_CLK_GEMGXLPLL] = {
>> @@ -662,6 +710,29 @@ static int sifive_fu540_prci_disable(struct clk *clk)
>>         return ret;
>>  }
>>
>> +#ifdef CONFIG_SPL_BUILD
>> +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;
>> @@ -687,6 +758,10 @@ static int sifive_fu540_prci_probe(struct udevice
>*dev)
>>                         __prci_wrpll_read_cfg0(pd, pc->pwd);
>>         }
>>
>> +#ifdef CONFIG_SPL_BUILD
>> +       ethernet_init(dev);
>> +#endif
>> +
>>         return 0;
>>  }
>
>Regards,
>Bin
Jagan Teki May 2, 2020, 4:14 p.m. UTC | #3
On Sat, May 2, 2020 at 3:38 PM Pragnesh Patel <pragnesh.patel at sifive.com> wrote:
>
> Add ddr clock release reset and ehternet clock initialization for
> SPL

Why ethernet still require for SPL?

Jagan.
Pragnesh Patel May 2, 2020, 4:35 p.m. UTC | #4
Hi Jagan,

>-----Original Message-----
>From: Jagan Teki <jagan at amarulasolutions.com>
>Sent: 02 May 2020 21:44
>To: Pragnesh Patel <pragnesh.patel at sifive.com>
>Cc: U-Boot-Denx <u-boot at lists.denx.de>; Atish Patra
><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>; Bin
>Meng <bmeng.cn at gmail.com>; Paul Walmsley <paul.walmsley at sifive.com>;
>Troy Benjegerdes <troy.benjegerdes at sifive.com>; Anup Patel
><anup.patel at wdc.com>; Sagar Kadam <sagar.kadam at sifive.com>; Rick Chen
><rick at andestech.com>; Lukasz Majewski <lukma at denx.de>; Anatolij
>Gustschin <agust at denx.de>; Simon Glass <sjg at chromium.org>
>Subject: Re: [PATCH v7 10/22] clk: sifive: fu540-prci: ddr and ethernet clock
>initialization in SPL
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>On Sat, May 2, 2020 at 3:38 PM Pragnesh Patel <pragnesh.patel at sifive.com>
>wrote:
>>
>> Add ddr clock release reset and ehternet clock initialization for SPL
>
>Why ethernet still require for SPL?

I think  we have already discussed this in v6.
https://patchwork.ozlabs.org/project/uboot/patch/20200329170538.25449-10-pragnesh.patel at sifive.com/

>
>Jagan.
Jagan Teki May 2, 2020, 4:44 p.m. UTC | #5
On Sat, May 2, 2020 at 10:05 PM Pragnesh Patel
<pragnesh.patel at sifive.com> wrote:
>
> Hi Jagan,
>
> >-----Original Message-----
> >From: Jagan Teki <jagan at amarulasolutions.com>
> >Sent: 02 May 2020 21:44
> >To: Pragnesh Patel <pragnesh.patel at sifive.com>
> >Cc: U-Boot-Denx <u-boot at lists.denx.de>; Atish Patra
> ><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>; Bin
> >Meng <bmeng.cn at gmail.com>; Paul Walmsley <paul.walmsley at sifive.com>;
> >Troy Benjegerdes <troy.benjegerdes at sifive.com>; Anup Patel
> ><anup.patel at wdc.com>; Sagar Kadam <sagar.kadam at sifive.com>; Rick Chen
> ><rick at andestech.com>; Lukasz Majewski <lukma at denx.de>; Anatolij
> >Gustschin <agust at denx.de>; Simon Glass <sjg at chromium.org>
> >Subject: Re: [PATCH v7 10/22] clk: sifive: fu540-prci: ddr and ethernet clock
> >initialization in SPL
> >
> >[External Email] Do not click links or attachments unless you recognize the
> >sender and know the content is safe
> >
> >On Sat, May 2, 2020 at 3:38 PM Pragnesh Patel <pragnesh.patel at sifive.com>
> >wrote:
> >>
> >> Add ddr clock release reset and ehternet clock initialization for SPL
> >
> >Why ethernet still require for SPL?
>
> I think  we have already discussed this in v6.
> https://patchwork.ozlabs.org/project/uboot/patch/20200329170538.25449-10-pragnesh.patel at sifive.com/

Understand, then make a separate patch for "Ethernet SPL" but not in
this series.
Pragnesh Patel May 3, 2020, 8:57 a.m. UTC | #6
Hi Jagan,

>-----Original Message-----
>From: Jagan Teki <jagan at amarulasolutions.com>
>Sent: 02 May 2020 22:15
>To: Pragnesh Patel <pragnesh.patel at sifive.com>
>Cc: U-Boot-Denx <u-boot at lists.denx.de>; Atish Patra
><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>; Bin
>Meng <bmeng.cn at gmail.com>; Paul Walmsley <paul.walmsley at sifive.com>;
>Troy Benjegerdes <troy.benjegerdes at sifive.com>; Anup Patel
><anup.patel at wdc.com>; Sagar Kadam <sagar.kadam at sifive.com>; Rick Chen
><rick at andestech.com>; Lukasz Majewski <lukma at denx.de>; Anatolij
>Gustschin <agust at denx.de>; Simon Glass <sjg at chromium.org>
>Subject: Re: [PATCH v7 10/22] clk: sifive: fu540-prci: ddr and ethernet clock
>initialization in SPL
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>On Sat, May 2, 2020 at 10:05 PM Pragnesh Patel <pragnesh.patel at sifive.com>
>wrote:
>>
>> Hi Jagan,
>>
>> >-----Original Message-----
>> >From: Jagan Teki <jagan at amarulasolutions.com>
>> >Sent: 02 May 2020 21:44
>> >To: Pragnesh Patel <pragnesh.patel at sifive.com>
>> >Cc: U-Boot-Denx <u-boot at lists.denx.de>; Atish Patra
>> ><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>;
>Bin
>> >Meng <bmeng.cn at gmail.com>; Paul Walmsley
><paul.walmsley at sifive.com>;
>> >Troy Benjegerdes <troy.benjegerdes at sifive.com>; Anup Patel
>> ><anup.patel at wdc.com>; Sagar Kadam <sagar.kadam at sifive.com>; Rick
>Chen
>> ><rick at andestech.com>; Lukasz Majewski <lukma at denx.de>; Anatolij
>> >Gustschin <agust at denx.de>; Simon Glass <sjg at chromium.org>
>> >Subject: Re: [PATCH v7 10/22] clk: sifive: fu540-prci: ddr and
>> >ethernet clock initialization in SPL
>> >
>> >[External Email] Do not click links or attachments unless you
>> >recognize the sender and know the content is safe
>> >
>> >On Sat, May 2, 2020 at 3:38 PM Pragnesh Patel
>> ><pragnesh.patel at sifive.com>
>> >wrote:
>> >>
>> >> Add ddr clock release reset and ehternet clock initialization for
>> >> SPL
>> >
>> >Why ethernet still require for SPL?
>>
>> I think  we have already discussed this in v6.
>> https://patchwork.ozlabs.org/project/uboot/patch/20200329170538.25449-
>> 10-pragnesh.patel at sifive.com/
>
>Understand, then make a separate patch for "Ethernet SPL" but not in this
>series.

I will make a separate patch in this series.
This series is not just for SPL MMC boot but the real intention is to replace FSBL with U-Boot SPL so
all FSBL functionality should be in one series.
Pragnesh Patel May 9, 2020, 11:29 a.m. UTC | #7
Hi Bin,

>-----Original Message-----
>From: U-Boot <u-boot-bounces at lists.denx.de> On Behalf Of Pragnesh Patel
>Sent: 02 May 2020 20:20
>To: Bin Meng <bmeng.cn at gmail.com>; Troy Benjegerdes
><troy.benjegerdes at sifive.com>
>Cc: U-Boot Mailing List <u-boot at lists.denx.de>; Atish Patra
><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>; Paul
>Walmsley <paul.walmsley at sifive.com>; Jagan Teki
><jagan at amarulasolutions.com>; Anup Patel <anup.patel at wdc.com>; Sagar
>Kadam <sagar.kadam at sifive.com>; Rick Chen <rick at andestech.com>; Lukasz
>Majewski <lukma at denx.de>; Anatolij Gustschin <agust at denx.de>; Simon
>Glass <sjg at chromium.org>
>Subject: RE: [PATCH v7 10/22] clk: sifive: fu540-prci: ddr and ethernet clock
>initialization in SPL
>
>Hi Bin,
>
>>-----Original Message-----
>>From: Bin Meng <bmeng.cn at gmail.com>
>>Sent: 02 May 2020 17:58
>>To: Pragnesh Patel <pragnesh.patel at sifive.com>
>>Cc: U-Boot Mailing List <u-boot at lists.denx.de>; Atish Patra
>><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>;
>Paul
>>Walmsley <paul.walmsley at sifive.com>; Jagan Teki
>><jagan at amarulasolutions.com>; Troy Benjegerdes
>><troy.benjegerdes at sifive.com>; Anup Patel <anup.patel at wdc.com>; Sagar
>>Kadam <sagar.kadam at sifive.com>; Rick Chen <rick at andestech.com>;
>Lukasz
>>Majewski <lukma at denx.de>; Anatolij Gustschin <agust at denx.de>; Simon
>>Glass <sjg at chromium.org>
>>Subject: Re: [PATCH v7 10/22] clk: sifive: fu540-prci: ddr and ethernet
>>clock initialization in SPL
>>
>>[External Email] Do not click links or attachments unless you recognize
>>the sender and know the content is safe
>>
>>Hi Pragnesh,
>>
>>On Sat, May 2, 2020 at 6:08 PM Pragnesh Patel
>><pragnesh.patel at sifive.com>
>>wrote:
>>>
>>> Add ddr clock release reset and ehternet clock initialization for SPL
>>>
>>> Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
>>> ---
>>>  drivers/clk/sifive/fu540-prci.c | 87
>>> ++++++++++++++++++++++++++++++---
>>>  1 file changed, 81 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/clk/sifive/fu540-prci.c
>>> b/drivers/clk/sifive/fu540-prci.c index bf06c3a3bb..1c89bdf242 100644
>>> --- a/drivers/clk/sifive/fu540-prci.c
>>> +++ b/drivers/clk/sifive/fu540-prci.c
>>> @@ -41,6 +41,8 @@
>>>  #include <linux/clk/analogbits-wrpll-cln28hpc.h>
>>>  #include <dt-bindings/clock/sifive-fu540-prci.h>
>>>
>>> +#define MHz            1000000
>>> +
>>>  /*
>>>   * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
>>expects:
>>>   *     hfclk and rtcclk
>>> @@ -152,6 +154,12 @@
>>>  #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)
>>> +
>>>  /*
>>>   * Private structures
>>>   */
>>> @@ -176,6 +184,7 @@ struct __prci_data {
>>>   * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
>>>   * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI
>>> base
>>address
>>>   * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI
>>> base address
>>> + * @release_reset: fn ptr to code to release clock reset
>>>   *
>>>   * @enable_bypass and @disable_bypass are used for WRPLL instances
>>>   * that contain a separate external glitchless clock mux downstream
>>> @@ -187,6 +196,9 @@ struct __prci_wrpll_data {
>>>         void (*disable_bypass)(struct __prci_data *pd);
>>>         u8 cfg0_offs;
>>>         u8 cfg1_offs;
>>> +#ifdef CONFIG_SPL_BUILD
>>> +       void (*release_reset)(struct __prci_data *pd); #endif
>>>  };
>>>
>>>  struct __prci_clock;
>>> @@ -476,6 +488,11 @@ static int sifive_fu540_prci_clock_enable(struct
>>> __prci_clock *pc, bool enable)
>>>
>>>         if (enable) {
>>>                 __prci_wrpll_write_cfg1(pd, pwd,
>>> PRCI_COREPLLCFG1_CKE_MASK);
>>> +
>>> +#ifdef CONFIG_SPL_BUILD
>>> +               if (pwd->release_reset)
>>> +                       pwd->release_reset(pd); #endif
>>>         } else {
>>>                 u32 r;
>>>
>>> @@ -495,11 +512,6 @@ static const struct __prci_clock_ops
>>sifive_fu540_prci_wrpll_clk_ops = {
>>>         .enable_clk = sifive_fu540_prci_clock_enable,  };
>>>
>>> -static const struct __prci_clock_ops sifive_fu540_prci_wrpll_ro_clk_ops =
>{
>>> -       .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
>>> -       .enable_clk = sifive_fu540_prci_clock_enable,
>>> -};
>>> -
>>>  /* TLCLKSEL clock integration */
>>>
>>>  static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(
>>> @@ -521,6 +533,39 @@ static const struct __prci_clock_ops
>>sifive_fu540_prci_tlclksel_clk_ops = {
>>>         .recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
>>>  };
>>>
>>> +#ifdef CONFIG_SPL_BUILD
>>> +/**
>>> + * __prci_ddr_release_reset() - Release DDR reset
>>> + * @pd: struct __prci_data * for the PRCI containing the DDRCLK mux
>>> +reg
>>> + *
>>> + */
>>> +static void __prci_ddr_release_reset(struct __prci_data *pd) {
>>> +       u32 v;
>>> +
>>> +       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'.
>>
>>nits: should use /* */
>
>Will update in v8.
>
>>
>>> +       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'.
>>
>>the same here
>
>Will update in v8.
>
>>
>>> +       asm volatile ("fence");
>>> +
>>> +       /* These take like 16 cycles to actually propagate. We can't
>>> + go sending
>>
>>nits: wrong multi-line comment format
>
>Will update in v8.
>
>>
>>> +        * stuff before they come out of reset. So wait. (TODO: Add a register
>>> +        * to read the current reset states, or DDR Control device?)
>>
>>Is there no register to reflect the reset states?
>
>As of now, I don't know about this. This is something copied from FSBL.
>Right now, we need to go with TODO.
>
>@Troy Benjegerdes Do you have any idea on this ?

I discussed this "TODO" with my colleagues and I got below :
This "TODO" refers to the hardware side -- we should add some registers to monitor stuff.
So as far as the software is concerned, we can just remove the TODO.

Will remove this TODO in v8.

>
>>
>>> +        */
>>> +       for (int i = 0; i < 256; i++)
>>> +               asm volatile ("nop"); } #endif
>>> +
>>>  /*
>>>   * PRCI integration data for each WRPLL instance
>>>   */
>>> @@ -535,6 +580,9 @@ static struct __prci_wrpll_data
>>> __prci_corepll_data = {  static struct __prci_wrpll_data
>>> __prci_ddrpll_data =
>>{
>>>         .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
>>>         .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
>>> +#ifdef CONFIG_SPL_BUILD
>>> +       .release_reset = __prci_ddr_release_reset, #endif
>>>  };
>>>
>>>  static struct __prci_wrpll_data __prci_gemgxlpll_data = { @@ -556,7
>>> +604,7 @@ static struct __prci_clock __prci_init_clocks[] = {
>>>         [PRCI_CLK_DDRPLL] = {
>>>                 .name = "ddrpll",
>>>                 .parent_name = "hfclk",
>>> -               .ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
>>> +               .ops = &sifive_fu540_prci_wrpll_clk_ops,
>>>                 .pwd = &__prci_ddrpll_data,
>>>         },
>>>         [PRCI_CLK_GEMGXLPLL] = {
>>> @@ -662,6 +710,29 @@ static int sifive_fu540_prci_disable(struct clk *clk)
>>>         return ret;
>>>  }
>>>
>>> +#ifdef CONFIG_SPL_BUILD
>>> +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;
>>> @@ -687,6 +758,10 @@ static int sifive_fu540_prci_probe(struct
>>> udevice
>>*dev)
>>>                         __prci_wrpll_read_cfg0(pd, pc->pwd);
>>>         }
>>>
>>> +#ifdef CONFIG_SPL_BUILD
>>> +       ethernet_init(dev);
>>> +#endif
>>> +
>>>         return 0;
>>>  }
>>
>>Regards,
>>Bin
diff mbox series

Patch

diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
index bf06c3a3bb..1c89bdf242 100644
--- a/drivers/clk/sifive/fu540-prci.c
+++ b/drivers/clk/sifive/fu540-prci.c
@@ -41,6 +41,8 @@ 
 #include <linux/clk/analogbits-wrpll-cln28hpc.h>
 #include <dt-bindings/clock/sifive-fu540-prci.h>
 
+#define MHz		1000000
+
 /*
  * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
  *     hfclk and rtcclk
@@ -152,6 +154,12 @@ 
 #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)
+
 /*
  * Private structures
  */
@@ -176,6 +184,7 @@  struct __prci_data {
  * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
  * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
  * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
+ * @release_reset: fn ptr to code to release clock reset
  *
  * @enable_bypass and @disable_bypass are used for WRPLL instances
  * that contain a separate external glitchless clock mux downstream
@@ -187,6 +196,9 @@  struct __prci_wrpll_data {
 	void (*disable_bypass)(struct __prci_data *pd);
 	u8 cfg0_offs;
 	u8 cfg1_offs;
+#ifdef CONFIG_SPL_BUILD
+	void (*release_reset)(struct __prci_data *pd);
+#endif
 };
 
 struct __prci_clock;
@@ -476,6 +488,11 @@  static int sifive_fu540_prci_clock_enable(struct __prci_clock *pc, bool enable)
 
 	if (enable) {
 		__prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
+
+#ifdef CONFIG_SPL_BUILD
+		if (pwd->release_reset)
+			pwd->release_reset(pd);
+#endif
 	} else {
 		u32 r;
 
@@ -495,11 +512,6 @@  static const struct __prci_clock_ops sifive_fu540_prci_wrpll_clk_ops = {
 	.enable_clk = sifive_fu540_prci_clock_enable,
 };
 
-static const struct __prci_clock_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
-	.recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
-	.enable_clk = sifive_fu540_prci_clock_enable,
-};
-
 /* TLCLKSEL clock integration */
 
 static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(
@@ -521,6 +533,39 @@  static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
 	.recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
 };
 
+#ifdef CONFIG_SPL_BUILD
+/**
+ * __prci_ddr_release_reset() - Release DDR reset
+ * @pd: struct __prci_data * for the PRCI containing the DDRCLK mux reg
+ *
+ */
+static void __prci_ddr_release_reset(struct __prci_data *pd)
+{
+	u32 v;
+
+	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");
+}
+#endif
+
 /*
  * PRCI integration data for each WRPLL instance
  */
@@ -535,6 +580,9 @@  static struct __prci_wrpll_data __prci_corepll_data = {
 static struct __prci_wrpll_data __prci_ddrpll_data = {
 	.cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
 	.cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
+#ifdef CONFIG_SPL_BUILD
+	.release_reset = __prci_ddr_release_reset,
+#endif
 };
 
 static struct __prci_wrpll_data __prci_gemgxlpll_data = {
@@ -556,7 +604,7 @@  static struct __prci_clock __prci_init_clocks[] = {
 	[PRCI_CLK_DDRPLL] = {
 		.name = "ddrpll",
 		.parent_name = "hfclk",
-		.ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
+		.ops = &sifive_fu540_prci_wrpll_clk_ops,
 		.pwd = &__prci_ddrpll_data,
 	},
 	[PRCI_CLK_GEMGXLPLL] = {
@@ -662,6 +710,29 @@  static int sifive_fu540_prci_disable(struct clk *clk)
 	return ret;
 }
 
+#ifdef CONFIG_SPL_BUILD
+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;
@@ -687,6 +758,10 @@  static int sifive_fu540_prci_probe(struct udevice *dev)
 			__prci_wrpll_read_cfg0(pd, pc->pwd);
 	}
 
+#ifdef CONFIG_SPL_BUILD
+	ethernet_init(dev);
+#endif
+
 	return 0;
 }