[U-Boot] [PATCH v9 4/9] clk: sifive: Sync-up main driver with upstream Linux
Rick Chen
rickchen36 at gmail.com
Fri Jul 19 05:50:16 UTC 2019
> > From: Anup Patel [mailto:Anup.Patel at wdc.com]
> > Sent: Tuesday, June 25, 2019 2:31 PM
> > To: Rick Jian-Zhi Chen(陳建志); Bin Meng; Lukas Auer; Simon Glass
> > Cc: Ramon Fried; Joe Hershberger; Palmer Dabbelt; Paul Walmsley; Troy
> > Benjegerdes; Atish Patra; Alistair Francis; U-Boot Mailing List; Anup Patel
> > Subject: [PATCH v9 4/9] clk: sifive: Sync-up main driver with upstream Linux
> >
> > The DT bindings of SiFive clock driver in upstream Linux has changes. As-per
> > latest DT bindings, the clock driver takes two parent clocks and compatible string
> > has also changed.
> >
> > This patch sync-up SiFive clock driver implementation as-per upstream Linux so
> > that we now use latest DT bindings.
> >
> > Signed-off-by: Anup Patel <anup.patel at wdc.com>
> > Reviewed-by: Bin Meng <bmeng.cn at gmail.com>
> > ---
> > drivers/clk/sifive/fu540-prci.c | 96 ++++++++++++++++++++-------------
> > 1 file changed, 60 insertions(+), 36 deletions(-)
> >
> > diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index
> > ceb318e062..ce0769f2d1 100644
> > --- a/drivers/clk/sifive/fu540-prci.c
> > +++ b/drivers/clk/sifive/fu540-prci.c
> > @@ -158,30 +158,32 @@
> > * PRCI per-device instance data
> > */
> > struct __prci_data {
> > - void *base;
> > - struct clk parent;
> > + void *va;
> > + struct clk parent_hfclk;
> > + struct clk parent_rtcclk;
> > };
> >
> > /**
> > * struct __prci_wrpll_data - WRPLL configuration and integration data
> > * @c: WRPLL current configuration record
> > - * @bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
> > - * @no_bypass: fn ptr to code to not bypass the WRPLL (if applicable; else
> > NULL)
> > + * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable;
> > + else NULL)
> > + * @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
> > *
> > - * @bypass and @no_bypass are used for WRPLL instances that contain a
> > separate
> > - * external glitchless clock mux downstream from the PLL. The WRPLL internal
> > - * bypass mux is not glitchless.
> > + * @enable_bypass and @disable_bypass are used for WRPLL instances
> > + * that contain a separate external glitchless clock mux downstream
> > + * from the PLL. The WRPLL internal bypass mux is not glitchless.
> > */
> > struct __prci_wrpll_data {
> > struct wrpll_cfg c;
> > - void (*bypass)(struct __prci_data *pd);
> > - void (*no_bypass)(struct __prci_data *pd);
> > + void (*enable_bypass)(struct __prci_data *pd);
> > + void (*disable_bypass)(struct __prci_data *pd);
> > u8 cfg0_offs;
> > };
> >
> > struct __prci_clock;
> >
> > +/* struct __prci_clock_ops - clock operations */
> > struct __prci_clock_ops {
> > int (*set_rate)(struct __prci_clock *pc,
> > unsigned long rate,
> > @@ -197,8 +199,7 @@ struct __prci_clock_ops {
> > * struct __prci_clock - describes a clock device managed by PRCI
> > * @name: user-readable clock name string - should match the manual
> > * @parent_name: parent name for this clock
> > - * @ops: struct clk_ops for the Linux clock framework to use for control
> > - * @hw: Linux-private clock data
> > + * @ops: struct __prci_clock_ops for control
> > * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
> > * @pd: PRCI-specific data associated with this clock (if not NULL)
> > *
> > @@ -232,12 +233,12 @@ struct __prci_clock {
> > */
> > static u32 __prci_readl(struct __prci_data *pd, u32 offs) {
> > - return readl(pd->base + offs);
> > + return readl(pd->va + offs);
> > }
> >
> > static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd) {
> > - return writel(v, pd->base + offs);
> > + writel(v, pd->va + offs);
> > }
> >
> > /* WRPLL-related private functions */
> > @@ -279,10 +280,8 @@ static void __prci_wrpll_unpack(struct wrpll_cfg *c,
> > u32 r)
> > c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
> > WRPLL_FLAGS_EXT_FEEDBACK_MASK);
> >
> > - if (r & PRCI_COREPLLCFG0_FSE_MASK)
> > - c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
> > - else
> > - c->flags |= WRPLL_FLAGS_EXT_FEEDBACK_MASK;
> > + /* external feedback mode not supported */
> > + c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
> > }
> >
> > /**
> > @@ -300,7 +299,7 @@ static void __prci_wrpll_unpack(struct wrpll_cfg *c,
> > u32 r)
> > * Returns: a value suitable for writing into a PRCI PLL configuration
> > * register
> > */
> > -static u32 __prci_wrpll_pack(struct wrpll_cfg *c)
> > +static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
> > {
> > u32 r = 0;
> >
> > @@ -308,8 +307,9 @@ static u32 __prci_wrpll_pack(struct wrpll_cfg *c)
> > r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
> > r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
> > r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
> > - if (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK)
> > - r |= PRCI_COREPLLCFG0_FSE_MASK;
> > +
> > + /* external feedback mode not supported */
> > + r |= PRCI_COREPLLCFG0_FSE_MASK;
> >
> > return r;
> > }
> > @@ -352,7 +352,7 @@ static void __prci_wrpll_write_cfg(struct __prci_data
> > *pd, {
> > __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
> >
> > - memcpy(&pwd->c, c, sizeof(struct wrpll_cfg));
> > + memcpy(&pwd->c, c, sizeof(*c));
> > }
> >
> > /* Core clock mux control */
> > @@ -431,17 +431,17 @@ static int sifive_fu540_prci_wrpll_set_rate(struct
> > __prci_clock *pc,
> >
> > r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
> > if (r)
> > - return -ERANGE;
> > + return r;
> >
> > - if (pwd->bypass)
> > - pwd->bypass(pd);
> > + if (pwd->enable_bypass)
> > + pwd->enable_bypass(pd);
> >
> > __prci_wrpll_write_cfg(pd, pwd, &pwd->c);
> >
> > udelay(wrpll_calc_max_lock_us(&pwd->c));
> >
> > - if (pwd->no_bypass)
> > - pwd->no_bypass(pd);
> > + if (pwd->disable_bypass)
> > + pwd->disable_bypass(pd);
> >
> > return 0;
> > }
> > @@ -483,8 +483,8 @@ static const struct __prci_clock_ops
> > sifive_fu540_prci_tlclksel_clk_ops = {
> >
> > static struct __prci_wrpll_data __prci_corepll_data = {
> > .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
> > - .bypass = __prci_coreclksel_use_hfclk,
> > - .no_bypass = __prci_coreclksel_use_corepll,
> > + .enable_bypass = __prci_coreclksel_use_hfclk,
> > + .disable_bypass = __prci_coreclksel_use_corepll,
> > };
> >
> > static struct __prci_wrpll_data __prci_ddrpll_data = { @@ -525,6 +525,27
> > @@ static struct __prci_clock __prci_init_clocks[] = {
> > },
> > };
> >
> > +static ulong sifive_fu540_prci_parent_rate(struct __prci_clock *pc) {
> > + ulong parent_rate;
> > + struct __prci_clock *p;
> > +
> > + if (strcmp(pc->parent_name, "corepll") == 0) {
> > + p = &__prci_init_clocks[PRCI_CLK_COREPLL];
> > + if (!p->pd || !p->ops->recalc_rate)
> > + return -ENXIO;
> > +
> > + return p->ops->recalc_rate(p, sifive_fu540_prci_parent_rate(p));
> > + }
> > +
> > + if (strcmp(pc->parent_name, "rtcclk") == 0)
> > + parent_rate = clk_get_rate(&pc->pd->parent_rtcclk);
> > + else
> > + parent_rate = clk_get_rate(&pc->pd->parent_hfclk);
> > +
> > + return parent_rate;
> > +}
> > +
> > static ulong sifive_fu540_prci_get_rate(struct clk *clk) {
> > struct __prci_clock *pc;
> > @@ -536,7 +557,7 @@ static ulong sifive_fu540_prci_get_rate(struct clk *clk)
> > if (!pc->pd || !pc->ops->recalc_rate)
> > return -ENXIO;
> >
> > - return pc->ops->recalc_rate(pc, clk_get_rate(&pc->pd->parent));
> > + return pc->ops->recalc_rate(pc, sifive_fu540_prci_parent_rate(pc));
> > }
> >
> > static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate) @@ -551,7
> > +572,7 @@ static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate)
> > if (!pc->pd || !pc->ops->set_rate)
> > return -ENXIO;
> >
> > - err = pc->ops->set_rate(pc, rate, clk_get_rate(&pc->pd->parent));
> > + err = pc->ops->set_rate(pc, rate, sifive_fu540_prci_parent_rate(pc));
> > if (err)
> > return err;
> >
> > @@ -564,11 +585,15 @@ static int sifive_fu540_prci_probe(struct udevice
> > *dev)
> > struct __prci_clock *pc;
> > struct __prci_data *pd = dev_get_priv(dev);
> >
> > - pd->base = (void *)dev_read_addr(dev);
> > - if (IS_ERR(pd->base))
> > - return PTR_ERR(pd->base);
> > + pd->va = (void *)dev_read_addr(dev);
> > + if (IS_ERR(pd->va))
> > + return PTR_ERR(pd->va);
> > +
> > + err = clk_get_by_index(dev, 0, &pd->parent_hfclk);
> > + if (err)
> > + return err;
> >
> > - err = clk_get_by_index(dev, 0, &pd->parent);
> > + err = clk_get_by_index(dev, 1, &pd->parent_rtcclk);
> > if (err)
> > return err;
> >
> > @@ -588,8 +613,7 @@ static struct clk_ops sifive_fu540_prci_ops = { };
> >
> > static const struct udevice_id sifive_fu540_prci_ids[] = {
> > - { .compatible = "sifive,fu540-c000-prci0" },
> > - { .compatible = "sifive,aloeprci0" },
> > + { .compatible = "sifive,fu540-c000-prci" },
> > { }
> > };
> >
Applied to u-boot-riscv/master, thanks!
Rick
More information about the U-Boot
mailing list