Skip to contentSkip to conversation

sunxi: usb: Turn the usbc code into a usb-phy driver

PATCH New Hans de Goede 2 participants 13 messages Apr 28, 2015 – May 2, 2015

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover sunxi: usb: Turn the usbc code into a usb-phy driver

Hi,

This is a preparation series for moving the sunxi ehci code over to the driver model and for adding ohci support.

Regards,

Hans

#1 lore raw

PATCH 1/6 sunxi: usb: Move setup of host controller clocks to the host controller drivers

The sunxi "usbc" code is mostly about phy setup, but currently also sets up the host controller clocks, which is something which really belongs in the host controller drivers, so move it there.

This is a preparation patch for moving the sunxi ehci code to the driver model and for adding ohci support.

---
 arch/arm/cpu/armv7/sunxi/usbc.c | 14 +-------------
 drivers/usb/host/ehci-sunxi.c   | 24 ++++++++++++++++++++++--
 drivers/usb/musb-new/sunxi.c    | 20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 15 deletions(-)
arch/arm/cpu/armv7/sunxi/usbc.c +1 -13
index 21032aa..6ae6dfa 100644
@@ -11,12 +11,12 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <common.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/usbc.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
-#include <common.h>
 #include <errno.h>
 #ifdef CONFIG_AXP152_POWER
 #include <axp152.h>
@@ -44,25 +44,21 @@
 static struct sunxi_usbc_hcd {
 	struct usb_hcd *hcd;
 	int usb_rst_mask;
-	int ahb_clk_mask;
 	int gpio_vbus;
 	int gpio_vbus_det;
 	int id;
 } sunxi_usbc_hcd[] = {
 	{
 		.usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK,
-		.ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB0,
 		.id = 0,
 	},
 	{
 		.usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK,
-		.ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0,
 		.id = 1,
 	},
 #if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1)
 	{
 		.usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK,
-		.ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1,
 		.id = 2,
 	}
 #endif
@@ -227,10 +223,6 @@ void sunxi_usbc_enable(int index)
 		setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
 
 	setbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
-	setbits_le32(&ccm->ahb_gate0, sunxi_usbc->ahb_clk_mask);
-#ifdef CONFIG_SUNXI_GEN_SUN6I
-	setbits_le32(&ccm->ahb_reset0_cfg, sunxi_usbc->ahb_clk_mask);
-#endif
 
 	sunxi_usb_phy_init(sunxi_usbc);
 
@@ -248,10 +240,6 @@ void sunxi_usbc_disable(int index)
 	if (sunxi_usbc->id != 0)
 		sunxi_usb_passby(sunxi_usbc, !SUNXI_USB_PASSBY_EN);
 
-#ifdef CONFIG_SUNXI_GEN_SUN6I
-	clrbits_le32(&ccm->ahb_reset0_cfg, sunxi_usbc->ahb_clk_mask);
-#endif
-	clrbits_le32(&ccm->ahb_gate0, sunxi_usbc->ahb_clk_mask);
 	clrbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
 
 	/* disable common PHY only once, for the last enabled hcd */
drivers/usb/host/ehci-sunxi.c +22 -2
index eda9f69..41e4d7f 100644
@@ -9,19 +9,29 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <asm/arch/usbc.h>
 #include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/usbc.h>
+#include <asm/io.h>
 #include "ehci.h"
 
 int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
 		struct ehci_hcor **hcor)
 {
-	int err;
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	int ahb_gate_offset, err;
 
 	err = sunxi_usbc_request_resources(index + 1);
 	if (err)
 		return err;
 
+	ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
+				  AHB_GATE_OFFSET_USB_EHCI0;
+	setbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+	setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset);
+#endif
+
 	sunxi_usbc_enable(index + 1);
 	sunxi_usbc_vbus_enable(index + 1);
 
@@ -39,8 +49,18 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
 
 int ehci_hcd_stop(int index)
 {
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	int ahb_gate_offset;
+
 	sunxi_usbc_vbus_disable(index + 1);
 	sunxi_usbc_disable(index + 1);
 
+	ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
+				  AHB_GATE_OFFSET_USB_EHCI0;
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+	clrbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset);
+#endif
+	clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
+
 	return sunxi_usbc_free_resources(index + 1);
 }
drivers/usb/musb-new/sunxi.c +20 -0
index c9a6a16..e3c6d6a 100644
@@ -22,6 +22,7 @@
  */
 #include <common.h>
 #include <asm/arch/cpu.h>
+#include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/usbc.h>
 #include <asm-generic/gpio.h>
@@ -219,11 +220,24 @@ static void sunxi_musb_enable(struct musb *musb)
 
 static void sunxi_musb_disable(struct musb *musb)
 {
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
 	pr_debug("%s():\n", __func__);
 
 	/* Put the controller back in a pristane state for "usb reset" */
 	if (musb->is_active) {
 		sunxi_usbc_disable(0);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+		clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
+#endif
+		clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0);
+
+		mdelay(10);
+
+		setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+		setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
+#endif
 		sunxi_usbc_enable(0);
 		musb->is_active = 0;
 	}
@@ -231,6 +245,7 @@ static void sunxi_musb_disable(struct musb *musb)
 
 static int sunxi_musb_init(struct musb *musb)
 {
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	int err;
 
 	pr_debug("%s():\n", __func__);
@@ -249,6 +264,11 @@ static int sunxi_musb_init(struct musb *musb)
 	}
 
 	musb->isr = sunxi_musb_interrupt;
+
+	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
+#endif
 	sunxi_usbc_enable(0);
 
 	USBC_ConfigFIFO_Base();
