[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