xref: /openbmc/linux/drivers/usb/dwc3/core.c (revision 45627ac6)
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 
5372246da4SFelipe Balbi #include <linux/usb/ch9.h>
5472246da4SFelipe Balbi #include <linux/usb/gadget.h>
5572246da4SFelipe Balbi 
5672246da4SFelipe Balbi #include "core.h"
5772246da4SFelipe Balbi #include "gadget.h"
5872246da4SFelipe Balbi #include "io.h"
5972246da4SFelipe Balbi 
6072246da4SFelipe Balbi #include "debug.h"
6172246da4SFelipe Balbi 
626c167fc9SFelipe Balbi static char *maximum_speed = "super";
636c167fc9SFelipe Balbi module_param(maximum_speed, charp, 0);
646c167fc9SFelipe Balbi MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
656c167fc9SFelipe Balbi 
668300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */
678300dd23SFelipe Balbi 
688300dd23SFelipe Balbi #define DWC3_DEVS_POSSIBLE	32
698300dd23SFelipe Balbi 
708300dd23SFelipe Balbi static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
718300dd23SFelipe Balbi 
728300dd23SFelipe Balbi int dwc3_get_device_id(void)
738300dd23SFelipe Balbi {
748300dd23SFelipe Balbi 	int		id;
758300dd23SFelipe Balbi 
768300dd23SFelipe Balbi again:
778300dd23SFelipe Balbi 	id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
788300dd23SFelipe Balbi 	if (id < DWC3_DEVS_POSSIBLE) {
798300dd23SFelipe Balbi 		int old;
808300dd23SFelipe Balbi 
818300dd23SFelipe Balbi 		old = test_and_set_bit(id, dwc3_devs);
828300dd23SFelipe Balbi 		if (old)
838300dd23SFelipe Balbi 			goto again;
848300dd23SFelipe Balbi 	} else {
858300dd23SFelipe Balbi 		pr_err("dwc3: no space for new device\n");
868300dd23SFelipe Balbi 		id = -ENOMEM;
878300dd23SFelipe Balbi 	}
888300dd23SFelipe Balbi 
89075cd14dSDan Carpenter 	return id;
908300dd23SFelipe Balbi }
918300dd23SFelipe Balbi EXPORT_SYMBOL_GPL(dwc3_get_device_id);
928300dd23SFelipe Balbi 
938300dd23SFelipe Balbi void dwc3_put_device_id(int id)
948300dd23SFelipe Balbi {
958300dd23SFelipe Balbi 	int			ret;
968300dd23SFelipe Balbi 
978300dd23SFelipe Balbi 	if (id < 0)
988300dd23SFelipe Balbi 		return;
998300dd23SFelipe Balbi 
1008300dd23SFelipe Balbi 	ret = test_bit(id, dwc3_devs);
1018300dd23SFelipe Balbi 	WARN(!ret, "dwc3: ID %d not in use\n", id);
1028300dd23SFelipe Balbi 	clear_bit(id, dwc3_devs);
1038300dd23SFelipe Balbi }
1048300dd23SFelipe Balbi EXPORT_SYMBOL_GPL(dwc3_put_device_id);
1058300dd23SFelipe Balbi 
1063140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
1073140e8cbSSebastian Andrzej Siewior {
1083140e8cbSSebastian Andrzej Siewior 	u32 reg;
1093140e8cbSSebastian Andrzej Siewior 
1103140e8cbSSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
1113140e8cbSSebastian Andrzej Siewior 	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
1123140e8cbSSebastian Andrzej Siewior 	reg |= DWC3_GCTL_PRTCAPDIR(mode);
1133140e8cbSSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
1143140e8cbSSebastian Andrzej Siewior }
1158300dd23SFelipe Balbi 
11672246da4SFelipe Balbi /**
11772246da4SFelipe Balbi  * dwc3_core_soft_reset - Issues core soft reset and PHY reset
11872246da4SFelipe Balbi  * @dwc: pointer to our context structure
11972246da4SFelipe Balbi  */
12072246da4SFelipe Balbi static void dwc3_core_soft_reset(struct dwc3 *dwc)
12172246da4SFelipe Balbi {
12272246da4SFelipe Balbi 	u32		reg;
12372246da4SFelipe Balbi 
12472246da4SFelipe Balbi 	/* Before Resetting PHY, put Core in Reset */
12572246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
12672246da4SFelipe Balbi 	reg |= DWC3_GCTL_CORESOFTRESET;
12772246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
12872246da4SFelipe Balbi 
12972246da4SFelipe Balbi 	/* Assert USB3 PHY reset */
13072246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
13172246da4SFelipe Balbi 	reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
13272246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
13372246da4SFelipe Balbi 
13472246da4SFelipe Balbi 	/* Assert USB2 PHY reset */
13572246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
13672246da4SFelipe Balbi 	reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
13772246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
13872246da4SFelipe Balbi 
13972246da4SFelipe Balbi 	mdelay(100);
14072246da4SFelipe Balbi 
14172246da4SFelipe Balbi 	/* Clear USB3 PHY reset */
14272246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
14372246da4SFelipe Balbi 	reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
14472246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
14572246da4SFelipe Balbi 
14672246da4SFelipe Balbi 	/* Clear USB2 PHY reset */
14772246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
14872246da4SFelipe Balbi 	reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
14972246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
15072246da4SFelipe Balbi 
151*45627ac6SPratyush Anand 	mdelay(100);
152*45627ac6SPratyush Anand 
15372246da4SFelipe Balbi 	/* After PHYs are stable we can take Core out of reset state */
15472246da4SFelipe Balbi 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
15572246da4SFelipe Balbi 	reg &= ~DWC3_GCTL_CORESOFTRESET;
15672246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
15772246da4SFelipe Balbi }
15872246da4SFelipe Balbi 
15972246da4SFelipe Balbi /**
16072246da4SFelipe Balbi  * dwc3_free_one_event_buffer - Frees one event buffer
16172246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
16272246da4SFelipe Balbi  * @evt: Pointer to event buffer to be freed
16372246da4SFelipe Balbi  */
16472246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
16572246da4SFelipe Balbi 		struct dwc3_event_buffer *evt)
16672246da4SFelipe Balbi {
16772246da4SFelipe Balbi 	dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
16872246da4SFelipe Balbi 	kfree(evt);
16972246da4SFelipe Balbi }
17072246da4SFelipe Balbi 
17172246da4SFelipe Balbi /**
1721d046793SPaul Zimmerman  * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
17372246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
17472246da4SFelipe Balbi  * @length: size of the event buffer
17572246da4SFelipe Balbi  *
1761d046793SPaul Zimmerman  * Returns a pointer to the allocated event buffer structure on success
17772246da4SFelipe Balbi  * otherwise ERR_PTR(errno).
17872246da4SFelipe Balbi  */
17972246da4SFelipe Balbi static struct dwc3_event_buffer *__devinit
18072246da4SFelipe Balbi dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
18172246da4SFelipe Balbi {
18272246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
18372246da4SFelipe Balbi 
18472246da4SFelipe Balbi 	evt = kzalloc(sizeof(*evt), GFP_KERNEL);
18572246da4SFelipe Balbi 	if (!evt)
18672246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
18772246da4SFelipe Balbi 
18872246da4SFelipe Balbi 	evt->dwc	= dwc;
18972246da4SFelipe Balbi 	evt->length	= length;
19072246da4SFelipe Balbi 	evt->buf	= dma_alloc_coherent(dwc->dev, length,
19172246da4SFelipe Balbi 			&evt->dma, GFP_KERNEL);
19272246da4SFelipe Balbi 	if (!evt->buf) {
19372246da4SFelipe Balbi 		kfree(evt);
19472246da4SFelipe Balbi 		return ERR_PTR(-ENOMEM);
19572246da4SFelipe Balbi 	}
19672246da4SFelipe Balbi 
19772246da4SFelipe Balbi 	return evt;
19872246da4SFelipe Balbi }
19972246da4SFelipe Balbi 
20072246da4SFelipe Balbi /**
20172246da4SFelipe Balbi  * dwc3_free_event_buffers - frees all allocated event buffers
20272246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
20372246da4SFelipe Balbi  */
20472246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc)
20572246da4SFelipe Balbi {
20672246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
20772246da4SFelipe Balbi 	int i;
20872246da4SFelipe Balbi 
2099f622b2aSFelipe Balbi 	for (i = 0; i < dwc->num_event_buffers; i++) {
21072246da4SFelipe Balbi 		evt = dwc->ev_buffs[i];
21164b6c8a7SAnton Tikhomirov 		if (evt)
21272246da4SFelipe Balbi 			dwc3_free_one_event_buffer(dwc, evt);
21372246da4SFelipe Balbi 	}
21464b6c8a7SAnton Tikhomirov 
21564b6c8a7SAnton Tikhomirov 	kfree(dwc->ev_buffs);
21672246da4SFelipe Balbi }
21772246da4SFelipe Balbi 
21872246da4SFelipe Balbi /**
21972246da4SFelipe Balbi  * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
2201d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
22172246da4SFelipe Balbi  * @length: size of event buffer
22272246da4SFelipe Balbi  *
2231d046793SPaul Zimmerman  * Returns 0 on success otherwise negative errno. In the error case, dwc
22472246da4SFelipe Balbi  * may contain some buffers allocated but not all which were requested.
22572246da4SFelipe Balbi  */
2269f622b2aSFelipe Balbi static int __devinit dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
22772246da4SFelipe Balbi {
2289f622b2aSFelipe Balbi 	int			num;
22972246da4SFelipe Balbi 	int			i;
23072246da4SFelipe Balbi 
2319f622b2aSFelipe Balbi 	num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
2329f622b2aSFelipe Balbi 	dwc->num_event_buffers = num;
2339f622b2aSFelipe Balbi 
234457d3f21SFelipe Balbi 	dwc->ev_buffs = kzalloc(sizeof(*dwc->ev_buffs) * num, GFP_KERNEL);
235457d3f21SFelipe Balbi 	if (!dwc->ev_buffs) {
236457d3f21SFelipe Balbi 		dev_err(dwc->dev, "can't allocate event buffers array\n");
237457d3f21SFelipe Balbi 		return -ENOMEM;
238457d3f21SFelipe Balbi 	}
239457d3f21SFelipe Balbi 
24072246da4SFelipe Balbi 	for (i = 0; i < num; i++) {
24172246da4SFelipe Balbi 		struct dwc3_event_buffer	*evt;
24272246da4SFelipe Balbi 
24372246da4SFelipe Balbi 		evt = dwc3_alloc_one_event_buffer(dwc, length);
24472246da4SFelipe Balbi 		if (IS_ERR(evt)) {
24572246da4SFelipe Balbi 			dev_err(dwc->dev, "can't allocate event buffer\n");
24672246da4SFelipe Balbi 			return PTR_ERR(evt);
24772246da4SFelipe Balbi 		}
24872246da4SFelipe Balbi 		dwc->ev_buffs[i] = evt;
24972246da4SFelipe Balbi 	}
25072246da4SFelipe Balbi 
25172246da4SFelipe Balbi 	return 0;
25272246da4SFelipe Balbi }
25372246da4SFelipe Balbi 
25472246da4SFelipe Balbi /**
25572246da4SFelipe Balbi  * dwc3_event_buffers_setup - setup our allocated event buffers
2561d046793SPaul Zimmerman  * @dwc: pointer to our controller context structure
25772246da4SFelipe Balbi  *
25872246da4SFelipe Balbi  * Returns 0 on success otherwise negative errno.
25972246da4SFelipe Balbi  */
2607acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc)
26172246da4SFelipe Balbi {
26272246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
26372246da4SFelipe Balbi 	int				n;
26472246da4SFelipe Balbi 
2659f622b2aSFelipe Balbi 	for (n = 0; n < dwc->num_event_buffers; n++) {
26672246da4SFelipe Balbi 		evt = dwc->ev_buffs[n];
26772246da4SFelipe Balbi 		dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
26872246da4SFelipe Balbi 				evt->buf, (unsigned long long) evt->dma,
26972246da4SFelipe Balbi 				evt->length);
27072246da4SFelipe Balbi 
2717acd85e0SPaul Zimmerman 		evt->lpos = 0;
2727acd85e0SPaul Zimmerman 
27372246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
27472246da4SFelipe Balbi 				lower_32_bits(evt->dma));
27572246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
27672246da4SFelipe Balbi 				upper_32_bits(evt->dma));
27772246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
27872246da4SFelipe Balbi 				evt->length & 0xffff);
27972246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
28072246da4SFelipe Balbi 	}
28172246da4SFelipe Balbi 
28272246da4SFelipe Balbi 	return 0;
28372246da4SFelipe Balbi }
28472246da4SFelipe Balbi 
28572246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
28672246da4SFelipe Balbi {
28772246da4SFelipe Balbi 	struct dwc3_event_buffer	*evt;
28872246da4SFelipe Balbi 	int				n;
28972246da4SFelipe Balbi 
2909f622b2aSFelipe Balbi 	for (n = 0; n < dwc->num_event_buffers; n++) {
29172246da4SFelipe Balbi 		evt = dwc->ev_buffs[n];
2927acd85e0SPaul Zimmerman 
2937acd85e0SPaul Zimmerman 		evt->lpos = 0;
2947acd85e0SPaul Zimmerman 
29572246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
29672246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
29772246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
29872246da4SFelipe Balbi 		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
29972246da4SFelipe Balbi 	}
30072246da4SFelipe Balbi }
30172246da4SFelipe Balbi 
30226ceca97SFelipe Balbi static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
30326ceca97SFelipe Balbi {
30426ceca97SFelipe Balbi 	struct dwc3_hwparams	*parms = &dwc->hwparams;
30526ceca97SFelipe Balbi 
30626ceca97SFelipe Balbi 	parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
30726ceca97SFelipe Balbi 	parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
30826ceca97SFelipe Balbi 	parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
30926ceca97SFelipe Balbi 	parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
31026ceca97SFelipe Balbi 	parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
31126ceca97SFelipe Balbi 	parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
31226ceca97SFelipe Balbi 	parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
31326ceca97SFelipe Balbi 	parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
31426ceca97SFelipe Balbi 	parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
31526ceca97SFelipe Balbi }
31626ceca97SFelipe Balbi 
31772246da4SFelipe Balbi /**
31872246da4SFelipe Balbi  * dwc3_core_init - Low-level initialization of DWC3 Core
31972246da4SFelipe Balbi  * @dwc: Pointer to our controller context structure
32072246da4SFelipe Balbi  *
32172246da4SFelipe Balbi  * Returns 0 on success otherwise negative errno.
32272246da4SFelipe Balbi  */
32372246da4SFelipe Balbi static int __devinit dwc3_core_init(struct dwc3 *dwc)
32472246da4SFelipe Balbi {
32572246da4SFelipe Balbi 	unsigned long		timeout;
32672246da4SFelipe Balbi 	u32			reg;
32772246da4SFelipe Balbi 	int			ret;
32872246da4SFelipe Balbi 
3297650bd74SSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
3307650bd74SSebastian Andrzej Siewior 	/* This should read as U3 followed by revision number */
3317650bd74SSebastian Andrzej Siewior 	if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
3327650bd74SSebastian Andrzej Siewior 		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
3337650bd74SSebastian Andrzej Siewior 		ret = -ENODEV;
3347650bd74SSebastian Andrzej Siewior 		goto err0;
3357650bd74SSebastian Andrzej Siewior 	}
336248b122bSFelipe Balbi 	dwc->revision = reg;
3377650bd74SSebastian Andrzej Siewior 
33872246da4SFelipe Balbi 	dwc3_core_soft_reset(dwc);
33972246da4SFelipe Balbi 
34072246da4SFelipe Balbi 	/* issue device SoftReset too */
34172246da4SFelipe Balbi 	timeout = jiffies + msecs_to_jiffies(500);
34272246da4SFelipe Balbi 	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
34372246da4SFelipe Balbi 	do {
34472246da4SFelipe Balbi 		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
34572246da4SFelipe Balbi 		if (!(reg & DWC3_DCTL_CSFTRST))
34672246da4SFelipe Balbi 			break;
34772246da4SFelipe Balbi 
34872246da4SFelipe Balbi 		if (time_after(jiffies, timeout)) {
34972246da4SFelipe Balbi 			dev_err(dwc->dev, "Reset Timed Out\n");
35072246da4SFelipe Balbi 			ret = -ETIMEDOUT;
35172246da4SFelipe Balbi 			goto err0;
35272246da4SFelipe Balbi 		}
35372246da4SFelipe Balbi 
35472246da4SFelipe Balbi 		cpu_relax();
35572246da4SFelipe Balbi 	} while (true);
35672246da4SFelipe Balbi 
3579f622b2aSFelipe Balbi 	dwc3_cache_hwparams(dwc);
3589f622b2aSFelipe Balbi 
3594878a028SSebastian Andrzej Siewior 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
3603e87c42aSPaul Zimmerman 	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
3614878a028SSebastian Andrzej Siewior 	reg &= ~DWC3_GCTL_DISSCRAMBLE;
3624878a028SSebastian Andrzej Siewior 
363164d7731SSebastian Andrzej Siewior 	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
3644878a028SSebastian Andrzej Siewior 	case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
3654878a028SSebastian Andrzej Siewior 		reg &= ~DWC3_GCTL_DSBLCLKGTNG;
3664878a028SSebastian Andrzej Siewior 		break;
3674878a028SSebastian Andrzej Siewior 	default:
3684878a028SSebastian Andrzej Siewior 		dev_dbg(dwc->dev, "No power optimization available\n");
3694878a028SSebastian Andrzej Siewior 	}
3704878a028SSebastian Andrzej Siewior 
3714878a028SSebastian Andrzej Siewior 	/*
3724878a028SSebastian Andrzej Siewior 	 * WORKAROUND: DWC3 revisions <1.90a have a bug
3731d046793SPaul Zimmerman 	 * where the device can fail to connect at SuperSpeed
3744878a028SSebastian Andrzej Siewior 	 * and falls back to high-speed mode which causes
3751d046793SPaul Zimmerman 	 * the device to enter a Connect/Disconnect loop
3764878a028SSebastian Andrzej Siewior 	 */
3774878a028SSebastian Andrzej Siewior 	if (dwc->revision < DWC3_REVISION_190A)
3784878a028SSebastian Andrzej Siewior 		reg |= DWC3_GCTL_U2RSTECN;
3794878a028SSebastian Andrzej Siewior 
3804878a028SSebastian Andrzej Siewior 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
3814878a028SSebastian Andrzej Siewior 
3829f622b2aSFelipe Balbi 	ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
38372246da4SFelipe Balbi 	if (ret) {
38472246da4SFelipe Balbi 		dev_err(dwc->dev, "failed to allocate event buffers\n");
38572246da4SFelipe Balbi 		ret = -ENOMEM;
38672246da4SFelipe Balbi 		goto err1;
38772246da4SFelipe Balbi 	}
38872246da4SFelipe Balbi 
38972246da4SFelipe Balbi 	ret = dwc3_event_buffers_setup(dwc);
39072246da4SFelipe Balbi 	if (ret) {
39172246da4SFelipe Balbi 		dev_err(dwc->dev, "failed to setup event buffers\n");
39272246da4SFelipe Balbi 		goto err1;
39372246da4SFelipe Balbi 	}
39472246da4SFelipe Balbi 
39572246da4SFelipe Balbi 	return 0;
39672246da4SFelipe Balbi 
39772246da4SFelipe Balbi err1:
39872246da4SFelipe Balbi 	dwc3_free_event_buffers(dwc);
39972246da4SFelipe Balbi 
40072246da4SFelipe Balbi err0:
40172246da4SFelipe Balbi 	return ret;
40272246da4SFelipe Balbi }
40372246da4SFelipe Balbi 
40472246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc)
40572246da4SFelipe Balbi {
40672246da4SFelipe Balbi 	dwc3_event_buffers_cleanup(dwc);
40772246da4SFelipe Balbi 	dwc3_free_event_buffers(dwc);
40872246da4SFelipe Balbi }
40972246da4SFelipe Balbi 
41072246da4SFelipe Balbi #define DWC3_ALIGN_MASK		(16 - 1)
41172246da4SFelipe Balbi 
41272246da4SFelipe Balbi static int __devinit dwc3_probe(struct platform_device *pdev)
41372246da4SFelipe Balbi {
414457e84b6SFelipe Balbi 	struct device_node	*node = pdev->dev.of_node;
41572246da4SFelipe Balbi 	struct resource		*res;
41672246da4SFelipe Balbi 	struct dwc3		*dwc;
417802ca850SChanho Park 	struct device		*dev = &pdev->dev;
4180949e99bSFelipe Balbi 
41972246da4SFelipe Balbi 	int			ret = -ENOMEM;
4200949e99bSFelipe Balbi 
4210949e99bSFelipe Balbi 	void __iomem		*regs;
42272246da4SFelipe Balbi 	void			*mem;
42372246da4SFelipe Balbi 
4240949e99bSFelipe Balbi 	u8			mode;
4250949e99bSFelipe Balbi 
426802ca850SChanho Park 	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
42772246da4SFelipe Balbi 	if (!mem) {
428802ca850SChanho Park 		dev_err(dev, "not enough memory\n");
429802ca850SChanho Park 		return -ENOMEM;
43072246da4SFelipe Balbi 	}
43172246da4SFelipe Balbi 	dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
43272246da4SFelipe Balbi 	dwc->mem = mem;
43372246da4SFelipe Balbi 
43451249dcaSIdo Shayevitz 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
43572246da4SFelipe Balbi 	if (!res) {
43651249dcaSIdo Shayevitz 		dev_err(dev, "missing IRQ\n");
437802ca850SChanho Park 		return -ENODEV;
43872246da4SFelipe Balbi 	}
43951249dcaSIdo Shayevitz 	dwc->xhci_resources[1] = *res;
44072246da4SFelipe Balbi 
44151249dcaSIdo Shayevitz 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
44251249dcaSIdo Shayevitz 	if (!res) {
44351249dcaSIdo Shayevitz 		dev_err(dev, "missing memory resource\n");
44451249dcaSIdo Shayevitz 		return -ENODEV;
44551249dcaSIdo Shayevitz 	}
44651249dcaSIdo Shayevitz 	dwc->xhci_resources[0] = *res;
44751249dcaSIdo Shayevitz 	dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
44851249dcaSIdo Shayevitz 					DWC3_XHCI_REGS_END;
449d07e8819SFelipe Balbi 
45051249dcaSIdo Shayevitz 	 /*
45151249dcaSIdo Shayevitz 	  * Request memory region but exclude xHCI regs,
45251249dcaSIdo Shayevitz 	  * since it will be requested by the xhci-plat driver.
45351249dcaSIdo Shayevitz 	  */
45451249dcaSIdo Shayevitz 	res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
45551249dcaSIdo Shayevitz 			resource_size(res) - DWC3_GLOBALS_REGS_START,
456802ca850SChanho Park 			dev_name(dev));
45772246da4SFelipe Balbi 	if (!res) {
458802ca850SChanho Park 		dev_err(dev, "can't request mem region\n");
459802ca850SChanho Park 		return -ENOMEM;
46072246da4SFelipe Balbi 	}
46172246da4SFelipe Balbi 
462802ca850SChanho Park 	regs = devm_ioremap(dev, res->start, resource_size(res));
46372246da4SFelipe Balbi 	if (!regs) {
464802ca850SChanho Park 		dev_err(dev, "ioremap failed\n");
465802ca850SChanho Park 		return -ENOMEM;
46672246da4SFelipe Balbi 	}
46772246da4SFelipe Balbi 
46872246da4SFelipe Balbi 	spin_lock_init(&dwc->lock);
46972246da4SFelipe Balbi 	platform_set_drvdata(pdev, dwc);
47072246da4SFelipe Balbi 
47172246da4SFelipe Balbi 	dwc->regs	= regs;
47272246da4SFelipe Balbi 	dwc->regs_size	= resource_size(res);
473802ca850SChanho Park 	dwc->dev	= dev;
47472246da4SFelipe Balbi 
4756c167fc9SFelipe Balbi 	if (!strncmp("super", maximum_speed, 5))
4766c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
4776c167fc9SFelipe Balbi 	else if (!strncmp("high", maximum_speed, 4))
4786c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
4796c167fc9SFelipe Balbi 	else if (!strncmp("full", maximum_speed, 4))
4806c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
4816c167fc9SFelipe Balbi 	else if (!strncmp("low", maximum_speed, 3))
4826c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
4836c167fc9SFelipe Balbi 	else
4846c167fc9SFelipe Balbi 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
4856c167fc9SFelipe Balbi 
486457e84b6SFelipe Balbi 	if (of_get_property(node, "tx-fifo-resize", NULL))
487457e84b6SFelipe Balbi 		dwc->needs_fifo_resize = true;
488457e84b6SFelipe Balbi 
489802ca850SChanho Park 	pm_runtime_enable(dev);
490802ca850SChanho Park 	pm_runtime_get_sync(dev);
491802ca850SChanho Park 	pm_runtime_forbid(dev);
49272246da4SFelipe Balbi 
49372246da4SFelipe Balbi 	ret = dwc3_core_init(dwc);
49472246da4SFelipe Balbi 	if (ret) {
495802ca850SChanho Park 		dev_err(dev, "failed to initialize core\n");
496802ca850SChanho Park 		return ret;
49772246da4SFelipe Balbi 	}
49872246da4SFelipe Balbi 
4990949e99bSFelipe Balbi 	mode = DWC3_MODE(dwc->hwparams.hwparams0);
5000949e99bSFelipe Balbi 
5010949e99bSFelipe Balbi 	switch (mode) {
5020949e99bSFelipe Balbi 	case DWC3_MODE_DEVICE:
5033140e8cbSSebastian Andrzej Siewior 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
50472246da4SFelipe Balbi 		ret = dwc3_gadget_init(dwc);
50572246da4SFelipe Balbi 		if (ret) {
506802ca850SChanho Park 			dev_err(dev, "failed to initialize gadget\n");
507802ca850SChanho Park 			goto err1;
50872246da4SFelipe Balbi 		}
5090949e99bSFelipe Balbi 		break;
510d07e8819SFelipe Balbi 	case DWC3_MODE_HOST:
5113140e8cbSSebastian Andrzej Siewior 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
512d07e8819SFelipe Balbi 		ret = dwc3_host_init(dwc);
513d07e8819SFelipe Balbi 		if (ret) {
514802ca850SChanho Park 			dev_err(dev, "failed to initialize host\n");
515802ca850SChanho Park 			goto err1;
51672246da4SFelipe Balbi 		}
517d07e8819SFelipe Balbi 		break;
518d07e8819SFelipe Balbi 	case DWC3_MODE_DRD:
5193140e8cbSSebastian Andrzej Siewior 		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
520d07e8819SFelipe Balbi 		ret = dwc3_host_init(dwc);
521d07e8819SFelipe Balbi 		if (ret) {
522802ca850SChanho Park 			dev_err(dev, "failed to initialize host\n");
523802ca850SChanho Park 			goto err1;
524d07e8819SFelipe Balbi 		}
525d07e8819SFelipe Balbi 
526d07e8819SFelipe Balbi 		ret = dwc3_gadget_init(dwc);
527d07e8819SFelipe Balbi 		if (ret) {
528802ca850SChanho Park 			dev_err(dev, "failed to initialize gadget\n");
529802ca850SChanho Park 			goto err1;
530d07e8819SFelipe Balbi 		}
531d07e8819SFelipe Balbi 		break;
5320949e99bSFelipe Balbi 	default:
533802ca850SChanho Park 		dev_err(dev, "Unsupported mode of operation %d\n", mode);
534802ca850SChanho Park 		goto err1;
53572246da4SFelipe Balbi 	}
5360949e99bSFelipe Balbi 	dwc->mode = mode;
53772246da4SFelipe Balbi 
53872246da4SFelipe Balbi 	ret = dwc3_debugfs_init(dwc);
53972246da4SFelipe Balbi 	if (ret) {
540802ca850SChanho Park 		dev_err(dev, "failed to initialize debugfs\n");
541802ca850SChanho Park 		goto err2;
54272246da4SFelipe Balbi 	}
54372246da4SFelipe Balbi 
544802ca850SChanho Park 	pm_runtime_allow(dev);
54572246da4SFelipe Balbi 
54672246da4SFelipe Balbi 	return 0;
54772246da4SFelipe Balbi 
548802ca850SChanho Park err2:
5490949e99bSFelipe Balbi 	switch (mode) {
5500949e99bSFelipe Balbi 	case DWC3_MODE_DEVICE:
55172246da4SFelipe Balbi 		dwc3_gadget_exit(dwc);
5520949e99bSFelipe Balbi 		break;
553d07e8819SFelipe Balbi 	case DWC3_MODE_HOST:
554d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
555d07e8819SFelipe Balbi 		break;
556d07e8819SFelipe Balbi 	case DWC3_MODE_DRD:
557d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
558d07e8819SFelipe Balbi 		dwc3_gadget_exit(dwc);
559d07e8819SFelipe Balbi 		break;
5600949e99bSFelipe Balbi 	default:
5610949e99bSFelipe Balbi 		/* do nothing */
5620949e99bSFelipe Balbi 		break;
5630949e99bSFelipe Balbi 	}
56472246da4SFelipe Balbi 
565802ca850SChanho Park err1:
56672246da4SFelipe Balbi 	dwc3_core_exit(dwc);
56772246da4SFelipe Balbi 
56872246da4SFelipe Balbi 	return ret;
56972246da4SFelipe Balbi }
57072246da4SFelipe Balbi 
57172246da4SFelipe Balbi static int __devexit dwc3_remove(struct platform_device *pdev)
57272246da4SFelipe Balbi {
57372246da4SFelipe Balbi 	struct dwc3	*dwc = platform_get_drvdata(pdev);
57472246da4SFelipe Balbi 	struct resource	*res;
57572246da4SFelipe Balbi 
57672246da4SFelipe Balbi 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
57772246da4SFelipe Balbi 
57872246da4SFelipe Balbi 	pm_runtime_put(&pdev->dev);
57972246da4SFelipe Balbi 	pm_runtime_disable(&pdev->dev);
58072246da4SFelipe Balbi 
58172246da4SFelipe Balbi 	dwc3_debugfs_exit(dwc);
58272246da4SFelipe Balbi 
5830949e99bSFelipe Balbi 	switch (dwc->mode) {
5840949e99bSFelipe Balbi 	case DWC3_MODE_DEVICE:
58572246da4SFelipe Balbi 		dwc3_gadget_exit(dwc);
5860949e99bSFelipe Balbi 		break;
587d07e8819SFelipe Balbi 	case DWC3_MODE_HOST:
588d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
589d07e8819SFelipe Balbi 		break;
590d07e8819SFelipe Balbi 	case DWC3_MODE_DRD:
591d07e8819SFelipe Balbi 		dwc3_host_exit(dwc);
592d07e8819SFelipe Balbi 		dwc3_gadget_exit(dwc);
593d07e8819SFelipe Balbi 		break;
5940949e99bSFelipe Balbi 	default:
5950949e99bSFelipe Balbi 		/* do nothing */
5960949e99bSFelipe Balbi 		break;
5970949e99bSFelipe Balbi 	}
59872246da4SFelipe Balbi 
59972246da4SFelipe Balbi 	dwc3_core_exit(dwc);
60072246da4SFelipe Balbi 
60172246da4SFelipe Balbi 	return 0;
60272246da4SFelipe Balbi }
60372246da4SFelipe Balbi 
60472246da4SFelipe Balbi static struct platform_driver dwc3_driver = {
60572246da4SFelipe Balbi 	.probe		= dwc3_probe,
60672246da4SFelipe Balbi 	.remove		= __devexit_p(dwc3_remove),
60772246da4SFelipe Balbi 	.driver		= {
60872246da4SFelipe Balbi 		.name	= "dwc3",
60972246da4SFelipe Balbi 	},
61072246da4SFelipe Balbi };
61172246da4SFelipe Balbi 
612b1116dccSTobias Klauser module_platform_driver(dwc3_driver);
613b1116dccSTobias Klauser 
6147ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3");
61572246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
61672246da4SFelipe Balbi MODULE_LICENSE("Dual BSD/GPL");
61772246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
618