xref: /openbmc/linux/drivers/usb/dwc3/core.c (revision 5eb30ced)
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 
4472246da4SFelipe Balbi #include "core.h"
4572246da4SFelipe Balbi #include "gadget.h"
4672246da4SFelipe Balbi #include "io.h"
4772246da4SFelipe Balbi 
4872246da4SFelipe Balbi #include "debug.h"
4972246da4SFelipe Balbi 
50fc8bb91bSFelipe Balbi #define DWC3_DEFAULT_AUTOSUSPEND_DELAY	5000 /* ms */
518300dd23SFelipe Balbi 
529d6173e1SThinh Nguyen /**
539d6173e1SThinh Nguyen  * dwc3_get_dr_mode - Validates and sets dr_mode
549d6173e1SThinh Nguyen  * @dwc: pointer to our context structure
559d6173e1SThinh Nguyen  */
569d6173e1SThinh Nguyen static int dwc3_get_dr_mode(struct dwc3 *dwc)
579d6173e1SThinh Nguyen {
589d6173e1SThinh Nguyen 	enum usb_dr_mode mode;
599d6173e1SThinh Nguyen 	struct device *dev = dwc->dev;
609d6173e1SThinh Nguyen 	unsigned int hw_mode;
619d6173e1SThinh Nguyen 
629d6173e1SThinh Nguyen 	if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
639d6173e1SThinh Nguyen 		dwc->dr_mode = USB_DR_MODE_OTG;
649d6173e1SThinh Nguyen 
659d6173e1SThinh Nguyen 	mode = dwc->dr_mode;
669d6173e1SThinh Nguyen 	hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
679d6173e1SThinh Nguyen 
689d6173e1SThinh Nguyen 	switch (hw_mode) {
699d6173e1SThinh Nguyen 	case DWC3_GHWPARAMS0_MODE_GADGET:
709d6173e1SThinh Nguyen 		if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) {
719d6173e1SThinh Nguyen 			dev_err(dev,
729d6173e1SThinh Nguyen 				"Controller does not support host mode.\n");
739d6173e1SThinh Nguyen 			return -EINVAL;
749d6173e1SThinh Nguyen 		}
759d6173e1SThinh Nguyen 		mode = USB_DR_MODE_PERIPHERAL;
769d6173e1SThinh Nguyen 		break;
779d6173e1SThinh Nguyen 	case DWC3_GHWPARAMS0_MODE_HOST:
789d6173e1SThinh Nguyen 		if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
799d6173e1SThinh Nguyen 			dev_err(dev,
809d6173e1SThinh Nguyen 				"Controller does not support device mode.\n");
819d6173e1SThinh Nguyen 			return -EINVAL;
829d6173e1SThinh Nguyen 		}
839d6173e1SThinh Nguyen 		mode = USB_DR_MODE_HOST;
849d6173e1SThinh Nguyen 		break;
859d6173e1SThinh Nguyen 	default:
869d6173e1SThinh Nguyen 		if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
879d6173e1SThinh Nguyen 			mode = USB_DR_MODE_HOST;
889d6173e1SThinh Nguyen 		else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
899d6173e1SThinh Nguyen 			mode = USB_DR_MODE_PERIPHERAL;
909d6173e1SThinh Nguyen 	}
919d6173e1SThinh Nguyen 
929d6173e1SThinh Nguyen 	if (mode != dwc->dr_mode) {
939d6173e1SThinh Nguyen 		dev_warn(dev,
949d6173e1SThinh Nguyen 			 "Configuration mismatch. dr_mode forced to %s\n",
959d6173e1SThinh Nguyen 			 mode == USB_DR_MODE_HOST ? "host" : "gadget");
969d6173e1SThinh Nguyen 
979d6173e1SThinh Nguyen 		dwc->dr_mode = mode;
989d6173e1SThinh Nguyen 	}
999d6173e1SThinh Nguyen 
1009d6173e1SThinh Nguyen 	return 0;
1019d6173e1SThinh Nguyen }
1029d6173e1SThinh Nguyen 
1033140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
1043140e8cbSSebastian Andrzej Siewior {
1053140e8cbSSebastian Andrzej Siewior 	u32 reg;
1063140e8cbSSebastian Andrzej Siewior 
1073140e8cbSSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
1083140e8cbSSebastian Andrzej Siewior 	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
1093140e8cbSSebastian Andrzej Siewior 	reg |= DWC3_GCTL_PRTCAPDIR(mode);
1103140e8cbSSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
1113140e8cbSSebastian Andrzej Siewior }
1128300dd23SFelipe Balbi 
113cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type)
114cf6d867dSFelipe Balbi {
115cf6d867dSFelipe Balbi 	struct dwc3		*dwc = dep->dwc;
116cf6d867dSFelipe Balbi 	u32			reg;
117cf6d867dSFelipe Balbi 
118cf6d867dSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE,
119cf6d867dSFelipe Balbi 			DWC3_GDBGFIFOSPACE_NUM(dep->number) |
120cf6d867dSFelipe Balbi 			DWC3_GDBGFIFOSPACE_TYPE(type));
121cf6d867dSFelipe Balbi 
122cf6d867dSFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE);
123cf6d867dSFelipe Balbi 
124cf6d867dSFelipe Balbi 	return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg);
125cf6d867dSFelipe Balbi }
126cf6d867dSFelipe Balbi 
12772246da4SFelipe Balbi /**
12872246da4SFelipe Balbi  * dwc3_core_soft_reset - Issues core soft reset and PHY reset
12972246da4SFelipe Balbi  * @dwc: pointer to our context structure
13072246da4SFelipe Balbi  */
13157303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc)
13272246da4SFelipe Balbi {
13372246da4SFelipe Balbi 	u32		reg;
134f59dcab1SFelipe Balbi 	int		retries = 1000;
13557303488SKishon Vijay Abraham I 	int		ret;
13672246da4SFelipe Balbi 
13751e1e7bcSFelipe Balbi 	usb_phy_init(dwc->usb2_phy);
13851e1e7bcSFelipe Balbi 	usb_phy_init(dwc->usb3_phy);
13957303488SKishon Vijay Abraham I 	ret = phy_init(dwc->usb2_generic_phy);
14057303488SKishon Vijay Abraham I 	if (ret < 0)
14157303488SKishon Vijay Abraham I 		return ret;
14257303488SKishon Vijay Abraham I 
14357303488SKishon Vijay Abraham I 	ret = phy_init(dwc->usb3_generic_phy);
14457303488SKishon Vijay Abraham I 	if (ret < 0) {
14557303488SKishon Vijay Abraham I 		phy_exit(dwc->usb2_generic_phy);
14657303488SKishon Vijay Abraham I 		return ret;
14757303488SKishon Vijay Abraham I 	}
14872246da4SFelipe Balbi 
149f59dcab1SFelipe Balbi 	/*
150f59dcab1SFelipe Balbi 	 * We're resetting only the device side because, if we're in host mode,
151f59dcab1SFelipe Balbi 	 * XHCI driver will reset the host block. If dwc3 was configured for
152f59dcab1SFelipe Balbi 	 * host-only mode, then we can return early.
153f59dcab1SFelipe Balbi 	 */
154f59dcab1SFelipe Balbi 	if (dwc->dr_mode == USB_DR_MODE_HOST)
15557303488SKishon Vijay Abraham I 		return 0;
156f59dcab1SFelipe Balbi 
157f59dcab1SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
158f59dcab1SFelipe Balbi 	reg |= DWC3_DCTL_CSFTRST;
159f59dcab1SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
160f59dcab1SFelipe Balbi 
161f59dcab1SFelipe Balbi 	do {
162f59dcab1SFelipe Balbi 		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
163f59dcab1SFelipe Balbi 		if (!(reg & DWC3_DCTL_CSFTRST))
164f59dcab1SFelipe Balbi 			return 0;
165f59dcab1SFelipe Balbi 
166f59dcab1SFelipe Balbi 		udelay(1);
167f59dcab1SFelipe Balbi 	} while (--retries);
168f59dcab1SFelipe Balbi 
169f59dcab1SFelipe Balbi 	return -ETIMEDOUT;
17072246da4SFelipe Balbi }
17172246da4SFelipe Balbi 
17272246da4SFelipe Balbi /**
173c5cc74e8SHeikki Krogerus  * dwc3_soft_reset - Issue soft reset
174c5cc74e8SHeikki Krogerus  * @dwc: Pointer to our controller context structure
175c5cc74e8SHeikki Krogerus  */
176c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc)
177c5cc74e8SHeikki Krogerus {
178c5cc74e8SHeikki Krogerus 	unsigned long timeout;
179c5cc74e8SHeikki Krogerus 	u32 reg;
180c5cc74e8SHeikki Krogerus 
181c5cc74e8SHeikki Krogerus 	timeout = jiffies + msecs_to_jiffies(500);
182c5cc74e8SHeikki Krogerus 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
183c5cc74e8SHeikki Krogerus 	do {
184c5cc74e8SHeikki Krogerus 		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
185c5cc74e8SHeikki Krogerus 		if (!(reg & DWC3_DCTL_CSFTRST))
186c5cc74e8SHeikki Krogerus 			break;
187c5cc74e8SHeikki Krogerus 
188c5cc74e8SHeikki Krogerus 		if (time_after(jiffies, timeout)) {
189c5cc74e8SHeikki Krogerus 			dev_err(dwc->dev, "Reset Timed Out\n");
190c5cc74e8SHeikki Krogerus 			return -ETIMEDOUT;
191c5cc74e8SHeikki Krogerus 		}
192c5cc74e8SHeikki Krogerus 
193c5cc74e8SHeikki Krogerus 		cpu_relax();
194c5cc74e8SHeikki Krogerus 	} while (true);
195c5cc74e8SHeikki Krogerus 
196c5cc74e8SHeikki Krogerus 	return 0;
197c5cc74e8SHeikki Krogerus }
198c5cc74e8SHeikki Krogerus 
199db2be4e9SNikhil Badola /*
200db2be4e9SNikhil Badola  * dwc3_frame_length_adjustment - Adjusts frame length if required
201db2be4e9SNikhil Badola  * @dwc3: Pointer to our controller context structure
202db2be4e9SNikhil Badola  */
203bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
204db2be4e9SNikhil Badola {
205db2be4e9SNikhil Badola 	u32 reg;
206db2be4e9SNikhil Badola 	u32 dft;
207db2be4e9SNikhil Badola 
208db2be4e9SNikhil Badola 	if (dwc->revision < DWC3_REVISION_250A)
209db2be4e9SNikhil Badola 		return;
210db2be4e9SNikhil Badola 
211bcdb3272SFelipe Balbi 	if (dwc->fladj == 0)
212db2be4e9SNikhil Badola 		return;
213db2be4e9SNikhil Badola 
214db2be4e9SNikhil Badola 	reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
215db2be4e9SNikhil Badola 	dft = reg & DWC3_GFLADJ_30MHZ_MASK;
216bcdb3272SFelipe Balbi 	if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj,
217db2be4e9SNikhil Badola 	    "request value same as default, ignoring\n")) {
218db2be4e9SNikhil Badola 		reg &= ~DWC3_GFLADJ_30MHZ_MASK;
219bcdb3272SFelipe Balbi 		reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
220db2be4e9SNikhil Badola 		dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
221db2be4e9SNikhil Badola 	}
222db2be4e9SNikhil Badola }
223db2be4e9SNikhil Badola 
224c5cc74e8SHeikki Krogerus /**
22572246da4SFelipe Balbi  * dwc3_free_one_event_buffer - Frees one event buffer
22672246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
22772246da4SFelipe Balbi  * @evt: Pointer to event buffer to be freed
22872246da4SFelipe Balbi  */
22972246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
23072246da4SFelipe Balbi 		struct dwc3_event_buffer *evt)
23172246da4SFelipe Balbi {
23272246da4SFelipe Balbi 	dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
23372246da4SFelipe Balbi }
23472246da4SFelipe Balbi 
23572246da4SFelipe Balbi /**
2361d046793SPaul Zimmerman  * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
23772246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
23872246da4SFelipe Balbi  * @length: size of the event buffer
23972246da4SFelipe Balbi  *
2401d046793SPaul Zimmerman  * Returns a pointer to the allocated event buffer structure on success
24172246da4SFelipe Balbi  * otherwise ERR_PTR(errno).
24272246da4SFelipe Balbi  */
24367d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
24467d0b500SFelipe Balbi 		unsigned length)
24572246da4SFelipe Balbi {
24672246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
24772246da4SFelipe Balbi 
248380f0d28SFelipe Balbi 	evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
24972246da4SFelipe Balbi 	if (!evt)
25072246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
25172246da4SFelipe Balbi 
25272246da4SFelipe Balbi 	evt->dwc	= dwc;
25372246da4SFelipe Balbi 	evt->length	= length;
25472246da4SFelipe Balbi 	evt->buf	= dma_alloc_coherent(dwc->dev, length,
25572246da4SFelipe Balbi 			&evt->dma, GFP_KERNEL);
256e32672f0SFelipe Balbi 	if (!evt->buf)
25772246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
25872246da4SFelipe Balbi 
25972246da4SFelipe Balbi 	return evt;
26072246da4SFelipe Balbi }
26172246da4SFelipe Balbi 
26272246da4SFelipe Balbi /**
26372246da4SFelipe Balbi  * dwc3_free_event_buffers - frees all allocated event buffers
26472246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
26572246da4SFelipe Balbi  */
26672246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc)
26772246da4SFelipe Balbi {
26872246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
26972246da4SFelipe Balbi 
270696c8b12SFelipe Balbi 	evt = dwc->ev_buf;
27164b6c8a7SAnton Tikhomirov 	if (evt)
27272246da4SFelipe Balbi 		dwc3_free_one_event_buffer(dwc, evt);
27372246da4SFelipe Balbi }
27472246da4SFelipe Balbi 
27572246da4SFelipe Balbi /**
27672246da4SFelipe Balbi  * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
2771d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
27872246da4SFelipe Balbi  * @length: size of event buffer
27972246da4SFelipe Balbi  *
2801d046793SPaul Zimmerman  * Returns 0 on success otherwise negative errno. In the error case, dwc
28172246da4SFelipe Balbi  * may contain some buffers allocated but not all which were requested.
28272246da4SFelipe Balbi  */
28341ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
28472246da4SFelipe Balbi {
28572246da4SFelipe Balbi 	struct dwc3_event_buffer *evt;
28672246da4SFelipe Balbi 
28772246da4SFelipe Balbi 	evt = dwc3_alloc_one_event_buffer(dwc, length);
28872246da4SFelipe Balbi 	if (IS_ERR(evt)) {
28972246da4SFelipe Balbi 		dev_err(dwc->dev, "can't allocate event buffer\n");
29072246da4SFelipe Balbi 		return PTR_ERR(evt);
29172246da4SFelipe Balbi 	}
292696c8b12SFelipe Balbi 	dwc->ev_buf = evt;
29372246da4SFelipe Balbi 
29472246da4SFelipe Balbi 	return 0;
29572246da4SFelipe Balbi }
29672246da4SFelipe Balbi 
29772246da4SFelipe Balbi /**
29872246da4SFelipe Balbi  * dwc3_event_buffers_setup - setup our allocated event buffers
2991d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
30072246da4SFelipe Balbi  *
30172246da4SFelipe Balbi  * Returns 0 on success otherwise negative errno.
30272246da4SFelipe Balbi  */
3037acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc)
30472246da4SFelipe Balbi {
30572246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
30672246da4SFelipe Balbi 
307696c8b12SFelipe Balbi 	evt = dwc->ev_buf;
3087acd85e0SPaul Zimmerman 	evt->lpos = 0;
309660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
31072246da4SFelipe Balbi 			lower_32_bits(evt->dma));
311660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0),
31272246da4SFelipe Balbi 			upper_32_bits(evt->dma));
313660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
31468d6a01bSFelipe Balbi 			DWC3_GEVNTSIZ_SIZE(evt->length));
315660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);
31672246da4SFelipe Balbi 
31772246da4SFelipe Balbi 	return 0;
31872246da4SFelipe Balbi }
31972246da4SFelipe Balbi 
32072246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
32172246da4SFelipe Balbi {
32272246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
32372246da4SFelipe Balbi 
324696c8b12SFelipe Balbi 	evt = dwc->ev_buf;
3257acd85e0SPaul Zimmerman 
3267acd85e0SPaul Zimmerman 	evt->lpos = 0;
3277acd85e0SPaul Zimmerman 
328660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0);
329660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0);
330660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK
33168d6a01bSFelipe Balbi 			| DWC3_GEVNTSIZ_SIZE(0));
332660e9bdeSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);
33372246da4SFelipe Balbi }
33472246da4SFelipe Balbi 
3350ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
3360ffcaf37SFelipe Balbi {
3370ffcaf37SFelipe Balbi 	if (!dwc->has_hibernation)
3380ffcaf37SFelipe Balbi 		return 0;
3390ffcaf37SFelipe Balbi 
3400ffcaf37SFelipe Balbi 	if (!dwc->nr_scratch)
3410ffcaf37SFelipe Balbi 		return 0;
3420ffcaf37SFelipe Balbi 
3430ffcaf37SFelipe Balbi 	dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
3440ffcaf37SFelipe Balbi 			DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
3450ffcaf37SFelipe Balbi 	if (!dwc->scratchbuf)
3460ffcaf37SFelipe Balbi 		return -ENOMEM;
3470ffcaf37SFelipe Balbi 
3480ffcaf37SFelipe Balbi 	return 0;
3490ffcaf37SFelipe Balbi }
3500ffcaf37SFelipe Balbi 
3510ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
3520ffcaf37SFelipe Balbi {
3530ffcaf37SFelipe Balbi 	dma_addr_t scratch_addr;
3540ffcaf37SFelipe Balbi 	u32 param;
3550ffcaf37SFelipe Balbi 	int ret;
3560ffcaf37SFelipe Balbi 
3570ffcaf37SFelipe Balbi 	if (!dwc->has_hibernation)
3580ffcaf37SFelipe Balbi 		return 0;
3590ffcaf37SFelipe Balbi 
3600ffcaf37SFelipe Balbi 	if (!dwc->nr_scratch)
3610ffcaf37SFelipe Balbi 		return 0;
3620ffcaf37SFelipe Balbi 
3630ffcaf37SFelipe Balbi 	 /* should never fall here */
3640ffcaf37SFelipe Balbi 	if (!WARN_ON(dwc->scratchbuf))
3650ffcaf37SFelipe Balbi 		return 0;
3660ffcaf37SFelipe Balbi 
3670ffcaf37SFelipe Balbi 	scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf,
3680ffcaf37SFelipe Balbi 			dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
3690ffcaf37SFelipe Balbi 			DMA_BIDIRECTIONAL);
3700ffcaf37SFelipe Balbi 	if (dma_mapping_error(dwc->dev, scratch_addr)) {
3710ffcaf37SFelipe Balbi 		dev_err(dwc->dev, "failed to map scratch buffer\n");
3720ffcaf37SFelipe Balbi 		ret = -EFAULT;
3730ffcaf37SFelipe Balbi 		goto err0;
3740ffcaf37SFelipe Balbi 	}
3750ffcaf37SFelipe Balbi 
3760ffcaf37SFelipe Balbi 	dwc->scratch_addr = scratch_addr;
3770ffcaf37SFelipe Balbi 
3780ffcaf37SFelipe Balbi 	param = lower_32_bits(scratch_addr);
3790ffcaf37SFelipe Balbi 
3800ffcaf37SFelipe Balbi 	ret = dwc3_send_gadget_generic_command(dwc,
3810ffcaf37SFelipe Balbi 			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
3820ffcaf37SFelipe Balbi 	if (ret < 0)
3830ffcaf37SFelipe Balbi 		goto err1;
3840ffcaf37SFelipe Balbi 
3850ffcaf37SFelipe Balbi 	param = upper_32_bits(scratch_addr);
3860ffcaf37SFelipe Balbi 
3870ffcaf37SFelipe Balbi 	ret = dwc3_send_gadget_generic_command(dwc,
3880ffcaf37SFelipe Balbi 			DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
3890ffcaf37SFelipe Balbi 	if (ret < 0)
3900ffcaf37SFelipe Balbi 		goto err1;
3910ffcaf37SFelipe Balbi 
3920ffcaf37SFelipe Balbi 	return 0;
3930ffcaf37SFelipe Balbi 
3940ffcaf37SFelipe Balbi err1:
3950ffcaf37SFelipe Balbi 	dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
3960ffcaf37SFelipe Balbi 			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
3970ffcaf37SFelipe Balbi 
3980ffcaf37SFelipe Balbi err0:
3990ffcaf37SFelipe Balbi 	return ret;
4000ffcaf37SFelipe Balbi }
4010ffcaf37SFelipe Balbi 
4020ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
4030ffcaf37SFelipe Balbi {
4040ffcaf37SFelipe Balbi 	if (!dwc->has_hibernation)
4050ffcaf37SFelipe Balbi 		return;
4060ffcaf37SFelipe Balbi 
4070ffcaf37SFelipe Balbi 	if (!dwc->nr_scratch)
4080ffcaf37SFelipe Balbi 		return;
4090ffcaf37SFelipe Balbi 
4100ffcaf37SFelipe Balbi 	 /* should never fall here */
4110ffcaf37SFelipe Balbi 	if (!WARN_ON(dwc->scratchbuf))
4120ffcaf37SFelipe Balbi 		return;
4130ffcaf37SFelipe Balbi 
4140ffcaf37SFelipe Balbi 	dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
4150ffcaf37SFelipe Balbi 			DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
4160ffcaf37SFelipe Balbi 	kfree(dwc->scratchbuf);
4170ffcaf37SFelipe Balbi }
4180ffcaf37SFelipe Balbi 
419789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc)
420789451f6SFelipe Balbi {
421789451f6SFelipe Balbi 	struct dwc3_hwparams	*parms = &dwc->hwparams;
422789451f6SFelipe Balbi 
423789451f6SFelipe Balbi 	dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
424789451f6SFelipe Balbi 	dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
425789451f6SFelipe Balbi }
426789451f6SFelipe Balbi 
42741ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc)
42826ceca97SFelipe Balbi {
42926ceca97SFelipe Balbi 	struct dwc3_hwparams	*parms = &dwc->hwparams;
43026ceca97SFelipe Balbi 
43126ceca97SFelipe Balbi 	parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
43226ceca97SFelipe Balbi 	parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
43326ceca97SFelipe Balbi 	parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
43426ceca97SFelipe Balbi 	parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
43526ceca97SFelipe Balbi 	parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
43626ceca97SFelipe Balbi 	parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
43726ceca97SFelipe Balbi 	parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
43826ceca97SFelipe Balbi 	parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
43926ceca97SFelipe Balbi 	parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
44026ceca97SFelipe Balbi }
44126ceca97SFelipe Balbi 
44272246da4SFelipe Balbi /**
443b5a65c40SHuang Rui  * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
444b5a65c40SHuang Rui  * @dwc: Pointer to our controller context structure
44588bc9d19SHeikki Krogerus  *
44688bc9d19SHeikki Krogerus  * Returns 0 on success. The USB PHY interfaces are configured but not
44788bc9d19SHeikki Krogerus  * initialized. The PHY interfaces and the PHYs get initialized together with
44888bc9d19SHeikki Krogerus  * the core in dwc3_core_init.
449b5a65c40SHuang Rui  */
45088bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc)
451b5a65c40SHuang Rui {
452b5a65c40SHuang Rui 	u32 reg;
45388bc9d19SHeikki Krogerus 	int ret;
454b5a65c40SHuang Rui 
455b5a65c40SHuang Rui 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
456b5a65c40SHuang Rui 
4572164a476SHuang Rui 	/*
4582164a476SHuang Rui 	 * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
4592164a476SHuang Rui 	 * to '0' during coreConsultant configuration. So default value
4602164a476SHuang Rui 	 * will be '0' when the core is reset. Application needs to set it
4612164a476SHuang Rui 	 * to '1' after the core initialization is completed.
4622164a476SHuang Rui 	 */
4632164a476SHuang Rui 	if (dwc->revision > DWC3_REVISION_194A)
4642164a476SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_SUSPHY;
4652164a476SHuang Rui 
466b5a65c40SHuang Rui 	if (dwc->u2ss_inp3_quirk)
467b5a65c40SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
468b5a65c40SHuang Rui 
469e58dd357SRajesh Bhagat 	if (dwc->dis_rxdet_inp3_quirk)
470e58dd357SRajesh Bhagat 		reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3;
471e58dd357SRajesh Bhagat 
472df31f5b3SHuang Rui 	if (dwc->req_p1p2p3_quirk)
473df31f5b3SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
474df31f5b3SHuang Rui 
475a2a1d0f5SHuang Rui 	if (dwc->del_p1p2p3_quirk)
476a2a1d0f5SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
477a2a1d0f5SHuang Rui 
47841c06ffdSHuang Rui 	if (dwc->del_phy_power_chg_quirk)
47941c06ffdSHuang Rui 		reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
48041c06ffdSHuang Rui 
481fb67afcaSHuang Rui 	if (dwc->lfps_filter_quirk)
482fb67afcaSHuang Rui 		reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
483fb67afcaSHuang Rui 
48414f4ac53SHuang Rui 	if (dwc->rx_detect_poll_quirk)
48514f4ac53SHuang Rui 		reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
48614f4ac53SHuang Rui 
4876b6a0c9aSHuang Rui 	if (dwc->tx_de_emphasis_quirk)
4886b6a0c9aSHuang Rui 		reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
4896b6a0c9aSHuang Rui 
490cd72f890SFelipe Balbi 	if (dwc->dis_u3_susphy_quirk)
49159acfa20SHuang Rui 		reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
49259acfa20SHuang Rui 
49300fe081dSWilliam Wu 	if (dwc->dis_del_phy_power_chg_quirk)
49400fe081dSWilliam Wu 		reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
49500fe081dSWilliam Wu 
496b5a65c40SHuang Rui 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
497b5a65c40SHuang Rui 
4982164a476SHuang Rui 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
4992164a476SHuang Rui 
5003e10a2ceSHeikki Krogerus 	/* Select the HS PHY interface */
5013e10a2ceSHeikki Krogerus 	switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) {
5023e10a2ceSHeikki Krogerus 	case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI:
50343cacb03SFelipe Balbi 		if (dwc->hsphy_interface &&
50443cacb03SFelipe Balbi 				!strncmp(dwc->hsphy_interface, "utmi", 4)) {
5053e10a2ceSHeikki Krogerus 			reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI;
50688bc9d19SHeikki Krogerus 			break;
50743cacb03SFelipe Balbi 		} else if (dwc->hsphy_interface &&
50843cacb03SFelipe Balbi 				!strncmp(dwc->hsphy_interface, "ulpi", 4)) {
5093e10a2ceSHeikki Krogerus 			reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
51088bc9d19SHeikki Krogerus 			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
5113e10a2ceSHeikki Krogerus 		} else {
51288bc9d19SHeikki Krogerus 			/* Relying on default value. */
51388bc9d19SHeikki Krogerus 			if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
5143e10a2ceSHeikki Krogerus 				break;
5153e10a2ceSHeikki Krogerus 		}
5163e10a2ceSHeikki Krogerus 		/* FALLTHROUGH */
51788bc9d19SHeikki Krogerus 	case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
51888bc9d19SHeikki Krogerus 		/* Making sure the interface and PHY are operational */
51988bc9d19SHeikki Krogerus 		ret = dwc3_soft_reset(dwc);
52088bc9d19SHeikki Krogerus 		if (ret)
52188bc9d19SHeikki Krogerus 			return ret;
52288bc9d19SHeikki Krogerus 
52388bc9d19SHeikki Krogerus 		udelay(1);
52488bc9d19SHeikki Krogerus 
52588bc9d19SHeikki Krogerus 		ret = dwc3_ulpi_init(dwc);
52688bc9d19SHeikki Krogerus 		if (ret)
52788bc9d19SHeikki Krogerus 			return ret;
52888bc9d19SHeikki Krogerus 		/* FALLTHROUGH */
5293e10a2ceSHeikki Krogerus 	default:
5303e10a2ceSHeikki Krogerus 		break;
5313e10a2ceSHeikki Krogerus 	}
5323e10a2ceSHeikki Krogerus 
53332f2ed86SWilliam Wu 	switch (dwc->hsphy_mode) {
53432f2ed86SWilliam Wu 	case USBPHY_INTERFACE_MODE_UTMI:
53532f2ed86SWilliam Wu 		reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
53632f2ed86SWilliam Wu 		       DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
53732f2ed86SWilliam Wu 		reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) |
53832f2ed86SWilliam Wu 		       DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT);
53932f2ed86SWilliam Wu 		break;
54032f2ed86SWilliam Wu 	case USBPHY_INTERFACE_MODE_UTMIW:
54132f2ed86SWilliam Wu 		reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK |
54232f2ed86SWilliam Wu 		       DWC3_GUSB2PHYCFG_USBTRDTIM_MASK);
54332f2ed86SWilliam Wu 		reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) |
54432f2ed86SWilliam Wu 		       DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT);
54532f2ed86SWilliam Wu 		break;
54632f2ed86SWilliam Wu 	default:
54732f2ed86SWilliam Wu 		break;
54832f2ed86SWilliam Wu 	}
54932f2ed86SWilliam Wu 
5502164a476SHuang Rui 	/*
5512164a476SHuang Rui 	 * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
5522164a476SHuang Rui 	 * '0' during coreConsultant configuration. So default value will
5532164a476SHuang Rui 	 * be '0' when the core is reset. Application needs to set it to
5542164a476SHuang Rui 	 * '1' after the core initialization is completed.
5552164a476SHuang Rui 	 */
5562164a476SHuang Rui 	if (dwc->revision > DWC3_REVISION_194A)
5572164a476SHuang Rui 		reg |= DWC3_GUSB2PHYCFG_SUSPHY;
5582164a476SHuang Rui 
559cd72f890SFelipe Balbi 	if (dwc->dis_u2_susphy_quirk)
5600effe0a3SHuang Rui 		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
5610effe0a3SHuang Rui 
562ec791d14SJohn Youn 	if (dwc->dis_enblslpm_quirk)
563ec791d14SJohn Youn 		reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
564ec791d14SJohn Youn 
56516199f33SWilliam Wu 	if (dwc->dis_u2_freeclk_exists_quirk)
56616199f33SWilliam Wu 		reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;
56716199f33SWilliam Wu 
5682164a476SHuang Rui 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
56988bc9d19SHeikki Krogerus 
57088bc9d19SHeikki Krogerus 	return 0;
571b5a65c40SHuang Rui }
572b5a65c40SHuang Rui 
573c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc)
574c499ff71SFelipe Balbi {
575c499ff71SFelipe Balbi 	dwc3_event_buffers_cleanup(dwc);
576c499ff71SFelipe Balbi 
577c499ff71SFelipe Balbi 	usb_phy_shutdown(dwc->usb2_phy);
578c499ff71SFelipe Balbi 	usb_phy_shutdown(dwc->usb3_phy);
579c499ff71SFelipe Balbi 	phy_exit(dwc->usb2_generic_phy);
580c499ff71SFelipe Balbi 	phy_exit(dwc->usb3_generic_phy);
581c499ff71SFelipe Balbi 
582c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb2_phy, 1);
583c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb3_phy, 1);
584c499ff71SFelipe Balbi 	phy_power_off(dwc->usb2_generic_phy);
585c499ff71SFelipe Balbi 	phy_power_off(dwc->usb3_generic_phy);
586c499ff71SFelipe Balbi }
587c499ff71SFelipe Balbi 
5880759956fSFelipe Balbi static bool dwc3_core_is_valid(struct dwc3 *dwc)
5890759956fSFelipe Balbi {
5900759956fSFelipe Balbi 	u32 reg;
5910759956fSFelipe Balbi 
5920759956fSFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
5930759956fSFelipe Balbi 
5940759956fSFelipe Balbi 	/* This should read as U3 followed by revision number */
5950759956fSFelipe Balbi 	if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
5960759956fSFelipe Balbi 		/* Detected DWC_usb3 IP */
5970759956fSFelipe Balbi 		dwc->revision = reg;
5980759956fSFelipe Balbi 	} else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) {
5990759956fSFelipe Balbi 		/* Detected DWC_usb31 IP */
6000759956fSFelipe Balbi 		dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
6010759956fSFelipe Balbi 		dwc->revision |= DWC3_REVISION_IS_DWC31;
6020759956fSFelipe Balbi 	} else {
6030759956fSFelipe Balbi 		return false;
6040759956fSFelipe Balbi 	}
6050759956fSFelipe Balbi 
6060759956fSFelipe Balbi 	return true;
6070759956fSFelipe Balbi }
6080759956fSFelipe Balbi 
609941f918eSFelipe Balbi static void dwc3_core_setup_global_control(struct dwc3 *dwc)
61072246da4SFelipe Balbi {
6110ffcaf37SFelipe Balbi 	u32 hwparams4 = dwc->hwparams.hwparams4;
61272246da4SFelipe Balbi 	u32 reg;
613c499ff71SFelipe Balbi 
6144878a028SSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
6153e87c42aSPaul Zimmerman 	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
6164878a028SSebastian Andrzej Siewior 
617164d7731SSebastian Andrzej Siewior 	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
6184878a028SSebastian Andrzej Siewior 	case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
61932a4a135SFelipe Balbi 		/**
62032a4a135SFelipe Balbi 		 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
62132a4a135SFelipe Balbi 		 * issue which would cause xHCI compliance tests to fail.
62232a4a135SFelipe Balbi 		 *
62332a4a135SFelipe Balbi 		 * Because of that we cannot enable clock gating on such
62432a4a135SFelipe Balbi 		 * configurations.
62532a4a135SFelipe Balbi 		 *
62632a4a135SFelipe Balbi 		 * Refers to:
62732a4a135SFelipe Balbi 		 *
62832a4a135SFelipe Balbi 		 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
62932a4a135SFelipe Balbi 		 * SOF/ITP Mode Used
63032a4a135SFelipe Balbi 		 */
63132a4a135SFelipe Balbi 		if ((dwc->dr_mode == USB_DR_MODE_HOST ||
63232a4a135SFelipe Balbi 				dwc->dr_mode == USB_DR_MODE_OTG) &&
63332a4a135SFelipe Balbi 				(dwc->revision >= DWC3_REVISION_210A &&
63432a4a135SFelipe Balbi 				dwc->revision <= DWC3_REVISION_250A))
63532a4a135SFelipe Balbi 			reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
63632a4a135SFelipe Balbi 		else
6374878a028SSebastian Andrzej Siewior 			reg &= ~DWC3_GCTL_DSBLCLKGTNG;
6384878a028SSebastian Andrzej Siewior 		break;
6390ffcaf37SFelipe Balbi 	case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
6400ffcaf37SFelipe Balbi 		/* enable hibernation here */
6410ffcaf37SFelipe Balbi 		dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
6422eac3992SHuang Rui 
6432eac3992SHuang Rui 		/*
6442eac3992SHuang Rui 		 * REVISIT Enabling this bit so that host-mode hibernation
6452eac3992SHuang Rui 		 * will work. Device-mode hibernation is not yet implemented.
6462eac3992SHuang Rui 		 */
6472eac3992SHuang Rui 		reg |= DWC3_GCTL_GBLHIBERNATIONEN;
6480ffcaf37SFelipe Balbi 		break;
6494878a028SSebastian Andrzej Siewior 	default:
6505eb30cedSFelipe Balbi 		/* nothing */
6515eb30cedSFelipe Balbi 		break;
6524878a028SSebastian Andrzej Siewior 	}
6534878a028SSebastian Andrzej Siewior 
654946bd579SHuang Rui 	/* check if current dwc3 is on simulation board */
655946bd579SHuang Rui 	if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
6565eb30cedSFelipe Balbi 		dev_info(dwc->dev, "Running with FPGA optmizations\n");
657946bd579SHuang Rui 		dwc->is_fpga = true;
658946bd579SHuang Rui 	}
659946bd579SHuang Rui 
6603b81221aSHuang Rui 	WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga,
6613b81221aSHuang Rui 			"disable_scramble cannot be used on non-FPGA builds\n");
6623b81221aSHuang Rui 
6633b81221aSHuang Rui 	if (dwc->disable_scramble_quirk && dwc->is_fpga)
6643b81221aSHuang Rui 		reg |= DWC3_GCTL_DISSCRAMBLE;
6653b81221aSHuang Rui 	else
6663b81221aSHuang Rui 		reg &= ~DWC3_GCTL_DISSCRAMBLE;
6673b81221aSHuang Rui 
6689a5b2f31SHuang Rui 	if (dwc->u2exit_lfps_quirk)
6699a5b2f31SHuang Rui 		reg |= DWC3_GCTL_U2EXIT_LFPS;
6709a5b2f31SHuang Rui 
6714878a028SSebastian Andrzej Siewior 	/*
6724878a028SSebastian Andrzej Siewior 	 * WORKAROUND: DWC3 revisions <1.90a have a bug
6731d046793SPaul Zimmerman 	 * where the device can fail to connect at SuperSpeed
6744878a028SSebastian Andrzej Siewior 	 * and falls back to high-speed mode which causes
6751d046793SPaul Zimmerman 	 * the device to enter a Connect/Disconnect loop
6764878a028SSebastian Andrzej Siewior 	 */
6774878a028SSebastian Andrzej Siewior 	if (dwc->revision < DWC3_REVISION_190A)
6784878a028SSebastian Andrzej Siewior 		reg |= DWC3_GCTL_U2RSTECN;
6794878a028SSebastian Andrzej Siewior 
6804878a028SSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
681941f918eSFelipe Balbi }
6824878a028SSebastian Andrzej Siewior 
683941f918eSFelipe Balbi /**
684941f918eSFelipe Balbi  * dwc3_core_init - Low-level initialization of DWC3 Core
685941f918eSFelipe Balbi  * @dwc: Pointer to our controller context structure
686941f918eSFelipe Balbi  *
687941f918eSFelipe Balbi  * Returns 0 on success otherwise negative errno.
688941f918eSFelipe Balbi  */
689941f918eSFelipe Balbi static int dwc3_core_init(struct dwc3 *dwc)
690941f918eSFelipe Balbi {
691941f918eSFelipe Balbi 	u32			reg;
692941f918eSFelipe Balbi 	int			ret;
693941f918eSFelipe Balbi 
694941f918eSFelipe Balbi 	if (!dwc3_core_is_valid(dwc)) {
695941f918eSFelipe Balbi 		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
696941f918eSFelipe Balbi 		ret = -ENODEV;
697941f918eSFelipe Balbi 		goto err0;
698941f918eSFelipe Balbi 	}
699941f918eSFelipe Balbi 
700941f918eSFelipe Balbi 	/*
701941f918eSFelipe Balbi 	 * Write Linux Version Code to our GUID register so it's easy to figure
702941f918eSFelipe Balbi 	 * out which kernel version a bug was found.
703941f918eSFelipe Balbi 	 */
704941f918eSFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE);
705941f918eSFelipe Balbi 
706941f918eSFelipe Balbi 	/* Handle USB2.0-only core configuration */
707941f918eSFelipe Balbi 	if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
708941f918eSFelipe Balbi 			DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
709941f918eSFelipe Balbi 		if (dwc->maximum_speed == USB_SPEED_SUPER)
710941f918eSFelipe Balbi 			dwc->maximum_speed = USB_SPEED_HIGH;
711941f918eSFelipe Balbi 	}
712941f918eSFelipe Balbi 
713941f918eSFelipe Balbi 	/* issue device SoftReset too */
714941f918eSFelipe Balbi 	ret = dwc3_soft_reset(dwc);
715941f918eSFelipe Balbi 	if (ret)
716941f918eSFelipe Balbi 		goto err0;
717941f918eSFelipe Balbi 
718941f918eSFelipe Balbi 	ret = dwc3_core_soft_reset(dwc);
719941f918eSFelipe Balbi 	if (ret)
720941f918eSFelipe Balbi 		goto err0;
721941f918eSFelipe Balbi 
722941f918eSFelipe Balbi 	ret = dwc3_phy_setup(dwc);
723941f918eSFelipe Balbi 	if (ret)
724941f918eSFelipe Balbi 		goto err0;
725941f918eSFelipe Balbi 
726941f918eSFelipe Balbi 	dwc3_core_setup_global_control(dwc);
727c499ff71SFelipe Balbi 	dwc3_core_num_eps(dwc);
7280ffcaf37SFelipe Balbi 
7290ffcaf37SFelipe Balbi 	ret = dwc3_setup_scratch_buffers(dwc);
7300ffcaf37SFelipe Balbi 	if (ret)
731c499ff71SFelipe Balbi 		goto err1;
732c499ff71SFelipe Balbi 
733c499ff71SFelipe Balbi 	/* Adjust Frame Length */
734c499ff71SFelipe Balbi 	dwc3_frame_length_adjustment(dwc);
735c499ff71SFelipe Balbi 
736c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb2_phy, 0);
737c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb3_phy, 0);
738c499ff71SFelipe Balbi 	ret = phy_power_on(dwc->usb2_generic_phy);
739c499ff71SFelipe Balbi 	if (ret < 0)
7400ffcaf37SFelipe Balbi 		goto err2;
7410ffcaf37SFelipe Balbi 
742c499ff71SFelipe Balbi 	ret = phy_power_on(dwc->usb3_generic_phy);
743c499ff71SFelipe Balbi 	if (ret < 0)
744c499ff71SFelipe Balbi 		goto err3;
745c499ff71SFelipe Balbi 
746c499ff71SFelipe Balbi 	ret = dwc3_event_buffers_setup(dwc);
747c499ff71SFelipe Balbi 	if (ret) {
748c499ff71SFelipe Balbi 		dev_err(dwc->dev, "failed to setup event buffers\n");
749c499ff71SFelipe Balbi 		goto err4;
750c499ff71SFelipe Balbi 	}
751c499ff71SFelipe Balbi 
75200af6233SBaolin Wang 	switch (dwc->dr_mode) {
75300af6233SBaolin Wang 	case USB_DR_MODE_PERIPHERAL:
75400af6233SBaolin Wang 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
75500af6233SBaolin Wang 		break;
75600af6233SBaolin Wang 	case USB_DR_MODE_HOST:
75700af6233SBaolin Wang 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
75800af6233SBaolin Wang 		break;
75900af6233SBaolin Wang 	case USB_DR_MODE_OTG:
76000af6233SBaolin Wang 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
76100af6233SBaolin Wang 		break;
76200af6233SBaolin Wang 	default:
76300af6233SBaolin Wang 		dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode);
76400af6233SBaolin Wang 		break;
76500af6233SBaolin Wang 	}
76600af6233SBaolin Wang 
76706281d46SJohn Youn 	/*
76806281d46SJohn Youn 	 * ENDXFER polling is available on version 3.10a and later of
76906281d46SJohn Youn 	 * the DWC_usb3 controller. It is NOT available in the
77006281d46SJohn Youn 	 * DWC_usb31 controller.
77106281d46SJohn Youn 	 */
77206281d46SJohn Youn 	if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) {
77306281d46SJohn Youn 		reg = dwc3_readl(dwc->regs, DWC3_GUCTL2);
77406281d46SJohn Youn 		reg |= DWC3_GUCTL2_RST_ACTBITLATER;
77506281d46SJohn Youn 		dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
77606281d46SJohn Youn 	}
77706281d46SJohn Youn 
7780bb39ca1SJohn Youn 	/*
7790bb39ca1SJohn Youn 	 * Enable hardware control of sending remote wakeup in HS when
7800bb39ca1SJohn Youn 	 * the device is in the L1 state.
7810bb39ca1SJohn Youn 	 */
7820bb39ca1SJohn Youn 	if (dwc->revision >= DWC3_REVISION_290A) {
7830bb39ca1SJohn Youn 		reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
7840bb39ca1SJohn Youn 		reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
7850bb39ca1SJohn Youn 		dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
7860bb39ca1SJohn Youn 	}
7870bb39ca1SJohn Youn 
78872246da4SFelipe Balbi 	return 0;
78972246da4SFelipe Balbi 
790c499ff71SFelipe Balbi err4:
791c499ff71SFelipe Balbi 	phy_power_off(dwc->usb2_generic_phy);
792c499ff71SFelipe Balbi 
793c499ff71SFelipe Balbi err3:
794c499ff71SFelipe Balbi 	phy_power_off(dwc->usb3_generic_phy);
795c499ff71SFelipe Balbi 
7960ffcaf37SFelipe Balbi err2:
797c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb2_phy, 1);
798c499ff71SFelipe Balbi 	usb_phy_set_suspend(dwc->usb3_phy, 1);
799c499ff71SFelipe Balbi 	dwc3_core_exit(dwc);
8000ffcaf37SFelipe Balbi 
8010ffcaf37SFelipe Balbi err1:
8020ffcaf37SFelipe Balbi 	usb_phy_shutdown(dwc->usb2_phy);
8030ffcaf37SFelipe Balbi 	usb_phy_shutdown(dwc->usb3_phy);
80457303488SKishon Vijay Abraham I 	phy_exit(dwc->usb2_generic_phy);
80557303488SKishon Vijay Abraham I 	phy_exit(dwc->usb3_generic_phy);
8060ffcaf37SFelipe Balbi 
80772246da4SFelipe Balbi err0:
80872246da4SFelipe Balbi 	return ret;
80972246da4SFelipe Balbi }
81072246da4SFelipe Balbi 
8113c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc)
81272246da4SFelipe Balbi {
8133c9f94acSFelipe Balbi 	struct device		*dev = dwc->dev;
814941ea361SFelipe Balbi 	struct device_node	*node = dev->of_node;
8153c9f94acSFelipe Balbi 	int ret;
81672246da4SFelipe Balbi 
8175088b6f5SKishon Vijay Abraham I 	if (node) {
8185088b6f5SKishon Vijay Abraham I 		dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
8195088b6f5SKishon Vijay Abraham I 		dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
820bb674907SFelipe Balbi 	} else {
821bb674907SFelipe Balbi 		dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
822bb674907SFelipe Balbi 		dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
8235088b6f5SKishon Vijay Abraham I 	}
8245088b6f5SKishon Vijay Abraham I 
825d105e7f8SFelipe Balbi 	if (IS_ERR(dwc->usb2_phy)) {
826d105e7f8SFelipe Balbi 		ret = PTR_ERR(dwc->usb2_phy);
827122f06e6SKishon Vijay Abraham I 		if (ret == -ENXIO || ret == -ENODEV) {
828122f06e6SKishon Vijay Abraham I 			dwc->usb2_phy = NULL;
829122f06e6SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
830d105e7f8SFelipe Balbi 			return ret;
831122f06e6SKishon Vijay Abraham I 		} else {
83251e1e7bcSFelipe Balbi 			dev_err(dev, "no usb2 phy configured\n");
833122f06e6SKishon Vijay Abraham I 			return ret;
834122f06e6SKishon Vijay Abraham I 		}
83551e1e7bcSFelipe Balbi 	}
83651e1e7bcSFelipe Balbi 
837d105e7f8SFelipe Balbi 	if (IS_ERR(dwc->usb3_phy)) {
838315955d7SRuchika Kharwar 		ret = PTR_ERR(dwc->usb3_phy);
839122f06e6SKishon Vijay Abraham I 		if (ret == -ENXIO || ret == -ENODEV) {
840122f06e6SKishon Vijay Abraham I 			dwc->usb3_phy = NULL;
841122f06e6SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
842d105e7f8SFelipe Balbi 			return ret;
843122f06e6SKishon Vijay Abraham I 		} else {
84451e1e7bcSFelipe Balbi 			dev_err(dev, "no usb3 phy configured\n");
845122f06e6SKishon Vijay Abraham I 			return ret;
846122f06e6SKishon Vijay Abraham I 		}
84751e1e7bcSFelipe Balbi 	}
84851e1e7bcSFelipe Balbi 
84957303488SKishon Vijay Abraham I 	dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
85057303488SKishon Vijay Abraham I 	if (IS_ERR(dwc->usb2_generic_phy)) {
85157303488SKishon Vijay Abraham I 		ret = PTR_ERR(dwc->usb2_generic_phy);
85257303488SKishon Vijay Abraham I 		if (ret == -ENOSYS || ret == -ENODEV) {
85357303488SKishon Vijay Abraham I 			dwc->usb2_generic_phy = NULL;
85457303488SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
85557303488SKishon Vijay Abraham I 			return ret;
85657303488SKishon Vijay Abraham I 		} else {
85757303488SKishon Vijay Abraham I 			dev_err(dev, "no usb2 phy configured\n");
85857303488SKishon Vijay Abraham I 			return ret;
85957303488SKishon Vijay Abraham I 		}
86057303488SKishon Vijay Abraham I 	}
86157303488SKishon Vijay Abraham I 
86257303488SKishon Vijay Abraham I 	dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
86357303488SKishon Vijay Abraham I 	if (IS_ERR(dwc->usb3_generic_phy)) {
86457303488SKishon Vijay Abraham I 		ret = PTR_ERR(dwc->usb3_generic_phy);
86557303488SKishon Vijay Abraham I 		if (ret == -ENOSYS || ret == -ENODEV) {
86657303488SKishon Vijay Abraham I 			dwc->usb3_generic_phy = NULL;
86757303488SKishon Vijay Abraham I 		} else if (ret == -EPROBE_DEFER) {
86857303488SKishon Vijay Abraham I 			return ret;
86957303488SKishon Vijay Abraham I 		} else {
87057303488SKishon Vijay Abraham I 			dev_err(dev, "no usb3 phy configured\n");
87157303488SKishon Vijay Abraham I 			return ret;
87257303488SKishon Vijay Abraham I 		}
87357303488SKishon Vijay Abraham I 	}
87457303488SKishon Vijay Abraham I 
8753c9f94acSFelipe Balbi 	return 0;
8763c9f94acSFelipe Balbi }
8773c9f94acSFelipe Balbi 
8785f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc)
8795f94adfeSFelipe Balbi {
8805f94adfeSFelipe Balbi 	struct device *dev = dwc->dev;
8815f94adfeSFelipe Balbi 	int ret;
8825f94adfeSFelipe Balbi 
8835f94adfeSFelipe Balbi 	switch (dwc->dr_mode) {
8845f94adfeSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
8855f94adfeSFelipe Balbi 		ret = dwc3_gadget_init(dwc);
8865f94adfeSFelipe Balbi 		if (ret) {
8879522def4SRoger Quadros 			if (ret != -EPROBE_DEFER)
8885f94adfeSFelipe Balbi 				dev_err(dev, "failed to initialize gadget\n");
8895f94adfeSFelipe Balbi 			return ret;
8905f94adfeSFelipe Balbi 		}
8915f94adfeSFelipe Balbi 		break;
8925f94adfeSFelipe Balbi 	case USB_DR_MODE_HOST:
8935f94adfeSFelipe Balbi 		ret = dwc3_host_init(dwc);
8945f94adfeSFelipe Balbi 		if (ret) {
8959522def4SRoger Quadros 			if (ret != -EPROBE_DEFER)
8965f94adfeSFelipe Balbi 				dev_err(dev, "failed to initialize host\n");
8975f94adfeSFelipe Balbi 			return ret;
8985f94adfeSFelipe Balbi 		}
8995f94adfeSFelipe Balbi 		break;
9005f94adfeSFelipe Balbi 	case USB_DR_MODE_OTG:
9015f94adfeSFelipe Balbi 		ret = dwc3_host_init(dwc);
9025f94adfeSFelipe Balbi 		if (ret) {
9039522def4SRoger Quadros 			if (ret != -EPROBE_DEFER)
9045f94adfeSFelipe Balbi 				dev_err(dev, "failed to initialize host\n");
9055f94adfeSFelipe Balbi 			return ret;
9065f94adfeSFelipe Balbi 		}
9075f94adfeSFelipe Balbi 
9085f94adfeSFelipe Balbi 		ret = dwc3_gadget_init(dwc);
9095f94adfeSFelipe Balbi 		if (ret) {
9109522def4SRoger Quadros 			if (ret != -EPROBE_DEFER)
9115f94adfeSFelipe Balbi 				dev_err(dev, "failed to initialize gadget\n");
9125f94adfeSFelipe Balbi 			return ret;
9135f94adfeSFelipe Balbi 		}
9145f94adfeSFelipe Balbi 		break;
9155f94adfeSFelipe Balbi 	default:
9165f94adfeSFelipe Balbi 		dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
9175f94adfeSFelipe Balbi 		return -EINVAL;
9185f94adfeSFelipe Balbi 	}
9195f94adfeSFelipe Balbi 
9205f94adfeSFelipe Balbi 	return 0;
9215f94adfeSFelipe Balbi }
9225f94adfeSFelipe Balbi 
9235f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc)
9245f94adfeSFelipe Balbi {
9255f94adfeSFelipe Balbi 	switch (dwc->dr_mode) {
9265f94adfeSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
9275f94adfeSFelipe Balbi 		dwc3_gadget_exit(dwc);
9285f94adfeSFelipe Balbi 		break;
9295f94adfeSFelipe Balbi 	case USB_DR_MODE_HOST:
9305f94adfeSFelipe Balbi 		dwc3_host_exit(dwc);
9315f94adfeSFelipe Balbi 		break;
9325f94adfeSFelipe Balbi 	case USB_DR_MODE_OTG:
9335f94adfeSFelipe Balbi 		dwc3_host_exit(dwc);
9345f94adfeSFelipe Balbi 		dwc3_gadget_exit(dwc);
9355f94adfeSFelipe Balbi 		break;
9365f94adfeSFelipe Balbi 	default:
9375f94adfeSFelipe Balbi 		/* do nothing */
9385f94adfeSFelipe Balbi 		break;
9395f94adfeSFelipe Balbi 	}
9405f94adfeSFelipe Balbi }
9415f94adfeSFelipe Balbi 
942c5ac6116SFelipe Balbi static void dwc3_get_properties(struct dwc3 *dwc)
9433c9f94acSFelipe Balbi {
944c5ac6116SFelipe Balbi 	struct device		*dev = dwc->dev;
94580caf7d2SHuang Rui 	u8			lpm_nyet_threshold;
9466b6a0c9aSHuang Rui 	u8			tx_de_emphasis;
947460d098cSHuang Rui 	u8			hird_threshold;
9483c9f94acSFelipe Balbi 
94980caf7d2SHuang Rui 	/* default to highest possible threshold */
95080caf7d2SHuang Rui 	lpm_nyet_threshold = 0xff;
95180caf7d2SHuang Rui 
9526b6a0c9aSHuang Rui 	/* default to -3.5dB de-emphasis */
9536b6a0c9aSHuang Rui 	tx_de_emphasis = 1;
9546b6a0c9aSHuang Rui 
955460d098cSHuang Rui 	/*
956460d098cSHuang Rui 	 * default to assert utmi_sleep_n and use maximum allowed HIRD
957460d098cSHuang Rui 	 * threshold value of 0b1100
958460d098cSHuang Rui 	 */
959460d098cSHuang Rui 	hird_threshold = 12;
960460d098cSHuang Rui 
96163863b98SHeikki Krogerus 	dwc->maximum_speed = usb_get_maximum_speed(dev);
96206e7114fSHeikki Krogerus 	dwc->dr_mode = usb_get_dr_mode(dev);
96332f2ed86SWilliam Wu 	dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);
96463863b98SHeikki Krogerus 
9653d128919SHeikki Krogerus 	dwc->has_lpm_erratum = device_property_read_bool(dev,
96680caf7d2SHuang Rui 				"snps,has-lpm-erratum");
9673d128919SHeikki Krogerus 	device_property_read_u8(dev, "snps,lpm-nyet-threshold",
96880caf7d2SHuang Rui 				&lpm_nyet_threshold);
9693d128919SHeikki Krogerus 	dwc->is_utmi_l1_suspend = device_property_read_bool(dev,
970460d098cSHuang Rui 				"snps,is-utmi-l1-suspend");
9713d128919SHeikki Krogerus 	device_property_read_u8(dev, "snps,hird-threshold",
972460d098cSHuang Rui 				&hird_threshold);
9733d128919SHeikki Krogerus 	dwc->usb3_lpm_capable = device_property_read_bool(dev,
974eac68e8fSRobert Baldyga 				"snps,usb3_lpm_capable");
9753c9f94acSFelipe Balbi 
9763d128919SHeikki Krogerus 	dwc->disable_scramble_quirk = device_property_read_bool(dev,
9773b81221aSHuang Rui 				"snps,disable_scramble_quirk");
9783d128919SHeikki Krogerus 	dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
9799a5b2f31SHuang Rui 				"snps,u2exit_lfps_quirk");
9803d128919SHeikki Krogerus 	dwc->u2ss_inp3_quirk = device_property_read_bool(dev,
981b5a65c40SHuang Rui 				"snps,u2ss_inp3_quirk");
9823d128919SHeikki Krogerus 	dwc->req_p1p2p3_quirk = device_property_read_bool(dev,
983df31f5b3SHuang Rui 				"snps,req_p1p2p3_quirk");
9843d128919SHeikki Krogerus 	dwc->del_p1p2p3_quirk = device_property_read_bool(dev,
985a2a1d0f5SHuang Rui 				"snps,del_p1p2p3_quirk");
9863d128919SHeikki Krogerus 	dwc->del_phy_power_chg_quirk = device_property_read_bool(dev,
98741c06ffdSHuang Rui 				"snps,del_phy_power_chg_quirk");
9883d128919SHeikki Krogerus 	dwc->lfps_filter_quirk = device_property_read_bool(dev,
989fb67afcaSHuang Rui 				"snps,lfps_filter_quirk");
9903d128919SHeikki Krogerus 	dwc->rx_detect_poll_quirk = device_property_read_bool(dev,
99114f4ac53SHuang Rui 				"snps,rx_detect_poll_quirk");
9923d128919SHeikki Krogerus 	dwc->dis_u3_susphy_quirk = device_property_read_bool(dev,
99359acfa20SHuang Rui 				"snps,dis_u3_susphy_quirk");
9943d128919SHeikki Krogerus 	dwc->dis_u2_susphy_quirk = device_property_read_bool(dev,
9950effe0a3SHuang Rui 				"snps,dis_u2_susphy_quirk");
996ec791d14SJohn Youn 	dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
997ec791d14SJohn Youn 				"snps,dis_enblslpm_quirk");
998e58dd357SRajesh Bhagat 	dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev,
999e58dd357SRajesh Bhagat 				"snps,dis_rxdet_inp3_quirk");
100016199f33SWilliam Wu 	dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev,
100116199f33SWilliam Wu 				"snps,dis-u2-freeclk-exists-quirk");
100200fe081dSWilliam Wu 	dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
100300fe081dSWilliam Wu 				"snps,dis-del-phy-power-chg-quirk");
10046b6a0c9aSHuang Rui 
10053d128919SHeikki Krogerus 	dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
10066b6a0c9aSHuang Rui 				"snps,tx_de_emphasis_quirk");
10073d128919SHeikki Krogerus 	device_property_read_u8(dev, "snps,tx_de_emphasis",
10086b6a0c9aSHuang Rui 				&tx_de_emphasis);
10093d128919SHeikki Krogerus 	device_property_read_string(dev, "snps,hsphy_interface",
10103e10a2ceSHeikki Krogerus 				    &dwc->hsphy_interface);
10113d128919SHeikki Krogerus 	device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
1012bcdb3272SFelipe Balbi 				 &dwc->fladj);
10133d128919SHeikki Krogerus 
101480caf7d2SHuang Rui 	dwc->lpm_nyet_threshold = lpm_nyet_threshold;
10156b6a0c9aSHuang Rui 	dwc->tx_de_emphasis = tx_de_emphasis;
101680caf7d2SHuang Rui 
1017460d098cSHuang Rui 	dwc->hird_threshold = hird_threshold
1018460d098cSHuang Rui 		| (dwc->is_utmi_l1_suspend << 4);
1019460d098cSHuang Rui 
1020c5ac6116SFelipe Balbi }
1021c5ac6116SFelipe Balbi 
1022c5ac6116SFelipe Balbi static int dwc3_probe(struct platform_device *pdev)
1023c5ac6116SFelipe Balbi {
1024c5ac6116SFelipe Balbi 	struct device		*dev = &pdev->dev;
1025c5ac6116SFelipe Balbi 	struct resource		*res;
1026c5ac6116SFelipe Balbi 	struct dwc3		*dwc;
1027c5ac6116SFelipe Balbi 
1028c5ac6116SFelipe Balbi 	int			ret;
1029c5ac6116SFelipe Balbi 
1030c5ac6116SFelipe Balbi 	void __iomem		*regs;
1031c5ac6116SFelipe Balbi 
1032c5ac6116SFelipe Balbi 	dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
1033c5ac6116SFelipe Balbi 	if (!dwc)
1034c5ac6116SFelipe Balbi 		return -ENOMEM;
1035c5ac6116SFelipe Balbi 
1036c5ac6116SFelipe Balbi 	dwc->dev = dev;
1037c5ac6116SFelipe Balbi 
1038c5ac6116SFelipe Balbi 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1039c5ac6116SFelipe Balbi 	if (!res) {
1040c5ac6116SFelipe Balbi 		dev_err(dev, "missing memory resource\n");
1041c5ac6116SFelipe Balbi 		return -ENODEV;
1042c5ac6116SFelipe Balbi 	}
1043c5ac6116SFelipe Balbi 
1044c5ac6116SFelipe Balbi 	dwc->xhci_resources[0].start = res->start;
1045c5ac6116SFelipe Balbi 	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
1046c5ac6116SFelipe Balbi 					DWC3_XHCI_REGS_END;
1047c5ac6116SFelipe Balbi 	dwc->xhci_resources[0].flags = res->flags;
1048c5ac6116SFelipe Balbi 	dwc->xhci_resources[0].name = res->name;
1049c5ac6116SFelipe Balbi 
1050c5ac6116SFelipe Balbi 	res->start += DWC3_GLOBALS_REGS_START;
1051c5ac6116SFelipe Balbi 
1052c5ac6116SFelipe Balbi 	/*
1053c5ac6116SFelipe Balbi 	 * Request memory region but exclude xHCI regs,
1054c5ac6116SFelipe Balbi 	 * since it will be requested by the xhci-plat driver.
1055c5ac6116SFelipe Balbi 	 */
1056c5ac6116SFelipe Balbi 	regs = devm_ioremap_resource(dev, res);
1057c5ac6116SFelipe Balbi 	if (IS_ERR(regs)) {
1058c5ac6116SFelipe Balbi 		ret = PTR_ERR(regs);
1059c5ac6116SFelipe Balbi 		goto err0;
1060c5ac6116SFelipe Balbi 	}
1061c5ac6116SFelipe Balbi 
1062c5ac6116SFelipe Balbi 	dwc->regs	= regs;
1063c5ac6116SFelipe Balbi 	dwc->regs_size	= resource_size(res);
1064c5ac6116SFelipe Balbi 
1065c5ac6116SFelipe Balbi 	dwc3_get_properties(dwc);
1066c5ac6116SFelipe Balbi 
10676c89cce0SHeikki Krogerus 	platform_set_drvdata(pdev, dwc);
10682917e718SHeikki Krogerus 	dwc3_cache_hwparams(dwc);
10696c89cce0SHeikki Krogerus 
10703c9f94acSFelipe Balbi 	ret = dwc3_core_get_phy(dwc);
10713c9f94acSFelipe Balbi 	if (ret)
10723da1f6eeSFelipe Balbi 		goto err0;
10733c9f94acSFelipe Balbi 
107472246da4SFelipe Balbi 	spin_lock_init(&dwc->lock);
107572246da4SFelipe Balbi 
107619bacdc9SHeikki Krogerus 	if (!dev->dma_mask) {
1077ddff14f1SKishon Vijay Abraham I 		dev->dma_mask = dev->parent->dma_mask;
1078ddff14f1SKishon Vijay Abraham I 		dev->dma_parms = dev->parent->dma_parms;
1079ddff14f1SKishon Vijay Abraham I 		dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
108019bacdc9SHeikki Krogerus 	}
1081ddff14f1SKishon Vijay Abraham I 
1082fc8bb91bSFelipe Balbi 	pm_runtime_set_active(dev);
1083fc8bb91bSFelipe Balbi 	pm_runtime_use_autosuspend(dev);
1084fc8bb91bSFelipe Balbi 	pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
1085802ca850SChanho Park 	pm_runtime_enable(dev);
108632808237SRoger Quadros 	ret = pm_runtime_get_sync(dev);
108732808237SRoger Quadros 	if (ret < 0)
108832808237SRoger Quadros 		goto err1;
108932808237SRoger Quadros 
1090802ca850SChanho Park 	pm_runtime_forbid(dev);
109172246da4SFelipe Balbi 
10923921426bSFelipe Balbi 	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
10933921426bSFelipe Balbi 	if (ret) {
10943921426bSFelipe Balbi 		dev_err(dwc->dev, "failed to allocate event buffers\n");
10953921426bSFelipe Balbi 		ret = -ENOMEM;
109632808237SRoger Quadros 		goto err2;
10973921426bSFelipe Balbi 	}
10983921426bSFelipe Balbi 
10999d6173e1SThinh Nguyen 	ret = dwc3_get_dr_mode(dwc);
11009d6173e1SThinh Nguyen 	if (ret)
11019d6173e1SThinh Nguyen 		goto err3;
110232a4a135SFelipe Balbi 
1103c499ff71SFelipe Balbi 	ret = dwc3_alloc_scratch_buffers(dwc);
1104c499ff71SFelipe Balbi 	if (ret)
110532808237SRoger Quadros 		goto err3;
1106c499ff71SFelipe Balbi 
110772246da4SFelipe Balbi 	ret = dwc3_core_init(dwc);
110872246da4SFelipe Balbi 	if (ret) {
1109802ca850SChanho Park 		dev_err(dev, "failed to initialize core\n");
111032808237SRoger Quadros 		goto err4;
111172246da4SFelipe Balbi 	}
111272246da4SFelipe Balbi 
111377966eb8SJohn Youn 	/* Check the maximum_speed parameter */
111477966eb8SJohn Youn 	switch (dwc->maximum_speed) {
111577966eb8SJohn Youn 	case USB_SPEED_LOW:
111677966eb8SJohn Youn 	case USB_SPEED_FULL:
111777966eb8SJohn Youn 	case USB_SPEED_HIGH:
111877966eb8SJohn Youn 	case USB_SPEED_SUPER:
111977966eb8SJohn Youn 	case USB_SPEED_SUPER_PLUS:
112077966eb8SJohn Youn 		break;
112177966eb8SJohn Youn 	default:
112277966eb8SJohn Youn 		dev_err(dev, "invalid maximum_speed parameter %d\n",
112377966eb8SJohn Youn 			dwc->maximum_speed);
112477966eb8SJohn Youn 		/* fall through */
112577966eb8SJohn Youn 	case USB_SPEED_UNKNOWN:
112677966eb8SJohn Youn 		/* default to superspeed */
11272c7f1bd9SJohn Youn 		dwc->maximum_speed = USB_SPEED_SUPER;
11282c7f1bd9SJohn Youn 
11292c7f1bd9SJohn Youn 		/*
11302c7f1bd9SJohn Youn 		 * default to superspeed plus if we are capable.
11312c7f1bd9SJohn Youn 		 */
11322c7f1bd9SJohn Youn 		if (dwc3_is_usb31(dwc) &&
11332c7f1bd9SJohn Youn 		    (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
11342c7f1bd9SJohn Youn 		     DWC3_GHWPARAMS3_SSPHY_IFC_GEN2))
11352c7f1bd9SJohn Youn 			dwc->maximum_speed = USB_SPEED_SUPER_PLUS;
113677966eb8SJohn Youn 
113777966eb8SJohn Youn 		break;
11382c7f1bd9SJohn Youn 	}
11392c7f1bd9SJohn Youn 
11405f94adfeSFelipe Balbi 	ret = dwc3_core_init_mode(dwc);
11415f94adfeSFelipe Balbi 	if (ret)
114232808237SRoger Quadros 		goto err5;
114372246da4SFelipe Balbi 
11444e9f3118SDu, Changbin 	dwc3_debugfs_init(dwc);
1145fc8bb91bSFelipe Balbi 	pm_runtime_put(dev);
114672246da4SFelipe Balbi 
114772246da4SFelipe Balbi 	return 0;
114872246da4SFelipe Balbi 
114932808237SRoger Quadros err5:
1150f122d33eSFelipe Balbi 	dwc3_event_buffers_cleanup(dwc);
1151f122d33eSFelipe Balbi 
115232808237SRoger Quadros err4:
1153c499ff71SFelipe Balbi 	dwc3_free_scratch_buffers(dwc);
115472246da4SFelipe Balbi 
115532808237SRoger Quadros err3:
11563921426bSFelipe Balbi 	dwc3_free_event_buffers(dwc);
115788bc9d19SHeikki Krogerus 	dwc3_ulpi_exit(dwc);
11583921426bSFelipe Balbi 
115932808237SRoger Quadros err2:
116032808237SRoger Quadros 	pm_runtime_allow(&pdev->dev);
116132808237SRoger Quadros 
116232808237SRoger Quadros err1:
116332808237SRoger Quadros 	pm_runtime_put_sync(&pdev->dev);
116432808237SRoger Quadros 	pm_runtime_disable(&pdev->dev);
116532808237SRoger Quadros 
11663da1f6eeSFelipe Balbi err0:
11673da1f6eeSFelipe Balbi 	/*
11683da1f6eeSFelipe Balbi 	 * restore res->start back to its original value so that, in case the
11693da1f6eeSFelipe Balbi 	 * probe is deferred, we don't end up getting error in request the
11703da1f6eeSFelipe Balbi 	 * memory region the next time probe is called.
11713da1f6eeSFelipe Balbi 	 */
11723da1f6eeSFelipe Balbi 	res->start -= DWC3_GLOBALS_REGS_START;
11733da1f6eeSFelipe Balbi 
117472246da4SFelipe Balbi 	return ret;
117572246da4SFelipe Balbi }
117672246da4SFelipe Balbi 
1177fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev)
117872246da4SFelipe Balbi {
117972246da4SFelipe Balbi 	struct dwc3	*dwc = platform_get_drvdata(pdev);
11803da1f6eeSFelipe Balbi 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
11813da1f6eeSFelipe Balbi 
1182fc8bb91bSFelipe Balbi 	pm_runtime_get_sync(&pdev->dev);
11833da1f6eeSFelipe Balbi 	/*
11843da1f6eeSFelipe Balbi 	 * restore res->start back to its original value so that, in case the
11853da1f6eeSFelipe Balbi 	 * probe is deferred, we don't end up getting error in request the
11863da1f6eeSFelipe Balbi 	 * memory region the next time probe is called.
11873da1f6eeSFelipe Balbi 	 */
11883da1f6eeSFelipe Balbi 	res->start -= DWC3_GLOBALS_REGS_START;
118972246da4SFelipe Balbi 
1190dc99f16fSFelipe Balbi 	dwc3_debugfs_exit(dwc);
1191dc99f16fSFelipe Balbi 	dwc3_core_exit_mode(dwc);
11928ba007a9SKishon Vijay Abraham I 
119372246da4SFelipe Balbi 	dwc3_core_exit(dwc);
119488bc9d19SHeikki Krogerus 	dwc3_ulpi_exit(dwc);
119572246da4SFelipe Balbi 
1196fc8bb91bSFelipe Balbi 	pm_runtime_put_sync(&pdev->dev);
1197fc8bb91bSFelipe Balbi 	pm_runtime_allow(&pdev->dev);
1198fc8bb91bSFelipe Balbi 	pm_runtime_disable(&pdev->dev);
1199fc8bb91bSFelipe Balbi 
1200c499ff71SFelipe Balbi 	dwc3_free_event_buffers(dwc);
1201c499ff71SFelipe Balbi 	dwc3_free_scratch_buffers(dwc);
1202c499ff71SFelipe Balbi 
120372246da4SFelipe Balbi 	return 0;
120472246da4SFelipe Balbi }
120572246da4SFelipe Balbi 
1206fc8bb91bSFelipe Balbi #ifdef CONFIG_PM
1207fc8bb91bSFelipe Balbi static int dwc3_suspend_common(struct dwc3 *dwc)
12087415f17cSFelipe Balbi {
1209fc8bb91bSFelipe Balbi 	unsigned long	flags;
12107415f17cSFelipe Balbi 
1211a45c82b8SRuchika Kharwar 	switch (dwc->dr_mode) {
1212a45c82b8SRuchika Kharwar 	case USB_DR_MODE_PERIPHERAL:
1213a45c82b8SRuchika Kharwar 	case USB_DR_MODE_OTG:
1214fc8bb91bSFelipe Balbi 		spin_lock_irqsave(&dwc->lock, flags);
12157415f17cSFelipe Balbi 		dwc3_gadget_suspend(dwc);
1216fc8bb91bSFelipe Balbi 		spin_unlock_irqrestore(&dwc->lock, flags);
121751f5d49aSFelipe Balbi 		break;
1218a45c82b8SRuchika Kharwar 	case USB_DR_MODE_HOST:
12197415f17cSFelipe Balbi 	default:
122051f5d49aSFelipe Balbi 		/* do nothing */
12217415f17cSFelipe Balbi 		break;
12227415f17cSFelipe Balbi 	}
12237415f17cSFelipe Balbi 
122451f5d49aSFelipe Balbi 	dwc3_core_exit(dwc);
12255c4ad318SFelipe Balbi 
1226fc8bb91bSFelipe Balbi 	return 0;
1227fc8bb91bSFelipe Balbi }
1228fc8bb91bSFelipe Balbi 
1229fc8bb91bSFelipe Balbi static int dwc3_resume_common(struct dwc3 *dwc)
1230fc8bb91bSFelipe Balbi {
1231fc8bb91bSFelipe Balbi 	unsigned long	flags;
1232fc8bb91bSFelipe Balbi 	int		ret;
1233fc8bb91bSFelipe Balbi 
1234fc8bb91bSFelipe Balbi 	ret = dwc3_core_init(dwc);
1235fc8bb91bSFelipe Balbi 	if (ret)
1236fc8bb91bSFelipe Balbi 		return ret;
1237fc8bb91bSFelipe Balbi 
1238fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1239fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1240fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1241fc8bb91bSFelipe Balbi 		spin_lock_irqsave(&dwc->lock, flags);
1242fc8bb91bSFelipe Balbi 		dwc3_gadget_resume(dwc);
1243fc8bb91bSFelipe Balbi 		spin_unlock_irqrestore(&dwc->lock, flags);
1244fc8bb91bSFelipe Balbi 		/* FALLTHROUGH */
1245fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1246fc8bb91bSFelipe Balbi 	default:
1247fc8bb91bSFelipe Balbi 		/* do nothing */
1248fc8bb91bSFelipe Balbi 		break;
1249fc8bb91bSFelipe Balbi 	}
1250fc8bb91bSFelipe Balbi 
1251fc8bb91bSFelipe Balbi 	return 0;
1252fc8bb91bSFelipe Balbi }
1253fc8bb91bSFelipe Balbi 
1254fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc)
1255fc8bb91bSFelipe Balbi {
1256fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1257fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1258fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1259fc8bb91bSFelipe Balbi 		if (dwc->connected)
1260fc8bb91bSFelipe Balbi 			return -EBUSY;
1261fc8bb91bSFelipe Balbi 		break;
1262fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1263fc8bb91bSFelipe Balbi 	default:
1264fc8bb91bSFelipe Balbi 		/* do nothing */
1265fc8bb91bSFelipe Balbi 		break;
1266fc8bb91bSFelipe Balbi 	}
1267fc8bb91bSFelipe Balbi 
1268fc8bb91bSFelipe Balbi 	return 0;
1269fc8bb91bSFelipe Balbi }
1270fc8bb91bSFelipe Balbi 
1271fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev)
1272fc8bb91bSFelipe Balbi {
1273fc8bb91bSFelipe Balbi 	struct dwc3     *dwc = dev_get_drvdata(dev);
1274fc8bb91bSFelipe Balbi 	int		ret;
1275fc8bb91bSFelipe Balbi 
1276fc8bb91bSFelipe Balbi 	if (dwc3_runtime_checks(dwc))
1277fc8bb91bSFelipe Balbi 		return -EBUSY;
1278fc8bb91bSFelipe Balbi 
1279fc8bb91bSFelipe Balbi 	ret = dwc3_suspend_common(dwc);
1280fc8bb91bSFelipe Balbi 	if (ret)
1281fc8bb91bSFelipe Balbi 		return ret;
1282fc8bb91bSFelipe Balbi 
1283fc8bb91bSFelipe Balbi 	device_init_wakeup(dev, true);
1284fc8bb91bSFelipe Balbi 
1285fc8bb91bSFelipe Balbi 	return 0;
1286fc8bb91bSFelipe Balbi }
1287fc8bb91bSFelipe Balbi 
1288fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev)
1289fc8bb91bSFelipe Balbi {
1290fc8bb91bSFelipe Balbi 	struct dwc3     *dwc = dev_get_drvdata(dev);
1291fc8bb91bSFelipe Balbi 	int		ret;
1292fc8bb91bSFelipe Balbi 
1293fc8bb91bSFelipe Balbi 	device_init_wakeup(dev, false);
1294fc8bb91bSFelipe Balbi 
1295fc8bb91bSFelipe Balbi 	ret = dwc3_resume_common(dwc);
1296fc8bb91bSFelipe Balbi 	if (ret)
1297fc8bb91bSFelipe Balbi 		return ret;
1298fc8bb91bSFelipe Balbi 
1299fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1300fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1301fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1302fc8bb91bSFelipe Balbi 		dwc3_gadget_process_pending_events(dwc);
1303fc8bb91bSFelipe Balbi 		break;
1304fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1305fc8bb91bSFelipe Balbi 	default:
1306fc8bb91bSFelipe Balbi 		/* do nothing */
1307fc8bb91bSFelipe Balbi 		break;
1308fc8bb91bSFelipe Balbi 	}
1309fc8bb91bSFelipe Balbi 
1310fc8bb91bSFelipe Balbi 	pm_runtime_mark_last_busy(dev);
1311b74c2d87SFelipe Balbi 	pm_runtime_put(dev);
1312fc8bb91bSFelipe Balbi 
1313fc8bb91bSFelipe Balbi 	return 0;
1314fc8bb91bSFelipe Balbi }
1315fc8bb91bSFelipe Balbi 
1316fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev)
1317fc8bb91bSFelipe Balbi {
1318fc8bb91bSFelipe Balbi 	struct dwc3     *dwc = dev_get_drvdata(dev);
1319fc8bb91bSFelipe Balbi 
1320fc8bb91bSFelipe Balbi 	switch (dwc->dr_mode) {
1321fc8bb91bSFelipe Balbi 	case USB_DR_MODE_PERIPHERAL:
1322fc8bb91bSFelipe Balbi 	case USB_DR_MODE_OTG:
1323fc8bb91bSFelipe Balbi 		if (dwc3_runtime_checks(dwc))
1324fc8bb91bSFelipe Balbi 			return -EBUSY;
1325fc8bb91bSFelipe Balbi 		break;
1326fc8bb91bSFelipe Balbi 	case USB_DR_MODE_HOST:
1327fc8bb91bSFelipe Balbi 	default:
1328fc8bb91bSFelipe Balbi 		/* do nothing */
1329fc8bb91bSFelipe Balbi 		break;
1330fc8bb91bSFelipe Balbi 	}
1331fc8bb91bSFelipe Balbi 
1332fc8bb91bSFelipe Balbi 	pm_runtime_mark_last_busy(dev);
1333fc8bb91bSFelipe Balbi 	pm_runtime_autosuspend(dev);
1334fc8bb91bSFelipe Balbi 
1335fc8bb91bSFelipe Balbi 	return 0;
1336fc8bb91bSFelipe Balbi }
1337fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */
1338fc8bb91bSFelipe Balbi 
1339fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP
1340fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev)
1341fc8bb91bSFelipe Balbi {
1342fc8bb91bSFelipe Balbi 	struct dwc3	*dwc = dev_get_drvdata(dev);
1343fc8bb91bSFelipe Balbi 	int		ret;
1344fc8bb91bSFelipe Balbi 
1345fc8bb91bSFelipe Balbi 	ret = dwc3_suspend_common(dwc);
1346fc8bb91bSFelipe Balbi 	if (ret)
1347fc8bb91bSFelipe Balbi 		return ret;
1348fc8bb91bSFelipe Balbi 
13496344475fSSekhar Nori 	pinctrl_pm_select_sleep_state(dev);
13506344475fSSekhar Nori 
13517415f17cSFelipe Balbi 	return 0;
13527415f17cSFelipe Balbi }
13537415f17cSFelipe Balbi 
13547415f17cSFelipe Balbi static int dwc3_resume(struct device *dev)
13557415f17cSFelipe Balbi {
13567415f17cSFelipe Balbi 	struct dwc3	*dwc = dev_get_drvdata(dev);
135757303488SKishon Vijay Abraham I 	int		ret;
13587415f17cSFelipe Balbi 
13596344475fSSekhar Nori 	pinctrl_pm_select_default_state(dev);
13606344475fSSekhar Nori 
1361fc8bb91bSFelipe Balbi 	ret = dwc3_resume_common(dwc);
136251f5d49aSFelipe Balbi 	if (ret)
13635c4ad318SFelipe Balbi 		return ret;
13645c4ad318SFelipe Balbi 
13657415f17cSFelipe Balbi 	pm_runtime_disable(dev);
13667415f17cSFelipe Balbi 	pm_runtime_set_active(dev);
13677415f17cSFelipe Balbi 	pm_runtime_enable(dev);
13687415f17cSFelipe Balbi 
13697415f17cSFelipe Balbi 	return 0;
13707415f17cSFelipe Balbi }
13717f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */
13727415f17cSFelipe Balbi 
13737415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = {
13747415f17cSFelipe Balbi 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
1375fc8bb91bSFelipe Balbi 	SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
1376fc8bb91bSFelipe Balbi 			dwc3_runtime_idle)
13777415f17cSFelipe Balbi };
13787415f17cSFelipe Balbi 
13795088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF
13805088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = {
13815088b6f5SKishon Vijay Abraham I 	{
138222a5aa17SFelipe Balbi 		.compatible = "snps,dwc3"
138322a5aa17SFelipe Balbi 	},
138422a5aa17SFelipe Balbi 	{
13855088b6f5SKishon Vijay Abraham I 		.compatible = "synopsys,dwc3"
13865088b6f5SKishon Vijay Abraham I 	},
13875088b6f5SKishon Vijay Abraham I 	{ },
13885088b6f5SKishon Vijay Abraham I };
13895088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match);
13905088b6f5SKishon Vijay Abraham I #endif
13915088b6f5SKishon Vijay Abraham I 
1392404905a6SHeikki Krogerus #ifdef CONFIG_ACPI
1393404905a6SHeikki Krogerus 
1394404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW	"808622B7"
1395404905a6SHeikki Krogerus 
1396404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = {
1397404905a6SHeikki Krogerus 	{ ACPI_ID_INTEL_BSW, 0 },
1398404905a6SHeikki Krogerus 	{ },
1399404905a6SHeikki Krogerus };
1400404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match);
1401404905a6SHeikki Krogerus #endif
1402404905a6SHeikki Krogerus 
140372246da4SFelipe Balbi static struct platform_driver dwc3_driver = {
140472246da4SFelipe Balbi 	.probe		= dwc3_probe,
14057690417dSBill Pemberton 	.remove		= dwc3_remove,
140672246da4SFelipe Balbi 	.driver		= {
140772246da4SFelipe Balbi 		.name	= "dwc3",
14085088b6f5SKishon Vijay Abraham I 		.of_match_table	= of_match_ptr(of_dwc3_match),
1409404905a6SHeikki Krogerus 		.acpi_match_table = ACPI_PTR(dwc3_acpi_match),
14107f370ed0SFelipe Balbi 		.pm	= &dwc3_dev_pm_ops,
141172246da4SFelipe Balbi 	},
141272246da4SFelipe Balbi };
141372246da4SFelipe Balbi 
1414b1116dccSTobias Klauser module_platform_driver(dwc3_driver);
1415b1116dccSTobias Klauser 
14167ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3");
141772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
14185945f789SFelipe Balbi MODULE_LICENSE("GPL v2");
141972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
1420