xref: /openbmc/linux/drivers/usb/dwc3/core.c (revision fc8bb91b)
172246da4SFelipe Balbi /**
272246da4SFelipe Balbi  * core.c - DesignWare USB3 DRD Controller Core file
372246da4SFelipe Balbi  *
472246da4SFelipe Balbi  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
572246da4SFelipe Balbi  *
672246da4SFelipe Balbi  * Authors: Felipe Balbi <balbi@ti.com>,
772246da4SFelipe Balbi  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
872246da4SFelipe Balbi  *
95945f789SFelipe Balbi  * This program is free software: you can redistribute it and/or modify
105945f789SFelipe Balbi  * it under the terms of the GNU General Public License version 2  of
115945f789SFelipe Balbi  * the License as published by the Free Software Foundation.
1272246da4SFelipe Balbi  *
135945f789SFelipe Balbi  * This program is distributed in the hope that it will be useful,
145945f789SFelipe Balbi  * but WITHOUT ANY WARRANTY; without even the implied warranty of
155945f789SFelipe Balbi  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
165945f789SFelipe Balbi  * GNU General Public License for more details.
1772246da4SFelipe Balbi  *
185945f789SFelipe Balbi  * You should have received a copy of the GNU General Public License
195945f789SFelipe Balbi  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
2072246da4SFelipe Balbi  */
2172246da4SFelipe Balbi 
22fa0ea13eSFelipe Balbi #include <linux/version.h>
23a72e658bSFelipe Balbi #include <linux/module.h>
2472246da4SFelipe Balbi #include <linux/kernel.h>
2572246da4SFelipe Balbi #include <linux/slab.h>
2672246da4SFelipe Balbi #include <linux/spinlock.h>
2772246da4SFelipe Balbi #include <linux/platform_device.h>
2872246da4SFelipe Balbi #include <linux/pm_runtime.h>
2972246da4SFelipe Balbi #include <linux/interrupt.h>
3072246da4SFelipe Balbi #include <linux/ioport.h>
3172246da4SFelipe Balbi #include <linux/io.h>
3272246da4SFelipe Balbi #include <linux/list.h>
3372246da4SFelipe Balbi #include <linux/delay.h>
3472246da4SFelipe Balbi #include <linux/dma-mapping.h>
35457e84b6SFelipe Balbi #include <linux/of.h>
36404905a6SHeikki Krogerus #include <linux/acpi.h>
376344475fSSekhar Nori #include <linux/pinctrl/consumer.h>
3872246da4SFelipe Balbi 
3972246da4SFelipe Balbi #include <linux/usb/ch9.h>
4072246da4SFelipe Balbi #include <linux/usb/gadget.h>
41f7e846f0SFelipe Balbi #include <linux/usb/of.h>
42a45c82b8SRuchika Kharwar #include <linux/usb/otg.h>
4372246da4SFelipe Balbi 
446462cbd5SFelipe Balbi #include "platform_data.h"
4572246da4SFelipe Balbi #include "core.h"
4672246da4SFelipe Balbi #include "gadget.h"
4772246da4SFelipe Balbi #include "io.h"
4872246da4SFelipe Balbi 
4972246da4SFelipe Balbi #include "debug.h"
5072246da4SFelipe Balbi 
51fc8bb91bSFelipe Balbi #define DWC3_DEFAULT_AUTOSUSPEND_DELAY	5000 /* ms */
528300dd23SFelipe Balbi 
533140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
543140e8cbSSebastian Andrzej Siewior {
553140e8cbSSebastian Andrzej Siewior 	u32 reg;
563140e8cbSSebastian Andrzej Siewior 
573140e8cbSSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
583140e8cbSSebastian Andrzej Siewior 	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
593140e8cbSSebastian Andrzej Siewior 	reg |= DWC3_GCTL_PRTCAPDIR(mode);
603140e8cbSSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
613140e8cbSSebastian Andrzej Siewior }
628300dd23SFelipe Balbi 
63cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type)
64cf6d867dSFelipe Balbi {
65cf6d867dSFelipe Balbi 	struct dwc3		*dwc = dep->dwc;
66cf6d867dSFelipe Balbi 	u32			reg;
67cf6d867dSFelipe Balbi 
68cf6d867dSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE,
69cf6d867dSFelipe Balbi 			DWC3_GDBGFIFOSPACE_NUM(dep->number) |
70cf6d867dSFelipe Balbi 			DWC3_GDBGFIFOSPACE_TYPE(type));
71cf6d867dSFelipe Balbi 
72cf6d867dSFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE);
73cf6d867dSFelipe Balbi 
74cf6d867dSFelipe Balbi 	return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg);
75cf6d867dSFelipe Balbi }
76cf6d867dSFelipe Balbi 
7772246da4SFelipe Balbi /**
7872246da4SFelipe Balbi  * dwc3_core_soft_reset - Issues core soft reset and PHY reset
7972246da4SFelipe Balbi  * @dwc: pointer to our context structure
8072246da4SFelipe Balbi  */
8157303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc)
8272246da4SFelipe Balbi {
8372246da4SFelipe Balbi 	u32		reg;
84f59dcab1SFelipe Balbi 	int		retries = 1000;
8557303488SKishon Vijay Abraham I 	int		ret;
8672246da4SFelipe Balbi 
8751e1e7bcSFelipe Balbi 	usb_phy_init(dwc->usb2_phy);
8851e1e7bcSFelipe Balbi 	usb_phy_init(dwc->usb3_phy);
8957303488SKishon Vijay Abraham I 	ret = phy_init(dwc->usb2_generic_phy);
9057303488SKishon Vijay Abraham I 	if (ret < 0)
9157303488SKishon Vijay Abraham I 		return ret;
9257303488SKishon Vijay Abraham I 
9357303488SKishon Vijay Abraham I 	ret = phy_init(dwc->usb3_generic_phy);
9457303488SKishon Vijay Abraham I 	if (ret < 0) {
9557303488SKishon Vijay Abraham I 		phy_exit(dwc->usb2_generic_phy);
9657303488SKishon Vijay Abraham I 		return ret;
9757303488SKishon Vijay Abraham I 	}
9872246da4SFelipe Balbi 
99f59dcab1SFelipe Balbi 	/*
100f59dcab1SFelipe Balbi 	 * We're resetting only the device side because, if we're in host mode,
101f59dcab1SFelipe Balbi 	 * XHCI driver will reset the host block. If dwc3 was configured for
102f59dcab1SFelipe Balbi 	 * host-only mode, then we can return early.
103f59dcab1SFelipe Balbi 	 */
104f59dcab1SFelipe Balbi 	if (dwc->dr_mode == USB_DR_MODE_HOST)
10557303488SKishon Vijay Abraham I 		return 0;
106f59dcab1SFelipe Balbi 
107f59dcab1SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
108f59dcab1SFelipe Balbi 	reg |= DWC3_DCTL_CSFTRST;
109f59dcab1SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
110f59dcab1SFelipe Balbi 
111f59dcab1SFelipe Balbi 	do {
112f59dcab1SFelipe Balbi 		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
113f59dcab1SFelipe Balbi 		if (!(reg & DWC3_DCTL_CSFTRST))
114f59dcab1SFelipe Balbi 			return 0;
115f59dcab1SFelipe Balbi 
116f59dcab1SFelipe Balbi 		udelay(1);
117f59dcab1SFelipe Balbi 	} while (--retries);
118f59dcab1SFelipe Balbi 
119f59dcab1SFelipe Balbi 	return -ETIMEDOUT;
12072246da4SFelipe Balbi }
12172246da4SFelipe Balbi 
12272246da4SFelipe Balbi /**
123c5cc74e8SHeikki Krogerus  * dwc3_soft_reset - Issue soft reset
124c5cc74e8SHeikki Krogerus  * @dwc: Pointer to our controller context structure
125c5cc74e8SHeikki Krogerus  */
126c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc)
127c5cc74e8SHeikki Krogerus {
128c5cc74e8SHeikki Krogerus 	unsigned long timeout;
129c5cc74e8SHeikki Krogerus 	u32 reg;
130c5cc74e8SHeikki Krogerus 
131c5cc74e8SHeikki Krogerus 	timeout = jiffies + msecs_to_jiffies(500);
132c5cc74e8SHeikki Krogerus 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
133c5cc74e8SHeikki Krogerus 	do {
134c5cc74e8SHeikki Krogerus 		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
135c5cc74e8SHeikki Krogerus 		if (!(reg & DWC3_DCTL_CSFTRST))
136c5cc74e8SHeikki Krogerus 			break;
137c5cc74e8SHeikki Krogerus 
138c5cc74e8SHeikki Krogerus 		if (time_after(jiffies, timeout)) {
139c5cc74e8SHeikki Krogerus 			dev_err(dwc->dev, "Reset Timed Out\n");
140c5cc74e8SHeikki Krogerus 			return -ETIMEDOUT;
141c5cc74e8SHeikki Krogerus 		}
142c5cc74e8SHeikki Krogerus 
143c5cc74e8SHeikki Krogerus 		cpu_relax();
144c5cc74e8SHeikki Krogerus 	} while (true);
145c5cc74e8SHeikki Krogerus 
146c5cc74e8SHeikki Krogerus 	return 0;
147c5cc74e8SHeikki Krogerus }
148c5cc74e8SHeikki Krogerus 
149db2be4e9SNikhil Badola /*
150db2be4e9SNikhil Badola  * dwc3_frame_length_adjustment - Adjusts frame length if required
151db2be4e9SNikhil Badola  * @dwc3: Pointer to our controller context structure
152db2be4e9SNikhil Badola  */
153bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
154db2be4e9SNikhil Badola {
155db2be4e9SNikhil Badola 	u32 reg;
156db2be4e9SNikhil Badola 	u32 dft;
157db2be4e9SNikhil Badola 
158db2be4e9SNikhil Badola 	if (dwc->revision < DWC3_REVISION_250A)
159db2be4e9SNikhil Badola 		return;
160db2be4e9SNikhil Badola 
161bcdb3272SFelipe Balbi 	if (dwc->fladj == 0)
162db2be4e9SNikhil Badola 		return;
163db2be4e9SNikhil Badola 
164db2be4e9SNikhil Badola 	reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
165db2be4e9SNikhil Badola 	dft = reg & DWC3_GFLADJ_30MHZ_MASK;
166bcdb3272SFelipe Balbi 	if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj,
167db2be4e9SNikhil Badola 	    "request value same as default, ignoring\n")) {
168db2be4e9SNikhil Badola 		reg &= ~DWC3_GFLADJ_30MHZ_MASK;
169bcdb3272SFelipe Balbi 		reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
170db2be4e9SNikhil Badola 		dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
171db2be4e9SNikhil Badola 	}
172db2be4e9SNikhil Badola }
173db2be4e9SNikhil Badola 
174c5cc74e8SHeikki Krogerus /**
17572246da4SFelipe Balbi  * dwc3_free_one_event_buffer - Frees one event buffer
17672246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
17772246da4SFelipe Balbi  * @evt: Pointer to event buffer to be freed
17872246da4SFelipe Balbi  */
17972246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
18072246da4SFelipe Balbi 		struct dwc3_event_buffer *evt)
18172246da4SFelipe Balbi {
18272246da4SFelipe Balbi 	dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
18372246da4SFelipe Balbi }
18472246da4SFelipe Balbi 
18572246da4SFelipe Balbi /**
1861d046793SPaul Zimmerman  * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
18772246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
18872246da4SFelipe Balbi  * @length: size of the event buffer
18972246da4SFelipe Balbi  *
1901d046793SPaul Zimmerman  * Returns a pointer to the allocated event buffer structure on success
19172246da4SFelipe Balbi  * otherwise ERR_PTR(errno).
19272246da4SFelipe Balbi  */
19367d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
19467d0b500SFelipe Balbi 		unsigned length)
19572246da4SFelipe Balbi {
19672246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
19772246da4SFelipe Balbi 
198380f0d28SFelipe Balbi 	evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
19972246da4SFelipe Balbi 	if (!evt)
20072246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
20172246da4SFelipe Balbi 
20272246da4SFelipe Balbi 	evt->dwc	= dwc;
20372246da4SFelipe Balbi 	evt->length	= length;
20472246da4SFelipe Balbi 	evt->buf	= dma_alloc_coherent(dwc->dev, length,
20572246da4SFelipe Balbi 			&evt->dma, GFP_KERNEL);
206e32672f0SFelipe Balbi 	if (!evt->buf)
20772246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
20872246da4SFelipe Balbi 
20972246da4SFelipe Balbi 	return evt;
21072246da4SFelipe Balbi }
21172246da4SFelipe Balbi 
21272246da4SFelipe Balbi /**
21372246da4SFelipe Balbi  * dwc3_free_event_buffers - frees all allocated event buffers
21472246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
21572246da4SFelipe Balbi  */
21672246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc)
21772246da4SFelipe Balbi {
21872246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
21972246da4SFelipe Balbi 
220696c8b12SFelipe Balbi 	evt = dwc->ev_buf;
22164b6c8a7SAnton Tikhomirov 	if (evt)
22272246da4SFelipe Balbi 		dwc3_free_one_event_buffer(dwc, evt);
22372246da4SFelipe Balbi }
22472246da4SFelipe Balbi 
22572246da4SFelipe Balbi /**
22672246da4SFelipe Balbi  * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
2271d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
22872246da4SFelipe Balbi  * @length: size of event buffer
22972246da4SFelipe Balbi  *
2301d046793SPaul Zimmerman  * Returns 0 on success otherwise negative errno. In the error case, dwc
23172246da4SFelipe Balbi  * may contain some buffers allocated but not all which were requested.
23272246da4SFelipe Balbi  */
23341ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
23472246da4SFelipe Balbi {
23572246da4SFelipe Balbi 	struct dwc3_event_buffer *evt;
23672246da4SFelipe Balbi 
23772246da4SFelipe Balbi 	evt = dwc3_alloc_one_event_buffer(dwc, length);
23872246da4SFelipe Balbi 	if (IS_ERR(evt)) {
23972246da4SFelipe Balbi 		dev_err(dwc->dev, "can't allocate event buffer\n");
24072246da4SFelipe Balbi 		return PTR_ERR(evt);
24172246da4SFelipe Balbi 	}
242696c8b12SFelipe Balbi 	dwc->ev_buf = evt;
24372246da4SFelipe Balbi 
24472246da4SFelipe Balbi 	return 0;
24572246da4SFelipe Balbi }
24672246da4SFelipe Balbi 
24772246da4SFelipe Balbi /**
24872246da4SFelipe Balbi  * dwc3_event_buffers_setup - setup our allocated event buffers
2491d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
25072246da4SFelipe Balbi  *
25172246da4SFelipe Balbi  * Returns 0 on success otherwise negative errno.
25272246da4SFelipe Balbi  */
2537acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc)
25472246da4SFelipe Balbi {
25572246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
25672246da4SFelipe Balbi 
257696c8b12SFelipe Balbi 	evt = dwc->ev_buf;
2581407bf13SFelipe Balbi 	dwc3_trace(trace_dwc3_core,
2591407bf13SFelipe Balbi 			"Event buf %p dma %08llx length %d\n",
26072246da4SFelipe Balbi 			evt->buf, (unsigned long long) evt->dma,
26172246da4SFelipe Balbi 			evt->length);
26272246da4SFelipe Balbi 
2637acd85e0SPaul Zimmerman 	evt->lpos = 0;
2647acd85e0SPaul Zimmerman 
265660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
26672246da4SFelipe Balbi 			lower_32_bits(evt->dma));
267660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0),
26872246da4SFelipe Balbi 			upper_32_bits(evt->dma));
269660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
27068d6a01bSFelipe Balbi 			DWC3_GEVNTSIZ_SIZE(evt->length));
271660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);
27272246da4SFelipe Balbi 
27372246da4SFelipe Balbi 	return 0;
27472246da4SFelipe Balbi }
27572246da4SFelipe Balbi 
27672246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
27772246da4SFelipe Balbi {
27872246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
27972246da4SFelipe Balbi 
280696c8b12SFelipe Balbi 	evt = dwc->ev_buf;
2817acd85e0SPaul Zimmerman 
2827acd85e0SPaul Zimmerman 	evt->lpos = 0;
2837acd85e0SPaul Zimmerman 
284660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0);
285660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0);
286660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK
28768d6a01bSFelipe Balbi 			| DWC3_GEVNTSIZ_SIZE(0));
288660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);
28972246da4SFelipe Balbi }
29072246da4SFelipe Balbi 
2910ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
2920ffcaf37SFelipe Balbi {
2930ffcaf37SFelipe Balbi 	if (!dwc->has_hibernation)
2940ffcaf37SFelipe Balbi 		return 0;
2950ffcaf37SFelipe Balbi 
2960ffcaf37SFelipe Balbi 	if (!dwc->nr_scratch)
2970ffcaf37SFelipe Balbi 		return 0;
2980ffcaf37SFelipe Balbi 
2990ffcaf37SFelipe Balbi 	dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
3000ffcaf37SFelipe Balbi 			DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
3010ffcaf37SFelipe Balbi 	if (!dwc->scratchbuf)
3020ffcaf37SFelipe Balbi 		return -ENOMEM;
3030ffcaf37SFelipe Balbi 
3040ffcaf37SFelipe Balbi 	return 0;
3050ffcaf37SFelipe Balbi }
3060ffcaf37SFelipe Balbi 
3070ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
3080ffcaf37SFelipe Balbi {
3090ffcaf37SFelipe Balbi 	dma_addr_t scratch_addr;
3100ffcaf37SFelipe Balbi 	u32 param;
3110ffcaf37SFelipe Balbi 	int ret;
3120ffcaf37SFelipe Balbi 
3130ffcaf37SFelipe Balbi 	if (!dwc->has_hibernation)
3140ffcaf37SFelipe Balbi 		return 0;
3150ffcaf37SFelipe Balbi 
3160ffcaf37SFelipe Balbi 	if (!dwc->nr_scratch)
3170ffcaf37SFelipe Balbi 		return 0;
3180ffcaf37SFelipe Balbi 
3190ffcaf37SFelipe Balbi 	 /* should never fall here */
3200ffcaf37SFelipe Balbi 	if (!WARN_ON(dwc->scratchbuf))
3210ffcaf37SFelipe Balbi 		return 0;
3220ffcaf37SFelipe Balbi 
3230ffcaf37SFelipe Balbi 	scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf,
3240ffcaf37SFelipe Balbi 			dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
3250ffcaf37SFelipe Balbi 			DMA_BIDIRECTIONAL);
3260ffcaf37SFelipe Balbi 	if (dma_mapping_error(dwc->dev, scratch_addr)) {
3270ffcaf37SFelipe Balbi 		dev_err(dwc->dev, "failed to map scratch buffer\n");
3280ffcaf37SFelipe Balbi 		ret = -EFAULT;
3290ffcaf37SFelipe Balbi 		goto err0;
3300ffcaf37SFelipe Balbi 	}
3310ffcaf37SFelipe Balbi 
3320ffcaf37SFelipe Balbi 	dwc->scratch_addr = scratch_addr;
3330ffcaf37SFelipe Balbi 
3340ffcaf37SFelipe Balbi 	param = lower_32_bits(scratch_addr);
3350ffcaf37SFelipe Balbi 
3360ffcaf37SFelipe Balbi 	ret = dwc3_send_gadget_generic_command(dwc,
3370ffcaf37SFelipe Balbi 			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
3380ffcaf37SFelipe Balbi 	if (ret < 0)
3390ffcaf37SFelipe Balbi 		goto err1;
3400ffcaf37SFelipe Balbi 
3410ffcaf37SFelipe Balbi 	param = upper_32_bits(scratch_addr);
3420ffcaf37SFelipe Balbi 
3430ffcaf37SFelipe Balbi 	ret = dwc3_send_gadget_generic_command(dwc,
3440ffcaf37SFelipe Balbi 			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
3450ffcaf37SFelipe Balbi 	if (ret < 0)
3460ffcaf37SFelipe Balbi 		goto err1;
3470ffcaf37SFelipe Balbi 
3480ffcaf37SFelipe Balbi 	return 0;
3490ffcaf37SFelipe Balbi 
3500ffcaf37SFelipe Balbi err1:
3510ffcaf37SFelipe Balbi 	dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
3520ffcaf37SFelipe Balbi 			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
3530ffcaf37SFelipe Balbi 
3540ffcaf37SFelipe Balbi err0:
3550ffcaf37SFelipe Balbi 	return ret;
3560ffcaf37SFelipe Balbi }
3570ffcaf37SFelipe Balbi 
3580ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
3590ffcaf37SFelipe Balbi {
3600ffcaf37SFelipe Balbi 	if (!dwc->has_hibernation)
3610ffcaf37SFelipe Balbi 		return;
3620ffcaf37SFelipe Balbi 
3630ffcaf37SFelipe Balbi 	if (!dwc->nr_scratch)
3640ffcaf37SFelipe Balbi 		return;
3650ffcaf37SFelipe Balbi 
3660ffcaf37SFelipe Balbi 	 /* should never fall here */
3670ffcaf37SFelipe Balbi 	if (!WARN_ON(dwc->scratchbuf))
3680ffcaf37SFelipe Balbi 		return;
3690ffcaf37SFelipe Balbi 
3700ffcaf37SFelipe Balbi 	dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
3710ffcaf37SFelipe Balbi 			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
3720ffcaf37SFelipe Balbi 	kfree(dwc->scratchbuf);
3730ffcaf37SFelipe Balbi }
3740ffcaf37SFelipe Balbi 
375789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc)
376789451f6SFelipe Balbi {
377789451f6SFelipe Balbi 	struct dwc3_hwparams	*parms = &dwc->hwparams;
378789451f6SFelipe Balbi 
379789451f6SFelipe Balbi 	dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
380789451f6SFelipe Balbi 	dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
381789451f6SFelipe Balbi 
38273815280SFelipe Balbi 	dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints",
383789451f6SFelipe Balbi 			dwc->num_in_eps, dwc->num_out_eps);
384789451f6SFelipe Balbi }
385789451f6SFelipe Balbi 
38641ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc)
38726ceca97SFelipe Balbi {
38826ceca97SFelipe Balbi 	struct dwc3_hwparams	*parms = &dwc->hwparams;
38926ceca97SFelipe Balbi 
39026ceca97SFelipe Balbi 	parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
39126ceca97SFelipe Balbi 	parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
39226ceca97SFelipe Balbi 	parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
39326ceca97SFelipe Balbi 	parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
39426ceca97SFelipe Balbi 	parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
39526ceca97SFelipe Balbi 	parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
39626ceca97SFelipe Balbi 	parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
39726ceca97SFelipe Balbi 	parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
39826ceca97SFelipe Balbi 	parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
39926ceca97SFelipe Balbi }
40026ceca97SFelipe Balbi 
40172246da4SFelipe Balbi /**
402b5a65c40SHuang Rui  * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
403b5a65c40SHuang Rui  * @dwc: Pointer to our controller context structure
40488bc9d19SHeikki Krogerus  *
40588bc9d19SHeikki Krogerus  * Returns 0 on success. The USB PHY interfaces are configured but not
40688bc9d19SHeikki Krogerus  * initialized. The PHY interfaces and the PHYs get initialized together with
40788bc9d19SHeikki Krogerus  * the core in dwc3_core_init.
408b5a65c40SHuang Rui  */
40988bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc)
410b5a65c40SHuang Rui {
411b5a65c40SHuang Rui 	u32 reg;
41288bc9d19SHeikki Krogerus 	int ret;
413b5a65c40SHuang Rui 
414b5a65c40SHuang Rui 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
415b5a65c40SHuang Rui 
4162164a476SHuang Rui 	/*
4172164a476SHuang Rui 	 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
4182164a476SHuang Rui 	 * to '0' during coreConsultant configuration. So default value
4192164a476SHuang Rui 	 * will be '0' when the core is reset. Application needs to set it
4202164a476SHuang Rui 	 * to '1' after the core initialization is completed.
4212164a476SHuang Rui 	 */
4222164a476SHuang Rui 	if (dwc->revision > DWC3_REVISION_194A)
4232164a476SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
4242164a476SHuang Rui 
425b5a65c40SHuang Rui 	if (dwc->u2ss_inp3_quirk)
426b5a65c40SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
427b5a65c40SHuang Rui 
428e58dd357SRajesh Bhagat 	if (dwc->dis_rxdet_inp3_quirk)
429e58dd357SRajesh Bhagat 		reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3;
430e58dd357SRajesh Bhagat 
431df31f5b3SHuang Rui 	if (dwc->req_p1p2p3_quirk)
432df31f5b3SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
433df31f5b3SHuang Rui 
434a2a1d0f5SHuang Rui 	if (dwc->del_p1p2p3_quirk)
435a2a1d0f5SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
436a2a1d0f5SHuang Rui 
43741c06ffdSHuang Rui 	if (dwc->del_phy_power_chg_quirk)
43841c06ffdSHuang Rui 		reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
43941c06ffdSHuang Rui 
440fb67afcaSHuang Rui 	if (dwc->lfps_filter_quirk)
441fb67afcaSHuang Rui 		reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
442fb67afcaSHuang Rui 
44314f4ac53SHuang Rui 	if (dwc->rx_detect_poll_quirk)
44414f4ac53SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
44514f4ac53SHuang Rui 
4466b6a0c9aSHuang Rui 	if (dwc->tx_de_emphasis_quirk)
4476b6a0c9aSHuang Rui 		reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
4486b6a0c9aSHuang Rui 
449cd72f890SFelipe Balbi 	if (dwc->dis_u3_susphy_quirk)
45059acfa20SHuang Rui 		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
45159acfa20SHuang Rui 
452b5a65c40SHuang Rui 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
453b5a65c40SHuang Rui 
4542164a476SHuang Rui 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
4552164a476SHuang Rui 
4563e10a2ceSHeikki Krogerus 	/* Select the HS PHY interface */
4573e10a2ceSHeikki Krogerus 	switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) {
4583e10a2ceSHeikki Krogerus 	case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI:
45943cacb03SFelipe Balbi 		if (dwc->hsphy_interface &&
46043cacb03SFelipe Balbi 				!strncmp(dwc->hsphy_interface, "utmi", 4)) {
4613e10a2ceSHeikki Krogerus 			reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI;
46288bc9d19SHeikki Krogerus 			break;
46343cacb03SFelipe Balbi 		} else if (dwc->hsphy_interface &&
46443cacb03SFelipe Balbi 				!strncmp(dwc->hsphy_interface, "ulpi", 4)) {
4653e10a2ceSHeikki Krogerus 			reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
46688bc9d19SHeikki Krogerus 			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
4673e10a2ceSHeikki Krogerus 		} else {
46888bc9d19SHeikki Krogerus 			/* Relying on default value. */
46988bc9d19SHeikki Krogerus 			if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
4703e10a2ceSHeikki Krogerus 				break;
4713e10a2ceSHeikki Krogerus 		}
4723e10a2ceSHeikki Krogerus 		/* FALLTHROUGH */
47388bc9d19SHeikki Krogerus 	case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
47488bc9d19SHeikki Krogerus 		/* Making sure the interface and PHY are operational */
47588bc9d19SHeikki Krogerus 		ret = dwc3_soft_reset(dwc);
47688bc9d19SHeikki Krogerus 		if (ret)
47788bc9d19SHeikki Krogerus 			return ret;
47888bc9d19SHeikki Krogerus 
47988bc9d19SHeikki Krogerus 		udelay(1);
48088bc9d19SHeikki Krogerus 
48188bc9d19SHeikki Krogerus 		ret = dwc3_ulpi_init(dwc);
48288bc9d19SHeikki Krogerus 		if (ret)
48388bc9d19SHeikki Krogerus 			return ret;
48488bc9d19SHeikki Krogerus 		/* FALLTHROUGH */
4853e10a2ceSHeikki Krogerus 	default:
4863e10a2ceSHeikki Krogerus 		break;
4873e10a2ceSHeikki Krogerus 	}
4883e10a2ceSHeikki Krogerus 
4892164a476SHuang Rui 	/*
4902164a476SHuang Rui 	 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
4912164a476SHuang Rui 	 * '0' during coreConsultant configuration. So default value will
4922164a476SHuang Rui 	 * be '0' when the core is reset. Application needs to set it to
4932164a476SHuang Rui 	 * '1' after the core initialization is completed.
4942164a476SHuang Rui 	 */
4952164a476SHuang Rui 	if (dwc->revision > DWC3_REVISION_194A)
4962164a476SHuang Rui 		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
4972164a476SHuang Rui 
498cd72f890SFelipe Balbi 	if (dwc->dis_u2_susphy_quirk)
4990effe0a3SHuang Rui 		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
5000effe0a3SHuang Rui 
501ec791d14SJohn Youn 	if (dwc->dis_enblslpm_quirk)
502ec791d14SJohn Youn 		reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
503ec791d14SJohn Youn 
5042164a476SHuang Rui 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
50588bc9d19SHeikki Krogerus 
50688bc9d19SHeikki Krogerus 	return 0;
507b5a65c40SHuang Rui }
508b5a65c40SHuang Rui 
509c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc)
510c499ff71SFelipe Balbi {
511c499ff71SFelipe Balbi 	dwc3_event_buffers_cleanup(dwc);
512c499ff71SFelipe Balbi 
513c499ff71SFelipe Balbi 	usb_phy_shutdown(dwc->usb2_phy);
514c499ff71SFelipe Balbi 	usb_phy_shutdown(dwc->usb3_phy);
515c499ff71SFelipe Balbi 	phy_exit(dwc->usb2_generic_phy);
516c499ff71SFelipe Balbi 	phy_exit(dwc->usb3_generic_phy);
517c499ff71SFelipe Balbi 
518c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb2_phy, 1);
519c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb3_phy, 1);
520c499ff71SFelipe Balbi 	phy_power_off(dwc->usb2_generic_phy);
521c499ff71SFelipe Balbi 	phy_power_off(dwc->usb3_generic_phy);
522c499ff71SFelipe Balbi }
523c499ff71SFelipe Balbi 
524b5a65c40SHuang Rui /**
52572246da4SFelipe Balbi  * dwc3_core_init - Low-level initialization of DWC3 Core
52672246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
52772246da4SFelipe Balbi  *
52872246da4SFelipe Balbi  * Returns 0 on success otherwise negative errno.
52972246da4SFelipe Balbi  */
53041ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc)
53172246da4SFelipe Balbi {
5320ffcaf37SFelipe Balbi 	u32			hwparams4 = dwc->hwparams.hwparams4;
53372246da4SFelipe Balbi 	u32			reg;
53472246da4SFelipe Balbi 	int			ret;
53572246da4SFelipe Balbi 
5367650bd74SSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
5377650bd74SSebastian Andrzej Siewior 	/* This should read as U3 followed by revision number */
538690fb371SJohn Youn 	if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
539690fb371SJohn Youn 		/* Detected DWC_usb3 IP */
540690fb371SJohn Youn 		dwc->revision = reg;
541690fb371SJohn Youn 	} else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) {
542690fb371SJohn Youn 		/* Detected DWC_usb31 IP */
543690fb371SJohn Youn 		dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
544690fb371SJohn Youn 		dwc->revision |= DWC3_REVISION_IS_DWC31;
545690fb371SJohn Youn 	} else {
5467650bd74SSebastian Andrzej Siewior 		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
5477650bd74SSebastian Andrzej Siewior 		ret = -ENODEV;
5487650bd74SSebastian Andrzej Siewior 		goto err0;
5497650bd74SSebastian Andrzej Siewior 	}
5507650bd74SSebastian Andrzej Siewior 
551fa0ea13eSFelipe Balbi 	/*
552fa0ea13eSFelipe Balbi 	 * Write Linux Version Code to our GUID register so it's easy to figure
553fa0ea13eSFelipe Balbi 	 * out which kernel version a bug was found.
554fa0ea13eSFelipe Balbi 	 */
555fa0ea13eSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE);
556fa0ea13eSFelipe Balbi 
5570e1e5c47SPaul Zimmerman 	/* Handle USB2.0-only core configuration */
5580e1e5c47SPaul Zimmerman 	if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
5590e1e5c47SPaul Zimmerman 			DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
5600e1e5c47SPaul Zimmerman 		if (dwc->maximum_speed == USB_SPEED_SUPER)
5610e1e5c47SPaul Zimmerman 			dwc->maximum_speed = USB_SPEED_HIGH;
5620e1e5c47SPaul Zimmerman 	}
5630e1e5c47SPaul Zimmerman 
56472246da4SFelipe Balbi 	/* issue device SoftReset too */
565c5cc74e8SHeikki Krogerus 	ret = dwc3_soft_reset(dwc);
566c5cc74e8SHeikki Krogerus 	if (ret)
56772246da4SFelipe Balbi 		goto err0;
56872246da4SFelipe Balbi 
56957303488SKishon Vijay Abraham I 	ret = dwc3_core_soft_reset(dwc);
57057303488SKishon Vijay Abraham I 	if (ret)
57157303488SKishon Vijay Abraham I 		goto err0;
57258a0f23fSPratyush Anand 
573c499ff71SFelipe Balbi 	ret = dwc3_phy_setup(dwc);
574c499ff71SFelipe Balbi 	if (ret)
575c499ff71SFelipe Balbi 		goto err0;
576c499ff71SFelipe Balbi 
5774878a028SSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
5783e87c42aSPaul Zimmerman 	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
5794878a028SSebastian Andrzej Siewior 
580164d7731SSebastian Andrzej Siewior 	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
5814878a028SSebastian Andrzej Siewior 	case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
58232a4a135SFelipe Balbi 		/**
58332a4a135SFelipe Balbi 		 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
58432a4a135SFelipe Balbi 		 * issue which would cause xHCI compliance tests to fail.
58532a4a135SFelipe Balbi 		 *
58632a4a135SFelipe Balbi 		 * Because of that we cannot enable clock gating on such
58732a4a135SFelipe Balbi 		 * configurations.
58832a4a135SFelipe Balbi 		 *
58932a4a135SFelipe Balbi 		 * Refers to:
59032a4a135SFelipe Balbi 		 *
59132a4a135SFelipe Balbi 		 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
59232a4a135SFelipe Balbi 		 * SOF/ITP Mode Used
59332a4a135SFelipe Balbi 		 */
59432a4a135SFelipe Balbi 		if ((dwc->dr_mode == USB_DR_MODE_HOST ||
59532a4a135SFelipe Balbi 				dwc->dr_mode == USB_DR_MODE_OTG) &&
59632a4a135SFelipe Balbi 				(dwc->revision >= DWC3_REVISION_210A &&
59732a4a135SFelipe Balbi 				dwc->revision <= DWC3_REVISION_250A))
59832a4a135SFelipe Balbi 			reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
59932a4a135SFelipe Balbi 		else
6004878a028SSebastian Andrzej Siewior 			reg &= ~DWC3_GCTL_DSBLCLKGTNG;
6014878a028SSebastian Andrzej Siewior 		break;
6020ffcaf37SFelipe Balbi 	case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
6030ffcaf37SFelipe Balbi 		/* enable hibernation here */
6040ffcaf37SFelipe Balbi 		dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
6052eac3992SHuang Rui 
6062eac3992SHuang Rui 		/*
6072eac3992SHuang Rui 		 * REVISIT Enabling this bit so that host-mode hibernation
6082eac3992SHuang Rui 		 * will work. Device-mode hibernation is not yet implemented.
6092eac3992SHuang Rui 		 */
6102eac3992SHuang Rui 		reg |= DWC3_GCTL_GBLHIBERNATIONEN;
6110ffcaf37SFelipe Balbi 		break;
6124878a028SSebastian Andrzej Siewior 	default:
6131407bf13SFelipe Balbi 		dwc3_trace(trace_dwc3_core, "No power optimization available\n");
6144878a028SSebastian Andrzej Siewior 	}
6154878a028SSebastian Andrzej Siewior 
616946bd579SHuang Rui 	/* check if current dwc3 is on simulation board */
617946bd579SHuang Rui 	if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
6181407bf13SFelipe Balbi 		dwc3_trace(trace_dwc3_core,
6191407bf13SFelipe Balbi 				"running on FPGA platform\n");
620946bd579SHuang Rui 		dwc->is_fpga = true;
621946bd579SHuang Rui 	}
622946bd579SHuang Rui 
6233b81221aSHuang Rui 	WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga,
6243b81221aSHuang Rui 			"disable_scramble cannot be used on non-FPGA builds\n");
6253b81221aSHuang Rui 
6263b81221aSHuang Rui 	if (dwc->disable_scramble_quirk && dwc->is_fpga)
6273b81221aSHuang Rui 		reg |= DWC3_GCTL_DISSCRAMBLE;
6283b81221aSHuang Rui 	else
6293b81221aSHuang Rui 		reg &= ~DWC3_GCTL_DISSCRAMBLE;
6303b81221aSHuang Rui 
6319a5b2f31SHuang Rui 	if (dwc->u2exit_lfps_quirk)
6329a5b2f31SHuang Rui 		reg |= DWC3_GCTL_U2EXIT_LFPS;
6339a5b2f31SHuang Rui 
6344878a028SSebastian Andrzej Siewior 	/*
6354878a028SSebastian Andrzej Siewior 	 * WORKAROUND: DWC3 revisions <1.90a have a bug
6361d046793SPaul Zimmerman 	 * where the device can fail to connect at SuperSpeed
6374878a028SSebastian Andrzej Siewior 	 * and falls back to high-speed mode which causes
6381d046793SPaul Zimmerman 	 * the device to enter a Connect/Disconnect loop
6394878a028SSebastian Andrzej Siewior 	 */
6404878a028SSebastian Andrzej Siewior 	if (dwc->revision < DWC3_REVISION_190A)
6414878a028SSebastian Andrzej Siewior 		reg |= DWC3_GCTL_U2RSTECN;
6424878a028SSebastian Andrzej Siewior 
6434878a028SSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
6444878a028SSebastian Andrzej Siewior 
645c499ff71SFelipe Balbi 	dwc3_core_num_eps(dwc);
6460ffcaf37SFelipe Balbi 
6470ffcaf37SFelipe Balbi 	ret = dwc3_setup_scratch_buffers(dwc);
6480ffcaf37SFelipe Balbi 	if (ret)
649c499ff71SFelipe Balbi 		goto err1;
650c499ff71SFelipe Balbi 
651c499ff71SFelipe Balbi 	/* Adjust Frame Length */
652c499ff71SFelipe Balbi 	dwc3_frame_length_adjustment(dwc);
653c499ff71SFelipe Balbi 
654c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb2_phy, 0);
655c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb3_phy, 0);
656c499ff71SFelipe Balbi 	ret = phy_power_on(dwc->usb2_generic_phy);
657c499ff71SFelipe Balbi 	if (ret < 0)
6580ffcaf37SFelipe Balbi 		goto err2;
6590ffcaf37SFelipe Balbi 
660c499ff71SFelipe Balbi 	ret = phy_power_on(dwc->usb3_generic_phy);
661c499ff71SFelipe Balbi 	if (ret < 0)
662c499ff71SFelipe Balbi 		goto err3;
663c499ff71SFelipe Balbi 
664c499ff71SFelipe Balbi 	ret = dwc3_event_buffers_setup(dwc);
665c499ff71SFelipe Balbi 	if (ret) {
666c499ff71SFelipe Balbi 		dev_err(dwc->dev, "failed to setup event buffers\n");
667c499ff71SFelipe Balbi 		goto err4;
668c499ff71SFelipe Balbi 	}
669c499ff71SFelipe Balbi 
67072246da4SFelipe Balbi 	return 0;
67172246da4SFelipe Balbi 
672c499ff71SFelipe Balbi err4:
673c499ff71SFelipe Balbi 	phy_power_off(dwc->usb2_generic_phy);
674c499ff71SFelipe Balbi 
675c499ff71SFelipe Balbi err3:
676c499ff71SFelipe Balbi 	phy_power_off(dwc->usb3_generic_phy);
677c499ff71SFelipe Balbi 
6780ffcaf37SFelipe Balbi err2:
679c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb2_phy, 1);
680c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb3_phy, 1);
681c499ff71SFelipe Balbi 	dwc3_core_exit(dwc);
6820ffcaf37SFelipe Balbi 
6830ffcaf37SFelipe Balbi err1:
6840ffcaf37SFelipe Balbi 	usb_phy_shutdown(dwc->usb2_phy);
6850ffcaf37SFelipe Balbi 	usb_phy_shutdown(dwc->usb3_phy);
68657303488SKishon Vijay Abraham I 	phy_exit(dwc->usb2_generic_phy);
68757303488SKishon Vijay Abraham I 	phy_exit(dwc->usb3_generic_phy);
6880ffcaf37SFelipe Balbi 
68972246da4SFelipe Balbi err0:
69072246da4SFelipe Balbi 	return ret;
69172246da4SFelipe Balbi }
69272246da4SFelipe Balbi 
6933c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc)
69472246da4SFelipe Balbi {
6953c9f94acSFelipe Balbi 	struct device		*dev = dwc->dev;
696941ea361SFelipe Balbi 	struct device_node	*node = dev->of_node;
6973c9f94acSFelipe Balbi 	int ret;
69872246da4SFelipe Balbi 
6995088b6f5SKishon Vijay Abraham I 	if (node) {
7005088b6f5SKishon Vijay Abraham I 		dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
7015088b6f5SKishon Vijay Abraham I 		dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
702bb674907SFelipe Balbi 	} else {
703bb674907SFelipe Balbi 		dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
704bb674907SFelipe Balbi 		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
7055088b6f5SKishon Vijay Abraham I 	}
7065088b6f5SKishon Vijay Abraham I 
707d105e7f8SFelipe Balbi 	if (IS_ERR(dwc->usb2_phy)) {
708d105e7f8SFelipe Balbi 		ret = PTR_ERR(dwc->usb2_phy);
709122f06e6SKishon Vijay Abraham I 		if (ret == -ENXIO || ret == -ENODEV) {
710122f06e6SKishon Vijay Abraham I 			dwc->usb2_phy = NULL;
711122f06e6SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
712d105e7f8SFelipe Balbi 			return ret;
713122f06e6SKishon Vijay Abraham I 		} else {
71451e1e7bcSFelipe Balbi 			dev_err(dev, "no usb2 phy configured\n");
715122f06e6SKishon Vijay Abraham I 			return ret;
716122f06e6SKishon Vijay Abraham I 		}
71751e1e7bcSFelipe Balbi 	}
71851e1e7bcSFelipe Balbi 
719d105e7f8SFelipe Balbi 	if (IS_ERR(dwc->usb3_phy)) {
720315955d7SRuchika Kharwar 		ret = PTR_ERR(dwc->usb3_phy);
721122f06e6SKishon Vijay Abraham I 		if (ret == -ENXIO || ret == -ENODEV) {
722122f06e6SKishon Vijay Abraham I 			dwc->usb3_phy = NULL;
723122f06e6SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
724d105e7f8SFelipe Balbi 			return ret;
725122f06e6SKishon Vijay Abraham I 		} else {
72651e1e7bcSFelipe Balbi 			dev_err(dev, "no usb3 phy configured\n");
727122f06e6SKishon Vijay Abraham I 			return ret;
728122f06e6SKishon Vijay Abraham I 		}
72951e1e7bcSFelipe Balbi 	}
73051e1e7bcSFelipe Balbi 
73157303488SKishon Vijay Abraham I 	dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
73257303488SKishon Vijay Abraham I 	if (IS_ERR(dwc->usb2_generic_phy)) {
73357303488SKishon Vijay Abraham I 		ret = PTR_ERR(dwc->usb2_generic_phy);
73457303488SKishon Vijay Abraham I 		if (ret == -ENOSYS || ret == -ENODEV) {
73557303488SKishon Vijay Abraham I 			dwc->usb2_generic_phy = NULL;
73657303488SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
73757303488SKishon Vijay Abraham I 			return ret;
73857303488SKishon Vijay Abraham I 		} else {
73957303488SKishon Vijay Abraham I 			dev_err(dev, "no usb2 phy configured\n");
74057303488SKishon Vijay Abraham I 			return ret;
74157303488SKishon Vijay Abraham I 		}
74257303488SKishon Vijay Abraham I 	}
74357303488SKishon Vijay Abraham I 
74457303488SKishon Vijay Abraham I 	dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
74557303488SKishon Vijay Abraham I 	if (IS_ERR(dwc->usb3_generic_phy)) {
74657303488SKishon Vijay Abraham I 		ret = PTR_ERR(dwc->usb3_generic_phy);
74757303488SKishon Vijay Abraham I 		if (ret == -ENOSYS || ret == -ENODEV) {
74857303488SKishon Vijay Abraham I 			dwc->usb3_generic_phy = NULL;
74957303488SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
75057303488SKishon Vijay Abraham I 			return ret;
75157303488SKishon Vijay Abraham I 		} else {
75257303488SKishon Vijay Abraham I 			dev_err(dev, "no usb3 phy configured\n");
75357303488SKishon Vijay Abraham I 			return ret;
75457303488SKishon Vijay Abraham I 		}
75557303488SKishon Vijay Abraham I 	}
75657303488SKishon Vijay Abraham I 
7573c9f94acSFelipe Balbi 	return 0;
7583c9f94acSFelipe Balbi }
7593c9f94acSFelipe Balbi 
7605f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc)
7615f94adfeSFelipe Balbi {
7625f94adfeSFelipe Balbi 	struct device *dev = dwc->dev;
7635f94adfeSFelipe Balbi 	int ret;
7645f94adfeSFelipe Balbi 
7655f94adfeSFelipe Balbi 	switch (dwc->dr_mode) {
7665f94adfeSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
7675f94adfeSFelipe Balbi 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
7685f94adfeSFelipe Balbi 		ret = dwc3_gadget_init(dwc);
7695f94adfeSFelipe Balbi 		if (ret) {
7705f94adfeSFelipe Balbi 			dev_err(dev, "failed to initialize gadget\n");
7715f94adfeSFelipe Balbi 			return ret;
7725f94adfeSFelipe Balbi 		}
7735f94adfeSFelipe Balbi 		break;
7745f94adfeSFelipe Balbi 	case USB_DR_MODE_HOST:
7755f94adfeSFelipe Balbi 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
7765f94adfeSFelipe Balbi 		ret = dwc3_host_init(dwc);
7775f94adfeSFelipe Balbi 		if (ret) {
7785f94adfeSFelipe Balbi 			dev_err(dev, "failed to initialize host\n");
7795f94adfeSFelipe Balbi 			return ret;
7805f94adfeSFelipe Balbi 		}
7815f94adfeSFelipe Balbi 		break;
7825f94adfeSFelipe Balbi 	case USB_DR_MODE_OTG:
7835f94adfeSFelipe Balbi 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
7845f94adfeSFelipe Balbi 		ret = dwc3_host_init(dwc);
7855f94adfeSFelipe Balbi 		if (ret) {
7865f94adfeSFelipe Balbi 			dev_err(dev, "failed to initialize host\n");
7875f94adfeSFelipe Balbi 			return ret;
7885f94adfeSFelipe Balbi 		}
7895f94adfeSFelipe Balbi 
7905f94adfeSFelipe Balbi 		ret = dwc3_gadget_init(dwc);
7915f94adfeSFelipe Balbi 		if (ret) {
7925f94adfeSFelipe Balbi 			dev_err(dev, "failed to initialize gadget\n");
7935f94adfeSFelipe Balbi 			return ret;
7945f94adfeSFelipe Balbi 		}
7955f94adfeSFelipe Balbi 		break;
7965f94adfeSFelipe Balbi 	default:
7975f94adfeSFelipe Balbi 		dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
7985f94adfeSFelipe Balbi 		return -EINVAL;
7995f94adfeSFelipe Balbi 	}
8005f94adfeSFelipe Balbi 
8015f94adfeSFelipe Balbi 	return 0;
8025f94adfeSFelipe Balbi }
8035f94adfeSFelipe Balbi 
8045f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc)
8055f94adfeSFelipe Balbi {
8065f94adfeSFelipe Balbi 	switch (dwc->dr_mode) {
8075f94adfeSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
8085f94adfeSFelipe Balbi 		dwc3_gadget_exit(dwc);
8095f94adfeSFelipe Balbi 		break;
8105f94adfeSFelipe Balbi 	case USB_DR_MODE_HOST:
8115f94adfeSFelipe Balbi 		dwc3_host_exit(dwc);
8125f94adfeSFelipe Balbi 		break;
8135f94adfeSFelipe Balbi 	case USB_DR_MODE_OTG:
8145f94adfeSFelipe Balbi 		dwc3_host_exit(dwc);
8155f94adfeSFelipe Balbi 		dwc3_gadget_exit(dwc);
8165f94adfeSFelipe Balbi 		break;
8175f94adfeSFelipe Balbi 	default:
8185f94adfeSFelipe Balbi 		/* do nothing */
8195f94adfeSFelipe Balbi 		break;
8205f94adfeSFelipe Balbi 	}
8215f94adfeSFelipe Balbi }
8225f94adfeSFelipe Balbi 
8233c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK		(16 - 1)
8243c9f94acSFelipe Balbi 
8253c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev)
8263c9f94acSFelipe Balbi {
8273c9f94acSFelipe Balbi 	struct device		*dev = &pdev->dev;
8283c9f94acSFelipe Balbi 	struct dwc3_platform_data *pdata = dev_get_platdata(dev);
8293c9f94acSFelipe Balbi 	struct resource		*res;
8303c9f94acSFelipe Balbi 	struct dwc3		*dwc;
83180caf7d2SHuang Rui 	u8			lpm_nyet_threshold;
8326b6a0c9aSHuang Rui 	u8			tx_de_emphasis;
833460d098cSHuang Rui 	u8			hird_threshold;
8343c9f94acSFelipe Balbi 
835b09e99eeSAndy Shevchenko 	int			ret;
8363c9f94acSFelipe Balbi 
8373c9f94acSFelipe Balbi 	void __iomem		*regs;
8383c9f94acSFelipe Balbi 	void			*mem;
8393c9f94acSFelipe Balbi 
8403c9f94acSFelipe Balbi 	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
841734d5a53SJingoo Han 	if (!mem)
8423c9f94acSFelipe Balbi 		return -ENOMEM;
843734d5a53SJingoo Han 
8443c9f94acSFelipe Balbi 	dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
8453c9f94acSFelipe Balbi 	dwc->mem = mem;
8463c9f94acSFelipe Balbi 	dwc->dev = dev;
8473c9f94acSFelipe Balbi 
8483c9f94acSFelipe Balbi 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
8493c9f94acSFelipe Balbi 	if (!res) {
8503c9f94acSFelipe Balbi 		dev_err(dev, "missing IRQ\n");
8513c9f94acSFelipe Balbi 		return -ENODEV;
8523c9f94acSFelipe Balbi 	}
8533c9f94acSFelipe Balbi 	dwc->xhci_resources[1].start = res->start;
8543c9f94acSFelipe Balbi 	dwc->xhci_resources[1].end = res->end;
8553c9f94acSFelipe Balbi 	dwc->xhci_resources[1].flags = res->flags;
8563c9f94acSFelipe Balbi 	dwc->xhci_resources[1].name = res->name;
8573c9f94acSFelipe Balbi 
8583c9f94acSFelipe Balbi 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8593c9f94acSFelipe Balbi 	if (!res) {
8603c9f94acSFelipe Balbi 		dev_err(dev, "missing memory resource\n");
8613c9f94acSFelipe Balbi 		return -ENODEV;
8623c9f94acSFelipe Balbi 	}
8633c9f94acSFelipe Balbi 
864f32a5e23SVivek Gautam 	dwc->xhci_resources[0].start = res->start;
865f32a5e23SVivek Gautam 	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
866f32a5e23SVivek Gautam 					DWC3_XHCI_REGS_END;
867f32a5e23SVivek Gautam 	dwc->xhci_resources[0].flags = res->flags;
868f32a5e23SVivek Gautam 	dwc->xhci_resources[0].name = res->name;
869f32a5e23SVivek Gautam 
870f32a5e23SVivek Gautam 	res->start += DWC3_GLOBALS_REGS_START;
871f32a5e23SVivek Gautam 
872f32a5e23SVivek Gautam 	/*
873f32a5e23SVivek Gautam 	 * Request memory region but exclude xHCI regs,
874f32a5e23SVivek Gautam 	 * since it will be requested by the xhci-plat driver.
875f32a5e23SVivek Gautam 	 */
876f32a5e23SVivek Gautam 	regs = devm_ioremap_resource(dev, res);
8773da1f6eeSFelipe Balbi 	if (IS_ERR(regs)) {
8783da1f6eeSFelipe Balbi 		ret = PTR_ERR(regs);
8793da1f6eeSFelipe Balbi 		goto err0;
8803da1f6eeSFelipe Balbi 	}
881f32a5e23SVivek Gautam 
882f32a5e23SVivek Gautam 	dwc->regs	= regs;
883f32a5e23SVivek Gautam 	dwc->regs_size	= resource_size(res);
884f32a5e23SVivek Gautam 
88580caf7d2SHuang Rui 	/* default to highest possible threshold */
88680caf7d2SHuang Rui 	lpm_nyet_threshold = 0xff;
88780caf7d2SHuang Rui 
8886b6a0c9aSHuang Rui 	/* default to -3.5dB de-emphasis */
8896b6a0c9aSHuang Rui 	tx_de_emphasis = 1;
8906b6a0c9aSHuang Rui 
891460d098cSHuang Rui 	/*
892460d098cSHuang Rui 	 * default to assert utmi_sleep_n and use maximum allowed HIRD
893460d098cSHuang Rui 	 * threshold value of 0b1100
894460d098cSHuang Rui 	 */
895460d098cSHuang Rui 	hird_threshold = 12;
896460d098cSHuang Rui 
89763863b98SHeikki Krogerus 	dwc->maximum_speed = usb_get_maximum_speed(dev);
89806e7114fSHeikki Krogerus 	dwc->dr_mode = usb_get_dr_mode(dev);
89963863b98SHeikki Krogerus 
9003d128919SHeikki Krogerus 	dwc->has_lpm_erratum = device_property_read_bool(dev,
90180caf7d2SHuang Rui 				"snps,has-lpm-erratum");
9023d128919SHeikki Krogerus 	device_property_read_u8(dev, "snps,lpm-nyet-threshold",
90380caf7d2SHuang Rui 				&lpm_nyet_threshold);
9043d128919SHeikki Krogerus 	dwc->is_utmi_l1_suspend = device_property_read_bool(dev,
905460d098cSHuang Rui 				"snps,is-utmi-l1-suspend");
9063d128919SHeikki Krogerus 	device_property_read_u8(dev, "snps,hird-threshold",
907460d098cSHuang Rui 				&hird_threshold);
9083d128919SHeikki Krogerus 	dwc->usb3_lpm_capable = device_property_read_bool(dev,
909eac68e8fSRobert Baldyga 				"snps,usb3_lpm_capable");
9103c9f94acSFelipe Balbi 
9113d128919SHeikki Krogerus 	dwc->disable_scramble_quirk = device_property_read_bool(dev,
9123b81221aSHuang Rui 				"snps,disable_scramble_quirk");
9133d128919SHeikki Krogerus 	dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
9149a5b2f31SHuang Rui 				"snps,u2exit_lfps_quirk");
9153d128919SHeikki Krogerus 	dwc->u2ss_inp3_quirk = device_property_read_bool(dev,
916b5a65c40SHuang Rui 				"snps,u2ss_inp3_quirk");
9173d128919SHeikki Krogerus 	dwc->req_p1p2p3_quirk = device_property_read_bool(dev,
918df31f5b3SHuang Rui 				"snps,req_p1p2p3_quirk");
9193d128919SHeikki Krogerus 	dwc->del_p1p2p3_quirk = device_property_read_bool(dev,
920a2a1d0f5SHuang Rui 				"snps,del_p1p2p3_quirk");
9213d128919SHeikki Krogerus 	dwc->del_phy_power_chg_quirk = device_property_read_bool(dev,
92241c06ffdSHuang Rui 				"snps,del_phy_power_chg_quirk");
9233d128919SHeikki Krogerus 	dwc->lfps_filter_quirk = device_property_read_bool(dev,
924fb67afcaSHuang Rui 				"snps,lfps_filter_quirk");
9253d128919SHeikki Krogerus 	dwc->rx_detect_poll_quirk = device_property_read_bool(dev,
92614f4ac53SHuang Rui 				"snps,rx_detect_poll_quirk");
9273d128919SHeikki Krogerus 	dwc->dis_u3_susphy_quirk = device_property_read_bool(dev,
92859acfa20SHuang Rui 				"snps,dis_u3_susphy_quirk");
9293d128919SHeikki Krogerus 	dwc->dis_u2_susphy_quirk = device_property_read_bool(dev,
9300effe0a3SHuang Rui 				"snps,dis_u2_susphy_quirk");
931ec791d14SJohn Youn 	dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
932ec791d14SJohn Youn 				"snps,dis_enblslpm_quirk");
933e58dd357SRajesh Bhagat 	dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev,
934e58dd357SRajesh Bhagat 				"snps,dis_rxdet_inp3_quirk");
9356b6a0c9aSHuang Rui 
9363d128919SHeikki Krogerus 	dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
9376b6a0c9aSHuang Rui 				"snps,tx_de_emphasis_quirk");
9383d128919SHeikki Krogerus 	device_property_read_u8(dev, "snps,tx_de_emphasis",
9396b6a0c9aSHuang Rui 				&tx_de_emphasis);
9403d128919SHeikki Krogerus 	device_property_read_string(dev, "snps,hsphy_interface",
9413e10a2ceSHeikki Krogerus 				    &dwc->hsphy_interface);
9423d128919SHeikki Krogerus 	device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
943bcdb3272SFelipe Balbi 				 &dwc->fladj);
9443d128919SHeikki Krogerus 
9453d128919SHeikki Krogerus 	if (pdata) {
9463c9f94acSFelipe Balbi 		dwc->maximum_speed = pdata->maximum_speed;
94780caf7d2SHuang Rui 		dwc->has_lpm_erratum = pdata->has_lpm_erratum;
94880caf7d2SHuang Rui 		if (pdata->lpm_nyet_threshold)
94980caf7d2SHuang Rui 			lpm_nyet_threshold = pdata->lpm_nyet_threshold;
950460d098cSHuang Rui 		dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend;
951460d098cSHuang Rui 		if (pdata->hird_threshold)
952460d098cSHuang Rui 			hird_threshold = pdata->hird_threshold;
9533c9f94acSFelipe Balbi 
954eac68e8fSRobert Baldyga 		dwc->usb3_lpm_capable = pdata->usb3_lpm_capable;
9553c9f94acSFelipe Balbi 		dwc->dr_mode = pdata->dr_mode;
9563b81221aSHuang Rui 
9573b81221aSHuang Rui 		dwc->disable_scramble_quirk = pdata->disable_scramble_quirk;
9589a5b2f31SHuang Rui 		dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk;
959b5a65c40SHuang Rui 		dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk;
960df31f5b3SHuang Rui 		dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk;
961a2a1d0f5SHuang Rui 		dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk;
96241c06ffdSHuang Rui 		dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk;
963fb67afcaSHuang Rui 		dwc->lfps_filter_quirk = pdata->lfps_filter_quirk;
96414f4ac53SHuang Rui 		dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk;
96559acfa20SHuang Rui 		dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk;
9660effe0a3SHuang Rui 		dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk;
967ec791d14SJohn Youn 		dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk;
968e58dd357SRajesh Bhagat 		dwc->dis_rxdet_inp3_quirk = pdata->dis_rxdet_inp3_quirk;
9696b6a0c9aSHuang Rui 
9706b6a0c9aSHuang Rui 		dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk;
9716b6a0c9aSHuang Rui 		if (pdata->tx_de_emphasis)
9726b6a0c9aSHuang Rui 			tx_de_emphasis = pdata->tx_de_emphasis;
9733e10a2ceSHeikki Krogerus 
9743e10a2ceSHeikki Krogerus 		dwc->hsphy_interface = pdata->hsphy_interface;
975bcdb3272SFelipe Balbi 		dwc->fladj = pdata->fladj_value;
9763c9f94acSFelipe Balbi 	}
9773c9f94acSFelipe Balbi 
97880caf7d2SHuang Rui 	dwc->lpm_nyet_threshold = lpm_nyet_threshold;
9796b6a0c9aSHuang Rui 	dwc->tx_de_emphasis = tx_de_emphasis;
98080caf7d2SHuang Rui 
981460d098cSHuang Rui 	dwc->hird_threshold = hird_threshold
982460d098cSHuang Rui 		| (dwc->is_utmi_l1_suspend << 4);
983460d098cSHuang Rui 
9846c89cce0SHeikki Krogerus 	platform_set_drvdata(pdev, dwc);
9852917e718SHeikki Krogerus 	dwc3_cache_hwparams(dwc);
9866c89cce0SHeikki Krogerus 
9873c9f94acSFelipe Balbi 	ret = dwc3_core_get_phy(dwc);
9883c9f94acSFelipe Balbi 	if (ret)
9893da1f6eeSFelipe Balbi 		goto err0;
9903c9f94acSFelipe Balbi 
99172246da4SFelipe Balbi 	spin_lock_init(&dwc->lock);
99272246da4SFelipe Balbi 
99319bacdc9SHeikki Krogerus 	if (!dev->dma_mask) {
994ddff14f1SKishon Vijay Abraham I 		dev->dma_mask = dev->parent->dma_mask;
995ddff14f1SKishon Vijay Abraham I 		dev->dma_parms = dev->parent->dma_parms;
996ddff14f1SKishon Vijay Abraham I 		dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
99719bacdc9SHeikki Krogerus 	}
998ddff14f1SKishon Vijay Abraham I 
999fc8bb91bSFelipe Balbi 	pm_runtime_set_active(dev);
1000fc8bb91bSFelipe Balbi 	pm_runtime_use_autosuspend(dev);
1001fc8bb91bSFelipe Balbi 	pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
1002802ca850SChanho Park 	pm_runtime_enable(dev);
1003802ca850SChanho Park 	pm_runtime_get_sync(dev);
1004802ca850SChanho Park 	pm_runtime_forbid(dev);
100572246da4SFelipe Balbi 
10063921426bSFelipe Balbi 	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
10073921426bSFelipe Balbi 	if (ret) {
10083921426bSFelipe Balbi 		dev_err(dwc->dev, "failed to allocate event buffers\n");
10093921426bSFelipe Balbi 		ret = -ENOMEM;
1010c499ff71SFelipe Balbi 		goto err0;
10113921426bSFelipe Balbi 	}
10123921426bSFelipe Balbi 
101332a4a135SFelipe Balbi 	if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
101432a4a135SFelipe Balbi 		dwc->dr_mode = USB_DR_MODE_HOST;
101532a4a135SFelipe Balbi 	else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
101632a4a135SFelipe Balbi 		dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
101732a4a135SFelipe Balbi 
101832a4a135SFelipe Balbi 	if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
101932a4a135SFelipe Balbi 		dwc->dr_mode = USB_DR_MODE_OTG;
102032a4a135SFelipe Balbi 
1021c499ff71SFelipe Balbi 	ret = dwc3_alloc_scratch_buffers(dwc);
1022c499ff71SFelipe Balbi 	if (ret)
1023c499ff71SFelipe Balbi 		goto err1;
1024c499ff71SFelipe Balbi 
102572246da4SFelipe Balbi 	ret = dwc3_core_init(dwc);
102672246da4SFelipe Balbi 	if (ret) {
1027802ca850SChanho Park 		dev_err(dev, "failed to initialize core\n");
1028c499ff71SFelipe Balbi 		goto err2;
102972246da4SFelipe Balbi 	}
103072246da4SFelipe Balbi 
103177966eb8SJohn Youn 	/* Check the maximum_speed parameter */
103277966eb8SJohn Youn 	switch (dwc->maximum_speed) {
103377966eb8SJohn Youn 	case USB_SPEED_LOW:
103477966eb8SJohn Youn 	case USB_SPEED_FULL:
103577966eb8SJohn Youn 	case USB_SPEED_HIGH:
103677966eb8SJohn Youn 	case USB_SPEED_SUPER:
103777966eb8SJohn Youn 	case USB_SPEED_SUPER_PLUS:
103877966eb8SJohn Youn 		break;
103977966eb8SJohn Youn 	default:
104077966eb8SJohn Youn 		dev_err(dev, "invalid maximum_speed parameter %d\n",
104177966eb8SJohn Youn 			dwc->maximum_speed);
104277966eb8SJohn Youn 		/* fall through */
104377966eb8SJohn Youn 	case USB_SPEED_UNKNOWN:
104477966eb8SJohn Youn 		/* default to superspeed */
10452c7f1bd9SJohn Youn 		dwc->maximum_speed = USB_SPEED_SUPER;
10462c7f1bd9SJohn Youn 
10472c7f1bd9SJohn Youn 		/*
10482c7f1bd9SJohn Youn 		 * default to superspeed plus if we are capable.
10492c7f1bd9SJohn Youn 		 */
10502c7f1bd9SJohn Youn 		if (dwc3_is_usb31(dwc) &&
10512c7f1bd9SJohn Youn 		    (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
10522c7f1bd9SJohn Youn 		     DWC3_GHWPARAMS3_SSPHY_IFC_GEN2))
10532c7f1bd9SJohn Youn 			dwc->maximum_speed = USB_SPEED_SUPER_PLUS;
105477966eb8SJohn Youn 
105577966eb8SJohn Youn 		break;
10562c7f1bd9SJohn Youn 	}
10572c7f1bd9SJohn Youn 
10585f94adfeSFelipe Balbi 	ret = dwc3_core_init_mode(dwc);
10595f94adfeSFelipe Balbi 	if (ret)
1060c499ff71SFelipe Balbi 		goto err3;
106172246da4SFelipe Balbi 
10624e9f3118SDu, Changbin 	dwc3_debugfs_init(dwc);
1063fc8bb91bSFelipe Balbi 	pm_runtime_put(dev);
106472246da4SFelipe Balbi 
106572246da4SFelipe Balbi 	return 0;
106672246da4SFelipe Balbi 
1067c499ff71SFelipe Balbi err3:
1068f122d33eSFelipe Balbi 	dwc3_event_buffers_cleanup(dwc);
1069f122d33eSFelipe Balbi 
10703da1f6eeSFelipe Balbi err2:
1071c499ff71SFelipe Balbi 	dwc3_free_scratch_buffers(dwc);
107272246da4SFelipe Balbi 
10733da1f6eeSFelipe Balbi err1:
10743921426bSFelipe Balbi 	dwc3_free_event_buffers(dwc);
107588bc9d19SHeikki Krogerus 	dwc3_ulpi_exit(dwc);
10763921426bSFelipe Balbi 
10773da1f6eeSFelipe Balbi err0:
10783da1f6eeSFelipe Balbi 	/*
10793da1f6eeSFelipe Balbi 	 * restore res->start back to its original value so that, in case the
10803da1f6eeSFelipe Balbi 	 * probe is deferred, we don't end up getting error in request the
10813da1f6eeSFelipe Balbi 	 * memory region the next time probe is called.
10823da1f6eeSFelipe Balbi 	 */
10833da1f6eeSFelipe Balbi 	res->start -= DWC3_GLOBALS_REGS_START;
10843da1f6eeSFelipe Balbi 
108572246da4SFelipe Balbi 	return ret;
108672246da4SFelipe Balbi }
108772246da4SFelipe Balbi 
1088fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev)
108972246da4SFelipe Balbi {
109072246da4SFelipe Balbi 	struct dwc3	*dwc = platform_get_drvdata(pdev);
10913da1f6eeSFelipe Balbi 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
10923da1f6eeSFelipe Balbi 
1093fc8bb91bSFelipe Balbi 	pm_runtime_get_sync(&pdev->dev);
10943da1f6eeSFelipe Balbi 	/*
10953da1f6eeSFelipe Balbi 	 * restore res->start back to its original value so that, in case the
10963da1f6eeSFelipe Balbi 	 * probe is deferred, we don't end up getting error in request the
10973da1f6eeSFelipe Balbi 	 * memory region the next time probe is called.
10983da1f6eeSFelipe Balbi 	 */
10993da1f6eeSFelipe Balbi 	res->start -= DWC3_GLOBALS_REGS_START;
110072246da4SFelipe Balbi 
1101dc99f16fSFelipe Balbi 	dwc3_debugfs_exit(dwc);
1102dc99f16fSFelipe Balbi 	dwc3_core_exit_mode(dwc);
11038ba007a9SKishon Vijay Abraham I 
110472246da4SFelipe Balbi 	dwc3_core_exit(dwc);
110588bc9d19SHeikki Krogerus 	dwc3_ulpi_exit(dwc);
110672246da4SFelipe Balbi 
1107fc8bb91bSFelipe Balbi 	pm_runtime_put_sync(&pdev->dev);
1108fc8bb91bSFelipe Balbi 	pm_runtime_allow(&pdev->dev);
1109fc8bb91bSFelipe Balbi 	pm_runtime_disable(&pdev->dev);
1110fc8bb91bSFelipe Balbi 
1111c499ff71SFelipe Balbi 	dwc3_free_event_buffers(dwc);
1112c499ff71SFelipe Balbi 	dwc3_free_scratch_buffers(dwc);
1113c499ff71SFelipe Balbi 
111472246da4SFelipe Balbi 	return 0;
111572246da4SFelipe Balbi }
111672246da4SFelipe Balbi 
1117fc8bb91bSFelipe Balbi #ifdef CONFIG_PM
1118fc8bb91bSFelipe Balbi static int dwc3_suspend_common(struct dwc3 *dwc)
11197415f17cSFelipe Balbi {
1120fc8bb91bSFelipe Balbi 	unsigned long	flags;
11217415f17cSFelipe Balbi 
1122a45c82b8SRuchika Kharwar 	switch (dwc->dr_mode) {
1123a45c82b8SRuchika Kharwar 	case USB_DR_MODE_PERIPHERAL:
1124a45c82b8SRuchika Kharwar 	case USB_DR_MODE_OTG:
1125fc8bb91bSFelipe Balbi 		spin_lock_irqsave(&dwc->lock, flags);
11267415f17cSFelipe Balbi 		dwc3_gadget_suspend(dwc);
1127fc8bb91bSFelipe Balbi 		spin_unlock_irqrestore(&dwc->lock, flags);
112851f5d49aSFelipe Balbi 		break;
1129a45c82b8SRuchika Kharwar 	case USB_DR_MODE_HOST:
11307415f17cSFelipe Balbi 	default:
113151f5d49aSFelipe Balbi 		/* do nothing */
11327415f17cSFelipe Balbi 		break;
11337415f17cSFelipe Balbi 	}
11347415f17cSFelipe Balbi 
113551f5d49aSFelipe Balbi 	dwc3_core_exit(dwc);
11365c4ad318SFelipe Balbi 
1137fc8bb91bSFelipe Balbi 	return 0;
1138fc8bb91bSFelipe Balbi }
1139fc8bb91bSFelipe Balbi 
1140fc8bb91bSFelipe Balbi static int dwc3_resume_common(struct dwc3 *dwc)
1141fc8bb91bSFelipe Balbi {
1142fc8bb91bSFelipe Balbi 	unsigned long	flags;
1143fc8bb91bSFelipe Balbi 	int		ret;
1144fc8bb91bSFelipe Balbi 
1145fc8bb91bSFelipe Balbi 	ret = dwc3_core_init(dwc);
1146fc8bb91bSFelipe Balbi 	if (ret)
1147fc8bb91bSFelipe Balbi 		return ret;
1148fc8bb91bSFelipe Balbi 
1149fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1150fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1151fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1152fc8bb91bSFelipe Balbi 		spin_lock_irqsave(&dwc->lock, flags);
1153fc8bb91bSFelipe Balbi 		dwc3_gadget_resume(dwc);
1154fc8bb91bSFelipe Balbi 		spin_unlock_irqrestore(&dwc->lock, flags);
1155fc8bb91bSFelipe Balbi 		/* FALLTHROUGH */
1156fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1157fc8bb91bSFelipe Balbi 	default:
1158fc8bb91bSFelipe Balbi 		/* do nothing */
1159fc8bb91bSFelipe Balbi 		break;
1160fc8bb91bSFelipe Balbi 	}
1161fc8bb91bSFelipe Balbi 
1162fc8bb91bSFelipe Balbi 	return 0;
1163fc8bb91bSFelipe Balbi }
1164fc8bb91bSFelipe Balbi 
1165fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc)
1166fc8bb91bSFelipe Balbi {
1167fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1168fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1169fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1170fc8bb91bSFelipe Balbi 		if (dwc->connected)
1171fc8bb91bSFelipe Balbi 			return -EBUSY;
1172fc8bb91bSFelipe Balbi 		break;
1173fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1174fc8bb91bSFelipe Balbi 	default:
1175fc8bb91bSFelipe Balbi 		/* do nothing */
1176fc8bb91bSFelipe Balbi 		break;
1177fc8bb91bSFelipe Balbi 	}
1178fc8bb91bSFelipe Balbi 
1179fc8bb91bSFelipe Balbi 	return 0;
1180fc8bb91bSFelipe Balbi }
1181fc8bb91bSFelipe Balbi 
1182fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev)
1183fc8bb91bSFelipe Balbi {
1184fc8bb91bSFelipe Balbi 	struct dwc3     *dwc = dev_get_drvdata(dev);
1185fc8bb91bSFelipe Balbi 	int		ret;
1186fc8bb91bSFelipe Balbi 
1187fc8bb91bSFelipe Balbi 	if (dwc3_runtime_checks(dwc))
1188fc8bb91bSFelipe Balbi 		return -EBUSY;
1189fc8bb91bSFelipe Balbi 
1190fc8bb91bSFelipe Balbi 	ret = dwc3_suspend_common(dwc);
1191fc8bb91bSFelipe Balbi 	if (ret)
1192fc8bb91bSFelipe Balbi 		return ret;
1193fc8bb91bSFelipe Balbi 
1194fc8bb91bSFelipe Balbi 	device_init_wakeup(dev, true);
1195fc8bb91bSFelipe Balbi 
1196fc8bb91bSFelipe Balbi 	return 0;
1197fc8bb91bSFelipe Balbi }
1198fc8bb91bSFelipe Balbi 
1199fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev)
1200fc8bb91bSFelipe Balbi {
1201fc8bb91bSFelipe Balbi 	struct dwc3     *dwc = dev_get_drvdata(dev);
1202fc8bb91bSFelipe Balbi 	int		ret;
1203fc8bb91bSFelipe Balbi 
1204fc8bb91bSFelipe Balbi 	device_init_wakeup(dev, false);
1205fc8bb91bSFelipe Balbi 
1206fc8bb91bSFelipe Balbi 	ret = dwc3_resume_common(dwc);
1207fc8bb91bSFelipe Balbi 	if (ret)
1208fc8bb91bSFelipe Balbi 		return ret;
1209fc8bb91bSFelipe Balbi 
1210fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1211fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1212fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1213fc8bb91bSFelipe Balbi 		dwc3_gadget_process_pending_events(dwc);
1214fc8bb91bSFelipe Balbi 		break;
1215fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1216fc8bb91bSFelipe Balbi 	default:
1217fc8bb91bSFelipe Balbi 		/* do nothing */
1218fc8bb91bSFelipe Balbi 		break;
1219fc8bb91bSFelipe Balbi 	}
1220fc8bb91bSFelipe Balbi 
1221fc8bb91bSFelipe Balbi 	pm_runtime_mark_last_busy(dev);
1222fc8bb91bSFelipe Balbi 
1223fc8bb91bSFelipe Balbi 	return 0;
1224fc8bb91bSFelipe Balbi }
1225fc8bb91bSFelipe Balbi 
1226fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev)
1227fc8bb91bSFelipe Balbi {
1228fc8bb91bSFelipe Balbi 	struct dwc3     *dwc = dev_get_drvdata(dev);
1229fc8bb91bSFelipe Balbi 
1230fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1231fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1232fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1233fc8bb91bSFelipe Balbi 		if (dwc3_runtime_checks(dwc))
1234fc8bb91bSFelipe Balbi 			return -EBUSY;
1235fc8bb91bSFelipe Balbi 		break;
1236fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1237fc8bb91bSFelipe Balbi 	default:
1238fc8bb91bSFelipe Balbi 		/* do nothing */
1239fc8bb91bSFelipe Balbi 		break;
1240fc8bb91bSFelipe Balbi 	}
1241fc8bb91bSFelipe Balbi 
1242fc8bb91bSFelipe Balbi 	pm_runtime_mark_last_busy(dev);
1243fc8bb91bSFelipe Balbi 	pm_runtime_autosuspend(dev);
1244fc8bb91bSFelipe Balbi 
1245fc8bb91bSFelipe Balbi 	return 0;
1246fc8bb91bSFelipe Balbi }
1247fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */
1248fc8bb91bSFelipe Balbi 
1249fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP
1250fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev)
1251fc8bb91bSFelipe Balbi {
1252fc8bb91bSFelipe Balbi 	struct dwc3	*dwc = dev_get_drvdata(dev);
1253fc8bb91bSFelipe Balbi 	int		ret;
1254fc8bb91bSFelipe Balbi 
1255fc8bb91bSFelipe Balbi 	ret = dwc3_suspend_common(dwc);
1256fc8bb91bSFelipe Balbi 	if (ret)
1257fc8bb91bSFelipe Balbi 		return ret;
1258fc8bb91bSFelipe Balbi 
12596344475fSSekhar Nori 	pinctrl_pm_select_sleep_state(dev);
12606344475fSSekhar Nori 
12617415f17cSFelipe Balbi 	return 0;
12627415f17cSFelipe Balbi }
12637415f17cSFelipe Balbi 
12647415f17cSFelipe Balbi static int dwc3_resume(struct device *dev)
12657415f17cSFelipe Balbi {
12667415f17cSFelipe Balbi 	struct dwc3	*dwc = dev_get_drvdata(dev);
126757303488SKishon Vijay Abraham I 	int		ret;
12687415f17cSFelipe Balbi 
12696344475fSSekhar Nori 	pinctrl_pm_select_default_state(dev);
12706344475fSSekhar Nori 
1271fc8bb91bSFelipe Balbi 	ret = dwc3_resume_common(dwc);
127251f5d49aSFelipe Balbi 	if (ret)
12735c4ad318SFelipe Balbi 		return ret;
12745c4ad318SFelipe Balbi 
12757415f17cSFelipe Balbi 	pm_runtime_disable(dev);
12767415f17cSFelipe Balbi 	pm_runtime_set_active(dev);
12777415f17cSFelipe Balbi 	pm_runtime_enable(dev);
12787415f17cSFelipe Balbi 
12797415f17cSFelipe Balbi 	return 0;
12807415f17cSFelipe Balbi }
12817f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */
12827415f17cSFelipe Balbi 
12837415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = {
12847415f17cSFelipe Balbi 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
1285fc8bb91bSFelipe Balbi 	SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
1286fc8bb91bSFelipe Balbi 			dwc3_runtime_idle)
12877415f17cSFelipe Balbi };
12887415f17cSFelipe Balbi 
12895088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF
12905088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = {
12915088b6f5SKishon Vijay Abraham I 	{
129222a5aa17SFelipe Balbi 		.compatible = "snps,dwc3"
129322a5aa17SFelipe Balbi 	},
129422a5aa17SFelipe Balbi 	{
12955088b6f5SKishon Vijay Abraham I 		.compatible = "synopsys,dwc3"
12965088b6f5SKishon Vijay Abraham I 	},
12975088b6f5SKishon Vijay Abraham I 	{ },
12985088b6f5SKishon Vijay Abraham I };
12995088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match);
13005088b6f5SKishon Vijay Abraham I #endif
13015088b6f5SKishon Vijay Abraham I 
1302404905a6SHeikki Krogerus #ifdef CONFIG_ACPI
1303404905a6SHeikki Krogerus 
1304404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW	"808622B7"
1305404905a6SHeikki Krogerus 
1306404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = {
1307404905a6SHeikki Krogerus 	{ ACPI_ID_INTEL_BSW, 0 },
1308404905a6SHeikki Krogerus 	{ },
1309404905a6SHeikki Krogerus };
1310404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match);
1311404905a6SHeikki Krogerus #endif
1312404905a6SHeikki Krogerus 
131372246da4SFelipe Balbi static struct platform_driver dwc3_driver = {
131472246da4SFelipe Balbi 	.probe		= dwc3_probe,
13157690417dSBill Pemberton 	.remove		= dwc3_remove,
131672246da4SFelipe Balbi 	.driver		= {
131772246da4SFelipe Balbi 		.name	= "dwc3",
13185088b6f5SKishon Vijay Abraham I 		.of_match_table	= of_match_ptr(of_dwc3_match),
1319404905a6SHeikki Krogerus 		.acpi_match_table = ACPI_PTR(dwc3_acpi_match),
13207f370ed0SFelipe Balbi 		.pm	= &dwc3_dev_pm_ops,
132172246da4SFelipe Balbi 	},
132272246da4SFelipe Balbi };
132372246da4SFelipe Balbi 
1324b1116dccSTobias Klauser module_platform_driver(dwc3_driver);
1325b1116dccSTobias Klauser 
13267ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3");
132772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
13285945f789SFelipe Balbi MODULE_LICENSE("GPL v2");
132972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
1330