Skip to contentSkip to conversation

sunxi: clock: Fix EHCI and OHCI clocks on A64

PATCH Superseded Vasily Khoruzhick 2 participants 5 messages Jun 7, 2018

Subsystems (5)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/4 sunxi: clock: Fix EHCI and OHCI clocks on A64

EHCI0 is bit 24, EHCI1 - 25, OHCI0 - 28, OHCI1 - 29

Fixes commit fef73766d9ad ("sunxi: clock: Fix OHCI clock gating for H3/H5")

---
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/arm/include/asm/arch-sunxi/clock_sun6i.h +4 -2
index 8acf79fbba..8afeaf872e 100644
@@ -280,8 +280,10 @@ struct sunxi_ccm_reg {
 #define AHB_GATE_OFFSET_USB_EHCI1	26
 #define AHB_GATE_OFFSET_USB_EHCI0	24
 #elif defined(CONFIG_MACH_SUN50I)
-#define AHB_GATE_OFFSET_USB_OHCI0	29
-#define AHB_GATE_OFFSET_USB_EHCI0	25
+#define AHB_GATE_OFFSET_USB_OHCI0	28
+#define AHB_GATE_OFFSET_USB_OHCI1	29
+#define AHB_GATE_OFFSET_USB_EHCI0	24
+#define AHB_GATE_OFFSET_USB_EHCI1	25
 #else
 #define AHB_GATE_OFFSET_USB_OHCI1	30
 #define AHB_GATE_OFFSET_USB_OHCI0	29
Signature · 1 line
2.17.1
#1 lore raw

PATCH v2 2/4 usb: sunxi: ehci: get rid of ifdefs

We can use compatibles instead.

---
 drivers/usb/host/ehci-sunxi.c | 89 +++++++++++++++++++++++++++--------
 1 file changed, 69 insertions(+), 20 deletions(-)
drivers/usb/host/ehci-sunxi.c +69 -20
index 360efc9116..39b98c21ca 100644
@@ -22,11 +22,24 @@
 #define AHB_CLK_DIST		1
 #endif
 
+enum ehci_sunxi_type {
+	sun4i_a10_ehci,
+	sun5i_a13_ehci,
+	sun6i_a31_ehci,
+	sun7i_a20_ehci,
+	sun8i_a23_ehci,
+	sun8i_a83t_ehci,
+	sun8i_h3_ehci,
+	sun9i_a80_ehci,
+	sun50i_a64_ehci,
+};
+
 struct ehci_sunxi_priv {
 	struct ehci_ctrl ehci;
 	struct sunxi_ccm_reg *ccm;
 	int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
 	struct phy phy;
+	enum ehci_sunxi_type type;
 };
 
 static int ehci_usb_probe(struct udevice *dev)
@@ -38,6 +51,7 @@ static int ehci_usb_probe(struct udevice *dev)
 	int extra_ahb_gate_mask = 0;
 	int phys, ret;
 
+	priv->type = (enum ehci_sunxi_type)dev_get_driver_data(dev);
 	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	if (IS_ERR(priv->ccm))
 		return PTR_ERR(priv->ccm);
@@ -72,18 +86,22 @@ no_phy:
 	 * clocks resp. phys.
 	 */
 	priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
-#if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I)
-	extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
-#endif
+	if (priv->type == sun8i_h3_ehci ||
+	    priv->type == sun50i_a64_ehci)
+		extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
 	priv->ahb_gate_mask <<= phys * AHB_CLK_DIST;
 	extra_ahb_gate_mask <<= phys * AHB_CLK_DIST;
 
 	setbits_le32(&priv->ccm->ahb_gate0,
 		     priv->ahb_gate_mask | extra_ahb_gate_mask);
-#ifdef CONFIG_SUNXI_GEN_SUN6I
-	setbits_le32(&priv->ccm->ahb_reset0_cfg,
-		     priv->ahb_gate_mask | extra_ahb_gate_mask);
-#endif
+	if (priv->type == sun6i_a31_ehci ||
+	    priv->type == sun8i_a23_ehci ||
+	    priv->type == sun8i_a83t_ehci ||
+	    priv->type == sun8i_h3_ehci ||
+	    priv->type == sun9i_a80_ehci ||
+	    priv->type == sun50i_a64_ehci)
+		setbits_le32(&priv->ccm->ahb_reset0_cfg,
+			     priv->ahb_gate_mask | extra_ahb_gate_mask);
 
 	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
@@ -108,25 +126,56 @@ static int ehci_usb_remove(struct udevice *dev)
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_SUNXI_GEN_SUN6I
-	clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
-#endif
+	if (priv->type == sun6i_a31_ehci ||
+	    priv->type == sun8i_a23_ehci ||
+	    priv->type == sun8i_a83t_ehci ||
+	    priv->type == sun8i_h3_ehci ||
+	    priv->type == sun9i_a80_ehci ||
+	    priv->type == sun50i_a64_ehci)
+		clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
 	clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask);
 
 	return 0;
 }
 
 static const struct udevice_id ehci_usb_ids[] = {
-	{ .compatible = "allwinner,sun4i-a10-ehci", },
-	{ .compatible = "allwinner,sun5i-a13-ehci", },
-	{ .compatible = "allwinner,sun6i-a31-ehci", },
-	{ .compatible = "allwinner,sun7i-a20-ehci", },
-	{ .compatible = "allwinner,sun8i-a23-ehci", },
-	{ .compatible = "allwinner,sun8i-a83t-ehci", },
-	{ .compatible = "allwinner,sun8i-h3-ehci",  },
-	{ .compatible = "allwinner,sun9i-a80-ehci", },
-	{ .compatible = "allwinner,sun50i-a64-ehci", },
-	{ }
+	{
+		.compatible = "allwinner,sun4i-a10-ehci",
+		.data = (ulong)sun4i_a10_ehci,
+	},
+	{
+		.compatible = "allwinner,sun5i-a13-ehci",
+		.data = (ulong)sun5i_a13_ehci,
+	},
+	{
+		.compatible = "allwinner,sun6i-a31-ehci",
+		.data = (ulong)sun6i_a31_ehci,
+	},
+	{
+		.compatible = "allwinner,sun7i-a20-ehci",
+		.data = (ulong)sun7i_a20_ehci,
+	},
+	{
+		.compatible = "allwinner,sun8i-a23-ehci",
+		.data = (ulong)sun8i_a23_ehci,
+	},
+	{
+		.compatible = "allwinner,sun8i-a83t-ehci",
+		.data = (ulong)sun8i_a83t_ehci,
+	},
+	{
+		.compatible = "allwinner,sun8i-h3-ehci",
+		.data = (ulong)sun8i_h3_ehci,
+	},
+	{
+		.compatible = "allwinner,sun9i-a80-ehci",
+		.data = (ulong)sun9i_a80_ehci,
+	},
+	{
+		.compatible = "allwinner,sun50i-a64-ehci",
+		.data = (ulong)sun50i_a64_ehci,
+	},
+	{ /* sentinel */ }
 };
 
 U_BOOT_DRIVER(ehci_sunxi) = {
Signature · 1 line
2.17.1
#2 lore raw

PATCH v2 3/4 usb: sunxi: ohci: get rid of ifdefs

In reply to Vasily Khoruzhick

We can use compatibles instead.

---
 drivers/usb/host/ohci-sunxi.c | 88 +++++++++++++++++++++++++++--------
 1 file changed, 68 insertions(+), 20 deletions(-)
drivers/usb/host/ohci-sunxi.c +68 -20
index ce2b47a5c4..dfdd1e538d 100644
@@ -22,12 +22,25 @@
 #define AHB_CLK_DIST		1
 #endif
 
+enum ohci_sunxi_type {
+	sun4i_a10_ohci,
+	sun5i_a13_ohci,
+	sun6i_a31_ohci,
+	sun7i_a20_ohci,
+	sun8i_a23_ohci,
+	sun8i_a83t_ohci,
+	sun8i_h3_ohci,
+	sun9i_a80_ohci,
+	sun50i_a64_ohci,
+};
+
 struct ohci_sunxi_priv {
 	struct sunxi_ccm_reg *ccm;
 	ohci_t ohci;
 	int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
 	int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */
 	struct phy phy;
+	enum ohci_sunxi_type type;
 };
 
 static int ohci_usb_probe(struct udevice *dev)
@@ -38,6 +51,7 @@ static int ohci_usb_probe(struct udevice *dev)
 	int extra_ahb_gate_mask = 0;
 	int phys, ret;
 
+	priv->type = (enum ohci_sunxi_type)dev_get_driver_data(dev);
 	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	if (IS_ERR(priv->ccm))
 		return PTR_ERR(priv->ccm);
@@ -74,9 +88,8 @@ no_phy:
 	 * clocks resp. phys.
 	 */
 	priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
-#ifdef CONFIG_MACH_SUN8I_H3
-	extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
-#endif
+	if (priv->type == sun8i_h3_ohci)
+		extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
 	priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK;
 	priv->ahb_gate_mask <<= phys * AHB_CLK_DIST;
 	extra_ahb_gate_mask <<= phys * AHB_CLK_DIST;
@@ -85,10 +98,14 @@ no_phy:
 	setbits_le32(&priv->ccm->ahb_gate0,
 		     priv->ahb_gate_mask | extra_ahb_gate_mask);
 	setbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask);
