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

Pragnesh Patel pragnesh.patel at sifive.com
Sat May 2 16:49:36 CEST 2020


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


More information about the U-Boot mailing list