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

Pragnesh Patel pragnesh.patel at sifive.com
Sat May 9 13:29:32 CEST 2020


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


More information about the U-Boot mailing list