Skip to content

Commit

Permalink
usb: chipidea: coordinate usb phy initialization for different phy type
Browse files Browse the repository at this point in the history
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: cd0b42c

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>
  • Loading branch information
Peter Chen authored and Greg Kroah-Hartman committed Apr 24, 2014
1 parent e988f30 commit cd84f00
Showing 1 changed file with 34 additions and 3 deletions.
37 changes: 34 additions & 3 deletions drivers/usb/chipidea/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
* @ci: the controller
Expand Down Expand Up @@ -543,8 +576,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}

hw_phymode_configure(ci);

if (ci->platdata->phy)
ci->transceiver = ci->platdata->phy;
else
Expand All @@ -564,7 +595,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}

ret = usb_phy_init(ci->transceiver);
ret = ci_usb_phy_init(ci);
if (ret) {
dev_err(dev, "unable to init phy: %d\n", ret);
return ret;
Expand Down

0 comments on commit cd84f00

Please sign in to comment.