@@ -262,6 +262,7 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
{
struct ehci_omap_clock_defs *ehci_clocks;
unsigned long timeout = jiffies + msecs_to_jiffies(100);
+ int ret = 0;
dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n");
@@ -293,7 +294,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
if (time_after(timeout, jiffies)) {
dev_dbg(hcd->self.controller, "operation timed out\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_idlest2;
}
}
/* End DPLL5 programming */
@@ -317,20 +319,26 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
/* Enable Clocks for USBHOST */
ehci_clocks->usbhost_ick_clk = clk_get(&dev->dev,
USBHOST_ICKL);
- if (IS_ERR(ehci_clocks->usbhost_ick_clk))
- return PTR_ERR(ehci_clocks->usbhost_ick_clk);
+ if (IS_ERR(ehci_clocks->usbhost_ick_clk)) {
+ ret = PTR_ERR(ehci_clocks->usbhost_ick_clk);
+ goto err_host_ick;
+ }
clk_enable(ehci_clocks->usbhost_ick_clk);
ehci_clocks->usbhost2_120m_fck_clk = clk_get(&dev->dev,
USBHOST_120M_FCLK);
- if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk))
- return PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk);
+ if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk)) {
+ ret = PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk);
+ goto err_host_120m_fck;
+ }
clk_enable(ehci_clocks->usbhost2_120m_fck_clk);
ehci_clocks->usbhost1_48m_fck_clk = clk_get(&dev->dev,
USBHOST_48M_FCLK);
- if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk))
- return PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk);
+ if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk)) {
+ ret = PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk);
+ goto err_host_48m_fck;
+ }
clk_enable(ehci_clocks->usbhost1_48m_fck_clk);
@@ -346,13 +354,17 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
/* Configure TLL for 60Mhz clk for ULPI */
ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
- if (IS_ERR(ehci_clocks->usbtll_fck_clk))
- return PTR_ERR(ehci_clocks->usbtll_fck_clk);
+ if (IS_ERR(ehci_clocks->usbtll_fck_clk)) {
+ ret = PTR_ERR(ehci_clocks->usbtll_fck_clk);
+ goto err_tll_fck;
+ }
clk_enable(ehci_clocks->usbtll_fck_clk);
ehci_clocks->usbtll_ick_clk = clk_get(&dev->dev, USBHOST_TLL_ICKL);
- if (IS_ERR(ehci_clocks->usbtll_ick_clk))
- return PTR_ERR(ehci_clocks->usbtll_ick_clk);
+ if (IS_ERR(ehci_clocks->usbtll_ick_clk)) {
+ ret = PTR_ERR(ehci_clocks->usbtll_ick_clk);
+ goto err_tll_ick;
+ }
clk_enable(ehci_clocks->usbtll_ick_clk);
/* Disable Auto Idle of USBTLL */
@@ -366,7 +378,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
if (time_after(timeout, jiffies)) {
dev_dbg(hcd->self.controller, "operation timed out\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_idlest3;
}
}
@@ -381,7 +394,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
if (time_after(timeout, jiffies)) {
dev_dbg(hcd->self.controller, "operation timed out\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_sys_status;
}
}
@@ -418,7 +432,8 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
if (time_after(timeout, jiffies)) {
dev_dbg(hcd->self.controller, "operation timed out\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_ulpi_bypass;
}
}
@@ -461,13 +476,50 @@ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
if (time_after(timeout, jiffies)) {
dev_dbg(hcd->self.controller, "operation timed out\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_ulpi_control;
}
}
#endif
return 0;
+
+#ifdef VBUS_INTERNAL_CHARGEPUMP_HACK
+err_ulpi_control:
+#endif
+#ifdef CONFIG_OMAP_EHCI_PHY_MODE
+err_ulpi_bypass:
+#endif
+err_sys_status:
+err_idlest3:
+ clk_disable(ehci_clocks->usbtll_ick_clk);
+ clk_put(ehci_clocks->usbtll_ick_clk);
+
+err_tll_ick:
+ clk_disable(ehci_clocks->usbtll_fck_clk);
+ clk_put(ehci_clocks->usbtll_fck_clk);
+
+err_tll_fck:
+ clk_disable(ehci_clocks->usbhost1_48m_fck_clk);
+ clk_put(ehci_clocks->usbhost1_48m_fck_clk);
+
+#ifdef EXTERNAL_PHY_RESET
+ gpio_free(EXT_PHY_RESET_GPIO_PORT1);
+ gpio_free(EXT_PHY_RESET_GPIO_PORT2);
+#endif
+
+err_host_48m_fck:
+ clk_disable(ehci_clocks->usbhost2_120m_fck_clk);
+ clk_put(ehci_clocks->usbhost2_120m_fck_clk);
+
+err_host_120m_fck:
+ clk_disable(ehci_clocks->usbhost_ick_clk);
+ clk_put(ehci_clocks->usbhost_ick_clk);
+
+err_host_ick:
+err_idlest2:
+ return ret;
}
static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
The driver wasn't releasing the requested resources on error, so make that work. Signed-off-by: Felipe Balbi <me@felipebalbi.com> --- drivers/usb/host/ehci-omap.c | 82 ++++++++++++++++++++++++++++++++++-------- 1 files changed, 67 insertions(+), 15 deletions(-)