Commit cd84f009 authored by Peter Chen's avatar Peter Chen Committed by Greg Kroah-Hartman

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: cd0b42c2

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
Cc: stable <stable@vger.kernel.org> # 3.14
Signed-off-by: default avatarPeter Chen <peter.chen@freescale.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e988f306
...@@ -276,6 +276,39 @@ static void hw_phymode_configure(struct ci_hdrc *ci) ...@@ -276,6 +276,39 @@ static void hw_phymode_configure(struct ci_hdrc *ci)
} }
} }
/**
* ci_usb_phy_init: initialize phy according to different phy type
* @ci: the controller
*
* This function returns an error code if usb_phy_init has failed
*/
static int ci_usb_phy_init(struct ci_hdrc *ci)
{
int ret;
switch (ci->platdata->phy_mode) {
case USBPHY_INTERFACE_MODE_UTMI:
case USBPHY_INTERFACE_MODE_UTMIW:
case USBPHY_INTERFACE_MODE_HSIC:
ret = usb_phy_init(ci->transceiver);
if (ret)
return ret;
hw_phymode_configure(ci);
break;
case USBPHY_INTERFACE_MODE_ULPI:
case USBPHY_INTERFACE_MODE_SERIAL:
hw_phymode_configure(ci);
ret = usb_phy_init(ci->transceiver);
if (ret)
return ret;
break;
default:
ret = usb_phy_init(ci->transceiver);
}
return ret;
}
/** /**
* hw_device_reset: resets chip (execute without interruption) * hw_device_reset: resets chip (execute without interruption)
* @ci: the controller * @ci: the controller
...@@ -543,8 +576,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) ...@@ -543,8 +576,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
hw_phymode_configure(ci);
if (ci->platdata->phy) if (ci->platdata->phy)
ci->transceiver = ci->platdata->phy; ci->transceiver = ci->platdata->phy;
else else
...@@ -564,7 +595,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) ...@@ -564,7 +595,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
ret = usb_phy_init(ci->transceiver); ret = ci_usb_phy_init(ci);
if (ret) { if (ret) {
dev_err(dev, "unable to init phy: %d\n", ret); dev_err(dev, "unable to init phy: %d\n", ret);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment