diff mbox series

[U-Boot,v9,4/9] clk: sifive: Sync-up main driver with upstream Linux

Message ID 20190625063030.6200-5-anup.patel@wdc.com
State Accepted
Commit ed0ef3776c209c5aefdb0bdf808a3dbdbccd1182
Delegated to: Joe Hershberger
Headers show
Series Update SiFive Unleashed Drivers | expand

Commit Message

Anup Patel June 25, 2019, 6:31 a.m. UTC
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@wdc.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
 drivers/clk/sifive/fu540-prci.c | 96 ++++++++++++++++++++-------------
 1 file changed, 60 insertions(+), 36 deletions(-)

Comments

Rick Chen July 19, 2019, 5:50 a.m. UTC | #1
> > From: Anup Patel [mailto:Anup.Patel@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@wdc.com>
> > Reviewed-by: Bin Meng <bmeng.cn@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
diff mbox series

Patch

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" },
 	{ }
 };