Signature · 1 line
2.3.5
#2 lore raw

PATCH 1/6 sunxi: usb: Move setup of host controller clocks to the host controller drivers

Quoted 8 lines · Hans de Goede

The sunxi "usbc" code is mostly about phy setup, but currently also sets up the host controller clocks, which is something which really belongs in the host controller drivers, so move it there.

This is a preparation patch for moving the sunxi ehci code to the driver model and for adding ohci support.

#3 lore raw

PATCH 2/6 sunxi: usb: Remove sunxi_usbc_get_io_base function

In reply to Hans de Goede

This is the only function left in sunxi/usbc.c which is not phy related, so remove it.

This is a preparation patch for turning the usbc.c code into a proper usb phy driver.

---
 arch/arm/cpu/armv7/sunxi/usbc.c        | 30 ++++++++++--------------------
 arch/arm/include/asm/arch-sunxi/usbc.h |  1 -
 drivers/usb/host/ehci-sunxi.c          |  5 ++++-
 3 files changed, 14 insertions(+), 22 deletions(-)
arch/arm/cpu/armv7/sunxi/usbc.c +10 -20
index 6ae6dfa..131e103 100644
@@ -66,20 +66,6 @@ static struct sunxi_usbc_hcd {
 
 static int enabled_hcd_count;
 
-void *sunxi_usbc_get_io_base(int index)
-{
-	switch (index) {
-	case 0:
-		return (void *)SUNXI_USB0_BASE;
-	case 1:
-		return (void *)SUNXI_USB1_BASE;
-	case 2:
-		return (void *)SUNXI_USB2_BASE;
-	default:
-		return NULL;
-	}
-}
-
 static int get_vbus_gpio(int index)
 {
 	switch (index) {
@@ -102,7 +88,7 @@ static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr,
 			  int data, int len)
 {
 	int j = 0, usbc_bit = 0;
-	void *dest = sunxi_usbc_get_io_base(0) + SUNXI_USB_CSR;
+	void *dest = (void *)SUNXI_USB0_BASE + SUNXI_USB_CSR;
 
 #ifdef CONFIG_MACH_SUN8I_A33
 	/* CSR needs to be explicitly initialized to 0 on A33 */
@@ -153,11 +139,15 @@ static void sunxi_usb_phy_init(struct sunxi_usbc_hcd *sunxi_usbc)
 	return;
 }
 
-static void sunxi_usb_passby(struct sunxi_usbc_hcd *sunxi_usbc, int enable)
+static void sunxi_usb_phy_passby(int index, int enable)
 {
 	unsigned long bits = 0;
-	void *addr = sunxi_usbc_get_io_base(sunxi_usbc->id) +
-		     SUNXI_USB_PMU_IRQ_ENABLE;
+	void *addr;
+
+	if (index == 1)
+		addr = (void *)SUNXI_USB1_BASE + SUNXI_USB_PMU_IRQ_ENABLE;
+	else
+		addr = (void *)SUNXI_USB2_BASE + SUNXI_USB_PMU_IRQ_ENABLE;
 
 	bits = SUNXI_EHCI_AHB_ICHR8_EN |
 		SUNXI_EHCI_AHB_INCR4_BURST_EN |
@@ -227,7 +217,7 @@ void sunxi_usbc_enable(int index)
 	sunxi_usb_phy_init(sunxi_usbc);
 
 	if (sunxi_usbc->id != 0)
-		sunxi_usb_passby(sunxi_usbc, SUNXI_USB_PASSBY_EN);
+		sunxi_usb_phy_passby(index, SUNXI_USB_PASSBY_EN);
 
 	enabled_hcd_count++;
 }
@@ -238,7 +228,7 @@ void sunxi_usbc_disable(int index)
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
 	if (sunxi_usbc->id != 0)
-		sunxi_usb_passby(sunxi_usbc, !SUNXI_USB_PASSBY_EN);
+		sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
 
 	clrbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
 
arch/arm/include/asm/arch-sunxi/usbc.h +0 -1
index ab0f272..41721f9 100644
@@ -13,7 +13,6 @@
 
 extern const struct musb_platform_ops sunxi_musb_ops;
 
-void *sunxi_usbc_get_io_base(int index);
 int sunxi_usbc_request_resources(int index);
 int sunxi_usbc_free_resources(int index);
 void sunxi_usbc_enable(int index);
drivers/usb/host/ehci-sunxi.c +4 -1
index 41e4d7f..5de20f9 100644
@@ -35,7 +35,10 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
 	sunxi_usbc_enable(index + 1);
 	sunxi_usbc_vbus_enable(index + 1);
 
-	*hccr = sunxi_usbc_get_io_base(index + 1);
+	if (index == 0)
+		*hccr = (void *)SUNXI_USB1_BASE;
+	else
+		*hccr = (void *)SUNXI_USB2_BASE;
 
 	*hcor = (struct ehci_hcor *)((uint32_t) *hccr
 				+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
Signature · 1 line
2.3.5
#5 lore raw

PATCH 3/6 sunxi: usb: Rename sunxi_usbc_foo functions to sunxi_usb_phy_bar

In reply to Hans de Goede

Rename the sunxi_usbc_foo functions to sunxi_usb_phy_bar to make it clear that these are usb-phy functions. Also change the verbs & nouns in the suffix to match the verbs & nouns used in the Linux kernels generic phy framework.

This patch purely renames things, it contains no functional changes.

---
 arch/arm/cpu/armv7/sunxi/usbc.c        | 124 ++++++++++++++++-----------------
 arch/arm/include/asm/arch-sunxi/usbc.h |  25 +++----
 board/sunxi/board.c                    |   2 +
 drivers/usb/host/ehci-sunxi.c          |  17 ++---
 drivers/usb/musb-new/musb_uboot.c      |   4 +-
 drivers/usb/musb-new/sunxi.c           |  20 +++---
 6 files changed, 95 insertions(+), 97 deletions(-)
arch/arm/cpu/armv7/sunxi/usbc.c +61 -63
index 131e103..71817c1 100644
@@ -1,9 +1,8 @@
 /*
- * Sunxi usb-controller code shared between the ehci and musb controllers
+ * Sunxi usb-phy code
  *
- * Copyright (C) 2014 Roman Byshko
- *
- * Roman Byshko <[email protected]>
+ * Copyright (C) 2015 Hans de Goede <[email protected]>
+ * Copyright (C) 2014 Roman Byshko <[email protected]>
  *
  * Based on code from
  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
@@ -41,13 +40,12 @@
 #define SUNXI_EHCI_AHB_INCRX_ALIGN_EN	(1 << 8)
 #define SUNXI_EHCI_ULPI_BYPASS_EN	(1 << 0)
 
-static struct sunxi_usbc_hcd {
-	struct usb_hcd *hcd;
+static struct sunxi_usb_phy {
 	int usb_rst_mask;
 	int gpio_vbus;
 	int gpio_vbus_det;
 	int id;
-} sunxi_usbc_hcd[] = {
+} sunxi_usb_phy[] = {
 	{
 		.usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK,
 		.id = 0,
@@ -64,7 +62,7 @@ static struct sunxi_usbc_hcd {
 #endif
 };
 
-static int enabled_hcd_count;
+static int sunxi_usb_phy_enabled_count;
 
 static int get_vbus_gpio(int index)
 {
@@ -84,7 +82,7 @@ static int get_vbus_detect_gpio(int index)
 	return -EINVAL;
 }
 
-static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr,
+static void usb_phy_write(struct sunxi_usb_phy *phy, int addr,
 			  int data, int len)
 {
 	int j = 0, usbc_bit = 0;
@@ -95,7 +93,7 @@ static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr,
 	writel(0, dest);
 #endif
 
-	usbc_bit = 1 << (sunxi_usbc->id * 2);
+	usbc_bit = 1 << (phy->id * 2);
 	for (j = 0; j < len; j++) {
 		/* set the bit address to be written */
 		clrbits_le32(dest, 0xff << 8);
@@ -116,24 +114,24 @@ static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr,
 	}
 }
 
-static void sunxi_usb_phy_init(struct sunxi_usbc_hcd *sunxi_usbc)
+static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy)
 {
 	/* The following comments are machine
 	 * translated from Chinese, you have been warned!
 	 */
 
 	/* Regulation 45 ohms */
-	if (sunxi_usbc->id == 0)
-		usb_phy_write(sunxi_usbc, 0x0c, 0x01, 1);
+	if (phy->id == 0)
+		usb_phy_write(phy, 0x0c, 0x01, 1);
 
 	/* adjust PHY's magnitude and rate */
-	usb_phy_write(sunxi_usbc, 0x20, 0x14, 5);
+	usb_phy_write(phy, 0x20, 0x14, 5);
 
 	/* threshold adjustment disconnect */
 #if defined CONFIG_MACH_SUN4I || defined CONFIG_MACH_SUN6I
-	usb_phy_write(sunxi_usbc, 0x2a, 3, 2);
+	usb_phy_write(phy, 0x2a, 3, 2);
 #else
-	usb_phy_write(sunxi_usbc, 0x2a, 2, 2);
+	usb_phy_write(phy, 0x2a, 2, 2);
 #endif
 
 	return;
@@ -162,110 +160,110 @@ static void sunxi_usb_phy_passby(int index, int enable)
 	return;
 }
 
