@@ -106,9 +106,9 @@ static int ehci_msm_probe(struct platform_device *pdev)
}
/*
- * OTG driver takes care of PHY initialization, clock management,
- * powering up VBUS, mapping of registers address space and power
- * management.
+ * If there is an OTG driver, let it take care of PHY initialization,
+ * clock management, powering up VBUS, mapping of registers address
+ * space and power management.
*/
if (pdev->dev.of_node)
phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
@@ -116,27 +116,35 @@ static int ehci_msm_probe(struct platform_device *pdev)
phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR(phy)) {
- dev_err(&pdev->dev, "unable to find transceiver\n");
- ret = -EPROBE_DEFER;
- goto put_hcd;
- }
-
- ret = otg_set_host(phy->otg, &hcd->self);
- if (ret < 0) {
- dev_err(&pdev->dev, "unable to register with transceiver\n");
- goto put_hcd;
+ if (PTR_ERR(phy) == -EPROBE_DEFER) {
+ dev_err(&pdev->dev, "unable to find transceiver\n");
+ ret = -EPROBE_DEFER;
+ goto put_hcd;
+ }
+ phy = NULL;
}
hcd->usb_phy = phy;
device_init_wakeup(&pdev->dev, 1);
- /*
- * OTG device parent of HCD takes care of putting
- * hardware into low power mode.
- */
- pm_runtime_no_callbacks(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
- /* FIXME: need to call usb_add_hcd() here? */
+ if (phy && phy->otg) {
+ /*
+ * MSM OTG driver takes care of adding the HCD and
+ * placing hardware into low power mode via runtime PM.
+ */
+ ret = otg_set_host(phy->otg, &hcd->self);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "unable to register with transceiver\n");
+ goto put_hcd;
+ }
+
+ pm_runtime_no_callbacks(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ } else {
+ ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+ if (ret)
+ goto put_hcd;
+ }
return 0;
@@ -154,9 +162,10 @@ static int ehci_msm_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
- otg_set_host(hcd->usb_phy->otg, NULL);
-
- /* FIXME: need to call usb_remove_hcd() here? */
+ if (hcd->usb_phy && hcd->usb_phy->otg)
+ otg_set_host(hcd->usb_phy->otg, NULL);
+ else
+ usb_remove_hcd(hcd);
usb_put_hcd(hcd);