linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Add functions to operate USB PHY related clock.
@ 2020-06-26 16:48 周琰杰 (Zhou Yanjie)
  2020-06-26 16:48 ` [PATCH 1/2] clk: JZ4780: Add functions for enable and disable USB PHY 周琰杰 (Zhou Yanjie)
  2020-06-26 16:48 ` [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of " 周琰杰 (Zhou Yanjie)
  0 siblings, 2 replies; 9+ messages in thread
From: 周琰杰 (Zhou Yanjie) @ 2020-06-26 16:48 UTC (permalink / raw)
  To: linux-clk
  Cc: linux-kernel, sboyd, paul, mturquette, dongsheng.qiu, aric.pzqi,
	rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

1.Add functions for enable and disable USB PHY in JZ4780.
2.Add support for calculat REFCLK of USB PHY in X1000.

周琰杰 (Zhou Yanjie) (2):
  clk: JZ4780: Add functions for enable and disable USB PHY.
  clk: X1000: Add support for calculat REFCLK of USB PHY.

 drivers/clk/ingenic/jz4780-cgu.c | 124 +++++++++++++++++++++++++--------------
 drivers/clk/ingenic/x1000-cgu.c  | 113 +++++++++++++++++++++++++++++++++++
 2 files changed, 193 insertions(+), 44 deletions(-)

-- 
2.11.0



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/2] clk: JZ4780: Add functions for enable and disable USB PHY.
  2020-06-26 16:48 [PATCH 0/2] Add functions to operate USB PHY related clock 周琰杰 (Zhou Yanjie)
@ 2020-06-26 16:48 ` 周琰杰 (Zhou Yanjie)
  2020-06-26 17:20   ` Paul Cercueil
  2020-06-26 16:48 ` [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of " 周琰杰 (Zhou Yanjie)
  1 sibling, 1 reply; 9+ messages in thread
From: 周琰杰 (Zhou Yanjie) @ 2020-06-26 16:48 UTC (permalink / raw)
  To: linux-clk
  Cc: linux-kernel, sboyd, paul, mturquette, dongsheng.qiu, aric.pzqi,
	rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Add new functions to "jz4780_otg_phy_ops" to enable or disable the
USB PHY in the Ingenic JZ4780 SoC.

Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
---
 drivers/clk/ingenic/jz4780-cgu.c | 124 +++++++++++++++++++++++++--------------
 1 file changed, 80 insertions(+), 44 deletions(-)

diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
index 6c5b8029cc8a..0ec50b9ab9c1 100644
--- a/drivers/clk/ingenic/jz4780-cgu.c
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2013-2015 Imagination Technologies
  * Author: Paul Burton <paul.burton@mips.com>
+ * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
  */
 
 #include <linux/clk-provider.h>
@@ -19,55 +20,57 @@
 
 /* CGU register offsets */
 #define CGU_REG_CLOCKCONTROL	0x00
-#define CGU_REG_LCR			0x04
-#define CGU_REG_APLL		0x10
-#define CGU_REG_MPLL		0x14
-#define CGU_REG_EPLL		0x18
-#define CGU_REG_VPLL		0x1c
-#define CGU_REG_CLKGR0		0x20
-#define CGU_REG_OPCR		0x24
-#define CGU_REG_CLKGR1		0x28
-#define CGU_REG_DDRCDR		0x2c
-#define CGU_REG_VPUCDR		0x30
-#define CGU_REG_USBPCR		0x3c
-#define CGU_REG_USBRDT		0x40
-#define CGU_REG_USBVBFIL	0x44
-#define CGU_REG_USBPCR1		0x48
-#define CGU_REG_LP0CDR		0x54
-#define CGU_REG_I2SCDR		0x60
-#define CGU_REG_LP1CDR		0x64
-#define CGU_REG_MSC0CDR		0x68
-#define CGU_REG_UHCCDR		0x6c
-#define CGU_REG_SSICDR		0x74
-#define CGU_REG_CIMCDR		0x7c
-#define CGU_REG_PCMCDR		0x84
-#define CGU_REG_GPUCDR		0x88
-#define CGU_REG_HDMICDR		0x8c
-#define CGU_REG_MSC1CDR		0xa4
-#define CGU_REG_MSC2CDR		0xa8
-#define CGU_REG_BCHCDR		0xac
-#define CGU_REG_CLOCKSTATUS	0xd4
+#define CGU_REG_LCR				0x04
+#define CGU_REG_APLL			0x10
+#define CGU_REG_MPLL			0x14
+#define CGU_REG_EPLL			0x18
+#define CGU_REG_VPLL			0x1c
+#define CGU_REG_CLKGR0			0x20
+#define CGU_REG_OPCR			0x24
+#define CGU_REG_CLKGR1			0x28
+#define CGU_REG_DDRCDR			0x2c
+#define CGU_REG_VPUCDR			0x30
+#define CGU_REG_USBPCR			0x3c
+#define CGU_REG_USBRDT			0x40
+#define CGU_REG_USBVBFIL		0x44
+#define CGU_REG_USBPCR1			0x48
+#define CGU_REG_LP0CDR			0x54
+#define CGU_REG_I2SCDR			0x60
+#define CGU_REG_LP1CDR			0x64
+#define CGU_REG_MSC0CDR			0x68
+#define CGU_REG_UHCCDR			0x6c
+#define CGU_REG_SSICDR			0x74
+#define CGU_REG_CIMCDR			0x7c
+#define CGU_REG_PCMCDR			0x84
+#define CGU_REG_GPUCDR			0x88
+#define CGU_REG_HDMICDR			0x8c
+#define CGU_REG_MSC1CDR			0xa4
+#define CGU_REG_MSC2CDR			0xa8
+#define CGU_REG_BCHCDR			0xac
+#define CGU_REG_CLOCKSTATUS		0xd4
 
 /* bits within the OPCR register */
-#define OPCR_SPENDN0		BIT(7)
-#define OPCR_SPENDN1		BIT(6)
+#define OPCR_SPENDN0			BIT(7)
+#define OPCR_SPENDN1			BIT(6)
 
 /* bits within the USBPCR register */
-#define USBPCR_USB_MODE		BIT(31)
+#define USBPCR_USB_MODE			BIT(31)
 #define USBPCR_IDPULLUP_MASK	(0x3 << 28)
-#define USBPCR_COMMONONN	BIT(25)
-#define USBPCR_VBUSVLDEXT	BIT(24)
+#define USBPCR_COMMONONN		BIT(25)
+#define USBPCR_VBUSVLDEXT		BIT(24)
 #define USBPCR_VBUSVLDEXTSEL	BIT(23)
-#define USBPCR_POR		BIT(22)
-#define USBPCR_OTG_DISABLE	BIT(20)
+#define USBPCR_POR				BIT(22)
+#define USBPCR_SIDDQ			BIT(21)
+#define USBPCR_OTG_DISABLE		BIT(20)
 #define USBPCR_COMPDISTUNE_MASK	(0x7 << 17)
-#define USBPCR_OTGTUNE_MASK	(0x7 << 14)
+#define USBPCR_OTGTUNE_MASK		(0x7 << 14)
 #define USBPCR_SQRXTUNE_MASK	(0x7 << 11)
 #define USBPCR_TXFSLSTUNE_MASK	(0xf << 7)
 #define USBPCR_TXPREEMPHTUNE	BIT(6)
 #define USBPCR_TXHSXVTUNE_MASK	(0x3 << 4)
 #define USBPCR_TXVREFTUNE_MASK	0xf
 
+
 /* bits within the USBPCR1 register */
 #define USBPCR1_REFCLKSEL_SHIFT	26
 #define USBPCR1_REFCLKSEL_MASK	(0x3 << USBPCR1_REFCLKSEL_SHIFT)
@@ -78,13 +81,13 @@
 #define USBPCR1_REFCLKDIV_48	(0x2 << USBPCR1_REFCLKDIV_SHIFT)
 #define USBPCR1_REFCLKDIV_24	(0x1 << USBPCR1_REFCLKDIV_SHIFT)
 #define USBPCR1_REFCLKDIV_12	(0x0 << USBPCR1_REFCLKDIV_SHIFT)
-#define USBPCR1_USB_SEL		BIT(28)
-#define USBPCR1_WORD_IF0	BIT(19)
-#define USBPCR1_WORD_IF1	BIT(18)
+#define USBPCR1_USB_SEL			BIT(28)
+#define USBPCR1_WORD_IF0		BIT(19)
+#define USBPCR1_WORD_IF1		BIT(18)
 
 /* bits within the USBRDT register */
-#define USBRDT_VBFIL_LD_EN	BIT(25)
-#define USBRDT_USBRDT_MASK	0x7fffff
+#define USBRDT_VBFIL_LD_EN		BIT(25)
+#define USBRDT_USBRDT_MASK		0x7fffff
 
 /* bits within the USBVBFIL register */
 #define USBVBFIL_IDDIGFIL_SHIFT	16
@@ -92,11 +95,11 @@
 #define USBVBFIL_USBVBFIL_MASK	(0xffff)
 
 /* bits within the LCR register */
-#define LCR_PD_SCPU			BIT(31)
-#define LCR_SCPUS			BIT(27)
+#define LCR_PD_SCPU				BIT(31)
+#define LCR_SCPUS				BIT(27)
 
 /* bits within the CLKGR1 register */
-#define CLKGR1_CORE1		BIT(15)
+#define CLKGR1_CORE1			BIT(15)
 
 static struct ingenic_cgu *cgu;
 
@@ -206,6 +209,35 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
 	return 0;
 }
 
+static int jz4780_otg_phy_enable(struct clk_hw *hw)
+{
+	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
+	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
+
+	writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
+	writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
+	return 0;
+}
+
+static void jz4780_otg_phy_disable(struct clk_hw *hw)
+{
+	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
+	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
+
+	writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
+	writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
+}
+
+static int jz4780_otg_phy_is_enabled(struct clk_hw *hw)
+{
+	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
+	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
+
+	return (readl(reg_opcr) & OPCR_SPENDN0) &&
+		!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
+		!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
+}
+
 static const struct clk_ops jz4780_otg_phy_ops = {
 	.get_parent = jz4780_otg_phy_get_parent,
 	.set_parent = jz4780_otg_phy_set_parent,
@@ -213,6 +245,10 @@ static const struct clk_ops jz4780_otg_phy_ops = {
 	.recalc_rate = jz4780_otg_phy_recalc_rate,
 	.round_rate = jz4780_otg_phy_round_rate,
 	.set_rate = jz4780_otg_phy_set_rate,
+
+	.enable		= jz4780_otg_phy_enable,
+	.disable	= jz4780_otg_phy_disable,
+	.is_enabled	= jz4780_otg_phy_is_enabled,
 };
 
 static int jz4780_core1_enable(struct clk_hw *hw)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of USB PHY.
  2020-06-26 16:48 [PATCH 0/2] Add functions to operate USB PHY related clock 周琰杰 (Zhou Yanjie)
  2020-06-26 16:48 ` [PATCH 1/2] clk: JZ4780: Add functions for enable and disable USB PHY 周琰杰 (Zhou Yanjie)