-void sunxi_usbc_enable_squelch_detect(int index, int enable)
+void sunxi_usb_phy_enable_squelch_detect(int index, int enable)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 
-	usb_phy_write(sunxi_usbc, 0x3c, enable ? 0 : 2, 2);
+	usb_phy_write(phy, 0x3c, enable ? 0 : 2, 2);
 }
 
-int sunxi_usbc_request_resources(int index)
+int sunxi_usb_phy_probe(int index)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	int ret = 0;
 
-	sunxi_usbc->gpio_vbus = get_vbus_gpio(index);
-	if (sunxi_usbc->gpio_vbus >= 0) {
-		ret |= gpio_request(sunxi_usbc->gpio_vbus, "usbc_vbus");
-		ret |= gpio_direction_output(sunxi_usbc->gpio_vbus, 0);
+	phy->gpio_vbus = get_vbus_gpio(index);
+	if (phy->gpio_vbus >= 0) {
+		ret |= gpio_request(phy->gpio_vbus, "usbc_vbus");
+		ret |= gpio_direction_output(phy->gpio_vbus, 0);
 	}
 
-	sunxi_usbc->gpio_vbus_det = get_vbus_detect_gpio(index);
-	if (sunxi_usbc->gpio_vbus_det >= 0) {
-		ret |= gpio_request(sunxi_usbc->gpio_vbus_det, "usbc_vbus_det");
-		ret |= gpio_direction_input(sunxi_usbc->gpio_vbus_det);
+	phy->gpio_vbus_det = get_vbus_detect_gpio(index);
+	if (phy->gpio_vbus_det >= 0) {
+		ret |= gpio_request(phy->gpio_vbus_det, "usbc_vbus_det");
+		ret |= gpio_direction_input(phy->gpio_vbus_det);
 	}
 
 	return ret;
 }
 
-int sunxi_usbc_free_resources(int index)
+int sunxi_usb_phy_remove(int index)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	int ret = 0;
 
-	if (sunxi_usbc->gpio_vbus >= 0)
-		ret |= gpio_free(sunxi_usbc->gpio_vbus);
+	if (phy->gpio_vbus >= 0)
+		ret |= gpio_free(phy->gpio_vbus);
 
-	if (sunxi_usbc->gpio_vbus_det >= 0)
-		ret |= gpio_free(sunxi_usbc->gpio_vbus_det);
+	if (phy->gpio_vbus_det >= 0)
+		ret |= gpio_free(phy->gpio_vbus_det);
 
 	return ret;
 }
 
