Linux 3.17-rc5
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc3 / dwc3-omap.c
index 07a736acd0f247e6675a4c21ab8a6ddeda085137..fc0de3753648187ab9f1fd68ac121a83cd808e91 100644 (file)
 #define USBOTGSS_DEV_EBC_EN                    0x0110
 #define USBOTGSS_DEBUG_OFFSET                  0x0600
 
-/* REVISION REGISTER */
-#define USBOTGSS_REVISION_XMAJOR(reg)          ((reg >> 8) & 0x7)
-#define USBOTGSS_REVISION_XMAJOR1              1
-#define USBOTGSS_REVISION_XMAJOR2              2
 /* SYSCONFIG REGISTER */
 #define USBOTGSS_SYSCONFIG_DMADISABLE          (1 << 16)
 
@@ -129,7 +125,6 @@ struct dwc3_omap {
        u32                     irq_eoi_offset;
        u32                     debug_offset;
        u32                     irq0_offset;
-       u32                     revision;
 
        u32                     dma_status:1;
 
@@ -383,6 +378,87 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
        return NOTIFY_DONE;
 }
 
+static void dwc3_omap_map_offset(struct dwc3_omap *omap)
+{
+       struct device_node      *node = omap->dev->of_node;
+
+       /*
+        * Differentiate between OMAP5 and AM437x.
+        *
+        * For OMAP5(ES2.0) and AM437x wrapper revision is same, even
+        * though there are changes in wrapper register offsets.
+        *
+        * Using dt compatible to differentiate AM437x.
+        */
+       if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
+               omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
+               omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
+               omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
+               omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
+               omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
+       }
+}
+
+static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
+{
+       u32                     reg;
+       struct device_node      *node = omap->dev->of_node;
+       int                     utmi_mode = 0;
+
+       reg = dwc3_omap_read_utmi_status(omap);
+
+       of_property_read_u32(node, "utmi-mode", &utmi_mode);
+
+       switch (utmi_mode) {
+       case DWC3_OMAP_UTMI_MODE_SW:
+               reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+               break;
+       case DWC3_OMAP_UTMI_MODE_HW:
+               reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+               break;
+       default:
+               dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
+       }
+
+       dwc3_omap_write_utmi_status(omap, reg);
+}
+
+static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
+{
+       int                     ret;
+       struct device_node      *node = omap->dev->of_node;
+       struct extcon_dev       *edev;
+
+       if (of_property_read_bool(node, "extcon")) {
+               edev = extcon_get_edev_by_phandle(omap->dev, 0);
+               if (IS_ERR(edev)) {
+                       dev_vdbg(omap->dev, "couldn't get extcon device\n");
+                       return -EPROBE_DEFER;
+               }
+
+               omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
+               ret = extcon_register_interest(&omap->extcon_vbus_dev,
+                                              edev->name, "USB",
+                                              &omap->vbus_nb);
+               if (ret < 0)
+                       dev_vdbg(omap->dev, "failed to register notifier for USB\n");
+
+               omap->id_nb.notifier_call = dwc3_omap_id_notifier;
+               ret = extcon_register_interest(&omap->extcon_id_dev,
+                                              edev->name, "USB-HOST",
+                                              &omap->id_nb);
+               if (ret < 0)
+                       dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
+
+               if (extcon_get_cable_state(edev, "USB") == true)
+                       dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
+               if (extcon_get_cable_state(edev, "USB-HOST") == true)
+                       dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+       }
+
+       return 0;
+}
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
        struct device_node      *node = pdev->dev.of_node;
@@ -390,15 +466,11 @@ static int dwc3_omap_probe(struct platform_device *pdev)
        struct dwc3_omap        *omap;
        struct resource         *res;
        struct device           *dev = &pdev->dev;
-       struct extcon_dev       *edev;
        struct regulator        *vbus_reg = NULL;
 
        int                     ret;
        int                     irq;
 
-       int                     utmi_mode = 0;
-       int                     x_major;
-
        u32                     reg;
 
        void __iomem            *base;
@@ -448,58 +520,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION);
-       omap->revision = reg;
-       x_major = USBOTGSS_REVISION_XMAJOR(reg);
-
-       /* Differentiate between OMAP5 and AM437x */
-       switch (x_major) {
-       case USBOTGSS_REVISION_XMAJOR1:
-       case USBOTGSS_REVISION_XMAJOR2:
-               omap->irq_eoi_offset = 0;
-               omap->irq0_offset = 0;
-               omap->irqmisc_offset = 0;
-               omap->utmi_otg_offset = 0;
-               omap->debug_offset = 0;
-               break;
-       default:
-               /* Default to the latest revision */
-               omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-               omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-               omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-               omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-               omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-               break;
-       }
-
-       /* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are
-        * changes in wrapper registers, Using dt compatible for aegis
-        */
-
-       if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
-               omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
-               omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
-               omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
-               omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
-               omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
-       }
-
-       reg = dwc3_omap_read_utmi_status(omap);
-
-       of_property_read_u32(node, "utmi-mode", &utmi_mode);
-
-       switch (utmi_mode) {
-       case DWC3_OMAP_UTMI_MODE_SW:
-               reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-               break;
-       case DWC3_OMAP_UTMI_MODE_HW:
-               reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-               break;
-       default:
-               dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
-       }
-
-       dwc3_omap_write_utmi_status(omap, reg);
+       dwc3_omap_map_offset(omap);
+       dwc3_omap_set_utmi_mode(omap);
 
        /* check the DMA Status */
        reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
@@ -515,31 +537,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
        dwc3_omap_enable_irqs(omap);
 
-       if (of_property_read_bool(node, "extcon")) {
-               edev = extcon_get_edev_by_phandle(dev, 0);
-               if (IS_ERR(edev)) {
-                       dev_vdbg(dev, "couldn't get extcon device\n");
-                       ret = -EPROBE_DEFER;
-                       goto err2;
-               }
-
-               omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
-               ret = extcon_register_interest(&omap->extcon_vbus_dev,
-                       edev->name, "USB", &omap->vbus_nb);
-               if (ret < 0)
-                       dev_vdbg(dev, "failed to register notifier for USB\n");
-               omap->id_nb.notifier_call = dwc3_omap_id_notifier;
-               ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
-                                        "USB-HOST", &omap->id_nb);
-               if (ret < 0)
-                       dev_vdbg(dev,
-                               "failed to register notifier for USB-HOST\n");
-
-               if (extcon_get_cable_state(edev, "USB") == true)
-                       dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
-               if (extcon_get_cable_state(edev, "USB-HOST") == true)
-                       dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
-       }
+       ret = dwc3_omap_extcon_register(omap);
+       if (ret < 0)
+               goto err2;
 
        ret = of_platform_populate(node, NULL, NULL, dev);
        if (ret) {
@@ -576,9 +576,9 @@ static int dwc3_omap_remove(struct platform_device *pdev)
        if (omap->extcon_id_dev.edev)
                extcon_unregister_interest(&omap->extcon_id_dev);
        dwc3_omap_disable_irqs(omap);
+       device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
-       device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
 
        return 0;
 }