
Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 02 May 2020 17:58 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Jagan Teki jagan@amarulasolutions.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Anatolij Gustschin agust@denx.de; Simon Glass sjg@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@sifive.com wrote:
Add ddr clock release reset and ehternet clock initialization for SPL
Signed-off-by: Pragnesh Patel pragnesh.patel@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