18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * dwc3-omap.c - OMAP Specific Glue layer 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Authors: Felipe Balbi <balbi@ti.com>, 88c2ecf20Sopenharmony_ci * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/irq.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 178c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 188c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 198c2ecf20Sopenharmony_ci#include <linux/ioport.h> 208c2ecf20Sopenharmony_ci#include <linux/io.h> 218c2ecf20Sopenharmony_ci#include <linux/of.h> 228c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 238c2ecf20Sopenharmony_ci#include <linux/extcon.h> 248c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <linux/usb/otg.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * All these registers belong to OMAP's Wrapper around the 308c2ecf20Sopenharmony_ci * DesignWare USB3 Core. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define USBOTGSS_REVISION 0x0000 348c2ecf20Sopenharmony_ci#define USBOTGSS_SYSCONFIG 0x0010 358c2ecf20Sopenharmony_ci#define USBOTGSS_IRQ_EOI 0x0020 368c2ecf20Sopenharmony_ci#define USBOTGSS_EOI_OFFSET 0x0008 378c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_RAW_0 0x0024 388c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_0 0x0028 398c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_SET_0 0x002c 408c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_CLR_0 0x0030 418c2ecf20Sopenharmony_ci#define USBOTGSS_IRQ0_OFFSET 0x0004 428c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_RAW_1 0x0030 438c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_1 0x0034 448c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_SET_1 0x0038 458c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_CLR_1 0x003c 468c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_RAW_2 0x0040 478c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_2 0x0044 488c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_SET_2 0x0048 498c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_CLR_2 0x004c 508c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_RAW_3 0x0050 518c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_3 0x0054 528c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_SET_3 0x0058 538c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_CLR_3 0x005c 548c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_EOI_MISC 0x0030 558c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_RAW_MISC 0x0034 568c2ecf20Sopenharmony_ci#define USBOTGSS_IRQSTATUS_MISC 0x0038 578c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_SET_MISC 0x003c 588c2ecf20Sopenharmony_ci#define USBOTGSS_IRQENABLE_CLR_MISC 0x0040 598c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_OFFSET 0x03fc 608c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_STATUS 0x0080 618c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL 0x0084 628c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_OFFSET 0x0480 638c2ecf20Sopenharmony_ci#define USBOTGSS_TXFIFO_DEPTH 0x0508 648c2ecf20Sopenharmony_ci#define USBOTGSS_RXFIFO_DEPTH 0x050c 658c2ecf20Sopenharmony_ci#define USBOTGSS_MMRAM_OFFSET 0x0100 668c2ecf20Sopenharmony_ci#define USBOTGSS_FLADJ 0x0104 678c2ecf20Sopenharmony_ci#define USBOTGSS_DEBUG_CFG 0x0108 688c2ecf20Sopenharmony_ci#define USBOTGSS_DEBUG_DATA 0x010c 698c2ecf20Sopenharmony_ci#define USBOTGSS_DEV_EBC_EN 0x0110 708c2ecf20Sopenharmony_ci#define USBOTGSS_DEBUG_OFFSET 0x0600 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/* SYSCONFIG REGISTER */ 738c2ecf20Sopenharmony_ci#define USBOTGSS_SYSCONFIG_DMADISABLE BIT(16) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* IRQ_EOI REGISTER */ 768c2ecf20Sopenharmony_ci#define USBOTGSS_IRQ_EOI_LINE_NUMBER BIT(0) 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* IRQS0 BITS */ 798c2ecf20Sopenharmony_ci#define USBOTGSS_IRQO_COREIRQ_ST BIT(0) 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* IRQMISC BITS */ 828c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_DMADISABLECLR BIT(17) 838c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_OEVT BIT(16) 848c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_DRVVBUS_RISE BIT(13) 858c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_CHRGVBUS_RISE BIT(12) 868c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE BIT(11) 878c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_IDPULLUP_RISE BIT(8) 888c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_DRVVBUS_FALL BIT(5) 898c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_CHRGVBUS_FALL BIT(4) 908c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL BIT(3) 918c2ecf20Sopenharmony_ci#define USBOTGSS_IRQMISC_IDPULLUP_FALL BIT(0) 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* UTMI_OTG_STATUS REGISTER */ 948c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_STATUS_DRVVBUS BIT(5) 958c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_STATUS_CHRGVBUS BIT(4) 968c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_STATUS_DISCHRGVBUS BIT(3) 978c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_STATUS_IDPULLUP BIT(0) 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* UTMI_OTG_CTRL REGISTER */ 1008c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL_SW_MODE BIT(31) 1018c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT BIT(9) 1028c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL_TXBITSTUFFENABLE BIT(8) 1038c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL_IDDIG BIT(4) 1048c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL_SESSEND BIT(3) 1058c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL_SESSVALID BIT(2) 1068c2ecf20Sopenharmony_ci#define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID BIT(1) 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cienum dwc3_omap_utmi_mode { 1098c2ecf20Sopenharmony_ci DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, 1108c2ecf20Sopenharmony_ci DWC3_OMAP_UTMI_MODE_HW, 1118c2ecf20Sopenharmony_ci DWC3_OMAP_UTMI_MODE_SW, 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistruct dwc3_omap { 1158c2ecf20Sopenharmony_ci struct device *dev; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci int irq; 1188c2ecf20Sopenharmony_ci void __iomem *base; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci u32 utmi_otg_ctrl; 1218c2ecf20Sopenharmony_ci u32 utmi_otg_offset; 1228c2ecf20Sopenharmony_ci u32 irqmisc_offset; 1238c2ecf20Sopenharmony_ci u32 irq_eoi_offset; 1248c2ecf20Sopenharmony_ci u32 debug_offset; 1258c2ecf20Sopenharmony_ci u32 irq0_offset; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci struct extcon_dev *edev; 1288c2ecf20Sopenharmony_ci struct notifier_block vbus_nb; 1298c2ecf20Sopenharmony_ci struct notifier_block id_nb; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci struct regulator *vbus_reg; 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cienum omap_dwc3_vbus_id_status { 1358c2ecf20Sopenharmony_ci OMAP_DWC3_ID_FLOAT, 1368c2ecf20Sopenharmony_ci OMAP_DWC3_ID_GROUND, 1378c2ecf20Sopenharmony_ci OMAP_DWC3_VBUS_OFF, 1388c2ecf20Sopenharmony_ci OMAP_DWC3_VBUS_VALID, 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci return readl(base + offset); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci writel(value, base + offset); 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic u32 dwc3_omap_read_utmi_ctrl(struct dwc3_omap *omap) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci return dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_CTRL + 1548c2ecf20Sopenharmony_ci omap->utmi_otg_offset); 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic void dwc3_omap_write_utmi_ctrl(struct dwc3_omap *omap, u32 value) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_CTRL + 1608c2ecf20Sopenharmony_ci omap->utmi_otg_offset, value); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic u32 dwc3_omap_read_irq0_status(struct dwc3_omap *omap) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_RAW_0 - 1678c2ecf20Sopenharmony_ci omap->irq0_offset); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic void dwc3_omap_write_irq0_status(struct dwc3_omap *omap, u32 value) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0 - 1738c2ecf20Sopenharmony_ci omap->irq0_offset, value); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic u32 dwc3_omap_read_irqmisc_status(struct dwc3_omap *omap) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_RAW_MISC + 1808c2ecf20Sopenharmony_ci omap->irqmisc_offset); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic void dwc3_omap_write_irqmisc_status(struct dwc3_omap *omap, u32 value) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_MISC + 1868c2ecf20Sopenharmony_ci omap->irqmisc_offset, value); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic void dwc3_omap_write_irqmisc_set(struct dwc3_omap *omap, u32 value) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_MISC + 1938c2ecf20Sopenharmony_ci omap->irqmisc_offset, value); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0 - 2008c2ecf20Sopenharmony_ci omap->irq0_offset, value); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic void dwc3_omap_write_irqmisc_clr(struct dwc3_omap *omap, u32 value) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_MISC + 2068c2ecf20Sopenharmony_ci omap->irqmisc_offset, value); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic void dwc3_omap_write_irq0_clr(struct dwc3_omap *omap, u32 value) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_0 - 2128c2ecf20Sopenharmony_ci omap->irq0_offset, value); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic void dwc3_omap_set_mailbox(struct dwc3_omap *omap, 2168c2ecf20Sopenharmony_ci enum omap_dwc3_vbus_id_status status) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci int ret; 2198c2ecf20Sopenharmony_ci u32 val; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci switch (status) { 2228c2ecf20Sopenharmony_ci case OMAP_DWC3_ID_GROUND: 2238c2ecf20Sopenharmony_ci if (omap->vbus_reg) { 2248c2ecf20Sopenharmony_ci ret = regulator_enable(omap->vbus_reg); 2258c2ecf20Sopenharmony_ci if (ret) { 2268c2ecf20Sopenharmony_ci dev_err(omap->dev, "regulator enable failed\n"); 2278c2ecf20Sopenharmony_ci return; 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci val = dwc3_omap_read_utmi_ctrl(omap); 2328c2ecf20Sopenharmony_ci val &= ~USBOTGSS_UTMI_OTG_CTRL_IDDIG; 2338c2ecf20Sopenharmony_ci dwc3_omap_write_utmi_ctrl(omap, val); 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci case OMAP_DWC3_VBUS_VALID: 2378c2ecf20Sopenharmony_ci val = dwc3_omap_read_utmi_ctrl(omap); 2388c2ecf20Sopenharmony_ci val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND; 2398c2ecf20Sopenharmony_ci val |= USBOTGSS_UTMI_OTG_CTRL_VBUSVALID 2408c2ecf20Sopenharmony_ci | USBOTGSS_UTMI_OTG_CTRL_SESSVALID; 2418c2ecf20Sopenharmony_ci dwc3_omap_write_utmi_ctrl(omap, val); 2428c2ecf20Sopenharmony_ci break; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci case OMAP_DWC3_ID_FLOAT: 2458c2ecf20Sopenharmony_ci if (omap->vbus_reg && regulator_is_enabled(omap->vbus_reg)) 2468c2ecf20Sopenharmony_ci regulator_disable(omap->vbus_reg); 2478c2ecf20Sopenharmony_ci val = dwc3_omap_read_utmi_ctrl(omap); 2488c2ecf20Sopenharmony_ci val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG; 2498c2ecf20Sopenharmony_ci dwc3_omap_write_utmi_ctrl(omap, val); 2508c2ecf20Sopenharmony_ci break; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci case OMAP_DWC3_VBUS_OFF: 2538c2ecf20Sopenharmony_ci val = dwc3_omap_read_utmi_ctrl(omap); 2548c2ecf20Sopenharmony_ci val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID 2558c2ecf20Sopenharmony_ci | USBOTGSS_UTMI_OTG_CTRL_VBUSVALID); 2568c2ecf20Sopenharmony_ci val |= USBOTGSS_UTMI_OTG_CTRL_SESSEND; 2578c2ecf20Sopenharmony_ci dwc3_omap_write_utmi_ctrl(omap, val); 2588c2ecf20Sopenharmony_ci break; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci default: 2618c2ecf20Sopenharmony_ci dev_WARN(omap->dev, "invalid state\n"); 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic void dwc3_omap_enable_irqs(struct dwc3_omap *omap); 2668c2ecf20Sopenharmony_cistatic void dwc3_omap_disable_irqs(struct dwc3_omap *omap); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci struct dwc3_omap *omap = _omap; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (dwc3_omap_read_irqmisc_status(omap) || 2738c2ecf20Sopenharmony_ci dwc3_omap_read_irq0_status(omap)) { 2748c2ecf20Sopenharmony_ci /* mask irqs */ 2758c2ecf20Sopenharmony_ci dwc3_omap_disable_irqs(omap); 2768c2ecf20Sopenharmony_ci return IRQ_WAKE_THREAD; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci return IRQ_NONE; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic irqreturn_t dwc3_omap_interrupt_thread(int irq, void *_omap) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci struct dwc3_omap *omap = _omap; 2858c2ecf20Sopenharmony_ci u32 reg; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* clear irq status flags */ 2888c2ecf20Sopenharmony_ci reg = dwc3_omap_read_irqmisc_status(omap); 2898c2ecf20Sopenharmony_ci dwc3_omap_write_irqmisc_status(omap, reg); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci reg = dwc3_omap_read_irq0_status(omap); 2928c2ecf20Sopenharmony_ci dwc3_omap_write_irq0_status(omap, reg); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* unmask irqs */ 2958c2ecf20Sopenharmony_ci dwc3_omap_enable_irqs(omap); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic void dwc3_omap_enable_irqs(struct dwc3_omap *omap) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci u32 reg; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* enable all IRQs */ 3058c2ecf20Sopenharmony_ci reg = USBOTGSS_IRQO_COREIRQ_ST; 3068c2ecf20Sopenharmony_ci dwc3_omap_write_irq0_set(omap, reg); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci reg = (USBOTGSS_IRQMISC_OEVT | 3098c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DRVVBUS_RISE | 3108c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_CHRGVBUS_RISE | 3118c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | 3128c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_IDPULLUP_RISE | 3138c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DRVVBUS_FALL | 3148c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_CHRGVBUS_FALL | 3158c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | 3168c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_IDPULLUP_FALL); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci dwc3_omap_write_irqmisc_set(omap, reg); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic void dwc3_omap_disable_irqs(struct dwc3_omap *omap) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci u32 reg; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* disable all IRQs */ 3268c2ecf20Sopenharmony_ci reg = USBOTGSS_IRQO_COREIRQ_ST; 3278c2ecf20Sopenharmony_ci dwc3_omap_write_irq0_clr(omap, reg); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci reg = (USBOTGSS_IRQMISC_OEVT | 3308c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DRVVBUS_RISE | 3318c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_CHRGVBUS_RISE | 3328c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | 3338c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_IDPULLUP_RISE | 3348c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DRVVBUS_FALL | 3358c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_CHRGVBUS_FALL | 3368c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | 3378c2ecf20Sopenharmony_ci USBOTGSS_IRQMISC_IDPULLUP_FALL); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci dwc3_omap_write_irqmisc_clr(omap, reg); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic int dwc3_omap_id_notifier(struct notifier_block *nb, 3438c2ecf20Sopenharmony_ci unsigned long event, void *ptr) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, id_nb); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (event) 3488c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); 3498c2ecf20Sopenharmony_ci else 3508c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return NOTIFY_DONE; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic int dwc3_omap_vbus_notifier(struct notifier_block *nb, 3568c2ecf20Sopenharmony_ci unsigned long event, void *ptr) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, vbus_nb); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (event) 3618c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); 3628c2ecf20Sopenharmony_ci else 3638c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci return NOTIFY_DONE; 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic void dwc3_omap_map_offset(struct dwc3_omap *omap) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct device_node *node = omap->dev->of_node; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci /* 3738c2ecf20Sopenharmony_ci * Differentiate between OMAP5 and AM437x. 3748c2ecf20Sopenharmony_ci * 3758c2ecf20Sopenharmony_ci * For OMAP5(ES2.0) and AM437x wrapper revision is same, even 3768c2ecf20Sopenharmony_ci * though there are changes in wrapper register offsets. 3778c2ecf20Sopenharmony_ci * 3788c2ecf20Sopenharmony_ci * Using dt compatible to differentiate AM437x. 3798c2ecf20Sopenharmony_ci */ 3808c2ecf20Sopenharmony_ci if (of_device_is_compatible(node, "ti,am437x-dwc3")) { 3818c2ecf20Sopenharmony_ci omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; 3828c2ecf20Sopenharmony_ci omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; 3838c2ecf20Sopenharmony_ci omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; 3848c2ecf20Sopenharmony_ci omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; 3858c2ecf20Sopenharmony_ci omap->debug_offset = USBOTGSS_DEBUG_OFFSET; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci u32 reg; 3928c2ecf20Sopenharmony_ci struct device_node *node = omap->dev->of_node; 3938c2ecf20Sopenharmony_ci u32 utmi_mode = 0; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci reg = dwc3_omap_read_utmi_ctrl(omap); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci of_property_read_u32(node, "utmi-mode", &utmi_mode); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci switch (utmi_mode) { 4008c2ecf20Sopenharmony_ci case DWC3_OMAP_UTMI_MODE_SW: 4018c2ecf20Sopenharmony_ci reg |= USBOTGSS_UTMI_OTG_CTRL_SW_MODE; 4028c2ecf20Sopenharmony_ci break; 4038c2ecf20Sopenharmony_ci case DWC3_OMAP_UTMI_MODE_HW: 4048c2ecf20Sopenharmony_ci reg &= ~USBOTGSS_UTMI_OTG_CTRL_SW_MODE; 4058c2ecf20Sopenharmony_ci break; 4068c2ecf20Sopenharmony_ci default: 4078c2ecf20Sopenharmony_ci dev_WARN(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode); 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci dwc3_omap_write_utmi_ctrl(omap, reg); 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic int dwc3_omap_extcon_register(struct dwc3_omap *omap) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci int ret; 4168c2ecf20Sopenharmony_ci struct device_node *node = omap->dev->of_node; 4178c2ecf20Sopenharmony_ci struct extcon_dev *edev; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci if (of_property_read_bool(node, "extcon")) { 4208c2ecf20Sopenharmony_ci edev = extcon_get_edev_by_phandle(omap->dev, 0); 4218c2ecf20Sopenharmony_ci if (IS_ERR(edev)) { 4228c2ecf20Sopenharmony_ci dev_vdbg(omap->dev, "couldn't get extcon device\n"); 4238c2ecf20Sopenharmony_ci return -EPROBE_DEFER; 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier; 4278c2ecf20Sopenharmony_ci ret = devm_extcon_register_notifier(omap->dev, edev, 4288c2ecf20Sopenharmony_ci EXTCON_USB, &omap->vbus_nb); 4298c2ecf20Sopenharmony_ci if (ret < 0) 4308c2ecf20Sopenharmony_ci dev_vdbg(omap->dev, "failed to register notifier for USB\n"); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci omap->id_nb.notifier_call = dwc3_omap_id_notifier; 4338c2ecf20Sopenharmony_ci ret = devm_extcon_register_notifier(omap->dev, edev, 4348c2ecf20Sopenharmony_ci EXTCON_USB_HOST, &omap->id_nb); 4358c2ecf20Sopenharmony_ci if (ret < 0) 4368c2ecf20Sopenharmony_ci dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n"); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci if (extcon_get_state(edev, EXTCON_USB) == true) 4398c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); 4408c2ecf20Sopenharmony_ci else 4418c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci if (extcon_get_state(edev, EXTCON_USB_HOST) == true) 4448c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); 4458c2ecf20Sopenharmony_ci else 4468c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci omap->edev = edev; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_cistatic int dwc3_omap_probe(struct platform_device *pdev) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci struct device_node *node = pdev->dev.of_node; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci struct dwc3_omap *omap; 4598c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 4608c2ecf20Sopenharmony_ci struct regulator *vbus_reg = NULL; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci int ret; 4638c2ecf20Sopenharmony_ci int irq; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci void __iomem *base; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci if (!node) { 4688c2ecf20Sopenharmony_ci dev_err(dev, "device node not found\n"); 4698c2ecf20Sopenharmony_ci return -EINVAL; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL); 4738c2ecf20Sopenharmony_ci if (!omap) 4748c2ecf20Sopenharmony_ci return -ENOMEM; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, omap); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci irq = platform_get_irq(pdev, 0); 4798c2ecf20Sopenharmony_ci if (irq < 0) 4808c2ecf20Sopenharmony_ci return irq; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci base = devm_platform_ioremap_resource(pdev, 0); 4838c2ecf20Sopenharmony_ci if (IS_ERR(base)) 4848c2ecf20Sopenharmony_ci return PTR_ERR(base); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci if (of_property_read_bool(node, "vbus-supply")) { 4878c2ecf20Sopenharmony_ci vbus_reg = devm_regulator_get(dev, "vbus"); 4888c2ecf20Sopenharmony_ci if (IS_ERR(vbus_reg)) { 4898c2ecf20Sopenharmony_ci dev_err(dev, "vbus init failed\n"); 4908c2ecf20Sopenharmony_ci return PTR_ERR(vbus_reg); 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci } 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci omap->dev = dev; 4958c2ecf20Sopenharmony_ci omap->irq = irq; 4968c2ecf20Sopenharmony_ci omap->base = base; 4978c2ecf20Sopenharmony_ci omap->vbus_reg = vbus_reg; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci pm_runtime_enable(dev); 5008c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(dev); 5018c2ecf20Sopenharmony_ci if (ret < 0) { 5028c2ecf20Sopenharmony_ci dev_err(dev, "get_sync failed with err %d\n", ret); 5038c2ecf20Sopenharmony_ci goto err1; 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci dwc3_omap_map_offset(omap); 5078c2ecf20Sopenharmony_ci dwc3_omap_set_utmi_mode(omap); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci ret = dwc3_omap_extcon_register(omap); 5108c2ecf20Sopenharmony_ci if (ret < 0) 5118c2ecf20Sopenharmony_ci goto err1; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci ret = of_platform_populate(node, NULL, NULL, dev); 5148c2ecf20Sopenharmony_ci if (ret) { 5158c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to create dwc3 core\n"); 5168c2ecf20Sopenharmony_ci goto err1; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt, 5208c2ecf20Sopenharmony_ci dwc3_omap_interrupt_thread, IRQF_SHARED, 5218c2ecf20Sopenharmony_ci "dwc3-omap", omap); 5228c2ecf20Sopenharmony_ci if (ret) { 5238c2ecf20Sopenharmony_ci dev_err(dev, "failed to request IRQ #%d --> %d\n", 5248c2ecf20Sopenharmony_ci omap->irq, ret); 5258c2ecf20Sopenharmony_ci goto err1; 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci dwc3_omap_enable_irqs(omap); 5288c2ecf20Sopenharmony_ci return 0; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cierr1: 5318c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev); 5328c2ecf20Sopenharmony_ci pm_runtime_disable(dev); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci return ret; 5358c2ecf20Sopenharmony_ci} 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_cistatic int dwc3_omap_remove(struct platform_device *pdev) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci struct dwc3_omap *omap = platform_get_drvdata(pdev); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci dwc3_omap_disable_irqs(omap); 5428c2ecf20Sopenharmony_ci disable_irq(omap->irq); 5438c2ecf20Sopenharmony_ci of_platform_depopulate(omap->dev); 5448c2ecf20Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 5458c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci return 0; 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_cistatic const struct of_device_id of_dwc3_match[] = { 5518c2ecf20Sopenharmony_ci { 5528c2ecf20Sopenharmony_ci .compatible = "ti,dwc3" 5538c2ecf20Sopenharmony_ci }, 5548c2ecf20Sopenharmony_ci { 5558c2ecf20Sopenharmony_ci .compatible = "ti,am437x-dwc3" 5568c2ecf20Sopenharmony_ci }, 5578c2ecf20Sopenharmony_ci { }, 5588c2ecf20Sopenharmony_ci}; 5598c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_dwc3_match); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 5628c2ecf20Sopenharmony_cistatic int dwc3_omap_suspend(struct device *dev) 5638c2ecf20Sopenharmony_ci{ 5648c2ecf20Sopenharmony_ci struct dwc3_omap *omap = dev_get_drvdata(dev); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci omap->utmi_otg_ctrl = dwc3_omap_read_utmi_ctrl(omap); 5678c2ecf20Sopenharmony_ci dwc3_omap_disable_irqs(omap); 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci return 0; 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic int dwc3_omap_resume(struct device *dev) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci struct dwc3_omap *omap = dev_get_drvdata(dev); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci dwc3_omap_write_utmi_ctrl(omap, omap->utmi_otg_ctrl); 5778c2ecf20Sopenharmony_ci dwc3_omap_enable_irqs(omap); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci pm_runtime_disable(dev); 5808c2ecf20Sopenharmony_ci pm_runtime_set_active(dev); 5818c2ecf20Sopenharmony_ci pm_runtime_enable(dev); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci return 0; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic void dwc3_omap_complete(struct device *dev) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci struct dwc3_omap *omap = dev_get_drvdata(dev); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci if (extcon_get_state(omap->edev, EXTCON_USB)) 5918c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); 5928c2ecf20Sopenharmony_ci else 5938c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci if (extcon_get_state(omap->edev, EXTCON_USB_HOST)) 5968c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); 5978c2ecf20Sopenharmony_ci else 5988c2ecf20Sopenharmony_ci dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT); 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cistatic const struct dev_pm_ops dwc3_omap_dev_pm_ops = { 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume) 6048c2ecf20Sopenharmony_ci .complete = dwc3_omap_complete, 6058c2ecf20Sopenharmony_ci}; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci#define DEV_PM_OPS (&dwc3_omap_dev_pm_ops) 6088c2ecf20Sopenharmony_ci#else 6098c2ecf20Sopenharmony_ci#define DEV_PM_OPS NULL 6108c2ecf20Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cistatic struct platform_driver dwc3_omap_driver = { 6138c2ecf20Sopenharmony_ci .probe = dwc3_omap_probe, 6148c2ecf20Sopenharmony_ci .remove = dwc3_omap_remove, 6158c2ecf20Sopenharmony_ci .driver = { 6168c2ecf20Sopenharmony_ci .name = "omap-dwc3", 6178c2ecf20Sopenharmony_ci .of_match_table = of_dwc3_match, 6188c2ecf20Sopenharmony_ci .pm = DEV_PM_OPS, 6198c2ecf20Sopenharmony_ci }, 6208c2ecf20Sopenharmony_ci}; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cimodule_platform_driver(dwc3_omap_driver); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:omap-dwc3"); 6258c2ecf20Sopenharmony_ciMODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 6268c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 6278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer"); 628