-#ifdef CONFIG_SUNXI_GEN_SUN6I
-	setbits_le32(&priv->ccm->ahb_reset0_cfg,
-		     priv->ahb_gate_mask | extra_ahb_gate_mask);
-#endif
+	if (priv->type == sun6i_a31_ohci ||
+	    priv->type == sun8i_a23_ohci ||
+	    priv->type == sun8i_a83t_ohci ||
+	    priv->type == sun8i_h3_ohci ||
+	    priv->type == sun9i_a80_ohci ||
+	    priv->type == sun50i_a64_ohci)
+		setbits_le32(&priv->ccm->ahb_reset0_cfg,
+			     priv->ahb_gate_mask | extra_ahb_gate_mask);
 
 	return ohci_register(dev, regs);
 }
@@ -110,9 +127,13 @@ static int ohci_usb_remove(struct udevice *dev)
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_SUNXI_GEN_SUN6I
-	clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
-#endif
+	if (priv->type == sun6i_a31_ohci ||
+	    priv->type == sun8i_a23_ohci ||
+	    priv->type == sun8i_a83t_ohci ||
+	    priv->type == sun8i_h3_ohci ||
+	    priv->type == sun9i_a80_ohci ||
+	    priv->type == sun50i_a64_ohci)
+		clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
 	clrbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask);
 	clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask);
 
