]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/usb/dwc3/dwc3-omap.c
usb: dwc3: dwc3-omap: Use the clear register inorder to clear the interrupts
[karo-tx-uboot.git] / drivers / usb / dwc3 / dwc3-omap.c
index 30d72101541d676b23f189ccc7f7bd1bfbc74c9e..ac9a856190f03bf107af581df879202b88a34a7d 100644 (file)
 #define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL              (1 << 3)
 #define USBOTGSS_IRQMISC_IDPULLUP_FALL         (1 << 0)
 
+#define USBOTGSS_INTERRUPTS (USBOTGSS_IRQMISC_OEVT | \
+                            USBOTGSS_IRQMISC_DRVVBUS_RISE | \
+                            USBOTGSS_IRQMISC_CHRGVBUS_RISE | \
+                            USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | \
+                            USBOTGSS_IRQMISC_IDPULLUP_RISE | \
+                            USBOTGSS_IRQMISC_DRVVBUS_FALL | \
+                            USBOTGSS_IRQMISC_CHRGVBUS_FALL | \
+                            USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | \
+                            USBOTGSS_IRQMISC_IDPULLUP_FALL)
+
 /* UTMI_OTG_CTRL REGISTER */
 #define USBOTGSS_UTMI_OTG_CTRL_DRVVBUS         (1 << 5)
 #define USBOTGSS_UTMI_OTG_CTRL_CHRGVBUS                (1 << 4)
@@ -119,9 +129,11 @@ struct dwc3_omap {
        u32                     irq0_offset;
 
        u32                     dma_status:1;
+       struct list_head        list;
+       u32                     index;
 };
 
-struct dwc3_omap *omap;
+static LIST_HEAD(dwc3_omap_list);
 
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 {
@@ -185,6 +197,18 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value)
                                                omap->irq0_offset, value);
 }
 
+static void dwc3_omap_write_irqmisc_clr(struct dwc3_omap *omap, u32 value)
+{
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_MISC +
+                                               omap->irqmisc_offset, value);
+}
+
+static void dwc3_omap_write_irq0_clr(struct dwc3_omap *omap, u32 value)
+{
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_0 -
+                                               omap->irq0_offset, value);
+}
+
 static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
        enum omap_dwc3_vbus_id_status status)
 {
@@ -283,30 +307,18 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 
 static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
 {
-       u32                     reg;
-
        /* enable all IRQs */
-       reg = USBOTGSS_IRQO_COREIRQ_ST;
-       dwc3_omap_write_irq0_set(omap, reg);
-
-       reg = (USBOTGSS_IRQMISC_OEVT |
-                       USBOTGSS_IRQMISC_DRVVBUS_RISE |
-                       USBOTGSS_IRQMISC_CHRGVBUS_RISE |
-                       USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
-                       USBOTGSS_IRQMISC_IDPULLUP_RISE |
-                       USBOTGSS_IRQMISC_DRVVBUS_FALL |
-                       USBOTGSS_IRQMISC_CHRGVBUS_FALL |
-                       USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
-                       USBOTGSS_IRQMISC_IDPULLUP_FALL);
-
-       dwc3_omap_write_irqmisc_set(omap, reg);
+       dwc3_omap_write_irq0_set(omap, USBOTGSS_IRQO_COREIRQ_ST);
+
+       dwc3_omap_write_irqmisc_set(omap, USBOTGSS_INTERRUPTS);
 }
 
 static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
 {
        /* disable all IRQs */
-       dwc3_omap_write_irqmisc_set(omap, 0x00);
-       dwc3_omap_write_irq0_set(omap, 0x00);
+       dwc3_omap_write_irq0_clr(omap, USBOTGSS_IRQO_COREIRQ_ST);
+
+       dwc3_omap_write_irqmisc_clr(omap, USBOTGSS_INTERRUPTS);
 }
 
 static void dwc3_omap_map_offset(struct dwc3_omap *omap)
@@ -363,12 +375,14 @@ int dwc3_omap_uboot_init(struct dwc3_omap_device *omap_dev)
 {
        u32                     reg;
        struct device           *dev;
+       struct dwc3_omap        *omap;
 
        omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
        if (!omap)
                return -ENOMEM;
 
        omap->base      = omap_dev->base;
+       omap->index     = omap_dev->index;
 
        dwc3_omap_map_offset(omap);
        dwc3_omap_set_utmi_mode(omap, omap_dev->utmi_mode);
@@ -380,6 +394,7 @@ int dwc3_omap_uboot_init(struct dwc3_omap_device *omap_dev)
        dwc3_omap_set_mailbox(omap, omap_dev->vbus_id_status);
 
        dwc3_omap_enable_irqs(omap);
+       list_add_tail(&omap->list, &dwc3_omap_list);
 
        return 0;
 }
@@ -389,14 +404,43 @@ int dwc3_omap_uboot_init(struct dwc3_omap_device *omap_dev)
  * @index: index of this controller
  *
  * Performs cleanup of memory allocated in dwc3_omap_uboot_init
- * (equivalent to dwc3_omap_remove in linux).
+ * (equivalent to dwc3_omap_remove in linux). index of _this_ controller
+ * should be passed and should match with the index passed in
+ * dwc3_omap_device during init.
  *
  * Generally called from board file.
  */
-void dwc3_omap_uboot_exit(void)
+void dwc3_omap_uboot_exit(int index)
 {
-       dwc3_omap_disable_irqs(omap);
-       kfree(omap);
+       struct dwc3_omap *omap = NULL;
+
+       list_for_each_entry(omap, &dwc3_omap_list, list) {
+               if (omap->index != index)
+                       continue;
+
+               dwc3_omap_disable_irqs(omap);
+               list_del(&omap->list);
+               kfree(omap);
+               break;
+       }
+}
+
+/**
+ * dwc3_omap_uboot_interrupt_status - check the status of interrupt
+ * @index: index of this controller
+ *
+ * Checks the status of interrupts and returns true if an interrupt
+ * is detected or false otherwise.
+ *
+ * Generally called from board file.
+ */
+int dwc3_omap_uboot_interrupt_status(int index)
+{
+       struct dwc3_omap *omap = NULL;
+
+       list_for_each_entry(omap, &dwc3_omap_list, list)
+               if (omap->index == index)
+                       return dwc3_omap_interrupt(-1, omap);
 
        return 0;
 }