aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2014-03-13 04:59:25 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:58:02 -0400
commit6e872f8e04da0a8cbf7be1d437998a06f3739f88 (patch)
treee47c3f3bc80c8dc15ab05edd872bef5a5a54af3b
parent5b28098e08a824a7761c542b8c8ed9f90a97774d (diff)
ENGR00303795-2 usb: chipidea: coordinate usb phy initialization for different phy type
For internal PHY (like UTMI), the phy clock may from internal pll, it is on/off on the fly, the access PORTSC.PTS will hang without phy clock. So, the usb_phy_init which will open phy clock needs to be called before hw_phymode_configure. See: http://marc.info/?l=linux-arm-kernel&m=139350618732108&w=2 For external PHY (like ulpi), it needs to configure portsc.pts before visit viewport, or the viewport can't be visited. so phy_phymode_configure needs to be called before usb_phy_init. See: cd0b42c2a6d2a74244f0053f8960f5dad5842278 It may not the best solution, but it can work for all situations. Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Chris Ruehl <chris.ruehl@gtsys.com.hk> Cc: shc_work@mail.ru Cc: denis@eukrea.com Cc: festevam@gmail.com Signed-off-by: Peter Chen <peter.chen@freescale.com>
-rw-r--r--drivers/usb/chipidea/core.c43
1 files changed, 38 insertions, 5 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 54e0830ed04c..0f86ed7429d6 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -289,6 +289,43 @@ static void hw_phymode_configure(struct ci_hdrc *ci)
289} 289}
290 290
291/** 291/**
292 * ci_usb_phy_init: initialize phy according to different phy type
293 * @ci: the controller
294 *
295 * This function returns an error code if usb_phy_init has failed
296 */
297static int ci_usb_phy_init(struct ci_hdrc *ci)
298{
299 int ret;
300
301 switch (ci->platdata->phy_mode) {
302 case USBPHY_INTERFACE_MODE_UTMI:
303 case USBPHY_INTERFACE_MODE_UTMIW:
304 case USBPHY_INTERFACE_MODE_HSIC:
305 ret = usb_phy_init(ci->transceiver);
306 if (!ret)
307 hw_wait_phy_stable();
308 else
309 return ret;
310 hw_phymode_configure(ci);
311 break;
312 case USBPHY_INTERFACE_MODE_ULPI:
313 case USBPHY_INTERFACE_MODE_SERIAL:
314 hw_phymode_configure(ci);
315 ret = usb_phy_init(ci->transceiver);
316 if (ret)
317 return ret;
318 break;
319 default:
320 ret = usb_phy_init(ci->transceiver);
321 if (!ret)
322 hw_wait_phy_stable();
323 }
324
325 return ret;
326}
327
328/**
292 * hw_device_reset: resets chip (execute without interruption) 329 * hw_device_reset: resets chip (execute without interruption)
293 * @ci: the controller 330 * @ci: the controller
294 * 331 *
@@ -589,8 +626,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
589 return -ENODEV; 626 return -ENODEV;
590 } 627 }
591 628
592 hw_phymode_configure(ci);
593
594 if (ci->platdata->phy) 629 if (ci->platdata->phy)
595 ci->transceiver = ci->platdata->phy; 630 ci->transceiver = ci->platdata->phy;
596 else 631 else
@@ -610,12 +645,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
610 return -EPROBE_DEFER; 645 return -EPROBE_DEFER;
611 } 646 }
612 647
613 ret = usb_phy_init(ci->transceiver); 648 ret = ci_usb_phy_init(ci);
614 if (ret) { 649 if (ret) {
615 dev_err(dev, "unable to init phy: %d\n", ret); 650 dev_err(dev, "unable to init phy: %d\n", ret);
616 return ret; 651 return ret;
617 } else {
618 hw_wait_phy_stable();
619 } 652 }
620 653
621 ci->hw_bank.phys = res->start; 654 ci->hw_bank.phys = res->start;