-void sunxi_usbc_enable(int index)
+void sunxi_usb_phy_init(int index)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
 	/* enable common PHY only once */
-	if (enabled_hcd_count == 0)
+	if (sunxi_usb_phy_enabled_count == 0)
 		setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
 
-	setbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
+	setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
 
-	sunxi_usb_phy_init(sunxi_usbc);
+	sunxi_usb_phy_config(phy);
 
-	if (sunxi_usbc->id != 0)
+	if (phy->id != 0)
 		sunxi_usb_phy_passby(index, SUNXI_USB_PASSBY_EN);
 
-	enabled_hcd_count++;
+	sunxi_usb_phy_enabled_count++;
 }
 
-void sunxi_usbc_disable(int index)
+void sunxi_usb_phy_exit(int index)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
-	if (sunxi_usbc->id != 0)
+	if (phy->id != 0)
 		sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
 
-	clrbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
+	clrbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
 
-	/* disable common PHY only once, for the last enabled hcd */
-	if (enabled_hcd_count == 1)
+	/* disable common PHY only once, for the last enabled phy */
+	if (sunxi_usb_phy_enabled_count == 1)
 		clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
 
-	enabled_hcd_count--;
+	sunxi_usb_phy_enabled_count--;
 }
 
-void sunxi_usbc_vbus_enable(int index)
+void sunxi_usb_phy_power_on(int index)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 
-	if (sunxi_usbc->gpio_vbus >= 0)
-		gpio_set_value(sunxi_usbc->gpio_vbus, 1);
+	if (phy->gpio_vbus >= 0)
+		gpio_set_value(phy->gpio_vbus, 1);
 }
 
-void sunxi_usbc_vbus_disable(int index)
+void sunxi_usb_phy_power_off(int index)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 
-	if (sunxi_usbc->gpio_vbus >= 0)
-		gpio_set_value(sunxi_usbc->gpio_vbus, 0);
+	if (phy->gpio_vbus >= 0)
+		gpio_set_value(phy->gpio_vbus, 0);
 }
 
-int sunxi_usbc_vbus_detect(int index)
+int sunxi_usb_phy_vbus_detect(int index)
 {
-	struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index];
+	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	int err, retries = 3;
 