@ 2020-06-26 16:48 ` 周琰杰 (Zhou Yanjie)
  2020-06-26 17:36   ` Paul Cercueil
  1 sibling, 1 reply; 9+ messages in thread
From: 周琰杰 (Zhou Yanjie) @ 2020-06-26 16:48 UTC (permalink / raw)
  To: linux-clk
  Cc: linux-kernel, sboyd, paul, mturquette, dongsheng.qiu, aric.pzqi,
	rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Add new functions to "x1000_otg_phy_ops" to calculat the rate of REFCLK,
which is needed by USB PHY in the Ingenic X1000 SoC.

Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
---
 drivers/clk/ingenic/x1000-cgu.c | 113 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/drivers/clk/ingenic/x1000-cgu.c b/drivers/clk/ingenic/x1000-cgu.c
index 453f3323cb99..a61c16f98a11 100644
--- a/drivers/clk/ingenic/x1000-cgu.c
+++ b/drivers/clk/ingenic/x1000-cgu.c
@@ -48,8 +48,114 @@
 #define USBPCR_SIDDQ		BIT(21)
 #define USBPCR_OTG_DISABLE	BIT(20)
 
+/* bits within the USBPCR1 register */
+#define USBPCR1_REFCLKSEL_SHIFT	26
+#define USBPCR1_REFCLKSEL_MASK	(0x3 << USBPCR1_REFCLKSEL_SHIFT)
+#define USBPCR1_REFCLKSEL_CORE	(0x2 << USBPCR1_REFCLKSEL_SHIFT)
+#define USBPCR1_REFCLKDIV_SHIFT	24
+#define USBPCR1_REFCLKDIV_MASK	(0x3 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_48	(0x2 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_24	(0x1 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_12	(0x0 << USBPCR1_REFCLKDIV_SHIFT)
+
 static struct ingenic_cgu *cgu;
 
