mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-27 13:43:53 +00:00
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 Cc: stable <stable@vger.kernel.org> # 3.14 Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e988f306e7
commit
cd84f009e9
@ -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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user