-	if (sunxi_usbc->gpio_vbus_det < 0) {
+	if (phy->gpio_vbus_det < 0) {
 		eprintf("Error: invalid vbus detection pin\n");
-		return sunxi_usbc->gpio_vbus_det;
+		return phy->gpio_vbus_det;
 	}
 
-	err = gpio_get_value(sunxi_usbc->gpio_vbus_det);
+	err = gpio_get_value(phy->gpio_vbus_det);
 	/*
 	 * Vbus may have been provided by the board and just been turned of
 	 * some milliseconds ago on reset, what we're measuring then is a
@@ -273,7 +271,7 @@ int sunxi_usbc_vbus_detect(int index)
 	 */
 	while (err > 0 && retries--) {
 		mdelay(100);
-		err = gpio_get_value(sunxi_usbc->gpio_vbus_det);
+		err = gpio_get_value(phy->gpio_vbus_det);
 	}
 
 	return err;
arch/arm/include/asm/arch-sunxi/usbc.h +11 -14
index 41721f9..14ed081 100644
@@ -1,9 +1,8 @@
 /*
- * Sunxi usb-controller code shared between the ehci and musb controllers
+ * Sunxi usb-phy code
  *
- * Copyright (C) 2014 Roman Byshko
- *
- * Roman Byshko <[email protected]>
+ * Copyright (C) 2015 Hans de Goede <[email protected]>
+ * Copyright (C) 2014 Roman Byshko <[email protected]>
  *
  * Based on code from
  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
@@ -11,13 +10,11 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-extern const struct musb_platform_ops sunxi_musb_ops;
-
-int sunxi_usbc_request_resources(int index);
-int sunxi_usbc_free_resources(int index);
-void sunxi_usbc_enable(int index);
-void sunxi_usbc_disable(int index);
-void sunxi_usbc_vbus_enable(int index);
-void sunxi_usbc_vbus_disable(int index);
-int sunxi_usbc_vbus_detect(int index);
-void sunxi_usbc_enable_squelch_detect(int index, int enable);
+int sunxi_usb_phy_probe(int index);
+int sunxi_usb_phy_remove(int index);
+void sunxi_usb_phy_init(int index);
+void sunxi_usb_phy_exit(int index);
+void sunxi_usb_phy_power_on(int index);
+void sunxi_usb_phy_power_off(int index);
+int sunxi_usb_phy_vbus_detect(int index);
+void sunxi_usb_phy_enable_squelch_detect(int index, int enable);
board/sunxi/board.c +2 -0
index ee66f98..4ddd848 100644
@@ -452,6 +452,8 @@ void sunxi_board_init(void)
 #endif
 
 #if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET)
+extern const struct musb_platform_ops sunxi_musb_ops;
+
 static struct musb_hdrc_config musb_config = {
 	.multipoint     = 1,
 	.dyn_fifo       = 1,
drivers/usb/host/ehci-sunxi.c +9 -8
index 5de20f9..b6fa538 100644
@@ -1,7 +1,8 @@
 /*
- * Copyright (C) 2014 Roman Byshko
+ * Sunxi ehci glue
  *
- * Roman Byshko <[email protected]>
+ * Copyright (C) 2015 Hans de Goede <[email protected]>
+ * Copyright (C) 2014 Roman Byshko <[email protected]>
  *
  * Based on code from
  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
@@ -21,7 +22,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	int ahb_gate_offset, err;
 
-	err = sunxi_usbc_request_resources(index + 1);
+	err = sunxi_usb_phy_probe(index + 1);
 	if (err)
 		return err;
 
@@ -32,8 +33,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
 	setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset);
 #endif
 
-	sunxi_usbc_enable(index + 1);
-	sunxi_usbc_vbus_enable(index + 1);
+	sunxi_usb_phy_init(index + 1);
+	sunxi_usb_phy_power_on(index + 1);
 
 	if (index == 0)
 		*hccr = (void *)SUNXI_USB1_BASE;
@@ -55,8 +56,8 @@ int ehci_hcd_stop(int index)
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	int ahb_gate_offset;
 
-	sunxi_usbc_vbus_disable(index + 1);
-	sunxi_usbc_disable(index + 1);
+	sunxi_usb_phy_power_off(index + 1);
+	sunxi_usb_phy_exit(index + 1);
 
 	ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
 				  AHB_GATE_OFFSET_USB_EHCI0;
@@ -65,5 +66,5 @@ int ehci_hcd_stop(int index)
 #endif
 	clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
 
-	return sunxi_usbc_free_resources(index + 1);
+	return sunxi_usb_phy_remove(index + 1);
 }
drivers/usb/musb-new/musb_uboot.c +2 -2
index 7d90ebc..4d0213a 100644
@@ -195,12 +195,12 @@ int usb_reset_root_port(void)
 	 * when clearing reset on low-speed devices, temporary disable
 	 * squelch detection to work around this.
 	 */
-	sunxi_usbc_enable_squelch_detect(0, 0);
+	sunxi_usb_phy_enable_squelch_detect(0, 0);
 #endif
 	power = musb_readb(mbase, MUSB_POWER);
 	musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
 #ifdef CONFIG_ARCH_SUNXI
-	sunxi_usbc_enable_squelch_detect(0, 1);
+	sunxi_usb_phy_enable_squelch_detect(0, 1);
 #endif
 	host->isr(0, host);
 	host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
drivers/usb/musb-new/sunxi.c +10 -10
index e3c6d6a..5a9d39c 100644
@@ -214,7 +214,7 @@ static void sunxi_musb_enable(struct musb *musb)
 
 	if (is_host_enabled(musb)) {
 		/* port power on */
-		sunxi_usbc_vbus_enable(0);
+		sunxi_usb_phy_power_on(0);
 	}
 }
 
@@ -226,7 +226,7 @@ static void sunxi_musb_disable(struct musb *musb)
 
 	/* Put the controller back in a pristane state for "usb reset" */
 	if (musb->is_active) {
-		sunxi_usbc_disable(0);
+		sunxi_usb_phy_exit(0);
 #ifdef CONFIG_SUNXI_GEN_SUN6I
 		clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
 #endif
@@ -238,7 +238,7 @@ static void sunxi_musb_disable(struct musb *musb)
 #ifdef CONFIG_SUNXI_GEN_SUN6I
 		setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
 #endif
-		sunxi_usbc_enable(0);
+		sunxi_usb_phy_init(0);
 		musb->is_active = 0;
 	}
 }
@@ -250,15 +250,15 @@ static int sunxi_musb_init(struct musb *musb)
 
 	pr_debug("%s():\n", __func__);
 
-	err = sunxi_usbc_request_resources(0);
+	err = sunxi_usb_phy_probe(0);
 	if (err)
 		return err;
 
 	if (is_host_enabled(musb)) {
-		err = sunxi_usbc_vbus_detect(0);
+		err = sunxi_usb_phy_vbus_detect(0);
 		if (err) {
 			eprintf("Error: A charger is plugged into the OTG\n");
-			sunxi_usbc_free_resources(0);
+			sunxi_usb_phy_remove(0);
 			return -EIO;
 		}
 	}
@@ -269,7 +269,7 @@ static int sunxi_musb_init(struct musb *musb)
 #ifdef CONFIG_SUNXI_GEN_SUN6I
 	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
 #endif
-	sunxi_usbc_enable(0);
+	sunxi_usb_phy_init(0);
 
 	USBC_ConfigFIFO_Base();
 	USBC_EnableDpDmPullUp(musb->mregs);
@@ -293,10 +293,10 @@ static int sunxi_musb_exit(struct musb *musb)
 
 	USBC_DisableDpDmPullUp(musb->mregs);
 	USBC_DisableIdPullUp(musb->mregs);
-	sunxi_usbc_vbus_disable(0);
-	sunxi_usbc_disable(0);
+	sunxi_usb_phy_power_off(0);
+	sunxi_usb_phy_exit(0);
 
