aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeshava Munegowda <Keshava_mgowda@ti.com>2012-03-19 02:42:47 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-04-16 12:47:00 -0400
commit1fcb57d0f6e1150003d222051aaaf4bc4a9ccc94 (patch)
treec2fbf05be7ed93970f74654a26598e5a6c9baee5
parent8eaeb9393397be8eb700ab38a69c450975463b77 (diff)
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>
-rw-r--r--drivers/mfd/omap-usb-host.c44
-rw-r--r--drivers/usb/host/ehci-omap.c39
2 files changed, 37 insertions, 46 deletions
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 95a2e546a489..c8aae6640e64 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -25,7 +25,6 @@
25#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/dma-mapping.h> 26#include <linux/dma-mapping.h>
27#include <linux/spinlock.h> 27#include <linux/spinlock.h>
28#include <linux/gpio.h>
29#include <plat/usb.h> 28#include <plat/usb.h>
30#include <linux/pm_runtime.h> 29#include <linux/pm_runtime.h>
31 30
@@ -502,19 +501,6 @@ static void omap_usbhs_init(struct device *dev)
502 pm_runtime_get_sync(dev); 501 pm_runtime_get_sync(dev);
503 spin_lock_irqsave(&omap->lock, flags); 502 spin_lock_irqsave(&omap->lock, flags);
504 503
505 if (pdata->ehci_data->phy_reset) {
506 if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
507 gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
508 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
509
510 if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
511 gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
512 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
513
514 /* Hold the PHY in RESET for enough time till DIR is high */
515 udelay(10);
516 }
517
518 omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); 504 omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
519 dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); 505 dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
520 506
@@ -593,39 +579,10 @@ static void omap_usbhs_init(struct device *dev)
593 usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT); 579 usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
594 } 580 }
595 581
596 if (pdata->ehci_data->phy_reset) {
597 /* Hold the PHY in RESET for enough time till
598 * PHY is settled and ready
599 */
600 udelay(10);
601
602 if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
603 gpio_set_value
604 (pdata->ehci_data->reset_gpio_port[0], 1);
605
606 if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
607 gpio_set_value
608 (pdata->ehci_data->reset_gpio_port[1], 1);
609 }
610
611 spin_unlock_irqrestore(&omap->lock, flags); 582 spin_unlock_irqrestore(&omap->lock, flags);
612 pm_runtime_put_sync(dev); 583 pm_runtime_put_sync(dev);
613} 584}
614 585
615static void omap_usbhs_deinit(struct device *dev)
616{
617 struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
618 struct usbhs_omap_platform_data *pdata = &omap->platdata;
619
620 if (pdata->ehci_data->phy_reset) {
621 if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
622 gpio_free(pdata->ehci_data->reset_gpio_port[0]);
623
624 if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
625 gpio_free(pdata->ehci_data->reset_gpio_port[1]);
626 }
627}
628
629 586
630/** 587/**
631 * usbhs_omap_probe - initialize TI-based HCDs 588 * usbhs_omap_probe - initialize TI-based HCDs
@@ -860,7 +817,6 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
860{ 817{
861 struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); 818 struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
862 819
863 omap_usbhs_deinit(&pdev->dev);
864 iounmap(omap->tll_base); 820 iounmap(omap->tll_base);
865 iounmap(omap->uhh_base); 821 iounmap(omap->uhh_base);
866 clk_put(omap->init_60m_fclk); 822 clk_put(omap->init_60m_fclk);
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index bba9850f32f0..5c78f9e71466 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -42,6 +42,7 @@
42#include <plat/usb.h> 42#include <plat/usb.h>
43#include <linux/regulator/consumer.h> 43#include <linux/regulator/consumer.h>
44#include <linux/pm_runtime.h> 44#include <linux/pm_runtime.h>
45#include <linux/gpio.h>
45 46
46/* EHCI Register Set */ 47/* EHCI Register Set */
47#define EHCI_INSNREG04 (0xA0) 48#define EHCI_INSNREG04 (0xA0)
@@ -191,6 +192,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
191 } 192 }
192 } 193 }
193 194
195 if (pdata->phy_reset) {
196 if (gpio_is_valid(pdata->reset_gpio_port[0]))
197 gpio_request_one(pdata->reset_gpio_port[0],
198 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
199
200 if (gpio_is_valid(pdata->reset_gpio_port[1]))
201 gpio_request_one(pdata->reset_gpio_port[1],
202 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
203
204 /* Hold the PHY in RESET for enough time till DIR is high */
205 udelay(10);
206 }
207
194 pm_runtime_enable(dev); 208 pm_runtime_enable(dev);
195 pm_runtime_get_sync(dev); 209 pm_runtime_get_sync(dev);
196 210
@@ -237,6 +251,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
237 /* root ports should always stay powered */ 251 /* root ports should always stay powered */
238 ehci_port_power(omap_ehci, 1); 252 ehci_port_power(omap_ehci, 1);
239 253
254 if (pdata->phy_reset) {
255 /* Hold the PHY in RESET for enough time till
256 * PHY is settled and ready
257 */
258 udelay(10);
259
260 if (gpio_is_valid(pdata->reset_gpio_port[0]))
261 gpio_set_value(pdata->reset_gpio_port[0], 1);
262
263 if (gpio_is_valid(pdata->reset_gpio_port[1]))
264 gpio_set_value(pdata->reset_gpio_port[1], 1);
265 }
266
240 return 0; 267 return 0;
241 268
242err_add_hcd: 269err_add_hcd:
@@ -259,8 +286,9 @@ err_io:
259 */ 286 */
260static int ehci_hcd_omap_remove(struct platform_device *pdev) 287static int ehci_hcd_omap_remove(struct platform_device *pdev)
261{ 288{
262 struct device *dev = &pdev->dev; 289 struct device *dev = &pdev->dev;
263 struct usb_hcd *hcd = dev_get_drvdata(dev); 290 struct usb_hcd *hcd = dev_get_drvdata(dev);
291 struct ehci_hcd_omap_platform_data *pdata = dev->platform_data;
264 292
265 usb_remove_hcd(hcd); 293 usb_remove_hcd(hcd);
266 disable_put_regulator(dev->platform_data); 294 disable_put_regulator(dev->platform_data);
@@ -269,6 +297,13 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
269 pm_runtime_put_sync(dev); 297 pm_runtime_put_sync(dev);
270 pm_runtime_disable(dev); 298 pm_runtime_disable(dev);
271 299
300 if (pdata->phy_reset) {
301 if (gpio_is_valid(pdata->reset_gpio_port[0]))
302 gpio_free(pdata->reset_gpio_port[0]);
303
304 if (gpio_is_valid(pdata->reset_gpio_port[1]))
305 gpio_free(pdata->reset_gpio_port[1]);
306 }
272 return 0; 307 return 0;
273} 308}
274 309