@@ -120,16 +141,43 @@ static int ohci_usb_remove(struct udevice *dev)
 }
 
 static const struct udevice_id ohci_usb_ids[] = {
-	{ .compatible = "allwinner,sun4i-a10-ohci", },
-	{ .compatible = "allwinner,sun5i-a13-ohci", },
-	{ .compatible = "allwinner,sun6i-a31-ohci", },
-	{ .compatible = "allwinner,sun7i-a20-ohci", },
-	{ .compatible = "allwinner,sun8i-a23-ohci", },
-	{ .compatible = "allwinner,sun8i-a83t-ohci", },
-	{ .compatible = "allwinner,sun8i-h3-ohci",  },
-	{ .compatible = "allwinner,sun9i-a80-ohci", },
-	{ .compatible = "allwinner,sun50i-a64-ohci", },
-	{ }
+	{
+		.compatible = "allwinner,sun4i-a10-ohci",
+		.data = (ulong)sun4i_a10_ohci,
+	},
+	{
+		.compatible = "allwinner,sun5i-a13-ohci",
+		.data = (ulong)sun5i_a13_ohci,
+	},
+	{
+		.compatible = "allwinner,sun6i-a31-ohci",
+		.data = (ulong)sun6i_a31_ohci,
+	},
+	{
+		.compatible = "allwinner,sun7i-a20-ohci",
+		.data = (ulong)sun7i_a20_ohci,
+	},
+	{
+		.compatible = "allwinner,sun8i-a23-ohci",
+		.data = (ulong)sun8i_a23_ohci,
+	},
+	{
+		.compatible = "allwinner,sun8i-a83t-ohci",
+		.data = (ulong)sun8i_a83t_ohci,
+	},
+	{
+		.compatible = "allwinner,sun8i-h3-ohci",
+		.data = (ulong)sun8i_h3_ohci,
+	},
+	{
+		.compatible = "allwinner,sun9i-a80-ohci",
+		.data = (ulong)sun9i_a80_ohci,
+	},
+	{
+		.compatible = "allwinner,sun50i-a64-ohci",
+		.data = (ulong)sun50i_a64_ohci,
+	},
+	{ /* sentinel */ }
 };
 
 U_BOOT_DRIVER(usb_ohci) = {
Signature · 1 line
2.17.1
#3 lore raw

PATCH v2 3/4 usb: sunxi: ohci: get rid of ifdefs

Hi,

Quoted 24 lines · Vasily Khoruzhick

We can use compatibles instead.

---
 drivers/usb/host/ohci-sunxi.c | 88 +++++++++++++++++++++++++++--------
 1 file changed, 68 insertions(+), 20 deletions(-)
drivers/usb/host/ohci-sunxi.c +9 -0
index ce2b47a5c4..dfdd1e538d 100644
@@ -22,12 +22,25 @@
 #define AHB_CLK_DIST		1
 #endif
 
+enum ohci_sunxi_type {
+	sun4i_a10_ohci,
+	sun5i_a13_ohci,
+	sun6i_a31_ohci,
+	sun7i_a20_ohci,
+	sun8i_a23_ohci,
+	sun8i_a83t_ohci,
+	sun8i_h3_ohci,
+	sun9i_a80_ohci,

drivers/usb/host/ohci-sunxi.c line 43

Quoted 10 lines
drivers/usb/host/ohci-sunxi.c +4 -0
+	sun50i_a64_ohci,
+};
+
 struct ohci_sunxi_priv {
 	struct sunxi_ccm_reg *ccm;
 	ohci_t ohci;
 	int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
 	int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */
 	struct phy phy;
+	enum ohci_sunxi_type type;

I'm really not a big fan of those ID, especially when we already have a structure here that have some very similar data embedded into it. In this particular case, it looks like you just need to add a bool to say if it has a reset, and an int for the extra_ahb_gate_mask, like we have the ahb_gate_mask already.

This also applies to the EHCI patch.

Maxime

Signature · 3 lines
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
#4 lore raw

PATCH v2 4/4 usb: sunxi: sun50i: enable OHCI0 clock when OHCI1 is in use

In reply to Vasily Khoruzhick

On A64 OHCI1 clock source is OHCI0 clock, so we need to enable OHCI0 clock when OHCI1 is in use.

Fixes commit dd3228170ad7 ("usb: sunxi: Switch to use generic-phy")

---
 drivers/usb/host/ohci-sunxi.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/usb/host/ohci-sunxi.c +5 -1
index dfdd1e538d..f024df2f9c 100644
@@ -49,6 +49,7 @@ static int ohci_usb_probe(struct udevice *dev)
 	struct ohci_sunxi_priv *priv = dev_get_priv(dev);
 	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
 	int extra_ahb_gate_mask = 0;
+	int extra_usb_gate_mask = 0;
 	int phys, ret;
 
 	priv->type = (enum ohci_sunxi_type)dev_get_driver_data(dev);
@@ -91,13 +92,16 @@ no_phy:
 	if (priv->type == sun8i_h3_ohci)
 		extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
 	priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK;
+	if (priv->type == sun50i_a64_ohci)
+		extra_usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK;
 	priv->ahb_gate_mask <<= phys * AHB_CLK_DIST;
 	extra_ahb_gate_mask <<= phys * AHB_CLK_DIST;
 	priv->usb_gate_mask <<= phys;
 
 	setbits_le32(&priv->ccm->ahb_gate0,
 		     priv->ahb_gate_mask | extra_ahb_gate_mask);
-	setbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask);
+	setbits_le32(&priv->ccm->usb_clk_cfg,
+		     priv->usb_gate_mask | extra_usb_gate_mask);
 	if (priv->type == sun6i_a31_ohci ||
 	    priv->type == sun8i_a23_ohci ||
 	    priv->type == sun8i_a83t_ohci ||
Signature · 1 line
2.17.1