-	return sunxi_usbc_free_resources(0);
+	return sunxi_usb_phy_remove(0);
 }
 
 const struct musb_platform_ops sunxi_musb_ops = {
Signature · 1 line
2.3.5
#6 lore raw

PATCH 3/6 sunxi: usb: Rename sunxi_usbc_foo functions to sunxi_usb_phy_bar

Quoted 5 lines · Hans de Goede

Rename the sunxi_usbc_foo functions to sunxi_usb_phy_bar to make it clear that these are usb-phy functions. Also change the verbs & nouns in the suffix to match the verbs & nouns used in the Linux kernels generic phy framework.

This patch purely renames things, it contains no functional changes.

That being the case, without reading:

Quoted 1 line
#7 lore raw

PATCH 4/6 sunxi: usb: Rename the usbc.? files to usb_phy.?

In reply to Hans de Goede

The usbc.? files now only contain usb-phy related code, rename them to make this clear.

---
 arch/arm/cpu/armv7/sunxi/Makefile                     | 2 +-
 arch/arm/cpu/armv7/sunxi/{usbc.c => usb_phy.c}        | 2 +-
 arch/arm/include/asm/arch-sunxi/{usbc.h => usb_phy.h} | 0
 board/sunxi/board.c                                   | 2 +-
 drivers/usb/host/ehci-sunxi.c                         | 2 +-
 drivers/usb/musb-new/musb_uboot.c                     | 2 +-
 drivers/usb/musb-new/sunxi.c                          | 2 +-
 7 files changed, 6 insertions(+), 6 deletions(-)
 rename arch/arm/cpu/armv7/sunxi/{usbc.c => usb_phy.c} (99%)
 rename arch/arm/include/asm/arch-sunxi/{usbc.h => usb_phy.h} (100%)
arch/arm/cpu/armv7/sunxi/Makefile +1 -1
index 5221902..406a866 100644
@@ -14,7 +14,7 @@ obj-y	+= cpu_info.o
 obj-y	+= dram_helpers.o
 obj-y	+= pinmux.o
 ifndef CONFIG_MACH_SUN9I
-obj-y	+= usbc.o
+obj-y	+= usb_phy.o
 endif
 obj-$(CONFIG_MACH_SUN6I)	+= prcm.o
 obj-$(CONFIG_MACH_SUN8I_A23)	+= prcm.o
arch/arm/cpu/armv7/sunxi/usb_phy.c renamed from arch/arm/cpu/armv7/sunxi/usbc.c +1 -1
similarity index 99%
rename from arch/arm/cpu/armv7/sunxi/usbc.c
rename to arch/arm/cpu/armv7/sunxi/usb_phy.c
index 71817c1..c238d38 100644
@@ -13,7 +13,7 @@
 #include <common.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/usbc.h>
+#include <asm/arch/usb_phy.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <errno.h>
arch/arm/include/asm/arch-sunxi/usb_phy.h renamed from arch/arm/include/asm/arch-sunxi/usbc.h +0 -0
similarity index 100%
rename from arch/arm/include/asm/arch-sunxi/usbc.h
rename to arch/arm/include/asm/arch-sunxi/usb_phy.h
board/sunxi/board.c +1 -1
index 4ddd848..7333946 100644
@@ -28,7 +28,7 @@
 #include <asm/arch/dram.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
-#include <asm/arch/usbc.h>
+#include <asm/arch/usb_phy.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <linux/usb/musb.h>
drivers/usb/host/ehci-sunxi.c +1 -1
index b6fa538..9e74a0b 100644
@@ -12,7 +12,7 @@
 
 #include <common.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/usbc.h>
+#include <asm/arch/usb_phy.h>
 #include <asm/io.h>
 #include "ehci.h"
 
drivers/usb/musb-new/musb_uboot.c +1 -1
index 4d0213a..d1ee5f8 100644
@@ -1,7 +1,7 @@
 #include <common.h>
 #include <watchdog.h>
 #ifdef CONFIG_ARCH_SUNXI
-#include <asm/arch/usbc.h>
+#include <asm/arch/usb_phy.h>
 #endif
 #include <asm/errno.h>
 #include <linux/usb/ch9.h>
drivers/usb/musb-new/sunxi.c +1 -1
index 5a9d39c..4f08f9f 100644
@@ -24,7 +24,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
-#include <asm/arch/usbc.h>
+#include <asm/arch/usb_phy.h>
 #include <asm-generic/gpio.h>
 #include "linux-compat.h"
 #include "musb_core.h"
Signature · 1 line
2.3.5
#9 lore raw

PATCH 5/6 sunxi: usb: Do not call phy_probe from hcd code

In reply to Hans de Goede

The 2/3 usb-phys on the sunxi SoCs are really a single separate functional block, and are modelled as such in devicetree. So once we've moved all the sunxi usb code to the driver-model then phy_probe will be called once for the entire block from the driver-model enumeration code.

Move to this now as this also avoids problems with phy_probe being called multiple times once we introduce ohci support. This allows us to get rid of the sunxi_usb_phy_enabled_count variable as phy_probe now is guaranteed to be called only once.

Since we're effectively rewriting the probe / remove functions, move them to the end of the file while we are at it, as that is the most logical place for them.

---
 arch/arm/cpu/armv7/sunxi/usb_phy.c        | 106 ++++++++++++++++--------------
 arch/arm/include/asm/arch-sunxi/usb_phy.h |   4 +-
 board/sunxi/board.c                       |   4 ++
 drivers/usb/host/ehci-sunxi.c             |   8 +--
 drivers/usb/musb-new/sunxi.c              |   7 +-
 include/configs/sun4i.h                   |   2 +
 include/configs/sun5i.h                   |   2 +
 include/configs/sun6i.h                   |   2 +
 include/configs/sun7i.h                   |   2 +
 include/configs/sun8i.h                   |   2 +
 10 files changed, 76 insertions(+), 63 deletions(-)
arch/arm/cpu/armv7/sunxi/usb_phy.c +57 -49
index c238d38..1f85dec 100644
@@ -54,7 +54,7 @@ static struct sunxi_usb_phy {
 		.usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK,
 		.id = 1,
 	},
-#if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1)
+#if CONFIG_SUNXI_USB_PHYS >= 3
 	{
 		.usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK,
 		.id = 2,
@@ -62,8 +62,6 @@ static struct sunxi_usb_phy {
 #endif
 };
 
-static int sunxi_usb_phy_enabled_count;
-
 static int get_vbus_gpio(int index)
 {
 	switch (index) {
@@ -167,57 +165,17 @@ void sunxi_usb_phy_enable_squelch_detect(int index, int enable)
 	usb_phy_write(phy, 0x3c, enable ? 0 : 2, 2);
 }
 
-int sunxi_usb_phy_probe(int index)
-{
-	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
-	int ret = 0;
-
-	phy->gpio_vbus = get_vbus_gpio(index);
-	if (phy->gpio_vbus >= 0) {
-		ret |= gpio_request(phy->gpio_vbus, "usbc_vbus");
-		ret |= gpio_direction_output(phy->gpio_vbus, 0);
-	}
-
-	phy->gpio_vbus_det = get_vbus_detect_gpio(index);
-	if (phy->gpio_vbus_det >= 0) {
-		ret |= gpio_request(phy->gpio_vbus_det, "usbc_vbus_det");
-		ret |= gpio_direction_input(phy->gpio_vbus_det);
-	}
-
-	return ret;
-}
-
-int sunxi_usb_phy_remove(int index)
-{
-	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
-	int ret = 0;
-
-	if (phy->gpio_vbus >= 0)
-		ret |= gpio_free(phy->gpio_vbus);
-
-	if (phy->gpio_vbus_det >= 0)
-		ret |= gpio_free(phy->gpio_vbus_det);
-
-	return ret;
-}
-
 void sunxi_usb_phy_init(int index)
 {
 	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
-	/* enable common PHY only once */
-	if (sunxi_usb_phy_enabled_count == 0)
-		setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
-
 	setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
 
 	sunxi_usb_phy_config(phy);
 
 	if (phy->id != 0)
 		sunxi_usb_phy_passby(index, SUNXI_USB_PASSBY_EN);
-
-	sunxi_usb_phy_enabled_count++;
 }
 
 void sunxi_usb_phy_exit(int index)
@@ -229,12 +187,6 @@ void sunxi_usb_phy_exit(int index)
 		sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
 
 	clrbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
-
-	/* disable common PHY only once, for the last enabled phy */
-	if (sunxi_usb_phy_enabled_count == 1)
-		clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
-
-	sunxi_usb_phy_enabled_count--;
 }
 
 void sunxi_usb_phy_power_on(int index)
@@ -276,3 +228,59 @@ int sunxi_usb_phy_vbus_detect(int index)
 
 	return err;
 }
+
+int sunxi_usb_phy_probe(void)
+{
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_usb_phy *phy;
+	int i, ret = 0;
+
+	for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) {
+		phy = &sunxi_usb_phy[i];
+
+		phy->gpio_vbus = get_vbus_gpio(i);
+		if (phy->gpio_vbus >= 0) {
+			ret = gpio_request(phy->gpio_vbus, "usb_vbus");
+			if (ret)
+				return ret;
+			ret = gpio_direction_output(phy->gpio_vbus, 0);
+			if (ret)
+				return ret;
+		}
+
+		phy->gpio_vbus_det = get_vbus_detect_gpio(i);
+		if (phy->gpio_vbus_det >= 0) {
+			ret = gpio_request(phy->gpio_vbus_det, "usb_vbus_det");
+			if (ret)
+				return ret;
+			ret = gpio_direction_input(phy->gpio_vbus_det);
+			if (ret)
+				return ret;
+		}
+	}
+
+	setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
+
+	return 0;
+}
+
+int sunxi_usb_phy_remove(void)
+{
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_usb_phy *phy;
+	int i;
+
+	clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
+
+	for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) {
+		phy = &sunxi_usb_phy[i];
+
+		if (phy->gpio_vbus >= 0)
+			gpio_free(phy->gpio_vbus);
+
+		if (phy->gpio_vbus_det >= 0)
+			gpio_free(phy->gpio_vbus_det);
+	}
+
+	return 0;
+}
arch/arm/include/asm/arch-sunxi/usb_phy.h +2 -2
index 14ed081..b7b831e 100644
@@ -10,8 +10,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-int sunxi_usb_phy_probe(int index);
-int sunxi_usb_phy_remove(int index);
+int sunxi_usb_phy_probe(void);
+int sunxi_usb_phy_remove(void);
 void sunxi_usb_phy_init(int index);
 void sunxi_usb_phy_exit(int index);
 void sunxi_usb_phy_power_on(int index);
