[PATCH] usb: ehci_omap: fix device detect issue with modules

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently devices don't get detected automatically if the ehci
module is inserted 2nd time onward. We need to disconnect and
reconnect the device for it to get detected and enumerated.

Resetting the USB PHY after the EHCI controller has been initilized
fixes this issue. Tested on OMAP3EVM.

Signed-off-by: Ajay Kumar Gupta <ajay.gupta@xxxxxx>
---
 drivers/usb/host/ehci-omap.c |   86 ++++++++++++++++++-----------------------
 1 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 5450e62..a2c3d7f 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -236,6 +236,31 @@ static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask)
 
 /*-------------------------------------------------------------------------*/
 
+static void ehci_omap_phy_reset(struct ehci_hcd_omap *omap)
+{
+	if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) &&
+			gpio_is_valid(omap->reset_gpio_port[0])) {
+		gpio_request(omap->reset_gpio_port[0], "HSUSB0 reset");
+		gpio_direction_output(omap->reset_gpio_port[0], 0);
+	}
+
+	if ((omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) &&
+			gpio_is_valid(omap->reset_gpio_port[1])) {
+		gpio_request(omap->reset_gpio_port[1], "HSUSB1 reset");
+		gpio_direction_output(omap->reset_gpio_port[1], 0);
+	}
+
+	/* Hold the PHY in RESET for enough time till DIR is high */
+	udelay(10);
+
+	if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) &&
+			gpio_is_valid(omap->reset_gpio_port[0]))
+		gpio_set_value(omap->reset_gpio_port[0], 1);
+	if ((omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) &&
+			gpio_is_valid(omap->reset_gpio_port[1]))
+		gpio_set_value(omap->reset_gpio_port[1], 1);
+}
+
 /* omap_start_ehc
  *	- Start the TI USBHOST controller
  */
@@ -270,24 +295,6 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
 	}
 	clk_enable(omap->usbhost1_48m_fck);
 
-	if (omap->phy_reset) {
-		/* Refer: ISSUE1 */
-		if (gpio_is_valid(omap->reset_gpio_port[0])) {
-			gpio_request(omap->reset_gpio_port[0],
-						"USB1 PHY reset");
-			gpio_direction_output(omap->reset_gpio_port[0], 0);
-		}
-
-		if (gpio_is_valid(omap->reset_gpio_port[1])) {
-			gpio_request(omap->reset_gpio_port[1],
-						"USB2 PHY reset");
-			gpio_direction_output(omap->reset_gpio_port[1], 0);
-		}
-
-		/* Hold the PHY in RESET for enough time till DIR is high */
-		udelay(10);
-	}
-
 	/* Configure TLL for 60Mhz clk for ULPI */
 	omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck");
 	if (IS_ERR(omap->usbtll_fck)) {
@@ -411,20 +418,6 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
 		omap_usb_utmi_init(omap, tll_ch_mask);
 	}
 
-	if (omap->phy_reset) {
-		/* Refer ISSUE1:
-		 * Hold the PHY in RESET for enough time till
-		 * PHY is settled and ready
-		 */
-		udelay(10);
-
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_set_value(omap->reset_gpio_port[0], 1);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_set_value(omap->reset_gpio_port[1], 1);
-	}
-
 	return 0;
 
 err_sys_status:
@@ -439,14 +432,6 @@ err_tll_fck:
 	clk_disable(omap->usbhost1_48m_fck);
 	clk_put(omap->usbhost1_48m_fck);
 
-	if (omap->phy_reset) {
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_free(omap->reset_gpio_port[0]);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_free(omap->reset_gpio_port[1]);
-	}
-
 err_host_48m_fck:
 	clk_disable(omap->usbhost2_120m_fck);
 	clk_put(omap->usbhost2_120m_fck);
@@ -532,14 +517,6 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
 		omap->usbtll_ick = NULL;
 	}
 
-	if (omap->phy_reset) {
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_free(omap->reset_gpio_port[0]);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_free(omap->reset_gpio_port[1]);
-	}
-
 	dev_dbg(omap->dev, "Clock to USB host has been disabled\n");
 }
 
@@ -673,6 +650,10 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 		goto err_add_hcd;
 	}
 
+	/* reset the USB PHY */
+	if (omap->phy_reset)
+		ehci_omap_phy_reset(omap);
+
 	/* root ports should always stay powered */
 	ehci_port_power(omap->ehci, 1);
 
@@ -725,6 +706,15 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
 
 	usb_remove_hcd(hcd);
 	omap_stop_ehc(omap, hcd);
+
+	if (omap->phy_reset) {
+		if (gpio_is_valid(omap->reset_gpio_port[0]))
+			gpio_free(omap->reset_gpio_port[0]);
+
+		if (gpio_is_valid(omap->reset_gpio_port[1]))
+			gpio_free(omap->reset_gpio_port[1]);
+	}
+
 	iounmap(hcd->regs);
 	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
 		if (omap->regulator[i]) {
-- 
1.6.2.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux