xref: /linux/drivers/usb/dwc3/dwc3-omap.c (revision ff5599816711d2e67da2d7561fd36ac48debd433)
1 /**
2  * dwc3-omap.c - OMAP Specific Glue layer
3  *
4  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
5  *
6  * Authors: Felipe Balbi <balbi@ti.com>,
7  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions, and the following disclaimer,
14  *    without modification.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The names of the above-listed copyright holders may not be used
19  *    to endorse or promote products derived from this software without
20  *    specific prior written permission.
21  *
22  * ALTERNATIVELY, this software may be distributed under the terms of the
23  * GNU General Public License ("GPL") version 2, as published by the Free
24  * Software Foundation.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
27  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
28  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
30  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <linux/module.h>
40 #include <linux/kernel.h>
41 #include <linux/slab.h>
42 #include <linux/interrupt.h>
43 #include <linux/spinlock.h>
44 #include <linux/platform_device.h>
45 #include <linux/platform_data/dwc3-omap.h>
46 #include <linux/usb/dwc3-omap.h>
47 #include <linux/pm_runtime.h>
48 #include <linux/dma-mapping.h>
49 #include <linux/ioport.h>
50 #include <linux/io.h>
51 #include <linux/of.h>
52 #include <linux/of_platform.h>
53 
54 #include <linux/usb/otg.h>
55 
56 /*
57  * All these registers belong to OMAP's Wrapper around the
58  * DesignWare USB3 Core.
59  */
60 
61 #define USBOTGSS_REVISION			0x0000
62 #define USBOTGSS_SYSCONFIG			0x0010
63 #define USBOTGSS_IRQ_EOI			0x0020
64 #define USBOTGSS_EOI_OFFSET			0x0008
65 #define USBOTGSS_IRQSTATUS_RAW_0		0x0024
66 #define USBOTGSS_IRQSTATUS_0			0x0028
67 #define USBOTGSS_IRQENABLE_SET_0		0x002c
68 #define USBOTGSS_IRQENABLE_CLR_0		0x0030
69 #define USBOTGSS_IRQ0_OFFSET			0x0004
70 #define USBOTGSS_IRQSTATUS_RAW_1		0x0030
71 #define USBOTGSS_IRQSTATUS_1			0x0034
72 #define USBOTGSS_IRQENABLE_SET_1		0x0038
73 #define USBOTGSS_IRQENABLE_CLR_1		0x003c
74 #define USBOTGSS_IRQSTATUS_RAW_2		0x0040
75 #define USBOTGSS_IRQSTATUS_2			0x0044
76 #define USBOTGSS_IRQENABLE_SET_2		0x0048
77 #define USBOTGSS_IRQENABLE_CLR_2		0x004c
78 #define USBOTGSS_IRQSTATUS_RAW_3		0x0050
79 #define USBOTGSS_IRQSTATUS_3			0x0054
80 #define USBOTGSS_IRQENABLE_SET_3		0x0058
81 #define USBOTGSS_IRQENABLE_CLR_3		0x005c
82 #define USBOTGSS_IRQSTATUS_EOI_MISC		0x0030
83 #define USBOTGSS_IRQSTATUS_RAW_MISC		0x0034
84 #define USBOTGSS_IRQSTATUS_MISC			0x0038
85 #define USBOTGSS_IRQENABLE_SET_MISC		0x003c
86 #define USBOTGSS_IRQENABLE_CLR_MISC		0x0040
87 #define USBOTGSS_IRQMISC_OFFSET			0x03fc
88 #define USBOTGSS_UTMI_OTG_CTRL			0x0080
89 #define USBOTGSS_UTMI_OTG_STATUS		0x0084
90 #define USBOTGSS_UTMI_OTG_OFFSET		0x0480
91 #define USBOTGSS_TXFIFO_DEPTH			0x0508
92 #define USBOTGSS_RXFIFO_DEPTH			0x050c
93 #define USBOTGSS_MMRAM_OFFSET			0x0100
94 #define USBOTGSS_FLADJ				0x0104
95 #define USBOTGSS_DEBUG_CFG			0x0108
96 #define USBOTGSS_DEBUG_DATA			0x010c
97 #define USBOTGSS_DEV_EBC_EN			0x0110
98 #define USBOTGSS_DEBUG_OFFSET			0x0600
99 
100 /* REVISION REGISTER */
101 #define USBOTGSS_REVISION_XMAJOR(reg)		((reg >> 8) & 0x7)
102 #define USBOTGSS_REVISION_XMAJOR1		1
103 #define USBOTGSS_REVISION_XMAJOR2		2
104 /* SYSCONFIG REGISTER */
105 #define USBOTGSS_SYSCONFIG_DMADISABLE		(1 << 16)
106 
107 /* IRQ_EOI REGISTER */
108 #define USBOTGSS_IRQ_EOI_LINE_NUMBER		(1 << 0)
109 
110 /* IRQS0 BITS */
111 #define USBOTGSS_IRQO_COREIRQ_ST		(1 << 0)
112 
113 /* IRQMISC BITS */
114 #define USBOTGSS_IRQMISC_DMADISABLECLR		(1 << 17)
115 #define USBOTGSS_IRQMISC_OEVT			(1 << 16)
116 #define USBOTGSS_IRQMISC_DRVVBUS_RISE		(1 << 13)
117 #define USBOTGSS_IRQMISC_CHRGVBUS_RISE		(1 << 12)
118 #define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE	(1 << 11)
119 #define USBOTGSS_IRQMISC_IDPULLUP_RISE		(1 << 8)
120 #define USBOTGSS_IRQMISC_DRVVBUS_FALL		(1 << 5)
121 #define USBOTGSS_IRQMISC_CHRGVBUS_FALL		(1 << 4)
122 #define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL		(1 << 3)
123 #define USBOTGSS_IRQMISC_IDPULLUP_FALL		(1 << 0)
124 
125 /* UTMI_OTG_CTRL REGISTER */
126 #define USBOTGSS_UTMI_OTG_CTRL_DRVVBUS		(1 << 5)
127 #define USBOTGSS_UTMI_OTG_CTRL_CHRGVBUS		(1 << 4)
128 #define USBOTGSS_UTMI_OTG_CTRL_DISCHRGVBUS	(1 << 3)
129 #define USBOTGSS_UTMI_OTG_CTRL_IDPULLUP		(1 << 0)
130 
131 /* UTMI_OTG_STATUS REGISTER */
132 #define USBOTGSS_UTMI_OTG_STATUS_SW_MODE	(1 << 31)
133 #define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT	(1 << 9)
134 #define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE (1 << 8)
135 #define USBOTGSS_UTMI_OTG_STATUS_IDDIG		(1 << 4)
136 #define USBOTGSS_UTMI_OTG_STATUS_SESSEND	(1 << 3)
137 #define USBOTGSS_UTMI_OTG_STATUS_SESSVALID	(1 << 2)
138 #define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID	(1 << 1)
139 
140 struct dwc3_omap {
141 	/* device lock */
142 	spinlock_t		lock;
143 
144 	struct device		*dev;
145 
146 	int			irq;
147 	void __iomem		*base;
148 
149 	u32			utmi_otg_status;
150 	u32			utmi_otg_offset;
151 	u32			irqmisc_offset;
152 	u32			irq_eoi_offset;
153 	u32			debug_offset;
154 	u32			irq0_offset;
155 	u32			revision;
156 
157 	u32			dma_status:1;
158 };
159 
160 static struct dwc3_omap		*_omap;
161 
162 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
163 {
164 	return readl(base + offset);
165 }
166 
167 static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
168 {
169 	writel(value, base + offset);
170 }
171 
172 static u32 dwc3_omap_read_utmi_status(struct dwc3_omap *omap)
173 {
174 	return dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS +
175 							omap->utmi_otg_offset);
176 }
177 
178 static void dwc3_omap_write_utmi_status(struct dwc3_omap *omap, u32 value)
179 {
180 	dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS +
181 					omap->utmi_otg_offset, value);
182 
183 }
184 
185 static u32 dwc3_omap_read_irq0_status(struct dwc3_omap *omap)
186 {
187 	return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_0 -
188 						omap->irq0_offset);
189 }
190 
191 static void dwc3_omap_write_irq0_status(struct dwc3_omap *omap, u32 value)
192 {
193 	dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0 -
194 						omap->irq0_offset, value);
195 
196 }
197 
198 static u32 dwc3_omap_read_irqmisc_status(struct dwc3_omap *omap)
199 {
200 	return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_MISC +
201 						omap->irqmisc_offset);
202 }
203 
204 static void dwc3_omap_write_irqmisc_status(struct dwc3_omap *omap, u32 value)
205 {
206 	dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_MISC +
207 					omap->irqmisc_offset, value);
208 
209 }
210 
211 static void dwc3_omap_write_irqmisc_set(struct dwc3_omap *omap, u32 value)
212 {
213 	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_MISC +
214 						omap->irqmisc_offset, value);
215 
216 }
217 
218 static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value)
219 {
220 	dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0 -
221 						omap->irq0_offset, value);
222 }
223 
224 int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
225 {
226 	u32			val;
227 	struct dwc3_omap	*omap = _omap;
228 
229 	if (!omap)
230 		return -EPROBE_DEFER;
231 
232 	switch (status) {
233 	case OMAP_DWC3_ID_GROUND:
234 		dev_dbg(omap->dev, "ID GND\n");
235 
236 		val = dwc3_omap_read_utmi_status(omap);
237 		val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
238 				| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
239 				| USBOTGSS_UTMI_OTG_STATUS_SESSEND);
240 		val |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID
241 				| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
242 		dwc3_omap_write_utmi_status(omap, val);
243 		break;
244 
245 	case OMAP_DWC3_VBUS_VALID:
246 		dev_dbg(omap->dev, "VBUS Connect\n");
247 
248 		val = dwc3_omap_read_utmi_status(omap);
249 		val &= ~USBOTGSS_UTMI_OTG_STATUS_SESSEND;
250 		val |= USBOTGSS_UTMI_OTG_STATUS_IDDIG
251 				| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
252 				| USBOTGSS_UTMI_OTG_STATUS_SESSVALID
253 				| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
254 		dwc3_omap_write_utmi_status(omap, val);
255 		break;
256 
257 	case OMAP_DWC3_ID_FLOAT:
258 	case OMAP_DWC3_VBUS_OFF:
259 		dev_dbg(omap->dev, "VBUS Disconnect\n");
260 
261 		val = dwc3_omap_read_utmi_status(omap);
262 		val &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSVALID
263 				| USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
264 				| USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT);
265 		val |= USBOTGSS_UTMI_OTG_STATUS_SESSEND
266 				| USBOTGSS_UTMI_OTG_STATUS_IDDIG;
267 		dwc3_omap_write_utmi_status(omap, val);
268 		break;
269 
270 	default:
271 		dev_dbg(omap->dev, "ID float\n");
272 	}
273 
274 	return 0;
275 }
276 EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
277 
278 static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
279 {
280 	struct dwc3_omap	*omap = _omap;
281 	u32			reg;
282 
283 	spin_lock(&omap->lock);
284 
285 	reg = dwc3_omap_read_irqmisc_status(omap);
286 
287 	if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) {
288 		dev_dbg(omap->dev, "DMA Disable was Cleared\n");
289 		omap->dma_status = false;
290 	}
291 
292 	if (reg & USBOTGSS_IRQMISC_OEVT)
293 		dev_dbg(omap->dev, "OTG Event\n");
294 
295 	if (reg & USBOTGSS_IRQMISC_DRVVBUS_RISE)
296 		dev_dbg(omap->dev, "DRVVBUS Rise\n");
297 
298 	if (reg & USBOTGSS_IRQMISC_CHRGVBUS_RISE)
299 		dev_dbg(omap->dev, "CHRGVBUS Rise\n");
300 
301 	if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_RISE)
302 		dev_dbg(omap->dev, "DISCHRGVBUS Rise\n");
303 
304 	if (reg & USBOTGSS_IRQMISC_IDPULLUP_RISE)
305 		dev_dbg(omap->dev, "IDPULLUP Rise\n");
306 
307 	if (reg & USBOTGSS_IRQMISC_DRVVBUS_FALL)
308 		dev_dbg(omap->dev, "DRVVBUS Fall\n");
309 
310 	if (reg & USBOTGSS_IRQMISC_CHRGVBUS_FALL)
311 		dev_dbg(omap->dev, "CHRGVBUS Fall\n");
312 
313 	if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_FALL)
314 		dev_dbg(omap->dev, "DISCHRGVBUS Fall\n");
315 
316 	if (reg & USBOTGSS_IRQMISC_IDPULLUP_FALL)
317 		dev_dbg(omap->dev, "IDPULLUP Fall\n");
318 
319 	dwc3_omap_write_irqmisc_status(omap, reg);
320 
321 	reg = dwc3_omap_read_irq0_status(omap);
322 
323 	dwc3_omap_write_irq0_status(omap, reg);
324 
325 	spin_unlock(&omap->lock);
326 
327 	return IRQ_HANDLED;
328 }
329 
330 static int dwc3_omap_remove_core(struct device *dev, void *c)
331 {
332 	struct platform_device *pdev = to_platform_device(dev);
333 
334 	platform_device_unregister(pdev);
335 
336 	return 0;
337 }
338 
339 static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
340 {
341 	u32			reg;
342 
343 	/* enable all IRQs */
344 	reg = USBOTGSS_IRQO_COREIRQ_ST;
345 	dwc3_omap_write_irq0_set(omap, reg);
346 
347 	reg = (USBOTGSS_IRQMISC_OEVT |
348 			USBOTGSS_IRQMISC_DRVVBUS_RISE |
349 			USBOTGSS_IRQMISC_CHRGVBUS_RISE |
350 			USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
351 			USBOTGSS_IRQMISC_IDPULLUP_RISE |
352 			USBOTGSS_IRQMISC_DRVVBUS_FALL |
353 			USBOTGSS_IRQMISC_CHRGVBUS_FALL |
354 			USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
355 			USBOTGSS_IRQMISC_IDPULLUP_FALL);
356 
357 	dwc3_omap_write_irqmisc_set(omap, reg);
358 }
359 
360 static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
361 {
362 	/* disable all IRQs */
363 	dwc3_omap_write_irqmisc_set(omap, 0x00);
364 	dwc3_omap_write_irq0_set(omap, 0x00);
365 }
366 
367 static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
368 
369 static int dwc3_omap_probe(struct platform_device *pdev)
370 {
371 	struct device_node	*node = pdev->dev.of_node;
372 
373 	struct dwc3_omap	*omap;
374 	struct resource		*res;
375 	struct device		*dev = &pdev->dev;
376 
377 	int			ret = -ENOMEM;
378 	int			irq;
379 
380 	int			utmi_mode = 0;
381 	int			x_major;
382 
383 	u32			reg;
384 
385 	void __iomem		*base;
386 
387 	if (!node) {
388 		dev_err(dev, "device node not found\n");
389 		return -EINVAL;
390 	}
391 
392 	omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
393 	if (!omap) {
394 		dev_err(dev, "not enough memory\n");
395 		return -ENOMEM;
396 	}
397 
398 	platform_set_drvdata(pdev, omap);
399 
400 	irq = platform_get_irq(pdev, 0);
401 	if (irq < 0) {
402 		dev_err(dev, "missing IRQ resource\n");
403 		return -EINVAL;
404 	}
405 
406 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
407 	if (!res) {
408 		dev_err(dev, "missing memory base resource\n");
409 		return -EINVAL;
410 	}
411 
412 	base = devm_ioremap_nocache(dev, res->start, resource_size(res));
413 	if (!base) {
414 		dev_err(dev, "ioremap failed\n");
415 		return -ENOMEM;
416 	}
417 
418 	spin_lock_init(&omap->lock);
419 
420 	omap->dev	= dev;
421 	omap->irq	= irq;
422 	omap->base	= base;
423 	dev->dma_mask	= &dwc3_omap_dma_mask;
424 
425 	/*
426 	 * REVISIT if we ever have two instances of the wrapper, we will be
427 	 * in big trouble
428 	 */
429 	_omap	= omap;
430 
431 	pm_runtime_enable(dev);
432 	ret = pm_runtime_get_sync(dev);
433 	if (ret < 0) {
434 		dev_err(dev, "get_sync failed with err %d\n", ret);
435 		goto err0;
436 	}
437 
438 	reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION);
439 	omap->revision = reg;
440 	x_major = USBOTGSS_REVISION_XMAJOR(reg);
441 
442 	/* Differentiate between OMAP5 and AM437x */
443 	switch (x_major) {
444 	case USBOTGSS_REVISION_XMAJOR1:
445 	case USBOTGSS_REVISION_XMAJOR2:
446 		omap->irq_eoi_offset = 0;
447 		omap->irq0_offset = 0;
448 		omap->irqmisc_offset = 0;
449 		omap->utmi_otg_offset = 0;
450 		omap->debug_offset = 0;
451 		break;
452 	default:
453 		/* Default to the latest revision */
454 		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
455 		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
456 		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
457 		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
458 		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
459 		break;
460 	}
461 
462 	/* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are
463 	 * changes in wrapper registers, Using dt compatible for aegis
464 	 */
465 
466 	if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
467 		omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
468 		omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
469 		omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
470 		omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
471 		omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
472 	}
473 
474 	reg = dwc3_omap_read_utmi_status(omap);
475 
476 	of_property_read_u32(node, "utmi-mode", &utmi_mode);
477 
478 	switch (utmi_mode) {
479 	case DWC3_OMAP_UTMI_MODE_SW:
480 		reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
481 		break;
482 	case DWC3_OMAP_UTMI_MODE_HW:
483 		reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
484 		break;
485 	default:
486 		dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
487 	}
488 
489 	dwc3_omap_write_utmi_status(omap, reg);
490 
491 	/* check the DMA Status */
492 	reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
493 	omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
494 
495 	ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
496 			"dwc3-omap", omap);
497 	if (ret) {
498 		dev_err(dev, "failed to request IRQ #%d --> %d\n",
499 				omap->irq, ret);
500 		goto err1;
501 	}
502 
503 	dwc3_omap_enable_irqs(omap);
504 
505 	ret = of_platform_populate(node, NULL, NULL, dev);
506 	if (ret) {
507 		dev_err(&pdev->dev, "failed to create dwc3 core\n");
508 		goto err2;
509 	}
510 
511 	return 0;
512 
513 err2:
514 	dwc3_omap_disable_irqs(omap);
515 
516 err1:
517 	pm_runtime_put_sync(dev);
518 
519 err0:
520 	pm_runtime_disable(dev);
521 
522 	return ret;
523 }
524 
525 static int dwc3_omap_remove(struct platform_device *pdev)
526 {
527 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
528 
529 	dwc3_omap_disable_irqs(omap);
530 	pm_runtime_put_sync(&pdev->dev);
531 	pm_runtime_disable(&pdev->dev);
532 	device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
533 
534 	return 0;
535 }
536 
537 static const struct of_device_id of_dwc3_match[] = {
538 	{
539 		.compatible =	"ti,dwc3"
540 	},
541 	{
542 		.compatible =	"ti,am437x-dwc3"
543 	},
544 	{ },
545 };
546 MODULE_DEVICE_TABLE(of, of_dwc3_match);
547 
548 #ifdef CONFIG_PM_SLEEP
549 static int dwc3_omap_prepare(struct device *dev)
550 {
551 	struct dwc3_omap	*omap = dev_get_drvdata(dev);
552 
553 	dwc3_omap_disable_irqs(omap);
554 
555 	return 0;
556 }
557 
558 static void dwc3_omap_complete(struct device *dev)
559 {
560 	struct dwc3_omap	*omap = dev_get_drvdata(dev);
561 
562 	dwc3_omap_enable_irqs(omap);
563 }
564 
565 static int dwc3_omap_suspend(struct device *dev)
566 {
567 	struct dwc3_omap	*omap = dev_get_drvdata(dev);
568 
569 	omap->utmi_otg_status = dwc3_omap_read_utmi_status(omap);
570 
571 	return 0;
572 }
573 
574 static int dwc3_omap_resume(struct device *dev)
575 {
576 	struct dwc3_omap	*omap = dev_get_drvdata(dev);
577 
578 	dwc3_omap_write_utmi_status(omap, omap->utmi_otg_status);
579 
580 	pm_runtime_disable(dev);
581 	pm_runtime_set_active(dev);
582 	pm_runtime_enable(dev);
583 
584 	return 0;
585 }
586 
587 static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
588 	.prepare	= dwc3_omap_prepare,
589 	.complete	= dwc3_omap_complete,
590 
591 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
592 };
593 
594 #define DEV_PM_OPS	(&dwc3_omap_dev_pm_ops)
595 #else
596 #define DEV_PM_OPS	NULL
597 #endif /* CONFIG_PM_SLEEP */
598 
599 static struct platform_driver dwc3_omap_driver = {
600 	.probe		= dwc3_omap_probe,
601 	.remove		= dwc3_omap_remove,
602 	.driver		= {
603 		.name	= "omap-dwc3",
604 		.of_match_table	= of_dwc3_match,
605 		.pm	= DEV_PM_OPS,
606 	},
607 };
608 
609 module_platform_driver(dwc3_omap_driver);
610 
611 MODULE_ALIAS("platform:omap-dwc3");
612 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
613 MODULE_LICENSE("Dual BSD/GPL");
614 MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");
615