#include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/dwc3-omap.h>
+#include <linux/usb/dwc3-omap.h>
 #include <linux/pm_runtime.h>
 #include <linux/dma-mapping.h>
 #include <linux/ioport.h>
        u32                     dma_status:1;
 };
 
+struct dwc3_omap               *_omap;
+
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 {
        return readl(base + offset);
        writel(value, base + offset);
 }
 
+void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+{
+       u32                     val;
+       struct dwc3_omap        *omap = _omap;
+
+       switch (status) {
+       case OMAP_DWC3_ID_GROUND:
+               dev_dbg(omap->dev, "ID GND\n");
+
+               val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
+               val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
+                               | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
+                               | USBOTGSS_UTMI_OTG_STATUS_SESSEND);
+               val |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID
+                               | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
+               dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
+               break;
+
+       case OMAP_DWC3_VBUS_VALID:
+               dev_dbg(omap->dev, "VBUS Connect\n");
+
+               val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
+               val &= ~USBOTGSS_UTMI_OTG_STATUS_SESSEND;
+               val |= USBOTGSS_UTMI_OTG_STATUS_IDDIG
+                               | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
+                               | USBOTGSS_UTMI_OTG_STATUS_SESSVALID
+                               | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
+               dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
+               break;
+
+       case OMAP_DWC3_ID_FLOAT:
+       case OMAP_DWC3_VBUS_OFF:
+               dev_dbg(omap->dev, "VBUS Disconnect\n");
+
+               val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
+               val &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSVALID
+                               | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
+                               | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT);
+               val |= USBOTGSS_UTMI_OTG_STATUS_SESSEND
+                               | USBOTGSS_UTMI_OTG_STATUS_IDDIG;
+               dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val);
+               break;
+
+       default:
+               dev_dbg(omap->dev, "ID float\n");
+       }
+
+       return;
+}
+EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
+
 static int dwc3_omap_register_phys(struct dwc3_omap *omap)
 {
        struct nop_usb_xceiv_platform_data pdata;
        omap->irq       = irq;
        omap->base      = base;
 
+       /*
+        * REVISIT if we ever have two instances of the wrapper, we will be
+        * in big trouble
+        */
+       _omap   = omap;
+
        pm_runtime_enable(dev);
        ret = pm_runtime_get_sync(dev);
        if (ret < 0) {
 
--- /dev/null
+/*
+ * Copyright (C) 2013 by Texas Instruments
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ */
+
+#ifndef __DWC3_OMAP_H__
+#define __DWC3_OMAP_H__
+
+enum omap_dwc3_vbus_id_status {
+       OMAP_DWC3_UNKNOWN = 0,
+       OMAP_DWC3_ID_GROUND,
+       OMAP_DWC3_ID_FLOAT,
+       OMAP_DWC3_VBUS_VALID,
+       OMAP_DWC3_VBUS_OFF,
+};
+
+#if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE))
+extern void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
+#else
+static inline void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+{
+       return;
+}
+#endif
+
+#endif /* __DWC3_OMAP_H__ */