* [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).