Skip to content

Commit

Permalink
ARM: OMAP3: USB: Fix the EHCI ULPI PHY reset issue
Browse files Browse the repository at this point in the history
It is observed that the echi ports of 3430 sdp board
are not working due to the random timing of programming
the associated GPIOs of the ULPI PHYs of the EHCI for reset.
If the PHYs are reset at during usbhs core driver, host ports will
not work because EHCI driver is loaded after the resetting PHYs.
The PHYs should be in reset state while initializing the EHCI
controller.
The code which does the GPIO pins associated with the PHYs
are programmed to reset is moved from the USB host core driver
to EHCI driver.

Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
Reviewed-by: Partha Basak <parthab@india.ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Tested-by: Igor Grinberg <grinberg@compulab.co.il>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Keshava Munegowda authored and Samuel Ortiz committed Apr 16, 2012
1 parent 8eaeb93 commit 1fcb57d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 46 deletions.
44 changes: 0 additions & 44 deletions drivers/mfd/omap-usb-host.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/gpio.h>
#include <plat/usb.h>
#include <linux/pm_runtime.h>

Expand Down Expand Up @@ -502,19 +501,6 @@ static void omap_usbhs_init(struct device *dev)
pm_runtime_get_sync(dev);
spin_lock_irqsave(&omap->lock, flags);

if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");

if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");

/* Hold the PHY in RESET for enough time till DIR is high */
udelay(10);
}

omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);

Expand Down Expand Up @@ -593,39 +579,10 @@ static void omap_usbhs_init(struct device *dev)
usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
}

if (pdata->ehci_data->phy_reset) {
/* Hold the PHY in RESET for enough time till
* PHY is settled and ready
*/
udelay(10);

if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_set_value
(pdata->ehci_data->reset_gpio_port[0], 1);

if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_set_value
(pdata->ehci_data->reset_gpio_port[1], 1);
}

spin_unlock_irqrestore(&omap->lock, flags);
pm_runtime_put_sync(dev);
}

static void omap_usbhs_deinit(struct device *dev)
{
struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
struct usbhs_omap_platform_data *pdata = &omap->platdata;

if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_free(pdata->ehci_data->reset_gpio_port[0]);

if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_free(pdata->ehci_data->reset_gpio_port[1]);
}
}


/**
* usbhs_omap_probe - initialize TI-based HCDs
Expand Down Expand Up @@ -860,7 +817,6 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
{
struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);

omap_usbhs_deinit(&pdev->dev);
iounmap(omap->tll_base);
iounmap(omap->uhh_base);
clk_put(omap->init_60m_fclk);
Expand Down
39 changes: 37 additions & 2 deletions drivers/usb/host/ehci-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <plat/usb.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/gpio.h>

/* EHCI Register Set */
#define EHCI_INSNREG04 (0xA0)
Expand Down Expand Up @@ -191,6 +192,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
}
}

if (pdata->phy_reset) {
if (gpio_is_valid(pdata->reset_gpio_port[0]))
gpio_request_one(pdata->reset_gpio_port[0],
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");

if (gpio_is_valid(pdata->reset_gpio_port[1]))
gpio_request_one(pdata->reset_gpio_port[1],
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");

/* Hold the PHY in RESET for enough time till DIR is high */
udelay(10);
}

pm_runtime_enable(dev);
pm_runtime_get_sync(dev);

Expand Down Expand Up @@ -237,6 +251,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
/* root ports should always stay powered */
ehci_port_power(omap_ehci, 1);

if (pdata->phy_reset) {
/* Hold the PHY in RESET for enough time till
* PHY is settled and ready
*/
udelay(10);

if (gpio_is_valid(pdata->reset_gpio_port[0]))
gpio_set_value(pdata->reset_gpio_port[0], 1);

if (gpio_is_valid(pdata->reset_gpio_port[1]))
gpio_set_value(pdata->reset_gpio_port[1], 1);
}

return 0;

err_add_hcd:
Expand All @@ -259,8 +286,9 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
*/
static int ehci_hcd_omap_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct device *dev = &pdev->dev;
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ehci_hcd_omap_platform_data *pdata = dev->platform_data;

usb_remove_hcd(hcd);
disable_put_regulator(dev->platform_data);
Expand All @@ -269,6 +297,13 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);

if (pdata->phy_reset) {
if (gpio_is_valid(pdata->reset_gpio_port[0]))
gpio_free(pdata->reset_gpio_port[0]);

if (gpio_is_valid(pdata->reset_gpio_port[1]))
gpio_free(pdata->reset_gpio_port[1]);
}
return 0;
}

Expand Down

0 comments on commit 1fcb57d

Please sign in to comment.