xref: /openbmc/linux/drivers/usb/dwc3/core.c (revision 4fd24483)
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  *
972246da4SFelipe Balbi  * Redistribution and use in source and binary forms, with or without
1072246da4SFelipe Balbi  * modification, are permitted provided that the following conditions
1172246da4SFelipe Balbi  * are met:
1272246da4SFelipe Balbi  * 1. Redistributions of source code must retain the above copyright
1372246da4SFelipe Balbi  *    notice, this list of conditions, and the following disclaimer,
1472246da4SFelipe Balbi  *    without modification.
1572246da4SFelipe Balbi  * 2. Redistributions in binary form must reproduce the above copyright
1672246da4SFelipe Balbi  *    notice, this list of conditions and the following disclaimer in the
1772246da4SFelipe Balbi  *    documentation and/or other materials provided with the distribution.
1872246da4SFelipe Balbi  * 3. The names of the above-listed copyright holders may not be used
1972246da4SFelipe Balbi  *    to endorse or promote products derived from this software without
2072246da4SFelipe Balbi  *    specific prior written permission.
2172246da4SFelipe Balbi  *
2272246da4SFelipe Balbi  * ALTERNATIVELY, this software may be distributed under the terms of the
2372246da4SFelipe Balbi  * GNU General Public License ("GPL") version 2, as published by the Free
2472246da4SFelipe Balbi  * Software Foundation.
2572246da4SFelipe Balbi  *
2672246da4SFelipe Balbi  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2772246da4SFelipe Balbi  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2872246da4SFelipe Balbi  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2972246da4SFelipe Balbi  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
3072246da4SFelipe Balbi  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3172246da4SFelipe Balbi  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3272246da4SFelipe Balbi  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3372246da4SFelipe Balbi  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3472246da4SFelipe Balbi  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3572246da4SFelipe Balbi  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3672246da4SFelipe Balbi  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3772246da4SFelipe Balbi  */
3872246da4SFelipe Balbi 
39a72e658bSFelipe Balbi #include <linux/module.h>
4072246da4SFelipe Balbi #include <linux/kernel.h>
4172246da4SFelipe Balbi #include <linux/slab.h>
4272246da4SFelipe Balbi #include <linux/spinlock.h>
4372246da4SFelipe Balbi #include <linux/platform_device.h>
4472246da4SFelipe Balbi #include <linux/pm_runtime.h>
4572246da4SFelipe Balbi #include <linux/interrupt.h>
4672246da4SFelipe Balbi #include <linux/ioport.h>
4772246da4SFelipe Balbi #include <linux/io.h>
4872246da4SFelipe Balbi #include <linux/list.h>
4972246da4SFelipe Balbi #include <linux/delay.h>
5072246da4SFelipe Balbi #include <linux/dma-mapping.h>
51457e84b6SFelipe Balbi #include <linux/of.h>
5272246da4SFelipe Balbi 
5351e1e7bcSFelipe Balbi #include <linux/usb/otg.h>
5472246da4SFelipe Balbi #include <linux/usb/ch9.h>
5572246da4SFelipe Balbi #include <linux/usb/gadget.h>
5672246da4SFelipe Balbi 
5772246da4SFelipe Balbi #include "core.h"
5872246da4SFelipe Balbi #include "gadget.h"
5972246da4SFelipe Balbi #include "io.h"
6072246da4SFelipe Balbi 
6172246da4SFelipe Balbi #include "debug.h"
6272246da4SFelipe Balbi 
636c167fc9SFelipe Balbi static char *maximum_speed = "super";
646c167fc9SFelipe Balbi module_param(maximum_speed, charp, 0);
656c167fc9SFelipe Balbi MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
666c167fc9SFelipe Balbi 
678300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */
688300dd23SFelipe Balbi 
693140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
703140e8cbSSebastian Andrzej Siewior {
713140e8cbSSebastian Andrzej Siewior 	u32 reg;
723140e8cbSSebastian Andrzej Siewior 
733140e8cbSSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
743140e8cbSSebastian Andrzej Siewior 	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
753140e8cbSSebastian Andrzej Siewior 	reg |= DWC3_GCTL_PRTCAPDIR(mode);
763140e8cbSSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
773140e8cbSSebastian Andrzej Siewior }
788300dd23SFelipe Balbi 
7972246da4SFelipe Balbi /**
8072246da4SFelipe Balbi  * dwc3_core_soft_reset - Issues core soft reset and PHY reset
8172246da4SFelipe Balbi  * @dwc: pointer to our context structure
8272246da4SFelipe Balbi  */
8372246da4SFelipe Balbi static void dwc3_core_soft_reset(struct dwc3 *dwc)
8472246da4SFelipe Balbi {
8572246da4SFelipe Balbi 	u32		reg;
8672246da4SFelipe Balbi 
8772246da4SFelipe Balbi 	/* Before Resetting PHY, put Core in Reset */
8872246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
8972246da4SFelipe Balbi 	reg |= DWC3_GCTL_CORESOFTRESET;
9072246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
9172246da4SFelipe Balbi 
9272246da4SFelipe Balbi 	/* Assert USB3 PHY reset */
9372246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
9472246da4SFelipe Balbi 	reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
9572246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
9672246da4SFelipe Balbi 
9772246da4SFelipe Balbi 	/* Assert USB2 PHY reset */
9872246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
9972246da4SFelipe Balbi 	reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
10072246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
10172246da4SFelipe Balbi 
10251e1e7bcSFelipe Balbi 	usb_phy_init(dwc->usb2_phy);
10351e1e7bcSFelipe Balbi 	usb_phy_init(dwc->usb3_phy);
10472246da4SFelipe Balbi 	mdelay(100);
10572246da4SFelipe Balbi 
10672246da4SFelipe Balbi 	/* Clear USB3 PHY reset */
10772246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
10872246da4SFelipe Balbi 	reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
10972246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
11072246da4SFelipe Balbi 
11172246da4SFelipe Balbi 	/* Clear USB2 PHY reset */
11272246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
11372246da4SFelipe Balbi 	reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
11472246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
11572246da4SFelipe Balbi 
11645627ac6SPratyush Anand 	mdelay(100);
11745627ac6SPratyush Anand 
11872246da4SFelipe Balbi 	/* After PHYs are stable we can take Core out of reset state */
11972246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
12072246da4SFelipe Balbi 	reg &= ~DWC3_GCTL_CORESOFTRESET;
12172246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
12272246da4SFelipe Balbi }
12372246da4SFelipe Balbi 
12472246da4SFelipe Balbi /**
12572246da4SFelipe Balbi  * dwc3_free_one_event_buffer - Frees one event buffer
12672246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
12772246da4SFelipe Balbi  * @evt: Pointer to event buffer to be freed
12872246da4SFelipe Balbi  */
12972246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
13072246da4SFelipe Balbi 		struct dwc3_event_buffer *evt)
13172246da4SFelipe Balbi {
13272246da4SFelipe Balbi 	dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
13372246da4SFelipe Balbi }
13472246da4SFelipe Balbi 
13572246da4SFelipe Balbi /**
1361d046793SPaul Zimmerman  * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
13772246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
13872246da4SFelipe Balbi  * @length: size of the event buffer
13972246da4SFelipe Balbi  *
1401d046793SPaul Zimmerman  * Returns a pointer to the allocated event buffer structure on success
14172246da4SFelipe Balbi  * otherwise ERR_PTR(errno).
14272246da4SFelipe Balbi  */
14372246da4SFelipe Balbi static struct dwc3_event_buffer *__devinit
14472246da4SFelipe Balbi dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
14572246da4SFelipe Balbi {
14672246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
14772246da4SFelipe Balbi 
148380f0d28SFelipe Balbi 	evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
14972246da4SFelipe Balbi 	if (!evt)
15072246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
15172246da4SFelipe Balbi 
15272246da4SFelipe Balbi 	evt->dwc	= dwc;
15372246da4SFelipe Balbi 	evt->length	= length;
15472246da4SFelipe Balbi 	evt->buf	= dma_alloc_coherent(dwc->dev, length,
15572246da4SFelipe Balbi 			&evt->dma, GFP_KERNEL);
156e32672f0SFelipe Balbi 	if (!evt->buf)
15772246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
15872246da4SFelipe Balbi 
15972246da4SFelipe Balbi 	return evt;
16072246da4SFelipe Balbi }
16172246da4SFelipe Balbi 
16272246da4SFelipe Balbi /**
16372246da4SFelipe Balbi  * dwc3_free_event_buffers - frees all allocated event buffers
16472246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
16572246da4SFelipe Balbi  */
16672246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc)
16772246da4SFelipe Balbi {
16872246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
16972246da4SFelipe Balbi 	int i;
17072246da4SFelipe Balbi 
1719f622b2aSFelipe Balbi 	for (i = 0; i < dwc->num_event_buffers; i++) {
17272246da4SFelipe Balbi 		evt = dwc->ev_buffs[i];
17364b6c8a7SAnton Tikhomirov 		if (evt)
17472246da4SFelipe Balbi 			dwc3_free_one_event_buffer(dwc, evt);
17572246da4SFelipe Balbi 	}
17672246da4SFelipe Balbi }
17772246da4SFelipe Balbi 
17872246da4SFelipe Balbi /**
17972246da4SFelipe Balbi  * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
1801d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
18172246da4SFelipe Balbi  * @length: size of event buffer
18272246da4SFelipe Balbi  *
1831d046793SPaul Zimmerman  * Returns 0 on success otherwise negative errno. In the error case, dwc
18472246da4SFelipe Balbi  * may contain some buffers allocated but not all which were requested.
18572246da4SFelipe Balbi  */
1869f622b2aSFelipe Balbi static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
18772246da4SFelipe Balbi {
1889f622b2aSFelipe Balbi 	int			num;
18972246da4SFelipe Balbi 	int			i;
19072246da4SFelipe Balbi 
1919f622b2aSFelipe Balbi 	num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
1929f622b2aSFelipe Balbi 	dwc->num_event_buffers = num;
1939f622b2aSFelipe Balbi 
194380f0d28SFelipe Balbi 	dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
195380f0d28SFelipe Balbi 			GFP_KERNEL);
196457d3f21SFelipe Balbi 	if (!dwc->ev_buffs) {
197457d3f21SFelipe Balbi 		dev_err(dwc->dev, "can't allocate event buffers array\n");
198457d3f21SFelipe Balbi 		return -ENOMEM;
199457d3f21SFelipe Balbi 	}
200457d3f21SFelipe Balbi 
20172246da4SFelipe Balbi 	for (i = 0; i < num; i++) {
20272246da4SFelipe Balbi 		struct dwc3_event_buffer	*evt;
20372246da4SFelipe Balbi 
20472246da4SFelipe Balbi 		evt = dwc3_alloc_one_event_buffer(dwc, length);
20572246da4SFelipe Balbi 		if (IS_ERR(evt)) {
20672246da4SFelipe Balbi 			dev_err(dwc->dev, "can't allocate event buffer\n");
20772246da4SFelipe Balbi 			return PTR_ERR(evt);
20872246da4SFelipe Balbi 		}
20972246da4SFelipe Balbi 		dwc->ev_buffs[i] = evt;
21072246da4SFelipe Balbi 	}
21172246da4SFelipe Balbi 
21272246da4SFelipe Balbi 	return 0;
21372246da4SFelipe Balbi }
21472246da4SFelipe Balbi 
21572246da4SFelipe Balbi /**
21672246da4SFelipe Balbi  * dwc3_event_buffers_setup - setup our allocated event buffers
2171d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
21872246da4SFelipe Balbi  *
21972246da4SFelipe Balbi  * Returns 0 on success otherwise negative errno.
22072246da4SFelipe Balbi  */
2217acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc)
22272246da4SFelipe Balbi {
22372246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
22472246da4SFelipe Balbi 	int				n;
22572246da4SFelipe Balbi 
2269f622b2aSFelipe Balbi 	for (n = 0; n < dwc->num_event_buffers; n++) {
22772246da4SFelipe Balbi 		evt = dwc->ev_buffs[n];
22872246da4SFelipe Balbi 		dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
22972246da4SFelipe Balbi 				evt->buf, (unsigned long long) evt->dma,
23072246da4SFelipe Balbi 				evt->length);
23172246da4SFelipe Balbi 
2327acd85e0SPaul Zimmerman 		evt->lpos = 0;
2337acd85e0SPaul Zimmerman 
23472246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
23572246da4SFelipe Balbi 				lower_32_bits(evt->dma));
23672246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
23772246da4SFelipe Balbi 				upper_32_bits(evt->dma));
23872246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
23972246da4SFelipe Balbi 				evt->length & 0xffff);
24072246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
24172246da4SFelipe Balbi 	}
24272246da4SFelipe Balbi 
24372246da4SFelipe Balbi 	return 0;
24472246da4SFelipe Balbi }
24572246da4SFelipe Balbi 
24672246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
24772246da4SFelipe Balbi {
24872246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
24972246da4SFelipe Balbi 	int				n;
25072246da4SFelipe Balbi 
2519f622b2aSFelipe Balbi 	for (n = 0; n < dwc->num_event_buffers; n++) {
25272246da4SFelipe Balbi 		evt = dwc->ev_buffs[n];
2537acd85e0SPaul Zimmerman 
2547acd85e0SPaul Zimmerman 		evt->lpos = 0;
2557acd85e0SPaul Zimmerman 
25672246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
25772246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
25872246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
25972246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
26072246da4SFelipe Balbi 	}
26172246da4SFelipe Balbi }
26272246da4SFelipe Balbi 
26326ceca97SFelipe Balbi static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
26426ceca97SFelipe Balbi {
26526ceca97SFelipe Balbi 	struct dwc3_hwparams	*parms = &dwc->hwparams;
26626ceca97SFelipe Balbi 
26726ceca97SFelipe Balbi 	parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
26826ceca97SFelipe Balbi 	parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
26926ceca97SFelipe Balbi 	parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
27026ceca97SFelipe Balbi 	parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
27126ceca97SFelipe Balbi 	parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
27226ceca97SFelipe Balbi 	parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
27326ceca97SFelipe Balbi 	parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
27426ceca97SFelipe Balbi 	parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
27526ceca97SFelipe Balbi 	parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
27626ceca97SFelipe Balbi }
27726ceca97SFelipe Balbi 
27872246da4SFelipe Balbi /**
27972246da4SFelipe Balbi  * dwc3_core_init - Low-level initialization of DWC3 Core
28072246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
28172246da4SFelipe Balbi  *
28272246da4SFelipe Balbi  * Returns 0 on success otherwise negative errno.
28372246da4SFelipe Balbi  */
28472246da4SFelipe Balbi static int __devinit dwc3_core_init(struct dwc3 *dwc)
28572246da4SFelipe Balbi {
28672246da4SFelipe Balbi 	unsigned long		timeout;
28772246da4SFelipe Balbi 	u32			reg;
28872246da4SFelipe Balbi 	int			ret;
28972246da4SFelipe Balbi 
2907650bd74SSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
2917650bd74SSebastian Andrzej Siewior 	/* This should read as U3 followed by revision number */
2927650bd74SSebastian Andrzej Siewior 	if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
2937650bd74SSebastian Andrzej Siewior 		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
2947650bd74SSebastian Andrzej Siewior 		ret = -ENODEV;
2957650bd74SSebastian Andrzej Siewior 		goto err0;
2967650bd74SSebastian Andrzej Siewior 	}
297248b122bSFelipe Balbi 	dwc->revision = reg;
2987650bd74SSebastian Andrzej Siewior 
29972246da4SFelipe Balbi 	/* issue device SoftReset too */
30072246da4SFelipe Balbi 	timeout = jiffies + msecs_to_jiffies(500);
30172246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
30272246da4SFelipe Balbi 	do {
30372246da4SFelipe Balbi 		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
30472246da4SFelipe Balbi 		if (!(reg & DWC3_DCTL_CSFTRST))
30572246da4SFelipe Balbi 			break;
30672246da4SFelipe Balbi 
30772246da4SFelipe Balbi 		if (time_after(jiffies, timeout)) {
30872246da4SFelipe Balbi 			dev_err(dwc->dev, "Reset Timed Out\n");
30972246da4SFelipe Balbi 			ret = -ETIMEDOUT;
31072246da4SFelipe Balbi 			goto err0;
31172246da4SFelipe Balbi 		}
31272246da4SFelipe Balbi 
31372246da4SFelipe Balbi 		cpu_relax();
31472246da4SFelipe Balbi 	} while (true);
31572246da4SFelipe Balbi 
31658a0f23fSPratyush Anand 	dwc3_core_soft_reset(dwc);
31758a0f23fSPratyush Anand 
3184878a028SSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
3193e87c42aSPaul Zimmerman 	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
3204878a028SSebastian Andrzej Siewior 	reg &= ~DWC3_GCTL_DISSCRAMBLE;
3214878a028SSebastian Andrzej Siewior 
322164d7731SSebastian Andrzej Siewior 	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
3234878a028SSebastian Andrzej Siewior 	case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
3244878a028SSebastian Andrzej Siewior 		reg &= ~DWC3_GCTL_DSBLCLKGTNG;
3254878a028SSebastian Andrzej Siewior 		break;
3264878a028SSebastian Andrzej Siewior 	default:
3274878a028SSebastian Andrzej Siewior 		dev_dbg(dwc->dev, "No power optimization available\n");
3284878a028SSebastian Andrzej Siewior 	}
3294878a028SSebastian Andrzej Siewior 
3304878a028SSebastian Andrzej Siewior 	/*
3314878a028SSebastian Andrzej Siewior 	 * WORKAROUND: DWC3 revisions <1.90a have a bug
3321d046793SPaul Zimmerman 	 * where the device can fail to connect at SuperSpeed
3334878a028SSebastian Andrzej Siewior 	 * and falls back to high-speed mode which causes
3341d046793SPaul Zimmerman 	 * the device to enter a Connect/Disconnect loop
3354878a028SSebastian Andrzej Siewior 	 */
3364878a028SSebastian Andrzej Siewior 	if (dwc->revision < DWC3_REVISION_190A)
3374878a028SSebastian Andrzej Siewior 		reg |= DWC3_GCTL_U2RSTECN;
3384878a028SSebastian Andrzej Siewior 
3394878a028SSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
3404878a028SSebastian Andrzej Siewior 
34172246da4SFelipe Balbi 	ret = dwc3_event_buffers_setup(dwc);
34272246da4SFelipe Balbi 	if (ret) {
34372246da4SFelipe Balbi 		dev_err(dwc->dev, "failed to setup event buffers\n");
3443921426bSFelipe Balbi 		goto err0;
34572246da4SFelipe Balbi 	}
34672246da4SFelipe Balbi 
34772246da4SFelipe Balbi 	return 0;
34872246da4SFelipe Balbi 
34972246da4SFelipe Balbi err0:
35072246da4SFelipe Balbi 	return ret;
35172246da4SFelipe Balbi }
35272246da4SFelipe Balbi 
35372246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc)
35472246da4SFelipe Balbi {
35572246da4SFelipe Balbi 	dwc3_event_buffers_cleanup(dwc);
35601b8daf7SVivek Gautam 
35701b8daf7SVivek Gautam 	usb_phy_shutdown(dwc->usb2_phy);
35801b8daf7SVivek Gautam 	usb_phy_shutdown(dwc->usb3_phy);
35972246da4SFelipe Balbi }
36072246da4SFelipe Balbi 
36172246da4SFelipe Balbi #define DWC3_ALIGN_MASK		(16 - 1)
36272246da4SFelipe Balbi 
36372246da4SFelipe Balbi static int __devinit dwc3_probe(struct platform_device *pdev)
36472246da4SFelipe Balbi {
365457e84b6SFelipe Balbi 	struct device_node	*node = pdev->dev.of_node;
36672246da4SFelipe Balbi 	struct resource		*res;
36772246da4SFelipe Balbi 	struct dwc3		*dwc;
368802ca850SChanho Park 	struct device		*dev = &pdev->dev;
3690949e99bSFelipe Balbi 
37072246da4SFelipe Balbi 	int			ret = -ENOMEM;
3710949e99bSFelipe Balbi 
3720949e99bSFelipe Balbi 	void __iomem		*regs;
37372246da4SFelipe Balbi 	void			*mem;
37472246da4SFelipe Balbi 
3750949e99bSFelipe Balbi 	u8			mode;
3760949e99bSFelipe Balbi 
377802ca850SChanho Park 	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
37872246da4SFelipe Balbi 	if (!mem) {
379802ca850SChanho Park 		dev_err(dev, "not enough memory\n");
380802ca850SChanho Park 		return -ENOMEM;
38172246da4SFelipe Balbi 	}
38272246da4SFelipe Balbi 	dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
38372246da4SFelipe Balbi 	dwc->mem = mem;
38472246da4SFelipe Balbi 
38551249dcaSIdo Shayevitz 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
38672246da4SFelipe Balbi 	if (!res) {
38751249dcaSIdo Shayevitz 		dev_err(dev, "missing IRQ\n");
388802ca850SChanho Park 		return -ENODEV;
38972246da4SFelipe Balbi 	}
390066618bcSKishon Vijay Abraham I 	dwc->xhci_resources[1].start = res->start;
391066618bcSKishon Vijay Abraham I 	dwc->xhci_resources[1].end = res->end;
392066618bcSKishon Vijay Abraham I 	dwc->xhci_resources[1].flags = res->flags;
393066618bcSKishon Vijay Abraham I 	dwc->xhci_resources[1].name = res->name;
39472246da4SFelipe Balbi 
39551249dcaSIdo Shayevitz 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
39651249dcaSIdo Shayevitz 	if (!res) {
39751249dcaSIdo Shayevitz 		dev_err(dev, "missing memory resource\n");
39851249dcaSIdo Shayevitz 		return -ENODEV;
39951249dcaSIdo Shayevitz 	}
400066618bcSKishon Vijay Abraham I 	dwc->xhci_resources[0].start = res->start;
40151249dcaSIdo Shayevitz 	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
40251249dcaSIdo Shayevitz 					DWC3_XHCI_REGS_END;
403066618bcSKishon Vijay Abraham I 	dwc->xhci_resources[0].flags = res->flags;
404066618bcSKishon Vijay Abraham I 	dwc->xhci_resources[0].name = res->name;
405d07e8819SFelipe Balbi 
40651249dcaSIdo Shayevitz 	 /*
40751249dcaSIdo Shayevitz 	  * Request memory region but exclude xHCI regs,
40851249dcaSIdo Shayevitz 	  * since it will be requested by the xhci-plat driver.
40951249dcaSIdo Shayevitz 	  */
41051249dcaSIdo Shayevitz 	res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
41151249dcaSIdo Shayevitz 			resource_size(res) - DWC3_GLOBALS_REGS_START,
412802ca850SChanho Park 			dev_name(dev));
41372246da4SFelipe Balbi 	if (!res) {
414802ca850SChanho Park 		dev_err(dev, "can't request mem region\n");
415802ca850SChanho Park 		return -ENOMEM;
41672246da4SFelipe Balbi 	}
41772246da4SFelipe Balbi 
418b7e38aa6SFelipe Balbi 	regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
41972246da4SFelipe Balbi 	if (!regs) {
420802ca850SChanho Park 		dev_err(dev, "ioremap failed\n");
421802ca850SChanho Park 		return -ENOMEM;
42272246da4SFelipe Balbi 	}
42372246da4SFelipe Balbi 
42451e1e7bcSFelipe Balbi 	dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
42551e1e7bcSFelipe Balbi 	if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
42651e1e7bcSFelipe Balbi 		dev_err(dev, "no usb2 phy configured\n");
42751e1e7bcSFelipe Balbi 		return -EPROBE_DEFER;
42851e1e7bcSFelipe Balbi 	}
42951e1e7bcSFelipe Balbi 
43051e1e7bcSFelipe Balbi 	dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
43151e1e7bcSFelipe Balbi 	if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
43251e1e7bcSFelipe Balbi 		dev_err(dev, "no usb3 phy configured\n");
43351e1e7bcSFelipe Balbi 		return -EPROBE_DEFER;
43451e1e7bcSFelipe Balbi 	}
43551e1e7bcSFelipe Balbi 
43672246da4SFelipe Balbi 	spin_lock_init(&dwc->lock);
43772246da4SFelipe Balbi 	platform_set_drvdata(pdev, dwc);
43872246da4SFelipe Balbi 
43972246da4SFelipe Balbi 	dwc->regs	= regs;
44072246da4SFelipe Balbi 	dwc->regs_size	= resource_size(res);
441802ca850SChanho Park 	dwc->dev	= dev;
44272246da4SFelipe Balbi 
4436c167fc9SFelipe Balbi 	if (!strncmp("super", maximum_speed, 5))
4446c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
4456c167fc9SFelipe Balbi 	else if (!strncmp("high", maximum_speed, 4))
4466c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
4476c167fc9SFelipe Balbi 	else if (!strncmp("full", maximum_speed, 4))
4486c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
4496c167fc9SFelipe Balbi 	else if (!strncmp("low", maximum_speed, 3))
4506c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
4516c167fc9SFelipe Balbi 	else
4526c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
4536c167fc9SFelipe Balbi 
454457e84b6SFelipe Balbi 	if (of_get_property(node, "tx-fifo-resize", NULL))
455457e84b6SFelipe Balbi 		dwc->needs_fifo_resize = true;
456457e84b6SFelipe Balbi 
457802ca850SChanho Park 	pm_runtime_enable(dev);
458802ca850SChanho Park 	pm_runtime_get_sync(dev);
459802ca850SChanho Park 	pm_runtime_forbid(dev);
46072246da4SFelipe Balbi 
4614fd24483SKishon Vijay Abraham I 	dwc3_cache_hwparams(dwc);
4624fd24483SKishon Vijay Abraham I 
4633921426bSFelipe Balbi 	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
4643921426bSFelipe Balbi 	if (ret) {
4653921426bSFelipe Balbi 		dev_err(dwc->dev, "failed to allocate event buffers\n");
4663921426bSFelipe Balbi 		ret = -ENOMEM;
4673921426bSFelipe Balbi 		goto err0;
4683921426bSFelipe Balbi 	}
4693921426bSFelipe Balbi 
47072246da4SFelipe Balbi 	ret = dwc3_core_init(dwc);
47172246da4SFelipe Balbi 	if (ret) {
472802ca850SChanho Park 		dev_err(dev, "failed to initialize core\n");
4733921426bSFelipe Balbi 		goto err0;
47472246da4SFelipe Balbi 	}
47572246da4SFelipe Balbi 
4760949e99bSFelipe Balbi 	mode = DWC3_MODE(dwc->hwparams.hwparams0);
4770949e99bSFelipe Balbi 
4780949e99bSFelipe Balbi 	switch (mode) {
4790949e99bSFelipe Balbi 	case DWC3_MODE_DEVICE:
4803140e8cbSSebastian Andrzej Siewior 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
48172246da4SFelipe Balbi 		ret = dwc3_gadget_init(dwc);
48272246da4SFelipe Balbi 		if (ret) {
483802ca850SChanho Park 			dev_err(dev, "failed to initialize gadget\n");
484802ca850SChanho Park 			goto err1;
48572246da4SFelipe Balbi 		}
4860949e99bSFelipe Balbi 		break;
487d07e8819SFelipe Balbi 	case DWC3_MODE_HOST:
4883140e8cbSSebastian Andrzej Siewior 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
489d07e8819SFelipe Balbi 		ret = dwc3_host_init(dwc);
490d07e8819SFelipe Balbi 		if (ret) {
491802ca850SChanho Park 			dev_err(dev, "failed to initialize host\n");
492802ca850SChanho Park 			goto err1;
49372246da4SFelipe Balbi 		}
494d07e8819SFelipe Balbi 		break;
495d07e8819SFelipe Balbi 	case DWC3_MODE_DRD:
4963140e8cbSSebastian Andrzej Siewior 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
497d07e8819SFelipe Balbi 		ret = dwc3_host_init(dwc);
498d07e8819SFelipe Balbi 		if (ret) {
499802ca850SChanho Park 			dev_err(dev, "failed to initialize host\n");
500802ca850SChanho Park 			goto err1;
501d07e8819SFelipe Balbi 		}
502d07e8819SFelipe Balbi 
503d07e8819SFelipe Balbi 		ret = dwc3_gadget_init(dwc);
504d07e8819SFelipe Balbi 		if (ret) {
505802ca850SChanho Park 			dev_err(dev, "failed to initialize gadget\n");
506802ca850SChanho Park 			goto err1;
507d07e8819SFelipe Balbi 		}
508d07e8819SFelipe Balbi 		break;
5090949e99bSFelipe Balbi 	default:
510802ca850SChanho Park 		dev_err(dev, "Unsupported mode of operation %d\n", mode);
511802ca850SChanho Park 		goto err1;
51272246da4SFelipe Balbi 	}
5130949e99bSFelipe Balbi 	dwc->mode = mode;
51472246da4SFelipe Balbi 
51572246da4SFelipe Balbi 	ret = dwc3_debugfs_init(dwc);
51672246da4SFelipe Balbi 	if (ret) {
517802ca850SChanho Park 		dev_err(dev, "failed to initialize debugfs\n");
518802ca850SChanho Park 		goto err2;
51972246da4SFelipe Balbi 	}
52072246da4SFelipe Balbi 
521802ca850SChanho Park 	pm_runtime_allow(dev);
52272246da4SFelipe Balbi 
52372246da4SFelipe Balbi 	return 0;
52472246da4SFelipe Balbi 
525802ca850SChanho Park err2:
5260949e99bSFelipe Balbi 	switch (mode) {
5270949e99bSFelipe Balbi 	case DWC3_MODE_DEVICE:
52872246da4SFelipe Balbi 		dwc3_gadget_exit(dwc);
5290949e99bSFelipe Balbi 		break;
530d07e8819SFelipe Balbi 	case DWC3_MODE_HOST:
531d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
532d07e8819SFelipe Balbi 		break;
533d07e8819SFelipe Balbi 	case DWC3_MODE_DRD:
534d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
535d07e8819SFelipe Balbi 		dwc3_gadget_exit(dwc);
536d07e8819SFelipe Balbi 		break;
5370949e99bSFelipe Balbi 	default:
5380949e99bSFelipe Balbi 		/* do nothing */
5390949e99bSFelipe Balbi 		break;
5400949e99bSFelipe Balbi 	}
54172246da4SFelipe Balbi 
542802ca850SChanho Park err1:
54372246da4SFelipe Balbi 	dwc3_core_exit(dwc);
54472246da4SFelipe Balbi 
5453921426bSFelipe Balbi err0:
5463921426bSFelipe Balbi 	dwc3_free_event_buffers(dwc);
5473921426bSFelipe Balbi 
54872246da4SFelipe Balbi 	return ret;
54972246da4SFelipe Balbi }
55072246da4SFelipe Balbi 
55172246da4SFelipe Balbi static int __devexit dwc3_remove(struct platform_device *pdev)
55272246da4SFelipe Balbi {
55372246da4SFelipe Balbi 	struct dwc3	*dwc = platform_get_drvdata(pdev);
55472246da4SFelipe Balbi 	struct resource	*res;
55572246da4SFelipe Balbi 
55672246da4SFelipe Balbi 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
55772246da4SFelipe Balbi 
55872246da4SFelipe Balbi 	pm_runtime_put(&pdev->dev);
55972246da4SFelipe Balbi 	pm_runtime_disable(&pdev->dev);
56072246da4SFelipe Balbi 
56172246da4SFelipe Balbi 	dwc3_debugfs_exit(dwc);
56272246da4SFelipe Balbi 
5630949e99bSFelipe Balbi 	switch (dwc->mode) {
5640949e99bSFelipe Balbi 	case DWC3_MODE_DEVICE:
56572246da4SFelipe Balbi 		dwc3_gadget_exit(dwc);
5660949e99bSFelipe Balbi 		break;
567d07e8819SFelipe Balbi 	case DWC3_MODE_HOST:
568d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
569d07e8819SFelipe Balbi 		break;
570d07e8819SFelipe Balbi 	case DWC3_MODE_DRD:
571d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
572d07e8819SFelipe Balbi 		dwc3_gadget_exit(dwc);
573d07e8819SFelipe Balbi 		break;
5740949e99bSFelipe Balbi 	default:
5750949e99bSFelipe Balbi 		/* do nothing */
5760949e99bSFelipe Balbi 		break;
5770949e99bSFelipe Balbi 	}
57872246da4SFelipe Balbi 
57972246da4SFelipe Balbi 	dwc3_core_exit(dwc);
58072246da4SFelipe Balbi 
58172246da4SFelipe Balbi 	return 0;
58272246da4SFelipe Balbi }
58372246da4SFelipe Balbi 
58472246da4SFelipe Balbi static struct platform_driver dwc3_driver = {
58572246da4SFelipe Balbi 	.probe		= dwc3_probe,
58672246da4SFelipe Balbi 	.remove		= __devexit_p(dwc3_remove),
58772246da4SFelipe Balbi 	.driver		= {
58872246da4SFelipe Balbi 		.name	= "dwc3",
58972246da4SFelipe Balbi 	},
59072246da4SFelipe Balbi };
59172246da4SFelipe Balbi 
592b1116dccSTobias Klauser module_platform_driver(dwc3_driver);
593b1116dccSTobias Klauser 
5947ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3");
59572246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
59672246da4SFelipe Balbi MODULE_LICENSE("Dual BSD/GPL");
59772246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
598