[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