summaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3/dwc3-omap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc3/dwc3-omap.c')
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index f85ae5e6129..831b75fa438 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -43,6 +43,7 @@
#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>
@@ -131,6 +132,8 @@ struct dwc3_omap {
u32 dma_status:1;
};
+struct dwc3_omap *_omap;
+
static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
{
return readl(base + offset);
@@ -141,6 +144,57 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
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;
@@ -320,6 +374,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
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) {