ARM: OMAP3: USB: Fix the EHCI ULPI PHY reset issue
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>
This commit is contained in:
parent
8eaeb93933
commit
1fcb57d0f6
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -261,6 +288,7 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
|
|||
{
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue