chipidea: pci: register nop PHY
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Wed, 11 Feb 2015 04:45:00 +0000 (12:45 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 18 Mar 2015 15:19:11 +0000 (16:19 +0100)
Since PHY for ChipIdea is optional (not all SoCs having PHY for ChipIdea should
be programmed), we register 'nop' PHY for platforms that do not have
programmable PHY.

Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/chipidea/ci_hdrc_pci.c

index 4df6694372117cb4c0bfbdebced3238e2914a11b..773d150512fa4da6af83e5df10b069cc0276914c 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/chipidea.h>
+#include <linux/usb/usb_phy_generic.h>
 
 /* driver name */
 #define UDC_DRIVER_NAME   "ci_hdrc_pci"
 
+struct ci_hdrc_pci {
+       struct platform_device  *ci;
+       struct platform_device  *phy;
+};
+
 /******************************************************************************
  * PCI block
  *****************************************************************************/
@@ -52,7 +58,7 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
                                       const struct pci_device_id *id)
 {
        struct ci_hdrc_platform_data *platdata = (void *)id->driver_data;
-       struct platform_device *plat_ci;
+       struct ci_hdrc_pci *ci;
        struct resource res[3];
        int retval = 0, nres = 2;
 
@@ -61,6 +67,10 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
                return -ENODEV;
        }
 
+       ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
+       if (!ci)
+               return -ENOMEM;
+
        retval = pcim_enable_device(pdev);
        if (retval)
                return retval;
@@ -73,6 +83,11 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
        pci_set_master(pdev);
        pci_try_set_mwi(pdev);
 
+       /* register a nop PHY */
+       ci->phy = usb_phy_generic_register();
+       if (!ci->phy)
+               return -ENOMEM;
+
        memset(res, 0, sizeof(res));
        res[0].start    = pci_resource_start(pdev, 0);
        res[0].end      = pci_resource_end(pdev, 0);
@@ -80,13 +95,14 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
        res[1].start    = pdev->irq;
        res[1].flags    = IORESOURCE_IRQ;
 
-       plat_ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata);
-       if (IS_ERR(plat_ci)) {
+       ci->ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata);
+       if (IS_ERR(ci->ci)) {
                dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
-               return PTR_ERR(plat_ci);
+               usb_phy_generic_unregister(ci->phy);
+               return PTR_ERR(ci->ci);
        }
 
-       pci_set_drvdata(pdev, plat_ci);
+       pci_set_drvdata(pdev, ci);
 
        return 0;
 }
@@ -101,9 +117,10 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
  */
 static void ci_hdrc_pci_remove(struct pci_dev *pdev)
 {
-       struct platform_device *plat_ci = pci_get_drvdata(pdev);
+       struct ci_hdrc_pci *ci = pci_get_drvdata(pdev);
 
-       ci_hdrc_remove_device(plat_ci);
+       ci_hdrc_remove_device(ci->ci);
+       usb_phy_generic_unregister(ci->phy);
 }
 
 /**