aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaviteja Garimella <raviteja.garimella@broadcom.com>2017-05-10 08:51:21 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2017-06-13 06:21:03 -0400
commit1b9f35adb0ffa143c7972a8459d6979c77d6c3c0 (patch)
treeb04e4a791e5a650133f4e45290c8e9043ace0903
parent92122a60d9f0ef3e3bc760e087588f71b2e86c97 (diff)
usb: gadget: udc: Add Synopsys UDC Platform driver
This patch adds platform driver support for Synopsys UDC. A new driver file (snps_udc_plat.c) is created for this purpose where the platform driver registration is done based on OF node. Currently, UDC integrated into Broadcom's iProc SoCs (Northstar2 and Cygnus) work with this driver. New members are added to the UDC data structure for having platform device support along with extcon and phy support. Kconfig and Makefiles are modified to select platform driver for compilation. Signed-off-by: Raviteja Garimella <raviteja.garimella@broadcom.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/gadget/udc/Kconfig16
-rw-r--r--drivers/usb/gadget/udc/Makefile1
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.h14
-rw-r--r--drivers/usb/gadget/udc/snps_udc_core.c54
-rw-r--r--drivers/usb/gadget/udc/snps_udc_plat.c344
5 files changed, 409 insertions, 20 deletions
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index 1c14c283cc47..e5d3ba9a8604 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -256,7 +256,7 @@ config USB_MV_U3D
256 controller, which support super speed USB peripheral. 256 controller, which support super speed USB peripheral.
257 257
258config USB_SNP_CORE 258config USB_SNP_CORE
259 depends on USB_AMD5536UDC 259 depends on (USB_AMD5536UDC || USB_SNP_UDC_PLAT)
260 tristate 260 tristate
261 help 261 help
262 This enables core driver support for Synopsys USB 2.0 Device 262 This enables core driver support for Synopsys USB 2.0 Device
@@ -269,6 +269,20 @@ config USB_SNP_CORE
269 This IP is different to the High Speed OTG IP that can be enabled 269 This IP is different to the High Speed OTG IP that can be enabled
270 by selecting USB_DWC2 or USB_DWC3 options. 270 by selecting USB_DWC2 or USB_DWC3 options.
271 271
272config USB_SNP_UDC_PLAT
273 tristate "Synopsys USB 2.0 Device controller"
274 depends on (USB_GADGET && OF)
275 select USB_GADGET_DUALSPEED
276 select USB_SNP_CORE
277 default ARCH_BCM_IPROC
278 help
279 This adds Platform Device support for Synopsys Designware core
280 AHB subsystem USB2.0 Device Controller (UDC).
281
282 This driver works with UDCs integrated into Broadcom's Northstar2
283 and Cygnus SoCs.
284
285 If unsure, say N.
272# 286#
273# Controllers available in both integrated and discrete versions 287# Controllers available in both integrated and discrete versions
274# 288#
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 4f4fd626b9ff..ea9e1c7f1923 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -37,4 +37,5 @@ obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
37obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o 37obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
38obj-$(CONFIG_USB_GR_UDC) += gr_udc.o 38obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
39obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o 39obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o
40obj-$(CONFIG_USB_SNP_UDC_PLAT) += snps_udc_plat.o
40obj-$(CONFIG_USB_BDC_UDC) += bdc/ 41obj-$(CONFIG_USB_BDC_UDC) += bdc/
diff --git a/drivers/usb/gadget/udc/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h
index 91aae23b7370..4fe22d432af2 100644
--- a/drivers/usb/gadget/udc/amd5536udc.h
+++ b/drivers/usb/gadget/udc/amd5536udc.h
@@ -16,6 +16,7 @@
16/* debug control */ 16/* debug control */
17/* #define UDC_VERBOSE */ 17/* #define UDC_VERBOSE */
18 18
19#include <linux/extcon.h>
19#include <linux/usb/ch9.h> 20#include <linux/usb/ch9.h>
20#include <linux/usb/gadget.h> 21#include <linux/usb/gadget.h>
21 22
@@ -28,6 +29,9 @@
28#define UDC_HSA0_REV 1 29#define UDC_HSA0_REV 1
29#define UDC_HSB1_REV 2 30#define UDC_HSB1_REV 2
30 31
32/* Broadcom chip rev. */
33#define UDC_BCM_REV 10
34
31/* 35/*
32 * SETUP usb commands 36 * SETUP usb commands
33 * needed, because some SETUP's are handled in hw, but must be passed to 37 * needed, because some SETUP's are handled in hw, but must be passed to
@@ -112,6 +116,7 @@
112#define UDC_DEVCTL_BRLEN_MASK 0x00ff0000 116#define UDC_DEVCTL_BRLEN_MASK 0x00ff0000
113#define UDC_DEVCTL_BRLEN_OFS 16 117#define UDC_DEVCTL_BRLEN_OFS 16
114 118
119#define UDC_DEVCTL_SRX_FLUSH 14
115#define UDC_DEVCTL_CSR_DONE 13 120#define UDC_DEVCTL_CSR_DONE 13
116#define UDC_DEVCTL_DEVNAK 12 121#define UDC_DEVCTL_DEVNAK 12
117#define UDC_DEVCTL_SD 10 122#define UDC_DEVCTL_SD 10
@@ -564,7 +569,15 @@ struct udc {
564 u16 cur_intf; 569 u16 cur_intf;
565 u16 cur_alt; 570 u16 cur_alt;
566 571
572 /* for platform device and extcon support */
567 struct device *dev; 573 struct device *dev;
574 struct phy *udc_phy;
575 struct extcon_dev *edev;
576 struct extcon_specific_cable_nb extcon_nb;
577 struct notifier_block nb;
578 struct delayed_work drd_work;
579 struct workqueue_struct *drd_wq;
580 u32 conn_type;
568}; 581};
569 582
570#define to_amd5536_udc(g) (container_of((g), struct udc, gadget)) 583#define to_amd5536_udc(g) (container_of((g), struct udc, gadget))
@@ -580,6 +593,7 @@ int udc_enable_dev_setup_interrupts(struct udc *dev);
580int udc_mask_unused_interrupts(struct udc *dev); 593int udc_mask_unused_interrupts(struct udc *dev);
581irqreturn_t udc_irq(int irq, void *pdev); 594irqreturn_t udc_irq(int irq, void *pdev);
582void gadget_release(struct device *pdev); 595void gadget_release(struct device *pdev);
596void empty_req_queue(struct udc_ep *ep);
583void udc_basic_init(struct udc *dev); 597void udc_basic_init(struct udc *dev);
584void free_dma_pools(struct udc *dev); 598void free_dma_pools(struct udc *dev);
585int init_dma_pools(struct udc *dev); 599int init_dma_pools(struct udc *dev);
diff --git a/drivers/usb/gadget/udc/snps_udc_core.c b/drivers/usb/gadget/udc/snps_udc_core.c
index d592f77da744..38a165dbf924 100644
--- a/drivers/usb/gadget/udc/snps_udc_core.c
+++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -41,7 +41,6 @@
41#include "amd5536udc.h" 41#include "amd5536udc.h"
42 42
43static void udc_tasklet_disconnect(unsigned long); 43static void udc_tasklet_disconnect(unsigned long);
44static void empty_req_queue(struct udc_ep *);
45static void udc_setup_endpoints(struct udc *dev); 44static void udc_setup_endpoints(struct udc *dev);
46static void udc_soft_reset(struct udc *dev); 45static void udc_soft_reset(struct udc *dev);
47static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep); 46static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
@@ -1244,7 +1243,7 @@ finished:
1244} 1243}
1245 1244
1246/* Empty request queue of an endpoint; caller holds spinlock */ 1245/* Empty request queue of an endpoint; caller holds spinlock */
1247static void empty_req_queue(struct udc_ep *ep) 1246void empty_req_queue(struct udc_ep *ep)
1248{ 1247{
1249 struct udc_request *req; 1248 struct udc_request *req;
1250 1249
@@ -1256,6 +1255,7 @@ static void empty_req_queue(struct udc_ep *ep)
1256 complete_req(ep, req, -ESHUTDOWN); 1255 complete_req(ep, req, -ESHUTDOWN);
1257 } 1256 }
1258} 1257}
1258EXPORT_SYMBOL_GPL(empty_req_queue);
1259 1259
1260/* Dequeues a request packet, called by gadget driver */ 1260/* Dequeues a request packet, called by gadget driver */
1261static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq) 1261static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
@@ -1623,6 +1623,9 @@ static void udc_setup_endpoints(struct udc *dev)
1623/* Bringup after Connect event, initial bringup to be ready for ep0 events */ 1623/* Bringup after Connect event, initial bringup to be ready for ep0 events */
1624static void usb_connect(struct udc *dev) 1624static void usb_connect(struct udc *dev)
1625{ 1625{
1626 /* Return if already connected */
1627 if (dev->connected)
1628 return;
1626 1629
1627 dev_info(dev->dev, "USB Connect\n"); 1630 dev_info(dev->dev, "USB Connect\n");
1628 1631
@@ -1641,6 +1644,9 @@ static void usb_connect(struct udc *dev)
1641 */ 1644 */
1642static void usb_disconnect(struct udc *dev) 1645static void usb_disconnect(struct udc *dev)
1643{ 1646{
1647 /* Return if already disconnected */
1648 if (!dev->connected)
1649 return;
1644 1650
1645 dev_info(dev->dev, "USB Disconnect\n"); 1651 dev_info(dev->dev, "USB Disconnect\n");
1646 1652
@@ -1715,11 +1721,15 @@ static void udc_soft_reset(struct udc *dev)
1715 /* device int. status reset */ 1721 /* device int. status reset */
1716 writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts); 1722 writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);
1717 1723
1718 spin_lock_irqsave(&udc_irq_spinlock, flags); 1724 /* Don't do this for Broadcom UDC since this is a reserved
1719 writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); 1725 * bit.
1720 readl(&dev->regs->cfg); 1726 */
1721 spin_unlock_irqrestore(&udc_irq_spinlock, flags); 1727 if (dev->chiprev != UDC_BCM_REV) {
1722 1728 spin_lock_irqsave(&udc_irq_spinlock, flags);
1729 writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
1730 readl(&dev->regs->cfg);
1731 spin_unlock_irqrestore(&udc_irq_spinlock, flags);
1732 }
1723} 1733}
1724 1734
1725/* RDE timer callback to set RDE bit */ 1735/* RDE timer callback to set RDE bit */
@@ -3171,21 +3181,27 @@ int udc_probe(struct udc *dev)
3171 dev_info(dev->dev, "%s\n", mod_desc); 3181 dev_info(dev->dev, "%s\n", mod_desc);
3172 3182
3173 snprintf(tmp, sizeof(tmp), "%d", dev->irq); 3183 snprintf(tmp, sizeof(tmp), "%d", dev->irq);
3174 dev_info(dev->dev, 3184
3175 "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n", 3185 /* Print this device info for AMD chips only*/
3176 tmp, dev->phys_addr, dev->chiprev, 3186 if (dev->chiprev == UDC_HSA0_REV ||
3177 (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1"); 3187 dev->chiprev == UDC_HSB1_REV) {
3178 strcpy(tmp, UDC_DRIVER_VERSION_STRING); 3188 dev_info(dev->dev, "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
3179 if (dev->chiprev == UDC_HSA0_REV) { 3189 tmp, dev->phys_addr, dev->chiprev,
3180 dev_err(dev->dev, "chip revision is A0; too old\n"); 3190 (dev->chiprev == UDC_HSA0_REV) ?
3181 retval = -ENODEV; 3191 "A0" : "B1");
3182 goto finished; 3192 strcpy(tmp, UDC_DRIVER_VERSION_STRING);
3193 if (dev->chiprev == UDC_HSA0_REV) {
3194 dev_err(dev->dev, "chip revision is A0; too old\n");
3195 retval = -ENODEV;
3196 goto finished;
3197 }
3198 dev_info(dev->dev,
3199 "driver version: %s(for Geode5536 B1)\n", tmp);
3183 } 3200 }
3184 dev_info(dev->dev, 3201
3185 "driver version: %s(for Geode5536 B1)\n", tmp);
3186 udc = dev; 3202 udc = dev;
3187 3203
3188 retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget, 3204 retval = usb_add_gadget_udc_release(udc->dev, &dev->gadget,
3189 gadget_release); 3205 gadget_release);
3190 if (retval) 3206 if (retval)
3191 goto finished; 3207 goto finished;
diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c
new file mode 100644
index 000000000000..2e11f19e07ae
--- /dev/null
+++ b/drivers/usb/gadget/udc/snps_udc_plat.c
@@ -0,0 +1,344 @@
1/*
2 * snps_udc_plat.c - Synopsys UDC Platform Driver
3 *
4 * Copyright (C) 2016 Broadcom
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/extcon.h>
17#include <linux/of_address.h>
18#include <linux/of_irq.h>
19#include <linux/of_gpio.h>
20#include <linux/platform_device.h>
21#include <linux/phy/phy.h>
22#include <linux/module.h>
23#include <linux/dmapool.h>
24#include <linux/interrupt.h>
25#include <linux/moduleparam.h>
26#include "amd5536udc.h"
27
28/* description */
29#define UDC_MOD_DESCRIPTION "Synopsys UDC platform driver"
30
31void start_udc(struct udc *udc)
32{
33 if (udc->driver) {
34 dev_info(udc->dev, "Connecting...\n");
35 udc_enable_dev_setup_interrupts(udc);
36 udc_basic_init(udc);
37 udc->connected = 1;
38 }
39}
40
41void stop_udc(struct udc *udc)
42{
43 int tmp;
44 u32 reg;
45
46 spin_lock(&udc->lock);
47
48 /* Flush the receieve fifo */
49 reg = readl(&udc->regs->ctl);
50 reg |= AMD_BIT(UDC_DEVCTL_SRX_FLUSH);
51 writel(reg, &udc->regs->ctl);
52
53 reg = readl(&udc->regs->ctl);
54 reg &= ~(AMD_BIT(UDC_DEVCTL_SRX_FLUSH));
55 writel(reg, &udc->regs->ctl);
56 dev_dbg(udc->dev, "ep rx queue flushed\n");
57
58 /* Mask interrupts. Required more so when the
59 * UDC is connected to a DRD phy.
60 */
61 udc_mask_unused_interrupts(udc);
62
63 /* Disconnect gadget driver */
64 if (udc->driver) {
65 spin_unlock(&udc->lock);
66 udc->driver->disconnect(&udc->gadget);
67 spin_lock(&udc->lock);
68
69 /* empty queues */
70 for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
71 empty_req_queue(&udc->ep[tmp]);
72 }
73 udc->connected = 0;
74
75 spin_unlock(&udc->lock);
76 dev_info(udc->dev, "Device disconnected\n");
77}
78
79void udc_drd_work(struct work_struct *work)
80{
81 struct udc *udc;
82
83 udc = container_of(to_delayed_work(work),
84 struct udc, drd_work);
85
86 if (udc->conn_type) {
87 dev_dbg(udc->dev, "idle -> device\n");
88 start_udc(udc);
89 } else {
90 dev_dbg(udc->dev, "device -> idle\n");
91 stop_udc(udc);
92 }
93}
94
95static int usbd_connect_notify(struct notifier_block *self,
96 unsigned long event, void *ptr)
97{
98 struct udc *udc = container_of(self, struct udc, nb);
99
100 dev_dbg(udc->dev, "%s: event: %lu\n", __func__, event);
101
102 udc->conn_type = event;
103
104 schedule_delayed_work(&udc->drd_work, 0);
105
106 return NOTIFY_OK;
107}
108
109static int udc_plat_probe(struct platform_device *pdev)
110{
111 struct device *dev = &pdev->dev;
112 struct resource *res;
113 struct udc *udc;
114 int ret;
115
116 udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
117 if (!udc)
118 return -ENOMEM;
119
120 spin_lock_init(&udc->lock);
121 udc->dev = dev;
122
123 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
124 udc->virt_addr = devm_ioremap_resource(dev, res);
125 if (IS_ERR(udc->regs))
126 return PTR_ERR(udc->regs);
127
128 /* udc csr registers base */
129 udc->csr = udc->virt_addr + UDC_CSR_ADDR;
130
131 /* dev registers base */
132 udc->regs = udc->virt_addr + UDC_DEVCFG_ADDR;
133
134 /* ep registers base */
135 udc->ep_regs = udc->virt_addr + UDC_EPREGS_ADDR;
136
137 /* fifo's base */
138 udc->rxfifo = (u32 __iomem *)(udc->virt_addr + UDC_RXFIFO_ADDR);
139 udc->txfifo = (u32 __iomem *)(udc->virt_addr + UDC_TXFIFO_ADDR);
140
141 udc->phys_addr = (unsigned long)res->start;
142
143 udc->irq = irq_of_parse_and_map(dev->of_node, 0);
144 if (udc->irq <= 0) {
145 dev_err(dev, "Can't parse and map interrupt\n");
146 return -EINVAL;
147 }
148
149 udc->udc_phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
150 if (IS_ERR(udc->udc_phy)) {
151 dev_err(dev, "Failed to obtain phy from device tree\n");
152 return PTR_ERR(udc->udc_phy);
153 }
154
155 ret = phy_init(udc->udc_phy);
156 if (ret) {
157 dev_err(dev, "UDC phy init failed");
158 return ret;
159 }
160
161 ret = phy_power_on(udc->udc_phy);
162 if (ret) {
163 dev_err(dev, "UDC phy power on failed");
164 phy_exit(udc->udc_phy);
165 return ret;
166 }
167
168 /* Register for extcon if supported */
169 if (of_get_property(dev->of_node, "extcon", NULL)) {
170 udc->edev = extcon_get_edev_by_phandle(dev, 0);
171 if (IS_ERR(udc->edev)) {
172 if (PTR_ERR(udc->edev) == -EPROBE_DEFER)
173 return -EPROBE_DEFER;
174 dev_err(dev, "Invalid or missing extcon\n");
175 ret = PTR_ERR(udc->edev);
176 goto exit_phy;
177 }
178
179 udc->nb.notifier_call = usbd_connect_notify;
180 ret = extcon_register_notifier(udc->edev, EXTCON_USB,
181 &udc->nb);
182 if (ret < 0) {
183 dev_err(dev, "Can't register extcon device\n");
184 goto exit_phy;
185 }
186
187 ret = extcon_get_cable_state_(udc->edev, EXTCON_USB);
188 if (ret < 0) {
189 dev_err(dev, "Can't get cable state\n");
190 goto exit_extcon;
191 } else if (ret) {
192 udc->conn_type = ret;
193 }
194 INIT_DELAYED_WORK(&udc->drd_work, udc_drd_work);
195 }
196
197 /* init dma pools */
198 if (use_dma) {
199 ret = init_dma_pools(udc);
200 if (ret != 0)
201 goto exit_extcon;
202 }
203
204 ret = devm_request_irq(dev, udc->irq, udc_irq, IRQF_SHARED,
205 "snps-udc", udc);
206 if (ret < 0) {
207 dev_err(dev, "Request irq %d failed for UDC\n", udc->irq);
208 goto exit_dma;
209 }
210
211 platform_set_drvdata(pdev, udc);
212 udc->chiprev = UDC_BCM_REV;
213
214 if (udc_probe(udc)) {
215 ret = -ENODEV;
216 goto exit_dma;
217 }
218 dev_info(dev, "Synopsys UDC platform driver probe successful\n");
219
220 return 0;
221
222exit_dma:
223 if (use_dma)
224 free_dma_pools(udc);
225exit_extcon:
226 if (udc->edev)
227 extcon_unregister_notifier(udc->edev, EXTCON_USB, &udc->nb);
228exit_phy:
229 if (udc->udc_phy) {
230 phy_power_off(udc->udc_phy);
231 phy_exit(udc->udc_phy);
232 }
233 return ret;
234}
235
236static int udc_plat_remove(struct platform_device *pdev)
237{
238 struct udc *dev;
239
240 dev = platform_get_drvdata(pdev);
241
242 usb_del_gadget_udc(&dev->gadget);
243 /* gadget driver must not be registered */
244 if (WARN_ON(dev->driver))
245 return 0;
246
247 /* dma pool cleanup */
248 free_dma_pools(dev);
249
250 udc_remove(dev);
251
252 platform_set_drvdata(pdev, NULL);
253
254 if (dev->drd_wq) {
255 flush_workqueue(dev->drd_wq);
256 destroy_workqueue(dev->drd_wq);
257 }
258
259 phy_power_off(dev->udc_phy);
260 phy_exit(dev->udc_phy);
261 extcon_unregister_notifier(dev->edev, EXTCON_USB, &dev->nb);
262
263 dev_info(&pdev->dev, "Synopsys UDC platform driver removed\n");
264
265 return 0;
266}
267
268#ifdef CONFIG_PM_SLEEP
269static int udc_plat_suspend(struct device *dev)
270{
271 struct udc *udc;
272
273 udc = dev_get_drvdata(dev);
274 stop_udc(udc);
275
276 if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) {
277 dev_dbg(udc->dev, "device -> idle\n");
278 stop_udc(udc);
279 }
280 phy_power_off(udc->udc_phy);
281 phy_exit(udc->udc_phy);
282
283 return 0;
284}
285
286static int udc_plat_resume(struct device *dev)
287{
288 struct udc *udc;
289 int ret;
290
291 udc = dev_get_drvdata(dev);
292
293 ret = phy_init(udc->udc_phy);
294 if (ret) {
295 dev_err(udc->dev, "UDC phy init failure");
296 return ret;
297 }
298
299 ret = phy_power_on(udc->udc_phy);
300 if (ret) {
301 dev_err(udc->dev, "UDC phy power on failure");
302 phy_exit(udc->udc_phy);
303 return ret;
304 }
305
306 if (extcon_get_cable_state_(udc->edev, EXTCON_USB) > 0) {
307 dev_dbg(udc->dev, "idle -> device\n");
308 start_udc(udc);
309 }
310
311 return 0;
312}
313static const struct dev_pm_ops udc_plat_pm_ops = {
314 .suspend = udc_plat_suspend,
315 .resume = udc_plat_resume,
316};
317#endif
318
319#if defined(CONFIG_OF)
320static const struct of_device_id of_udc_match[] = {
321 { .compatible = "brcm,ns2-udc", },
322 { .compatible = "brcm,cygnus-udc", },
323 { .compatible = "brcm,iproc-udc", },
324 { }
325};
326MODULE_DEVICE_TABLE(of, of_udc_match);
327#endif
328
329static struct platform_driver udc_plat_driver = {
330 .probe = udc_plat_probe,
331 .remove = udc_plat_remove,
332 .driver = {
333 .name = "snps-udc-plat",
334 .of_match_table = of_match_ptr(of_udc_match),
335#ifdef CONFIG_PM_SLEEP
336 .pm = &udc_plat_pm_ops,
337#endif
338 },
339};
340module_platform_driver(udc_plat_driver);
341
342MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
343MODULE_AUTHOR("Broadcom");
344MODULE_LICENSE("GPL v2");