board/sunxi/board.c +4 -0
index 7333946..bbe67a6 100644
@@ -530,6 +530,10 @@ int misc_init_r(void)
 		}
 	}
 
+	ret = sunxi_usb_phy_probe();
+	if (ret)
+		return ret;
+
 #if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET)
 	musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE);
 #endif
drivers/usb/host/ehci-sunxi.c +2 -6
index 9e74a0b..0edb643 100644
@@ -20,11 +20,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
 		struct ehci_hcor **hcor)
 {
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	int ahb_gate_offset, err;
-
-	err = sunxi_usb_phy_probe(index + 1);
-	if (err)
-		return err;
+	int ahb_gate_offset;
 
 	ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 :
 				  AHB_GATE_OFFSET_USB_EHCI0;
@@ -66,5 +62,5 @@ int ehci_hcd_stop(int index)
 #endif
 	clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
 
-	return sunxi_usb_phy_remove(index + 1);
+	return 0;
 }
drivers/usb/musb-new/sunxi.c +1 -6
index 4f08f9f..e8a3a23 100644
@@ -250,15 +250,10 @@ static int sunxi_musb_init(struct musb *musb)
 
 	pr_debug("%s():\n", __func__);
 
-	err = sunxi_usb_phy_probe(0);
-	if (err)
-		return err;
-
 	if (is_host_enabled(musb)) {
 		err = sunxi_usb_phy_vbus_detect(0);
 		if (err) {
 			eprintf("Error: A charger is plugged into the OTG\n");
-			sunxi_usb_phy_remove(0);
 			return -EIO;
 		}
 	}
