Hi Bin, >-----Original Message----- >From: Bin Meng <bmeng...@gmail.com> >Sent: 02 May 2020 17:58 >To: Pragnesh Patel <pragnesh.pa...@sifive.com> >Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Atish Patra ><atish.pa...@wdc.com>; Palmer Dabbelt <palmerdabb...@google.com>; Paul >Walmsley <paul.walms...@sifive.com>; Jagan Teki ><ja...@amarulasolutions.com>; Troy Benjegerdes ><troy.benjeger...@sifive.com>; Anup Patel <anup.pa...@wdc.com>; Sagar >Kadam <sagar.ka...@sifive.com>; Rick Chen <r...@andestech.com>; Lukasz >Majewski <lu...@denx.de>; Anatolij Gustschin <ag...@denx.de>; Simon >Glass <s...@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.pa...@sifive.com> >wrote: >> >> Add ddr clock release reset and ehternet clock initialization for SPL >> >> Signed-off-by: Pragnesh Patel <pragnesh.pa...@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