[PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
Bin Meng
bmeng.cn at gmail.com
Mon Apr 27 03:24:08 CEST 2020
Hi Pragnesh,
On Sun, Apr 26, 2020 at 6:00 PM Pragnesh Patel
<pragnesh.patel at sifive.com> wrote:
>
> Hi Jagan, Bin
>
> >-----Original Message-----
> >From: Jagan Teki <jagan at amarulasolutions.com>
> >Sent: 07 April 2020 01:06
> >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>; 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>; Simon Glass
> ><sjg at chromium.org>
> >Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for
> >SPL
> >
> >[External Email] Do not click links or attachments unless you recognize the
> >sender and know the content is safe
> >
> >On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel
> ><pragnesh.patel at sifive.com> wrote:
> >>
> >> Set corepll, ddrpll and ethernet PLL for u-boot-spl
> >>
> >> Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
> >> ---
> >> drivers/clk/sifive/fu540-prci.c | 118
> >> ++++++++++++++++++++++++++++++++
> >> 1 file changed, 118 insertions(+)
> >>
> >> diff --git a/drivers/clk/sifive/fu540-prci.c
> >> b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644
> >> --- a/drivers/clk/sifive/fu540-prci.c
> >> +++ b/drivers/clk/sifive/fu540-prci.c
> >> @@ -41,6 +41,10 @@
> >> #include <linux/clk/analogbits-wrpll-cln28hpc.h>
> >> #include <dt-bindings/clock/sifive-fu540-prci.h>
> >>
> >> +#define DDRCTLPLL_F 55
> >> +#define DDRCTLPLL_Q 2
> >> +#define MHz 1000000
> >> +
> >> /*
> >> * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
> >expects:
> >> * hfclk and rtcclk
> >> @@ -152,6 +156,27 @@
> >> #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)
> >> +
> >> +#define PLL_R(x) \
> >> + ((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
> >> +PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
> >> + ((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
> >> +PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
> >> + ((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
> >> +PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
> >> + ((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
> >> +PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
> >> + ((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
> >> +PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
> >> + ((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & PRCI_DDRPLLCFG0_FSE_MASK
> >> +#define PLL_LOCK(x) \
> >> + ((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
> >> +PRCI_DDRPLLCFG0_LOCK_MASK
> >> +
> >> /*
> >> * Private structures
> >> */
> >> @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk)
> >> return pc->ops->enable_clk(pc, 0); }
> >>
> >> +#ifdef CONFIG_SPL_BUILD
> >> +static void corepll_init(struct udevice *dev) {
>
> Will convert corepll into DM
>
> >> + u32 v;
> >> + struct clk clock;
> >> + struct __prci_data *pd = dev_get_priv(dev);
> >> +
> >> + v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
> >> + v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
> >> +
> >> + clock.id = PRCI_CLK_COREPLL;
> >> +
> >> + if (v) {
> >> + /* corepll 500 Mhz */
> >> + sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
> >> + } else {
> >> + /* corepll 1 Ghz */
> >> + sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
> >> + }
> >> +
> >> + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
> >> +1); }
> >> +
> >> +static void ddr_init(struct udevice *dev) {
> >> + u32 v;
> >> + struct clk clock;
> >> + struct __prci_data *pd = dev_get_priv(dev);
> >> +
> >> + //DDR init
> >> + u32 ddrctlmhz =
> >> + (PLL_R(0)) |
> >> + (PLL_F(DDRCTLPLL_F)) |
> >> + (PLL_Q(DDRCTLPLL_Q)) |
> >> + (PLL_RANGE(0x4)) |
> >> + (PLL_BYPASS(0)) |
> >> + (PLL_FSE(1));
> >> + __prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
> >> +
> >> + clock.id = PRCI_CLK_DDRPLL;
> >> + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
> >> + 1);
> >> +
> >> + /* Release DDR reset */
> >> + 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");
> >> +}
>
> With DDR clock DM,
> DDR clock can be enabled by clk_enable() and set rate with clk_set_rate() but after this
> DDR clock Reset needs to be released as shown below,
>
> /* Release DDR reset */
> v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
> v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
> __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
>
> Do you guys have any suggestion how to Release DDR reset in DM way in SPL or current implementation is
> fine for DDR clock initialization ?
Is it possible to do the DDR reset as part of the clk_enable() for the
DDR clock?
>
> >> +
> >> +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);
> >> +}
>
> SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled.
> So I am not planning to make any changes in ethernet_init() in v7
>
If performing DDR reset is not possible with clk_enable, we can leave
that here ...
> Any suggestions are welcome
>
Regards,
Bin
More information about the U-Boot
mailing list