@@ -296,7 +291,7 @@ static int sunxi_musb_exit(struct musb *musb)
 	sunxi_usb_phy_power_off(0);
 	sunxi_usb_phy_exit(0);
 
-	return sunxi_usb_phy_remove(0);
+	return 0;
 }
 
 const struct musb_platform_ops sunxi_musb_ops = {
include/configs/sun4i.h +2 -0
index 7cd5c69..ea079eb 100644
@@ -17,6 +17,8 @@
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #endif
 
+#define CONFIG_SUNXI_USB_PHYS	3
+
 /*
  * Include common sunxi configuration where most the settings are
  */
include/configs/sun5i.h +2 -0
index e0470d4..d257659 100644
@@ -17,6 +17,8 @@
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	1
 #endif
 
+#define CONFIG_SUNXI_USB_PHYS	2
+
 /*
  * Include common sunxi configuration where most the settings are
  */
include/configs/sun6i.h +2 -0
index 617c1cd..2c24bd2 100644
@@ -20,6 +20,8 @@
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #endif
 
+#define CONFIG_SUNXI_USB_PHYS	3
+
 /*
  * Include common sunxi configuration where most the settings are
  */
include/configs/sun7i.h +2 -0
index 7fa7cec..56101a9 100644
@@ -18,6 +18,8 @@
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #endif
 
+#define CONFIG_SUNXI_USB_PHYS	3
+
 #define CONFIG_ARMV7_PSCI		1
 #define CONFIG_ARMV7_SECURE_BASE	SUNXI_SRAM_B_BASE
 #define CONFIG_TIMER_CLK_FREQ		24000000
include/configs/sun8i.h +2 -0
index 79796d7..7111c63 100644
@@ -18,6 +18,8 @@
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	1
 #endif
 
+#define CONFIG_SUNXI_USB_PHYS	2
+
 /*
  * Include common sunxi configuration where most the settings are
  */
Signature · 1 line
2.3.5
#10 lore raw

PATCH 5/6 sunxi: usb: Do not call phy_probe from hcd code

Quoted 10 lines · Hans de Goede

The 2/3 usb-phys on the sunxi SoCs are really a single separate functional block, and are modelled as such in devicetree. So once we've moved all the sunxi usb code to the driver-model then phy_probe will be called once for the entire block from the driver-model enumeration code.

Move to this now as this also avoids problems with phy_probe being called multiple times once we introduce ohci support. This allows us to get rid of the sunxi_usb_phy_enabled_count variable as phy_probe now is guaranteed to be called only once.

Quoted 5 lines

Since we're effectively rewriting the probe / remove functions, move them to the end of the file while we are at it, as that is the most logical place for them.

#11 lore raw

PATCH 6/6 sunxi: usb: Protect phy-init and phy-power-on against multiple calls

In reply to Hans de Goede

Once we add support for the ohci controller the phy-init and phy-power-on functions may be called twice (once by the ehci code and once by the ohci code) protect them against this.

---
 arch/arm/cpu/armv7/sunxi/usb_phy.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
arch/arm/cpu/armv7/sunxi/usb_phy.c +18 -0
index 1f85dec..410669e 100644
@@ -45,6 +45,8 @@ static struct sunxi_usb_phy {
 	int gpio_vbus;
 	int gpio_vbus_det;
 	int id;
+	int init_count;
+	int power_on_count;
 } sunxi_usb_phy[] = {
 	{
 		.usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK,
@@ -170,6 +172,10 @@ void sunxi_usb_phy_init(int index)
 	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
+	phy->init_count++;
+	if (phy->init_count != 1)
+		return;
+
 	setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
 
 	sunxi_usb_phy_config(phy);
@@ -183,6 +189,10 @@ void sunxi_usb_phy_exit(int index)
 	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
+	phy->init_count--;
+	if (phy->init_count != 0)
+		return;
+
 	if (phy->id != 0)
 		sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
 
@@ -193,6 +203,10 @@ void sunxi_usb_phy_power_on(int index)
 {
 	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 
+	phy->power_on_count++;
+	if (phy->power_on_count != 1)
+		return;
+
 	if (phy->gpio_vbus >= 0)
 		gpio_set_value(phy->gpio_vbus, 1);
 }
@@ -201,6 +215,10 @@ void sunxi_usb_phy_power_off(int index)
 {
 	struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
 
+	phy->power_on_count--;
+	if (phy->power_on_count != 0)
+		return;
+
 	if (phy->gpio_vbus >= 0)
 		gpio_set_value(phy->gpio_vbus, 0);
 }
Signature · 1 line
2.3.5