+static u8 x1000_otg_phy_get_parent(struct clk_hw *hw)
+{
+	/* we only use CLKCORE, revisit if that ever changes */
+	return 0;
+}
+
+static int x1000_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
+{
+	unsigned long flags;
+	u32 usbpcr1;
+
+	if (idx > 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&cgu->lock, flags);
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
+	/* we only use CLKCORE */
+	usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
+	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
+
+	spin_unlock_irqrestore(&cgu->lock, flags);
+	return 0;
+}
+
+static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	u32 usbpcr1;
+	unsigned refclk_div;
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
+
+	switch (refclk_div) {
+	case USBPCR1_REFCLKDIV_12:
+		return 12000000;
+
+	case USBPCR1_REFCLKDIV_24:
+		return 24000000;
+
+	case USBPCR1_REFCLKDIV_48:
+		return 48000000;
+	}
+
+	BUG();
+	return parent_rate;
+}
+
+static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
+				      unsigned long *parent_rate)
+{
+	if (req_rate < 18000000)
+		return 12000000;
+
+	if (req_rate < 36000000)
+		return 24000000;
+
+	return 48000000;
+}
+
+static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
+				   unsigned long parent_rate)
+{
+	unsigned long flags;
+	u32 usbpcr1, div_bits;
+
+	switch (req_rate) {
+	case 12000000:
+		div_bits = USBPCR1_REFCLKDIV_12;
+		break;
+
+	case 24000000:
+		div_bits = USBPCR1_REFCLKDIV_24;
+		break;
+
+	case 48000000:
+		div_bits = USBPCR1_REFCLKDIV_48;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&cgu->lock, flags);
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
+	usbpcr1 |= div_bits;
+	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
+
+	spin_unlock_irqrestore(&cgu->lock, flags);
+	return 0;
+}
+
 static int x1000_usb_phy_enable(struct clk_hw *hw)
 {
 	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
@@ -80,6 +186,13 @@ static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
 }
 
 static const struct clk_ops x1000_otg_phy_ops = {
+	.get_parent = x1000_otg_phy_get_parent,
+	.set_parent = x1000_otg_phy_set_parent,
+
+	.recalc_rate = x1000_otg_phy_recalc_rate,
+	.round_rate = x1000_otg_phy_round_rate,
+	.set_rate = x1000_otg_phy_set_rate,
+
 	.enable		= x1000_usb_phy_enable,
 	.disable	= x1000_usb_phy_disable,
 	.is_enabled	= x1000_usb_phy_is_enabled,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] clk: JZ4780: Add functions for enable and disable USB PHY.
  2020-06-26 16:48 ` [PATCH 1/2] clk: JZ4780: Add functions for enable and disable USB PHY 周琰杰 (Zhou Yanjie)
@ 2020-06-26 17:20   ` Paul Cercueil
  2020-06-28 16:10     ` Zhou Yanjie
  0 siblings, 1 reply; 9+ messages in thread
From: Paul Cercueil @ 2020-06-26 17:20 UTC (permalink / raw)
  To: 周琰杰
  Cc: linux-clk, linux-kernel, sboyd, mturquette, dongsheng.qiu,
	aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Hi Zhou,

Le sam. 27 juin 2020 à 0:48, 周琰杰 (Zhou Yanjie) 
<zhouyanjie@wanyeetech.com> a écrit :
> Add new functions to "jz4780_otg_phy_ops" to enable or disable the
> USB PHY in the Ingenic JZ4780 SoC.
> 
> Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
> ---
>  drivers/clk/ingenic/jz4780-cgu.c | 124 
> +++++++++++++++++++++++++--------------
>  1 file changed, 80 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/clk/ingenic/jz4780-cgu.c 
> b/drivers/clk/ingenic/jz4780-cgu.c
> index 6c5b8029cc8a..0ec50b9ab9c1 100644
> --- a/drivers/clk/ingenic/jz4780-cgu.c
> +++ b/drivers/clk/ingenic/jz4780-cgu.c
> @@ -4,6 +4,7 @@
>   *
>   * Copyright (c) 2013-2015 Imagination Technologies
>   * Author: Paul Burton <paul.burton@mips.com>
> + * Copyright (c) 2020 周琰杰 (Zhou Yanjie) 
> <zhouyanjie@wanyeetech.com>
>   */
> 
>  #include <linux/clk-provider.h>
> @@ -19,55 +20,57 @@
> 
>  /* CGU register offsets */
>  #define CGU_REG_CLOCKCONTROL	0x00
> -#define CGU_REG_LCR			0x04
> -#define CGU_REG_APLL		0x10
> -#define CGU_REG_MPLL		0x14
> -#define CGU_REG_EPLL		0x18
> -#define CGU_REG_VPLL		0x1c
> -#define CGU_REG_CLKGR0		0x20
> -#define CGU_REG_OPCR		0x24
> -#define CGU_REG_CLKGR1		0x28
> -#define CGU_REG_DDRCDR		0x2c
> -#define CGU_REG_VPUCDR		0x30
> -#define CGU_REG_USBPCR		0x3c
> -#define CGU_REG_USBRDT		0x40
> -#define CGU_REG_USBVBFIL	0x44
> -#define CGU_REG_USBPCR1		0x48
> -#define CGU_REG_LP0CDR		0x54
> -#define CGU_REG_I2SCDR		0x60
> -#define CGU_REG_LP1CDR		0x64
> -#define CGU_REG_MSC0CDR		0x68
> -#define CGU_REG_UHCCDR		0x6c
> -#define CGU_REG_SSICDR		0x74
> -#define CGU_REG_CIMCDR		0x7c
> -#define CGU_REG_PCMCDR		0x84
> -#define CGU_REG_GPUCDR		0x88
> -#define CGU_REG_HDMICDR		0x8c
> -#define CGU_REG_MSC1CDR		0xa4
> -#define CGU_REG_MSC2CDR		0xa8
> -#define CGU_REG_BCHCDR		0xac
> -#define CGU_REG_CLOCKSTATUS	0xd4
> +#define CGU_REG_LCR				0x04
> +#define CGU_REG_APLL			0x10
> +#define CGU_REG_MPLL			0x14
> +#define CGU_REG_EPLL			0x18
> +#define CGU_REG_VPLL			0x1c
> +#define CGU_REG_CLKGR0			0x20
> +#define CGU_REG_OPCR			0x24
> +#define CGU_REG_CLKGR1			0x28
> +#define CGU_REG_DDRCDR			0x2c
> +#define CGU_REG_VPUCDR			0x30
> +#define CGU_REG_USBPCR			0x3c
> +#define CGU_REG_USBRDT			0x40
> +#define CGU_REG_USBVBFIL		0x44
> +#define CGU_REG_USBPCR1			0x48
> +#define CGU_REG_LP0CDR			0x54
> +#define CGU_REG_I2SCDR			0x60
> +#define CGU_REG_LP1CDR			0x64
> +#define CGU_REG_MSC0CDR			0x68
> +#define CGU_REG_UHCCDR			0x6c
> +#define CGU_REG_SSICDR			0x74
> +#define CGU_REG_CIMCDR			0x7c
> +#define CGU_REG_PCMCDR			0x84
> +#define CGU_REG_GPUCDR			0x88
> +#define CGU_REG_HDMICDR			0x8c
> +#define CGU_REG_MSC1CDR			0xa4
> +#define CGU_REG_MSC2CDR			0xa8
> +#define CGU_REG_BCHCDR			0xac
> +#define CGU_REG_CLOCKSTATUS		0xd4

If you want to reformat the code (add one level of indentation before 
the values) then please do it in a following patch, otherwise it's 
really hard to see what really changed.

The rest looks good so far.

Cheers,
-Paul

> 
>  /* bits within the OPCR register */
> -#define OPCR_SPENDN0		BIT(7)
> -#define OPCR_SPENDN1		BIT(6)
> +#define OPCR_SPENDN0			BIT(7)
> +#define OPCR_SPENDN1			BIT(6)
> 
>  /* bits within the USBPCR register */
> -#define USBPCR_USB_MODE		BIT(31)
> +#define USBPCR_USB_MODE			BIT(31)
>  #define USBPCR_IDPULLUP_MASK	(0x3 << 28)
> -#define USBPCR_COMMONONN	BIT(25)
> -#define USBPCR_VBUSVLDEXT	BIT(24)
> +#define USBPCR_COMMONONN		BIT(25)
> +#define USBPCR_VBUSVLDEXT		BIT(24)
>  #define USBPCR_VBUSVLDEXTSEL	BIT(23)
> -#define USBPCR_POR		BIT(22)
> -#define USBPCR_OTG_DISABLE	BIT(20)
> +#define USBPCR_POR				BIT(22)
> +#define USBPCR_SIDDQ			BIT(21)
> +#define USBPCR_OTG_DISABLE		BIT(20)
>  #define USBPCR_COMPDISTUNE_MASK	(0x7 << 17)
> -#define USBPCR_OTGTUNE_MASK	(0x7 << 14)
> +#define USBPCR_OTGTUNE_MASK		(0x7 << 14)
>  #define USBPCR_SQRXTUNE_MASK	(0x7 << 11)
>  #define USBPCR_TXFSLSTUNE_MASK	(0xf << 7)
>  #define USBPCR_TXPREEMPHTUNE	BIT(6)
>  #define USBPCR_TXHSXVTUNE_MASK	(0x3 << 4)
>  #define USBPCR_TXVREFTUNE_MASK	0xf
> 
> +
>  /* bits within the USBPCR1 register */
>  #define USBPCR1_REFCLKSEL_SHIFT	26
>  #define USBPCR1_REFCLKSEL_MASK	(0x3 << USBPCR1_REFCLKSEL_SHIFT)
> @@ -78,13 +81,13 @@
>  #define USBPCR1_REFCLKDIV_48	(0x2 << USBPCR1_REFCLKDIV_SHIFT)
>  #define USBPCR1_REFCLKDIV_24	(0x1 << USBPCR1_REFCLKDIV_SHIFT)
>  #define USBPCR1_REFCLKDIV_12	(0x0 << USBPCR1_REFCLKDIV_SHIFT)
> -#define USBPCR1_USB_SEL		BIT(28)
> -#define USBPCR1_WORD_IF0	BIT(19)
> -#define USBPCR1_WORD_IF1	BIT(18)
> +#define USBPCR1_USB_SEL			BIT(28)
> +#define USBPCR1_WORD_IF0		BIT(19)
> +#define USBPCR1_WORD_IF1		BIT(18)
> 
>  /* bits within the USBRDT register */
> -#define USBRDT_VBFIL_LD_EN	BIT(25)
> -#define USBRDT_USBRDT_MASK	0x7fffff
> +#define USBRDT_VBFIL_LD_EN		BIT(25)
> +#define USBRDT_USBRDT_MASK		0x7fffff
> 
>  /* bits within the USBVBFIL register */
>  #define USBVBFIL_IDDIGFIL_SHIFT	16
> @@ -92,11 +95,11 @@
>  #define USBVBFIL_USBVBFIL_MASK	(0xffff)
> 
>  /* bits within the LCR register */
> -#define LCR_PD_SCPU			BIT(31)
> -#define LCR_SCPUS			BIT(27)
> +#define LCR_PD_SCPU				BIT(31)
> +#define LCR_SCPUS				BIT(27)
> 
>  /* bits within the CLKGR1 register */
> -#define CLKGR1_CORE1		BIT(15)
> +#define CLKGR1_CORE1			BIT(15)
> 
>  static struct ingenic_cgu *cgu;
> 
> @@ -206,6 +209,35 @@ static int jz4780_otg_phy_set_rate(struct clk_hw 
> *hw, unsigned long req_rate,
>  	return 0;
>  }
> 
> +static int jz4780_otg_phy_enable(struct clk_hw *hw)
> +{
> +	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
> +	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
> +
> +	writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
> +	writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, 
> reg_usbpcr);
> +	return 0;
> +}
> +
> +static void jz4780_otg_phy_disable(struct clk_hw *hw)
> +{
> +	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
> +	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
> +
> +	writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
> +	writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, 
> reg_usbpcr);
> +}
> +
> +static int jz4780_otg_phy_is_enabled(struct clk_hw *hw)
> +{
> +	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
> +	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
> +
> +	return (readl(reg_opcr) & OPCR_SPENDN0) &&
> +		!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
> +		!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
> +}
> +
>  static const struct clk_ops jz4780_otg_phy_ops = {
>  	.get_parent = jz4780_otg_phy_get_parent,
>  	.set_parent = jz4780_otg_phy_set_parent,
> @@ -213,6 +245,10 @@ static const struct clk_ops jz4780_otg_phy_ops = 
> {
>  	.recalc_rate = jz4780_otg_phy_recalc_rate,
>  	.round_rate = jz4780_otg_phy_round_rate,
>  	.set_rate = jz4780_otg_phy_set_rate,
> +
> +	.enable		= jz4780_otg_phy_enable,
> +	.disable	= jz4780_otg_phy_disable,
> +	.is_enabled	= jz4780_otg_phy_is_enabled,
>  };
> 
>  static int jz4780_core1_enable(struct clk_hw *hw)
> --
> 2.11.0
> 



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of USB PHY.
  2020-06-26 16:48 ` [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of " 周琰杰 (Zhou Yanjie)
@ 2020-06-26 17:36   ` Paul Cercueil
  2020-06-28 16:18     ` Zhou Yanjie
  0 siblings, 1 reply; 9+ messages in thread
From: Paul Cercueil @ 2020-06-26 17:36 UTC (permalink / raw)
  To: 周琰杰
  Cc: linux-clk, linux-kernel, sboyd, mturquette, dongsheng.qiu,
	aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Hi Zhou,

Le sam. 27 juin 2020 à 0:48, 周琰杰 (Zhou Yanjie) 
<zhouyanjie@wanyeetech.com> a écrit :
> Add new functions to "x1000_otg_phy_ops" to calculat the rate of 
> REFCLK,
> which is needed by USB PHY in the Ingenic X1000 SoC.
> 
> Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
> ---
>  drivers/clk/ingenic/x1000-cgu.c | 113 
> ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 113 insertions(+)
> 
> diff --git a/drivers/clk/ingenic/x1000-cgu.c 
> b/drivers/clk/ingenic/x1000-cgu.c
> index 453f3323cb99..a61c16f98a11 100644
> --- a/drivers/clk/ingenic/x1000-cgu.c
> +++ b/drivers/clk/ingenic/x1000-cgu.c
> @@ -48,8 +48,114 @@
>  #define USBPCR_SIDDQ		BIT(21)
>  #define USBPCR_OTG_DISABLE	BIT(20)
> 
> +/* bits within the USBPCR1 register */
> +#define USBPCR1_REFCLKSEL_SHIFT	26
> +#define USBPCR1_REFCLKSEL_MASK	(0x3 << USBPCR1_REFCLKSEL_SHIFT)
> +#define USBPCR1_REFCLKSEL_CORE	(0x2 << USBPCR1_REFCLKSEL_SHIFT)
> +#define USBPCR1_REFCLKDIV_SHIFT	24
> +#define USBPCR1_REFCLKDIV_MASK	(0x3 << USBPCR1_REFCLKDIV_SHIFT)
> +#define USBPCR1_REFCLKDIV_48	(0x2 << USBPCR1_REFCLKDIV_SHIFT)
> +#define USBPCR1_REFCLKDIV_24	(0x1 << USBPCR1_REFCLKDIV_SHIFT)
> +#define USBPCR1_REFCLKDIV_12	(0x0 << USBPCR1_REFCLKDIV_SHIFT)
> +
>  static struct ingenic_cgu *cgu;
> 
> +static u8 x1000_otg_phy_get_parent(struct clk_hw *hw)
> +{
> +	/* we only use CLKCORE, revisit if that ever changes */
> +	return 0;
> +}
> +
> +static int x1000_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
> +{
> +	unsigned long flags;
> +	u32 usbpcr1;
> +
> +	if (idx > 0)
> +		return -EINVAL;
> +
> +	spin_lock_irqsave(&cgu->lock, flags);
> +
> +	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
> +	usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
> +	/* we only use CLKCORE */
> +	usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
> +	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
> +
> +	spin_unlock_irqrestore(&cgu->lock, flags);
> +	return 0;
> +}

If you only support one parent, maybe set that bit in the 
x1000_cgu_init(), then you can drop the get_parent/set_parent.

> +
> +static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
> +						unsigned long parent_rate)
> +{
> +	u32 usbpcr1;
> +	unsigned refclk_div;
> +
> +	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
> +	refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
> +
> +	switch (refclk_div) {
> +	case USBPCR1_REFCLKDIV_12:
> +		return 12000000;
> +
> +	case USBPCR1_REFCLKDIV_24:
> +		return 24000000;
> +
> +	case USBPCR1_REFCLKDIV_48:
> +		return 48000000;
> +	}

On your setup, what frequency is configured for the "otg" clock? Is it 
48 MHz?

I believe CLKCORE is the OTG core's clock (aka "otg"), and I'm pretty 
sure that these fields only represent CLKCORE/4, CLKCORE/2, CLKCORE/1, 
but the doc expects CLKCORE==48MHz.

In that case the "otg_phy" should be parented to "otg", and the rate 
should be computed according to the parent rate and the divider 
configured.

> +
> +	BUG();

Don't use BUG() - it pisses off Linus :)
And it's reserved for bugs that will take the whole system down, I 
think. Better use WARN().

Cheers,
-Paul

> +	return parent_rate;
> +}
> +
> +static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned 
> long req_rate,
> +				      unsigned long *parent_rate)
> +{
> +	if (req_rate < 18000000)
> +		return 12000000;
> +
> +	if (req_rate < 36000000)
> +		return 24000000;
> +
> +	return 48000000;
> +}
> +
> +static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long 
> req_rate,
> +				   unsigned long parent_rate)
> +{
> +	unsigned long flags;
> +	u32 usbpcr1, div_bits;
> +
> +	switch (req_rate) {
> +	case 12000000:
> +		div_bits = USBPCR1_REFCLKDIV_12;
> +		break;
> +
> +	case 24000000:
> +		div_bits = USBPCR1_REFCLKDIV_24;
> +		break;
> +
> +	case 48000000:
> +		div_bits = USBPCR1_REFCLKDIV_48;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	spin_lock_irqsave(&cgu->lock, flags);
> +
> +	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
> +	usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
> +	usbpcr1 |= div_bits;
> +	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
> +
> +	spin_unlock_irqrestore(&cgu->lock, flags);
> +	return 0;
> +}
> +
>  static int x1000_usb_phy_enable(struct clk_hw *hw)
>  {
>  	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
> @@ -80,6 +186,13 @@ static int x1000_usb_phy_is_enabled(struct clk_hw 
> *hw)
>  }
> 
>  static const struct clk_ops x1000_otg_phy_ops = {
> +	.get_parent = x1000_otg_phy_get_parent,
> +	.set_parent = x1000_otg_phy_set_parent,
> +
> +	.recalc_rate = x1000_otg_phy_recalc_rate,
> +	.round_rate = x1000_otg_phy_round_rate,
> +	.set_rate = x1000_otg_phy_set_rate,
> +
>  	.enable		= x1000_usb_phy_enable,
>  	.disable	= x1000_usb_phy_disable,
>  	.is_enabled	= x1000_usb_phy_is_enabled,
> --
> 2.11.0
> 



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] clk: JZ4780: Add functions for enable and disable USB PHY.
  2020-06-26 17:20   ` Paul Cercueil
@ 2020-06-28 16:10     ` Zhou Yanjie
  0 siblings, 0 replies; 9+ messages in thread
From: Zhou Yanjie @ 2020-06-28 16:10 UTC (permalink / raw)
  To: Paul Cercueil
  Cc: linux-clk, linux-kernel, sboyd, mturquette, dongsheng.qiu,
	aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Hi Paul,

在 2020/6/27 上午1:20, Paul Cercueil 写道:
> Hi Zhou,
>
> Le sam. 27 juin 2020 à 0:48, 周琰杰 (Zhou Yanjie) 
> <zhouyanjie@wanyeetech.com> a écrit :
>> Add new functions to "jz4780_otg_phy_ops" to enable or disable the
>> USB PHY in the Ingenic JZ4780 SoC.
>>
>> Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
>> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
>> ---
>>  drivers/clk/ingenic/jz4780-cgu.c | 124 
>> +++++++++++++++++++++++++--------------
>>  1 file changed, 80 insertions(+), 44 deletions(-)
>>
>> diff --git a/drivers/clk/ingenic/jz4780-cgu.c 
>> b/drivers/clk/ingenic/jz4780-cgu.c
>> index 6c5b8029cc8a..0ec50b9ab9c1 100644
>> --- a/drivers/clk/ingenic/jz4780-cgu.c
>> +++ b/drivers/clk/ingenic/jz4780-cgu.c
>> @@ -4,6 +4,7 @@
>>   *
>>   * Copyright (c) 2013-2015 Imagination Technologies
>>   * Author: Paul Burton <paul.burton@mips.com>
>> + * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
>>   */
>>
>>  #include <linux/clk-provider.h>
>> @@ -19,55 +20,57 @@
>>
>>  /* CGU register offsets */
>>  #define CGU_REG_CLOCKCONTROL    0x00
>> -#define CGU_REG_LCR            0x04
>> -#define CGU_REG_APLL        0x10
>> -#define CGU_REG_MPLL        0x14
>> -#define CGU_REG_EPLL        0x18
>> -#define CGU_REG_VPLL        0x1c
>> -#define CGU_REG_CLKGR0        0x20
>> -#define CGU_REG_OPCR        0x24
>> -#define CGU_REG_CLKGR1        0x28
>> -#define CGU_REG_DDRCDR        0x2c
>> -#define CGU_REG_VPUCDR        0x30
>> -#define CGU_REG_USBPCR        0x3c
>> -#define CGU_REG_USBRDT        0x40
>> -#define CGU_REG_USBVBFIL    0x44
>> -#define CGU_REG_USBPCR1        0x48
>> -#define CGU_REG_LP0CDR        0x54
>> -#define CGU_REG_I2SCDR        0x60
>> -#define CGU_REG_LP1CDR        0x64
>> -#define CGU_REG_MSC0CDR        0x68
>> -#define CGU_REG_UHCCDR        0x6c
>> -#define CGU_REG_SSICDR        0x74
>> -#define CGU_REG_CIMCDR        0x7c
>> -#define CGU_REG_PCMCDR        0x84
>> -#define CGU_REG_GPUCDR        0x88
>> -#define CGU_REG_HDMICDR        0x8c
>> -#define CGU_REG_MSC1CDR        0xa4
>> -#define CGU_REG_MSC2CDR        0xa8
>> -#define CGU_REG_BCHCDR        0xac
>> -#define CGU_REG_CLOCKSTATUS    0xd4
>> +#define CGU_REG_LCR                0x04
>> +#define CGU_REG_APLL            0x10
>> +#define CGU_REG_MPLL            0x14
>> +#define CGU_REG_EPLL            0x18
>> +#define CGU_REG_VPLL            0x1c
>> +#define CGU_REG_CLKGR0            0x20
>> +#define CGU_REG_OPCR            0x24
>> +#define CGU_REG_CLKGR1            0x28
>> +#define CGU_REG_DDRCDR            0x2c
>> +#define CGU_REG_VPUCDR            0x30
>> +#define CGU_REG_USBPCR            0x3c
>> +#define CGU_REG_USBRDT            0x40
>> +#define CGU_REG_USBVBFIL        0x44
>> +#define CGU_REG_USBPCR1            0x48
>> +#define CGU_REG_LP0CDR            0x54
>> +#define CGU_REG_I2SCDR            0x60
>> +#define CGU_REG_LP1CDR            0x64
>> +#define CGU_REG_MSC0CDR            0x68
>> +#define CGU_REG_UHCCDR            0x6c
>> +#define CGU_REG_SSICDR            0x74
>> +#define CGU_REG_CIMCDR            0x7c
>> +#define CGU_REG_PCMCDR            0x84
>> +#define CGU_REG_GPUCDR            0x88
>> +#define CGU_REG_HDMICDR            0x8c
>> +#define CGU_REG_MSC1CDR            0xa4
>> +#define CGU_REG_MSC2CDR            0xa8
>> +#define CGU_REG_BCHCDR            0xac
>> +#define CGU_REG_CLOCKSTATUS        0xd4
>
> If you want to reformat the code (add one level of indentation before 
> the values) then please do it in a following patch, otherwise it's 
> really hard to see what really changed.
>

Sure.


> The rest looks good so far.
>
> Cheers,
> -Paul
>
>>
>>  /* bits within the OPCR register */
>> -#define OPCR_SPENDN0        BIT(7)
>> -#define OPCR_SPENDN1        BIT(6)
>> +#define OPCR_SPENDN0            BIT(7)
>> +#define OPCR_SPENDN1            BIT(6)
>>
>>  /* bits within the USBPCR register */
>> -#define USBPCR_USB_MODE        BIT(31)
>> +#define USBPCR_USB_MODE            BIT(31)
>>  #define USBPCR_IDPULLUP_MASK    (0x3 << 28)
>> -#define USBPCR_COMMONONN    BIT(25)
>> -#define USBPCR_VBUSVLDEXT    BIT(24)
>> +#define USBPCR_COMMONONN        BIT(25)
>> +#define USBPCR_VBUSVLDEXT        BIT(24)
>>  #define USBPCR_VBUSVLDEXTSEL    BIT(23)
>> -#define USBPCR_POR        BIT(22)
>> -#define USBPCR_OTG_DISABLE    BIT(20)
>> +#define USBPCR_POR                BIT(22)
>> +#define USBPCR_SIDDQ            BIT(21)
>> +#define USBPCR_OTG_DISABLE        BIT(20)
>>  #define USBPCR_COMPDISTUNE_MASK    (0x7 << 17)
>> -#define USBPCR_OTGTUNE_MASK    (0x7 << 14)
>> +#define USBPCR_OTGTUNE_MASK        (0x7 << 14)
>>  #define USBPCR_SQRXTUNE_MASK    (0x7 << 11)
>>  #define USBPCR_TXFSLSTUNE_MASK    (0xf << 7)
>>  #define USBPCR_TXPREEMPHTUNE    BIT(6)
>>  #define USBPCR_TXHSXVTUNE_MASK    (0x3 << 4)
>>  #define USBPCR_TXVREFTUNE_MASK    0xf
>>
>> +
>>  /* bits within the USBPCR1 register */
>>  #define USBPCR1_REFCLKSEL_SHIFT    26
>>  #define USBPCR1_REFCLKSEL_MASK    (0x3 << USBPCR1_REFCLKSEL_SHIFT)
>> @@ -78,13 +81,13 @@
>>  #define USBPCR1_REFCLKDIV_48    (0x2 << USBPCR1_REFCLKDIV_SHIFT)
>>  #define USBPCR1_REFCLKDIV_24    (0x1 << USBPCR1_REFCLKDIV_SHIFT)
>>  #define USBPCR1_REFCLKDIV_12    (0x0 << USBPCR1_REFCLKDIV_SHIFT)
>> -#define USBPCR1_USB_SEL        BIT(28)
>> -#define USBPCR1_WORD_IF0    BIT(19)
>> -#define USBPCR1_WORD_IF1    BIT(18)
>> +#define USBPCR1_USB_SEL            BIT(28)
>> +#define USBPCR1_WORD_IF0        BIT(19)
>> +#define USBPCR1_WORD_IF1        BIT(18)
>>
>>  /* bits within the USBRDT register */
>> -#define USBRDT_VBFIL_LD_EN    BIT(25)
>> -#define USBRDT_USBRDT_MASK    0x7fffff
>> +#define USBRDT_VBFIL_LD_EN        BIT(25)
>> +#define USBRDT_USBRDT_MASK        0x7fffff
>>
>>  /* bits within the USBVBFIL register */
>>  #define USBVBFIL_IDDIGFIL_SHIFT    16
>> @@ -92,11 +95,11 @@
>>  #define USBVBFIL_USBVBFIL_MASK    (0xffff)
>>
>>  /* bits within the LCR register */
>> -#define LCR_PD_SCPU            BIT(31)
>> -#define LCR_SCPUS            BIT(27)
>> +#define LCR_PD_SCPU                BIT(31)
>> +#define LCR_SCPUS                BIT(27)
>>
>>  /* bits within the CLKGR1 register */
>> -#define CLKGR1_CORE1        BIT(15)
>> +#define CLKGR1_CORE1            BIT(15)
>>
>>  static struct ingenic_cgu *cgu;
>>
>> @@ -206,6 +209,35 @@ static int jz4780_otg_phy_set_rate(struct clk_hw 
>> *hw, unsigned long req_rate,
>>      return 0;
>>  }
>>
>> +static int jz4780_otg_phy_enable(struct clk_hw *hw)
>> +{
>> +    void __iomem *reg_opcr        = cgu->base + CGU_REG_OPCR;
>> +    void __iomem *reg_usbpcr    = cgu->base + CGU_REG_USBPCR;
>> +
>> +    writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
>> +    writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, 
>> reg_usbpcr);
>> +    return 0;
>> +}
>> +
>> +static void jz4780_otg_phy_disable(struct clk_hw *hw)
>> +{
>> +    void __iomem *reg_opcr        = cgu->base + CGU_REG_OPCR;
>> +    void __iomem *reg_usbpcr    = cgu->base + CGU_REG_USBPCR;
>> +
>> +    writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
>> +    writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, 
>> reg_usbpcr);
>> +}
>> +
>> +static int jz4780_otg_phy_is_enabled(struct clk_hw *hw)
>> +{
>> +    void __iomem *reg_opcr        = cgu->base + CGU_REG_OPCR;
>> +    void __iomem *reg_usbpcr    = cgu->base + CGU_REG_USBPCR;
>> +
>> +    return (readl(reg_opcr) & OPCR_SPENDN0) &&
>> +        !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
>> +        !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
>> +}
>> +
>>  static const struct clk_ops jz4780_otg_phy_ops = {
>>      .get_parent = jz4780_otg_phy_get_parent,
>>      .set_parent = jz4780_otg_phy_set_parent,
>> @@ -213,6 +245,10 @@ static const struct clk_ops jz4780_otg_phy_ops = {
>>      .recalc_rate = jz4780_otg_phy_recalc_rate,
>>      .round_rate = jz4780_otg_phy_round_rate,
>>      .set_rate = jz4780_otg_phy_set_rate,
>> +
>> +    .enable        = jz4780_otg_phy_enable,
>> +    .disable    = jz4780_otg_phy_disable,
>> +    .is_enabled    = jz4780_otg_phy_is_enabled,
>>  };
>>
>>  static int jz4780_core1_enable(struct clk_hw *hw)
>> -- 
>> 2.11.0
>>
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of USB PHY.
  2020-06-26 17:36   ` Paul Cercueil
@ 2020-06-28 16:18     ` Zhou Yanjie
  2020-06-28 17:03       ` Paul Cercueil
  0 siblings, 1 reply; 9+ messages in thread
From: Zhou Yanjie @ 2020-06-28 16:18 UTC (permalink / raw)
  To: Paul Cercueil
  Cc: linux-clk, linux-kernel, sboyd, mturquette, dongsheng.qiu,
	aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Hi Paul,

在 2020/6/27 上午1:36, Paul Cercueil 写道:
> Hi Zhou,
>
> Le sam. 27 juin 2020 à 0:48, 周琰杰 (Zhou Yanjie) 
> <zhouyanjie@wanyeetech.com> a écrit :
>> Add new functions to "x1000_otg_phy_ops" to calculat the rate of REFCLK,
>> which is needed by USB PHY in the Ingenic X1000 SoC.
>>
>> Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
>> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
>> ---
>>  drivers/clk/ingenic/x1000-cgu.c | 113 
>> ++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 113 insertions(+)
>>
>> diff --git a/drivers/clk/ingenic/x1000-cgu.c 
>> b/drivers/clk/ingenic/x1000-cgu.c
>> index 453f3323cb99..a61c16f98a11 100644
>> --- a/drivers/clk/ingenic/x1000-cgu.c
>> +++ b/drivers/clk/ingenic/x1000-cgu.c
>> @@ -48,8 +48,114 @@
>>  #define USBPCR_SIDDQ        BIT(21)
>>  #define USBPCR_OTG_DISABLE    BIT(20)
>>
>> +/* bits within the USBPCR1 register */
>> +#define USBPCR1_REFCLKSEL_SHIFT    26
>> +#define USBPCR1_REFCLKSEL_MASK    (0x3 << USBPCR1_REFCLKSEL_SHIFT)
>> +#define USBPCR1_REFCLKSEL_CORE    (0x2 << USBPCR1_REFCLKSEL_SHIFT)
>> +#define USBPCR1_REFCLKDIV_SHIFT    24
>> +#define USBPCR1_REFCLKDIV_MASK    (0x3 << USBPCR1_REFCLKDIV_SHIFT)
>> +#define USBPCR1_REFCLKDIV_48    (0x2 << USBPCR1_REFCLKDIV_SHIFT)
>> +#define USBPCR1_REFCLKDIV_24    (0x1 << USBPCR1_REFCLKDIV_SHIFT)
>> +#define USBPCR1_REFCLKDIV_12    (0x0 << USBPCR1_REFCLKDIV_SHIFT)
>> +
>>  static struct ingenic_cgu *cgu;
>>
>> +static u8 x1000_otg_phy_get_parent(struct clk_hw *hw)
>> +{
>> +    /* we only use CLKCORE, revisit if that ever changes */
>> +    return 0;
>> +}
>> +
>> +static int x1000_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
>> +{
>> +    unsigned long flags;
>> +    u32 usbpcr1;
>> +
>> +    if (idx > 0)
>> +        return -EINVAL;
>> +
>> +    spin_lock_irqsave(&cgu->lock, flags);
>> +
>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>> +    usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
>> +    /* we only use CLKCORE */
>> +    usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
>> +    writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
>> +
>> +    spin_unlock_irqrestore(&cgu->lock, flags);
>> +    return 0;
>> +}
>
> If you only support one parent, maybe set that bit in the 
> x1000_cgu_init(), then you can drop the get_parent/set_parent.
>

Sure.


>> +
>> +static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
>> +                        unsigned long parent_rate)
>> +{
>> +    u32 usbpcr1;
>> +    unsigned refclk_div;
>> +
>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>> +    refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
>> +
>> +    switch (refclk_div) {
>> +    case USBPCR1_REFCLKDIV_12:
>> +        return 12000000;
>> +
>> +    case USBPCR1_REFCLKDIV_24:
>> +        return 24000000;
>> +
>> +    case USBPCR1_REFCLKDIV_48:
>> +        return 48000000;
>> +    }
>
> On your setup, what frequency is configured for the "otg" clock? Is it 
> 48 MHz?
>
> I believe CLKCORE is the OTG core's clock (aka "otg"), and I'm pretty 
> sure that these fields only represent CLKCORE/4, CLKCORE/2, CLKCORE/1, 
> but the doc expects CLKCORE==48MHz.
>

This is the REFCLKDIV in USBPCR1 reg, it's for the usb phy, so it is not 
the otg clock. In X1000 and X1500 it is 24MHz, in JZ4780 it is 48MHz.


> In that case the "otg_phy" should be parented to "otg", and the rate 
> should be computed according to the parent rate and the divider 
> configured.
>
>> +
>> +    BUG();
>
> Don't use BUG() - it pisses off Linus :)
> And it's reserved for bugs that will take the whole system down, I 
> think. Better use WARN().
>

Sure, I will change it in the next version.

Thanks and best regards!


> Cheers,
> -Paul
>
>> +    return parent_rate;
>> +}
>> +
>> +static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned 
>> long req_rate,
>> +                      unsigned long *parent_rate)
>> +{
>> +    if (req_rate < 18000000)
>> +        return 12000000;
>> +
>> +    if (req_rate < 36000000)
>> +        return 24000000;
>> +
>> +    return 48000000;
>> +}
>> +
>> +static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long 
>> req_rate,
>> +                   unsigned long parent_rate)
>> +{
>> +    unsigned long flags;
>> +    u32 usbpcr1, div_bits;
>> +
>> +    switch (req_rate) {
>> +    case 12000000:
>> +        div_bits = USBPCR1_REFCLKDIV_12;
>> +        break;
>> +
>> +    case 24000000:
>> +        div_bits = USBPCR1_REFCLKDIV_24;
>> +        break;
>> +
>> +    case 48000000:
>> +        div_bits = USBPCR1_REFCLKDIV_48;
>> +        break;
>> +
>> +    default:
>> +        return -EINVAL;
>> +    }
>> +
>> +    spin_lock_irqsave(&cgu->lock, flags);
>> +
>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>> +    usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
>> +    usbpcr1 |= div_bits;
>> +    writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
>> +
>> +    spin_unlock_irqrestore(&cgu->lock, flags);
>> +    return 0;
>> +}
>> +
>>  static int x1000_usb_phy_enable(struct clk_hw *hw)
>>  {
>>      void __iomem *reg_opcr        = cgu->base + CGU_REG_OPCR;
>> @@ -80,6 +186,13 @@ static int x1000_usb_phy_is_enabled(struct clk_hw 
>> *hw)
>>  }
>>
>>  static const struct clk_ops x1000_otg_phy_ops = {
>> +    .get_parent = x1000_otg_phy_get_parent,
>> +    .set_parent = x1000_otg_phy_set_parent,
>> +
>> +    .recalc_rate = x1000_otg_phy_recalc_rate,
>> +    .round_rate = x1000_otg_phy_round_rate,
>> +    .set_rate = x1000_otg_phy_set_rate,
>> +
>>      .enable        = x1000_usb_phy_enable,
>>      .disable    = x1000_usb_phy_disable,
>>      .is_enabled    = x1000_usb_phy_is_enabled,
>> -- 
>> 2.11.0
>>
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of USB PHY.
  2020-06-28 16:18     ` Zhou Yanjie
@ 2020-06-28 17:03       ` Paul Cercueil
  2020-06-30 12:26         ` Zhou Yanjie
  0 siblings, 1 reply; 9+ messages in thread
From: Paul Cercueil @ 2020-06-28 17:03 UTC (permalink / raw)
  To: Zhou Yanjie
  Cc: linux-clk, linux-kernel, sboyd, mturquette, dongsheng.qiu,
	aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Hi Zhou,

Le lun. 29 juin 2020 à 0:18, Zhou Yanjie <zhouyanjie@wanyeetech.com> a 
écrit :
> Hi Paul,
> 
> 在 2020/6/27 上午1:36, Paul Cercueil 写道:
>> Hi Zhou,
>> 
>> Le sam. 27 juin 2020 à 0:48, 周琰杰 (Zhou Yanjie) 
>> \x7f<zhouyanjie@wanyeetech.com> a écrit :
>>> Add new functions to "x1000_otg_phy_ops" to calculat the rate of 
>>> REFCLK,
>>> which is needed by USB PHY in the Ingenic X1000 SoC.
>>> 
>>> Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
>>> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
>>> ---
>>>  drivers/clk/ingenic/x1000-cgu.c | 113 
>>> \x7f\x7f++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 113 insertions(+)
>>> 
>>> diff --git a/drivers/clk/ingenic/x1000-cgu.c 
>>> \x7f\x7fb/drivers/clk/ingenic/x1000-cgu.c
>>> index 453f3323cb99..a61c16f98a11 100644
>>> --- a/drivers/clk/ingenic/x1000-cgu.c
>>> +++ b/drivers/clk/ingenic/x1000-cgu.c
>>> @@ -48,8 +48,114 @@
>>>  #define USBPCR_SIDDQ        BIT(21)
>>>  #define USBPCR_OTG_DISABLE    BIT(20)
>>> 
>>> +/* bits within the USBPCR1 register */
>>> +#define USBPCR1_REFCLKSEL_SHIFT    26
>>> +#define USBPCR1_REFCLKSEL_MASK    (0x3 << USBPCR1_REFCLKSEL_SHIFT)
>>> +#define USBPCR1_REFCLKSEL_CORE    (0x2 << USBPCR1_REFCLKSEL_SHIFT)
>>> +#define USBPCR1_REFCLKDIV_SHIFT    24
>>> +#define USBPCR1_REFCLKDIV_MASK    (0x3 << USBPCR1_REFCLKDIV_SHIFT)
>>> +#define USBPCR1_REFCLKDIV_48    (0x2 << USBPCR1_REFCLKDIV_SHIFT)
>>> +#define USBPCR1_REFCLKDIV_24    (0x1 << USBPCR1_REFCLKDIV_SHIFT)
>>> +#define USBPCR1_REFCLKDIV_12    (0x0 << USBPCR1_REFCLKDIV_SHIFT)
>>> +
>>>  static struct ingenic_cgu *cgu;
>>> 
>>> +static u8 x1000_otg_phy_get_parent(struct clk_hw *hw)
>>> +{
>>> +    /* we only use CLKCORE, revisit if that ever changes */
>>> +    return 0;
>>> +}
>>> +
>>> +static int x1000_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
>>> +{
>>> +    unsigned long flags;
>>> +    u32 usbpcr1;
>>> +
>>> +    if (idx > 0)
>>> +        return -EINVAL;
>>> +
>>> +    spin_lock_irqsave(&cgu->lock, flags);
>>> +
>>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>>> +    usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
>>> +    /* we only use CLKCORE */
>>> +    usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
>>> +    writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
>>> +
>>> +    spin_unlock_irqrestore(&cgu->lock, flags);
>>> +    return 0;
>>> +}
>> 
>> If you only support one parent, maybe set that bit in the 
>> \x7fx1000_cgu_init(), then you can drop the get_parent/set_parent.
>> 
> 
> Sure.
> 
> 
>>> +
>>> +static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
>>> +                        unsigned long parent_rate)
>>> +{
>>> +    u32 usbpcr1;
>>> +    unsigned refclk_div;
>>> +
>>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>>> +    refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
>>> +
>>> +    switch (refclk_div) {
>>> +    case USBPCR1_REFCLKDIV_12:
>>> +        return 12000000;
>>> +
>>> +    case USBPCR1_REFCLKDIV_24:
>>> +        return 24000000;
>>> +
>>> +    case USBPCR1_REFCLKDIV_48:
>>> +        return 48000000;
>>> +    }
>> 
>> On your setup, what frequency is configured for the "otg" clock? Is 
>> it \x7f48 MHz?
>> 
>> I believe CLKCORE is the OTG core's clock (aka "otg"), and I'm 
>> pretty \x7fsure that these fields only represent CLKCORE/4, CLKCORE/2, 
>> CLKCORE/1, \x7fbut the doc expects CLKCORE==48MHz.
>> 
> 
> This is the REFCLKDIV in USBPCR1 reg, it's for the usb phy, so it is 
> not the otg clock. In X1000 and X1500 it is 24MHz, in JZ4780 it is 
> 48MHz.

I know it is for the OTG PHY clock, what I'm saying is that the OTG PHY 
clock is derived from CLKCORE which I believe is the "otg" clock. 
Unless the clock represents a crystal, it is derived from another 
clock, and as a result the clock rate should be computed from the 
parent clock rate.

-Paul

> 
>> In that case the "otg_phy" should be parented to "otg", and the rate 
>> \x7fshould be computed according to the parent rate and the divider 
>> \x7fconfigured.
>> 
>>> +
>>> +    BUG();
>> 
>> Don't use BUG() - it pisses off Linus :)
>> And it's reserved for bugs that will take the whole system down, I 
>> \x7fthink. Better use WARN().
>> 
> 
> Sure, I will change it in the next version.
> 
> Thanks and best regards!
> 
> 
>> Cheers,
>> -Paul
>> 
>>> +    return parent_rate;
>>> +}
>>> +
>>> +static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned 
>>> \x7f\x7flong req_rate,
>>> +                      unsigned long *parent_rate)
>>> +{
>>> +    if (req_rate < 18000000)
>>> +        return 12000000;
>>> +
>>> +    if (req_rate < 36000000)
>>> +        return 24000000;
>>> +
>>> +    return 48000000;
>>> +}
>>> +
>>> +static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long 
>>> \x7f\x7freq_rate,
>>> +                   unsigned long parent_rate)
>>> +{
>>> +    unsigned long flags;
>>> +    u32 usbpcr1, div_bits;
>>> +
>>> +    switch (req_rate) {
>>> +    case 12000000:
>>> +        div_bits = USBPCR1_REFCLKDIV_12;
>>> +        break;
>>> +
>>> +    case 24000000:
>>> +        div_bits = USBPCR1_REFCLKDIV_24;
>>> +        break;
>>> +
>>> +    case 48000000:
>>> +        div_bits = USBPCR1_REFCLKDIV_48;
>>> +        break;
>>> +
>>> +    default:
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    spin_lock_irqsave(&cgu->lock, flags);
>>> +
>>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>>> +    usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
>>> +    usbpcr1 |= div_bits;
>>> +    writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
>>> +
>>> +    spin_unlock_irqrestore(&cgu->lock, flags);
>>> +    return 0;
>>> +}
>>> +
>>>  static int x1000_usb_phy_enable(struct clk_hw *hw)
>>>  {
>>>      void __iomem *reg_opcr        = cgu->base + CGU_REG_OPCR;
>>> @@ -80,6 +186,13 @@ static int x1000_usb_phy_is_enabled(struct 
>>> clk_hw \x7f\x7f*hw)
>>>  }
>>> 
>>>  static const struct clk_ops x1000_otg_phy_ops = {
>>> +    .get_parent = x1000_otg_phy_get_parent,
>>> +    .set_parent = x1000_otg_phy_set_parent,
>>> +
>>> +    .recalc_rate = x1000_otg_phy_recalc_rate,
>>> +    .round_rate = x1000_otg_phy_round_rate,
>>> +    .set_rate = x1000_otg_phy_set_rate,
>>> +
>>>      .enable        = x1000_usb_phy_enable,
>>>      .disable    = x1000_usb_phy_disable,
>>>      .is_enabled    = x1000_usb_phy_is_enabled,
>>> --
>>> 2.11.0
>>> 
>> 



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of USB PHY.
  2020-06-28 17:03       ` Paul Cercueil
@ 2020-06-30 12:26         ` Zhou Yanjie
  0 siblings, 0 replies; 9+ messages in thread
From: Zhou Yanjie @ 2020-06-30 12:26 UTC (permalink / raw)
  To: Paul Cercueil
  Cc: linux-clk, linux-kernel, sboyd, mturquette, dongsheng.qiu,
	aric.pzqi, rick.tyliu, yanfei.li, sernia.zhou, zhenwenjin

Hi Paul,

在 2020/6/29 上午1:03, Paul Cercueil 写道:
> Hi Zhou,
>
> Le lun. 29 juin 2020 à 0:18, Zhou Yanjie <zhouyanjie@wanyeetech.com> a 
> écrit :
>> Hi Paul,
>>
>> 在 2020/6/27 上午1:36, Paul Cercueil 写道:
>>> Hi Zhou,
>>>
>>> Le sam. 27 juin 2020 à 0:48, 周琰杰 (Zhou Yanjie) 
>>> \x7f<zhouyanjie@wanyeetech.com> a écrit :
>>>> Add new functions to "x1000_otg_phy_ops" to calculat the rate of 
>>>> REFCLK,
>>>> which is needed by USB PHY in the Ingenic X1000 SoC.
>>>>
>>>> Tested-by: 周正 (Zhou Zheng) <sernia.zhou@foxmail.com>
>>>> Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
>>>> ---
>>>>  drivers/clk/ingenic/x1000-cgu.c | 113 
>>>> \x7f\x7f++++++++++++++++++++++++++++++++++++++++
>>>>  1 file changed, 113 insertions(+)
>>>>
>>>> diff --git a/drivers/clk/ingenic/x1000-cgu.c 
>>>> \x7f\x7fb/drivers/clk/ingenic/x1000-cgu.c
>>>> index 453f3323cb99..a61c16f98a11 100644
>>>> --- a/drivers/clk/ingenic/x1000-cgu.c
>>>> +++ b/drivers/clk/ingenic/x1000-cgu.c
>>>> @@ -48,8 +48,114 @@
>>>>  #define USBPCR_SIDDQ        BIT(21)
>>>>  #define USBPCR_OTG_DISABLE    BIT(20)
>>>>
>>>> +/* bits within the USBPCR1 register */
>>>> +#define USBPCR1_REFCLKSEL_SHIFT    26
>>>> +#define USBPCR1_REFCLKSEL_MASK    (0x3 << USBPCR1_REFCLKSEL_SHIFT)
>>>> +#define USBPCR1_REFCLKSEL_CORE    (0x2 << USBPCR1_REFCLKSEL_SHIFT)
>>>> +#define USBPCR1_REFCLKDIV_SHIFT    24
>>>> +#define USBPCR1_REFCLKDIV_MASK    (0x3 << USBPCR1_REFCLKDIV_SHIFT)
>>>> +#define USBPCR1_REFCLKDIV_48    (0x2 << USBPCR1_REFCLKDIV_SHIFT)
>>>> +#define USBPCR1_REFCLKDIV_24    (0x1 << USBPCR1_REFCLKDIV_SHIFT)
>>>> +#define USBPCR1_REFCLKDIV_12    (0x0 << USBPCR1_REFCLKDIV_SHIFT)
>>>> +
>>>>  static struct ingenic_cgu *cgu;
>>>>
>>>> +static u8 x1000_otg_phy_get_parent(struct clk_hw *hw)
>>>> +{
>>>> +    /* we only use CLKCORE, revisit if that ever changes */
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static int x1000_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
>>>> +{
>>>> +    unsigned long flags;
>>>> +    u32 usbpcr1;
>>>> +
>>>> +    if (idx > 0)
>>>> +        return -EINVAL;
>>>> +
>>>> +    spin_lock_irqsave(&cgu->lock, flags);
>>>> +
>>>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>>>> +    usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
>>>> +    /* we only use CLKCORE */
>>>> +    usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
>>>> +    writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
>>>> +
>>>> +    spin_unlock_irqrestore(&cgu->lock, flags);
>>>> +    return 0;
>>>> +}
>>>
>>> If you only support one parent, maybe set that bit in the 
>>> \x7fx1000_cgu_init(), then you can drop the get_parent/set_parent.
>>>
>>
>> Sure.
>>
>>
>>>> +
>>>> +static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
>>>> +                        unsigned long parent_rate)
>>>> +{
>>>> +    u32 usbpcr1;
>>>> +    unsigned refclk_div;
>>>> +
>>>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>>>> +    refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
>>>> +
>>>> +    switch (refclk_div) {
>>>> +    case USBPCR1_REFCLKDIV_12:
>>>> +        return 12000000;
>>>> +
>>>> +    case USBPCR1_REFCLKDIV_24:
>>>> +        return 24000000;
>>>> +
>>>> +    case USBPCR1_REFCLKDIV_48:
>>>> +        return 48000000;
>>>> +    }
>>>
>>> On your setup, what frequency is configured for the "otg" clock? Is 
>>> it \x7f48 MHz?
>>>
>>> I believe CLKCORE is the OTG core's clock (aka "otg"), and I'm 
>>> pretty \x7fsure that these fields only represent CLKCORE/4, CLKCORE/2, 
>>> CLKCORE/1, \x7fbut the doc expects CLKCORE==48MHz.
>>>
>>
>> This is the REFCLKDIV in USBPCR1 reg, it's for the usb phy, so it is 
>> not the otg clock. In X1000 and X1500 it is 24MHz, in JZ4780 it is 
>> 48MHz.
>
> I know it is for the OTG PHY clock, what I'm saying is that the OTG 
> PHY clock is derived from CLKCORE which I believe is the "otg" clock. 
> Unless the clock represents a crystal, it is derived from another 
> clock, and as a result the clock rate should be computed from the 
> parent clock rate.
>

In the current Ingenic SoCs I have in hand, only JZ4780/X1000/X1500 has 
this REFCLKDIV.

At present, the relevant drivers in X1000 are written with reference to 
the drivers in jz4780-cgu.c ( the author is Paul Burton ). I have 
already tested on X1000 and JZ4780 today, the driver is effective and 
can be configured by setting assigned-clock-rates in DT ( 48000000 for 
JZ4780, 24000000 for X1000 and X1500 ).

Thanks and best regards!


> -Paul
>
>>
>>> In that case the "otg_phy" should be parented to "otg", and the rate 
>>> \x7fshould be computed according to the parent rate and the divider 
>>> \x7fconfigured.
>>>
>>>> +
>>>> +    BUG();
>>>
>>> Don't use BUG() - it pisses off Linus :)
>>> And it's reserved for bugs that will take the whole system down, I 
>>> \x7fthink. Better use WARN().
>>>
>>
>> Sure, I will change it in the next version.
>>
>> Thanks and best regards!
>>
>>
>>> Cheers,
>>> -Paul
>>>
>>>> +    return parent_rate;
>>>> +}
>>>> +
>>>> +static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned 
>>>> \x7f\x7flong req_rate,
>>>> +                      unsigned long *parent_rate)
>>>> +{
>>>> +    if (req_rate < 18000000)
>>>> +        return 12000000;
>>>> +
>>>> +    if (req_rate < 36000000)
>>>> +        return 24000000;
>>>> +
>>>> +    return 48000000;
>>>> +}
>>>> +
>>>> +static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long 
>>>> \x7f\x7freq_rate,
>>>> +                   unsigned long parent_rate)
>>>> +{
>>>> +    unsigned long flags;
>>>> +    u32 usbpcr1, div_bits;
>>>> +
>>>> +    switch (req_rate) {
>>>> +    case 12000000:
>>>> +        div_bits = USBPCR1_REFCLKDIV_12;
>>>> +        break;
>>>> +
>>>> +    case 24000000:
>>>> +        div_bits = USBPCR1_REFCLKDIV_24;
>>>> +        break;
>>>> +
>>>> +    case 48000000:
>>>> +        div_bits = USBPCR1_REFCLKDIV_48;
>>>> +        break;
>>>> +
>>>> +    default:
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    spin_lock_irqsave(&cgu->lock, flags);
>>>> +
>>>> +    usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
>>>> +    usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
>>>> +    usbpcr1 |= div_bits;
>>>> +    writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
>>>> +
>>>> +    spin_unlock_irqrestore(&cgu->lock, flags);
>>>> +    return 0;
>>>> +}
>>>> +
>>>>  static int x1000_usb_phy_enable(struct clk_hw *hw)
>>>>  {
>>>>      void __iomem *reg_opcr        = cgu->base + CGU_REG_OPCR;
>>>> @@ -80,6 +186,13 @@ static int x1000_usb_phy_is_enabled(struct 
>>>> clk_hw \x7f\x7f*hw)
>>>>  }
>>>>
>>>>  static const struct clk_ops x1000_otg_phy_ops = {
>>>> +    .get_parent = x1000_otg_phy_get_parent,
>>>> +    .set_parent = x1000_otg_phy_set_parent,
>>>> +
>>>> +    .recalc_rate = x1000_otg_phy_recalc_rate,
>>>> +    .round_rate = x1000_otg_phy_round_rate,
>>>> +    .set_rate = x1000_otg_phy_set_rate,
>>>> +
>>>>      .enable        = x1000_usb_phy_enable,
>>>>      .disable    = x1000_usb_phy_disable,
>>>>      .is_enabled    = x1000_usb_phy_is_enabled,
>>>> -- 
>>>> 2.11.0
>>>>
>>>
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-06-30 12:26 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-26 16:48 [PATCH 0/2] Add functions to operate USB PHY related clock 周琰杰 (Zhou Yanjie)
2020-06-26 16:48 ` [PATCH 1/2] clk: JZ4780: Add functions for enable and disable USB PHY 周琰杰 (Zhou Yanjie)
2020-06-26 17:20   ` Paul Cercueil
2020-06-28 16:10     ` Zhou Yanjie
2020-06-26 16:48 ` [PATCH 2/2] clk: X1000: Add support for calculat REFCLK of " 周琰杰 (Zhou Yanjie)
2020-06-26 17:36   ` Paul Cercueil
2020-06-28 16:18     ` Zhou Yanjie
2020-06-28 17:03       ` Paul Cercueil
2020-06-30 12:26         ` Zhou Yanjie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).