提交 1fcb57d0 编写于 作者: K Keshava Munegowda 提交者: Samuel Ortiz

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: NKeshava Munegowda <keshava_mgowda@ti.com>
Reviewed-by: NPartha Basak <parthab@india.ti.com>
Acked-by: NFelipe Balbi <balbi@ti.com>
Tested-by: NIgor Grinberg <grinberg@compulab.co.il>
Signed-off-by: NSamuel Ortiz <sameo@linux.intel.com>
上级 8eaeb939
......@@ -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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册