diff mbox series

[v5,08/14] clk: sifive: fu540-prci: Add clock enable and disable ops

Message ID 20200311070320.21323-9-pragnesh.patel@sifive.com
State New
Headers show
Series RISC-V SiFive FU540 support SPL | expand

Commit Message

Pragnesh Patel March 11, 2020, 7:03 a.m. UTC
Added clock enable and disable functions in prci ops

Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
---
 drivers/clk/sifive/fu540-prci.c | 75 +++++++++++++++++++++++++++++++--
 1 file changed, 72 insertions(+), 3 deletions(-)

Comments

Bin Meng March 13, 2020, 7:57 a.m. UTC | #1
On Wed, Mar 11, 2020 at 3:04 PM Pragnesh Patel
<pragnesh.patel at sifive.com> wrote:
>
> Added clock enable and disable functions in prci ops
>
> Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
> ---
>  drivers/clk/sifive/fu540-prci.c | 75 +++++++++++++++++++++++++++++++--
>  1 file changed, 72 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
> index 8847178001..c02c0466a8 100644
> --- a/drivers/clk/sifive/fu540-prci.c
> +++ b/drivers/clk/sifive/fu540-prci.c
> @@ -68,6 +68,11 @@
>  #define PRCI_COREPLLCFG0_LOCK_SHIFT    31
>  #define PRCI_COREPLLCFG0_LOCK_MASK     (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
>
> +/* COREPLLCFG1 */
> +#define PRCI_COREPLLCFG1_OFFSET                0x8
> +#define PRCI_COREPLLCFG1_CKE_SHIFT     31
> +#define PRCI_COREPLLCFG1_CKE_MASK      (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
> +
>  /* DDRPLLCFG0 */
>  #define PRCI_DDRPLLCFG0_OFFSET         0xc
>  #define PRCI_DDRPLLCFG0_DIVR_SHIFT     0
> @@ -87,7 +92,7 @@
>
>  /* DDRPLLCFG1 */
>  #define PRCI_DDRPLLCFG1_OFFSET         0x10
> -#define PRCI_DDRPLLCFG1_CKE_SHIFT      24
> +#define PRCI_DDRPLLCFG1_CKE_SHIFT      31
>  #define PRCI_DDRPLLCFG1_CKE_MASK       (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
>
>  /* GEMGXLPLLCFG0 */
> @@ -114,7 +119,7 @@
>
>  /* GEMGXLPLLCFG1 */
>  #define PRCI_GEMGXLPLLCFG1_OFFSET      0x20
> -#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT   24
> +#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT   31
>  #define PRCI_GEMGXLPLLCFG1_CKE_MASK    (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
>
>  /* CORECLKSEL */
> @@ -142,7 +147,7 @@
>                         (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
>
>  /* CLKMUXSTATUSREG */
> -#define PRCI_CLKMUXSTATUSREG_OFFSET            0x2c
> +#define PRCI_CLKMUXSTATUSREG_OFFSET    0x2c
>  #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1
>  #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
>                         (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
> @@ -170,6 +175,7 @@ struct __prci_data {
>   * @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
> + * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
>   *
>   * @enable_bypass and @disable_bypass are used for WRPLL instances
>   * that contain a separate external glitchless clock mux downstream
> @@ -180,6 +186,7 @@ struct __prci_wrpll_data {
>         void (*enable_bypass)(struct __prci_data *pd);
>         void (*disable_bypass)(struct __prci_data *pd);
>         u8 cfg0_offs;
> +       u8 cfg1_offs;
>  };
>
>  struct __prci_clock;
> @@ -194,6 +201,7 @@ struct __prci_clock_ops {
>                                     unsigned long *parent_rate);
>         unsigned long (*recalc_rate)(struct __prci_clock *pc,
>                                      unsigned long parent_rate);
> +       int (*enable_clk)(struct __prci_clock *pc, bool enable);
>  };
>
>  /**
> @@ -356,6 +364,13 @@ static void __prci_wrpll_write_cfg(struct __prci_data *pd,
>         memcpy(&pwd->c, c, sizeof(*c));
>  }
>
> +static void __prci_wrpll_write_cfg1(struct __prci_data *pd,

nits: we should also rename the existing function
__prci_wrpll_write_cfg() to __prci_wrpll_write_cfg0()

> +                                   struct __prci_wrpll_data *pwd,
> +                                   u32 enable)
> +{
> +       __prci_writel(enable, pwd->cfg1_offs, pd);
> +}
> +

[snip]

Regards,
Bin
Pragnesh Patel March 13, 2020, 8:15 a.m. UTC | #2
Hi Bin,

>-----Original Message-----
>From: Bin Meng <bmeng.cn at gmail.com>
>Sent: 13 March 2020 13:27
>To: Pragnesh Patel <pragnesh.patel at sifive.com>
>Cc: U-Boot Mailing List <u-boot at lists.denx.de>; Atish Patra
><atish.patra at wdc.com>; Palmer Dabbelt <palmerdabbelt at google.com>; Paul
>Walmsley <paul.walmsley at sifive.com>; Jagan Teki
><jagan at amarulasolutions.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>; Anatolij Gustschin <agust at denx.de>; Simon
>Glass <sjg at chromium.org>
>Subject: Re: [PATCH v5 08/14] clk: sifive: fu540-prci: Add clock enable and
>disable ops
>
>On Wed, Mar 11, 2020 at 3:04 PM Pragnesh Patel
><pragnesh.patel at sifive.com> wrote:
>>
>> Added clock enable and disable functions in prci ops
>>
>> Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
>> ---
>>  drivers/clk/sifive/fu540-prci.c | 75
>> +++++++++++++++++++++++++++++++--
>>  1 file changed, 72 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/clk/sifive/fu540-prci.c
>> b/drivers/clk/sifive/fu540-prci.c index 8847178001..c02c0466a8 100644
>> --- a/drivers/clk/sifive/fu540-prci.c
>> +++ b/drivers/clk/sifive/fu540-prci.c
>> @@ -68,6 +68,11 @@
>>  #define PRCI_COREPLLCFG0_LOCK_SHIFT    31
>>  #define PRCI_COREPLLCFG0_LOCK_MASK     (0x1 <<
>PRCI_COREPLLCFG0_LOCK_SHIFT)
>>
>> +/* COREPLLCFG1 */
>> +#define PRCI_COREPLLCFG1_OFFSET                0x8
>> +#define PRCI_COREPLLCFG1_CKE_SHIFT     31
>> +#define PRCI_COREPLLCFG1_CKE_MASK      (0x1 <<
>PRCI_COREPLLCFG1_CKE_SHIFT)
>> +
>>  /* DDRPLLCFG0 */
>>  #define PRCI_DDRPLLCFG0_OFFSET         0xc
>>  #define PRCI_DDRPLLCFG0_DIVR_SHIFT     0
>> @@ -87,7 +92,7 @@
>>
>>  /* DDRPLLCFG1 */
>>  #define PRCI_DDRPLLCFG1_OFFSET         0x10
>> -#define PRCI_DDRPLLCFG1_CKE_SHIFT      24
>> +#define PRCI_DDRPLLCFG1_CKE_SHIFT      31
>>  #define PRCI_DDRPLLCFG1_CKE_MASK       (0x1 <<
>PRCI_DDRPLLCFG1_CKE_SHIFT)
>>
>>  /* GEMGXLPLLCFG0 */
>> @@ -114,7 +119,7 @@
>>
>>  /* GEMGXLPLLCFG1 */
>>  #define PRCI_GEMGXLPLLCFG1_OFFSET      0x20
>> -#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT   24
>> +#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT   31
>>  #define PRCI_GEMGXLPLLCFG1_CKE_MASK    (0x1 <<
>PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
>>
>>  /* CORECLKSEL */
>> @@ -142,7 +147,7 @@
>>                         (0x1 <<
>> PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
>>
>>  /* CLKMUXSTATUSREG */
>> -#define PRCI_CLKMUXSTATUSREG_OFFSET            0x2c
>> +#define PRCI_CLKMUXSTATUSREG_OFFSET    0x2c
>>  #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1  #define
>> PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
>>                         (0x1 <<
>> PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
>> @@ -170,6 +175,7 @@ struct __prci_data {
>>   * @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
>> + * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI
>> + base address
>>   *
>>   * @enable_bypass and @disable_bypass are used for WRPLL instances
>>   * that contain a separate external glitchless clock mux downstream
>> @@ -180,6 +186,7 @@ struct __prci_wrpll_data {
>>         void (*enable_bypass)(struct __prci_data *pd);
>>         void (*disable_bypass)(struct __prci_data *pd);
>>         u8 cfg0_offs;
>> +       u8 cfg1_offs;
>>  };
>>
>>  struct __prci_clock;
>> @@ -194,6 +201,7 @@ struct __prci_clock_ops {
>>                                     unsigned long *parent_rate);
>>         unsigned long (*recalc_rate)(struct __prci_clock *pc,
>>                                      unsigned long parent_rate);
>> +       int (*enable_clk)(struct __prci_clock *pc, bool enable);
>>  };
>>
>>  /**
>> @@ -356,6 +364,13 @@ static void __prci_wrpll_write_cfg(struct
>__prci_data *pd,
>>         memcpy(&pwd->c, c, sizeof(*c));  }
>>
>> +static void __prci_wrpll_write_cfg1(struct __prci_data *pd,
>
>nits: we should also rename the existing function
>__prci_wrpll_write_cfg() to __prci_wrpll_write_cfg0()
>

I think you are right. I will check and update in v6.

>> +                                   struct __prci_wrpll_data *pwd,
>> +                                   u32 enable) {
>> +       __prci_writel(enable, pwd->cfg1_offs, pd); }
>> +
>
>[snip]
>
>Regards,
>Bin
diff mbox series

Patch

diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
index 8847178001..c02c0466a8 100644
--- a/drivers/clk/sifive/fu540-prci.c
+++ b/drivers/clk/sifive/fu540-prci.c
@@ -68,6 +68,11 @@ 
 #define PRCI_COREPLLCFG0_LOCK_SHIFT	31
 #define PRCI_COREPLLCFG0_LOCK_MASK	(0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
 
+/* COREPLLCFG1 */
+#define PRCI_COREPLLCFG1_OFFSET		0x8
+#define PRCI_COREPLLCFG1_CKE_SHIFT	31
+#define PRCI_COREPLLCFG1_CKE_MASK	(0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
+
 /* DDRPLLCFG0 */
 #define PRCI_DDRPLLCFG0_OFFSET		0xc
 #define PRCI_DDRPLLCFG0_DIVR_SHIFT	0
@@ -87,7 +92,7 @@ 
 
 /* DDRPLLCFG1 */
 #define PRCI_DDRPLLCFG1_OFFSET		0x10
-#define PRCI_DDRPLLCFG1_CKE_SHIFT	24
+#define PRCI_DDRPLLCFG1_CKE_SHIFT	31
 #define PRCI_DDRPLLCFG1_CKE_MASK	(0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
 
 /* GEMGXLPLLCFG0 */
@@ -114,7 +119,7 @@ 
 
 /* GEMGXLPLLCFG1 */
 #define PRCI_GEMGXLPLLCFG1_OFFSET	0x20
-#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT	24
+#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT	31
 #define PRCI_GEMGXLPLLCFG1_CKE_MASK	(0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
 
 /* CORECLKSEL */
@@ -142,7 +147,7 @@ 
 			(0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
 
 /* CLKMUXSTATUSREG */
-#define PRCI_CLKMUXSTATUSREG_OFFSET		0x2c
+#define PRCI_CLKMUXSTATUSREG_OFFSET	0x2c
 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1
 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
 			(0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
@@ -170,6 +175,7 @@  struct __prci_data {
  * @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
+ * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
  *
  * @enable_bypass and @disable_bypass are used for WRPLL instances
  * that contain a separate external glitchless clock mux downstream
@@ -180,6 +186,7 @@  struct __prci_wrpll_data {
 	void (*enable_bypass)(struct __prci_data *pd);
 	void (*disable_bypass)(struct __prci_data *pd);
 	u8 cfg0_offs;
+	u8 cfg1_offs;
 };
 
 struct __prci_clock;
@@ -194,6 +201,7 @@  struct __prci_clock_ops {
 				    unsigned long *parent_rate);
 	unsigned long (*recalc_rate)(struct __prci_clock *pc,
 				     unsigned long parent_rate);
+	int (*enable_clk)(struct __prci_clock *pc, bool enable);
 };
 
 /**
@@ -356,6 +364,13 @@  static void __prci_wrpll_write_cfg(struct __prci_data *pd,
 	memcpy(&pwd->c, c, sizeof(*c));
 }
 
+static void __prci_wrpll_write_cfg1(struct __prci_data *pd,
+				    struct __prci_wrpll_data *pwd,
+				    u32 enable)
+{
+	__prci_writel(enable, pwd->cfg1_offs, pd);
+}
+
 /* Core clock mux control */
 
 /**
@@ -447,14 +462,35 @@  static int sifive_fu540_prci_wrpll_set_rate(struct __prci_clock *pc,
 	return 0;
 }
 
+static int sifive_fu540_prci_clock_enable(struct __prci_clock *pc, bool enable)
+{
+	struct __prci_wrpll_data *pwd = pc->pwd;
+	struct __prci_data *pd = pc->pd;
+
+	if (enable) {
+		__prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
+	} else {
+		u32 r;
+
+		r = __prci_readl(pd, pwd->cfg1_offs);
+		r &= ~PRCI_COREPLLCFG1_CKE_MASK;
+
+		__prci_wrpll_write_cfg1(pd, pwd, r);
+	}
+
+	return 0;
+}
+
 static const struct __prci_clock_ops sifive_fu540_prci_wrpll_clk_ops = {
 	.set_rate = sifive_fu540_prci_wrpll_set_rate,
 	.round_rate = sifive_fu540_prci_wrpll_round_rate,
 	.recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
+	.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 */
@@ -484,16 +520,19 @@  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,
+	.cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
 	.enable_bypass = __prci_coreclksel_use_hfclk,
 	.disable_bypass = __prci_coreclksel_use_corepll,
 };
 
 static struct __prci_wrpll_data __prci_ddrpll_data = {
 	.cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
+	.cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
 };
 
 static struct __prci_wrpll_data __prci_gemgxlpll_data = {
 	.cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
+	.cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
 };
 
 /*
@@ -580,6 +619,34 @@  static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate)
 	return rate;
 }
 
+static int sifive_fu540_prci_enable(struct clk *clk)
+{
+	struct __prci_clock *pc;
+
+	if (ARRAY_SIZE(__prci_init_clocks) <= clk->id)
+		return -ENXIO;
+
+	pc = &__prci_init_clocks[clk->id];
+	if (!pc->pd || !pc->ops->enable_clk)
+		return -ENXIO;
+
+	return pc->ops->enable_clk(pc, 1);
+}
+
+static int sifive_fu540_prci_disable(struct clk *clk)
+{
+	struct __prci_clock *pc;
+
+	if (ARRAY_SIZE(__prci_init_clocks) <= clk->id)
+		return -ENXIO;
+
+	pc = &__prci_init_clocks[clk->id];
+	if (!pc->pd || !pc->ops->enable_clk)
+		return -ENXIO;
+
+	return pc->ops->enable_clk(pc, 0);
+}
+
 static int sifive_fu540_prci_probe(struct udevice *dev)
 {
 	int i, err;
@@ -611,6 +678,8 @@  static int sifive_fu540_prci_probe(struct udevice *dev)
 static struct clk_ops sifive_fu540_prci_ops = {
 	.set_rate = sifive_fu540_prci_set_rate,
 	.get_rate = sifive_fu540_prci_get_rate,
+	.enable = sifive_fu540_prci_enable,
+	.disable = sifive_fu540_prci_disable,
 };
 
 static const struct udevice_id sifive_fu540_prci_ids[] = {