blob: ddfe7718e4a32c62084c45d59d14a3fe0c6fe93b [file] [log] [blame]
Felipe Balbi72246da2011-08-19 18:10:58 +03001/**
2 * core.c - DesignWare USB3 DRD Controller Core file
3 *
4 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
Felipe Balbi72246da2011-08-19 18:10:58 +03005 *
6 * Authors: Felipe Balbi <balbi@ti.com>,
7 * Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8 *
Felipe Balbi5945f782013-06-30 14:15:11 +03009 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 of
11 * the License as published by the Free Software Foundation.
Felipe Balbi72246da2011-08-19 18:10:58 +030012 *
Felipe Balbi5945f782013-06-30 14:15:11 +030013 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
Felipe Balbi72246da2011-08-19 18:10:58 +030017 *
Felipe Balbi5945f782013-06-30 14:15:11 +030018 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Felipe Balbi72246da2011-08-19 18:10:58 +030020 */
21
Felipe Balbifa0ea132014-09-19 15:51:11 -050022#include <linux/version.h>
Felipe Balbia72e6582011-09-05 13:37:28 +030023#include <linux/module.h>
Felipe Balbi72246da2011-08-19 18:10:58 +030024#include <linux/kernel.h>
25#include <linux/slab.h>
26#include <linux/spinlock.h>
27#include <linux/platform_device.h>
28#include <linux/pm_runtime.h>
29#include <linux/interrupt.h>
30#include <linux/ioport.h>
31#include <linux/io.h>
32#include <linux/list.h>
33#include <linux/delay.h>
34#include <linux/dma-mapping.h>
Felipe Balbi457e84b2012-01-18 18:04:09 +020035#include <linux/of.h>
Felipe Balbi72246da2011-08-19 18:10:58 +030036
37#include <linux/usb/ch9.h>
38#include <linux/usb/gadget.h>
Felipe Balbif7e846f2013-06-30 14:29:51 +030039#include <linux/usb/of.h>
Ruchika Kharwara45c82b82013-07-06 07:52:49 -050040#include <linux/usb/otg.h>
Felipe Balbi72246da2011-08-19 18:10:58 +030041
Felipe Balbi6462cbd2013-06-30 14:19:33 +030042#include "platform_data.h"
Felipe Balbi72246da2011-08-19 18:10:58 +030043#include "core.h"
44#include "gadget.h"
45#include "io.h"
46
47#include "debug.h"
48
Felipe Balbi8300dd22011-10-18 13:54:01 +030049/* -------------------------------------------------------------------------- */
50
Sebastian Andrzej Siewior3140e8c2011-10-31 22:25:40 +010051void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
52{
53 u32 reg;
54
55 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
56 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
57 reg |= DWC3_GCTL_PRTCAPDIR(mode);
58 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
59}
Felipe Balbi8300dd22011-10-18 13:54:01 +030060
Felipe Balbi72246da2011-08-19 18:10:58 +030061/**
62 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
63 * @dwc: pointer to our context structure
64 */
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +053065static int dwc3_core_soft_reset(struct dwc3 *dwc)
Felipe Balbi72246da2011-08-19 18:10:58 +030066{
67 u32 reg;
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +053068 int ret;
Felipe Balbi72246da2011-08-19 18:10:58 +030069
70 /* Before Resetting PHY, put Core in Reset */
71 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
72 reg |= DWC3_GCTL_CORESOFTRESET;
73 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
74
75 /* Assert USB3 PHY reset */
76 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
77 reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
78 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
79
80 /* Assert USB2 PHY reset */
81 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
82 reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
83 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
84
Felipe Balbi51e1e7b2012-07-19 14:09:48 +030085 usb_phy_init(dwc->usb2_phy);
86 usb_phy_init(dwc->usb3_phy);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +053087 ret = phy_init(dwc->usb2_generic_phy);
88 if (ret < 0)
89 return ret;
90
91 ret = phy_init(dwc->usb3_generic_phy);
92 if (ret < 0) {
93 phy_exit(dwc->usb2_generic_phy);
94 return ret;
95 }
Felipe Balbi72246da2011-08-19 18:10:58 +030096 mdelay(100);
97
98 /* Clear USB3 PHY reset */
99 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
100 reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
101 dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
102
103 /* Clear USB2 PHY reset */
104 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
105 reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
106 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
107
Pratyush Anand45627ac2012-06-21 17:44:28 +0530108 mdelay(100);
109
Felipe Balbi72246da2011-08-19 18:10:58 +0300110 /* After PHYs are stable we can take Core out of reset state */
111 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
112 reg &= ~DWC3_GCTL_CORESOFTRESET;
113 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530114
115 return 0;
Felipe Balbi72246da2011-08-19 18:10:58 +0300116}
117
118/**
119 * dwc3_free_one_event_buffer - Frees one event buffer
120 * @dwc: Pointer to our controller context structure
121 * @evt: Pointer to event buffer to be freed
122 */
123static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
124 struct dwc3_event_buffer *evt)
125{
126 dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
Felipe Balbi72246da2011-08-19 18:10:58 +0300127}
128
129/**
Paul Zimmerman1d046792012-02-15 18:56:56 -0800130 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
Felipe Balbi72246da2011-08-19 18:10:58 +0300131 * @dwc: Pointer to our controller context structure
132 * @length: size of the event buffer
133 *
Paul Zimmerman1d046792012-02-15 18:56:56 -0800134 * Returns a pointer to the allocated event buffer structure on success
Felipe Balbi72246da2011-08-19 18:10:58 +0300135 * otherwise ERR_PTR(errno).
136 */
Felipe Balbi67d0b502013-02-22 16:31:07 +0200137static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
138 unsigned length)
Felipe Balbi72246da2011-08-19 18:10:58 +0300139{
140 struct dwc3_event_buffer *evt;
141
Felipe Balbi380f0d22012-10-11 13:48:36 +0300142 evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
Felipe Balbi72246da2011-08-19 18:10:58 +0300143 if (!evt)
144 return ERR_PTR(-ENOMEM);
145
146 evt->dwc = dwc;
147 evt->length = length;
148 evt->buf = dma_alloc_coherent(dwc->dev, length,
149 &evt->dma, GFP_KERNEL);
Felipe Balbie32672f2012-11-08 15:26:41 +0200150 if (!evt->buf)
Felipe Balbi72246da2011-08-19 18:10:58 +0300151 return ERR_PTR(-ENOMEM);
Felipe Balbi72246da2011-08-19 18:10:58 +0300152
153 return evt;
154}
155
156/**
157 * dwc3_free_event_buffers - frees all allocated event buffers
158 * @dwc: Pointer to our controller context structure
159 */
160static void dwc3_free_event_buffers(struct dwc3 *dwc)
161{
162 struct dwc3_event_buffer *evt;
163 int i;
164
Felipe Balbi9f622b22011-10-12 10:31:04 +0300165 for (i = 0; i < dwc->num_event_buffers; i++) {
Felipe Balbi72246da2011-08-19 18:10:58 +0300166 evt = dwc->ev_buffs[i];
Anton Tikhomirov64b6c8a2012-03-06 17:05:15 +0900167 if (evt)
Felipe Balbi72246da2011-08-19 18:10:58 +0300168 dwc3_free_one_event_buffer(dwc, evt);
Felipe Balbi72246da2011-08-19 18:10:58 +0300169 }
170}
171
172/**
173 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
Paul Zimmerman1d046792012-02-15 18:56:56 -0800174 * @dwc: pointer to our controller context structure
Felipe Balbi72246da2011-08-19 18:10:58 +0300175 * @length: size of event buffer
176 *
Paul Zimmerman1d046792012-02-15 18:56:56 -0800177 * Returns 0 on success otherwise negative errno. In the error case, dwc
Felipe Balbi72246da2011-08-19 18:10:58 +0300178 * may contain some buffers allocated but not all which were requested.
179 */
Bill Pemberton41ac7b32012-11-19 13:21:48 -0500180static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
Felipe Balbi72246da2011-08-19 18:10:58 +0300181{
Felipe Balbi9f622b22011-10-12 10:31:04 +0300182 int num;
Felipe Balbi72246da2011-08-19 18:10:58 +0300183 int i;
184
Felipe Balbi9f622b22011-10-12 10:31:04 +0300185 num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
186 dwc->num_event_buffers = num;
187
Felipe Balbi380f0d22012-10-11 13:48:36 +0300188 dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
189 GFP_KERNEL);
Jingoo Han734d5a52014-07-17 12:45:11 +0900190 if (!dwc->ev_buffs)
Felipe Balbi457d3f22011-10-24 12:03:13 +0300191 return -ENOMEM;
Felipe Balbi457d3f22011-10-24 12:03:13 +0300192
Felipe Balbi72246da2011-08-19 18:10:58 +0300193 for (i = 0; i < num; i++) {
194 struct dwc3_event_buffer *evt;
195
196 evt = dwc3_alloc_one_event_buffer(dwc, length);
197 if (IS_ERR(evt)) {
198 dev_err(dwc->dev, "can't allocate event buffer\n");
199 return PTR_ERR(evt);
200 }
201 dwc->ev_buffs[i] = evt;
202 }
203
204 return 0;
205}
206
207/**
208 * dwc3_event_buffers_setup - setup our allocated event buffers
Paul Zimmerman1d046792012-02-15 18:56:56 -0800209 * @dwc: pointer to our controller context structure
Felipe Balbi72246da2011-08-19 18:10:58 +0300210 *
211 * Returns 0 on success otherwise negative errno.
212 */
Paul Zimmerman7acd85e2012-04-27 14:28:02 +0300213static int dwc3_event_buffers_setup(struct dwc3 *dwc)
Felipe Balbi72246da2011-08-19 18:10:58 +0300214{
215 struct dwc3_event_buffer *evt;
216 int n;
217
Felipe Balbi9f622b22011-10-12 10:31:04 +0300218 for (n = 0; n < dwc->num_event_buffers; n++) {
Felipe Balbi72246da2011-08-19 18:10:58 +0300219 evt = dwc->ev_buffs[n];
220 dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
221 evt->buf, (unsigned long long) evt->dma,
222 evt->length);
223
Paul Zimmerman7acd85e2012-04-27 14:28:02 +0300224 evt->lpos = 0;
225
Felipe Balbi72246da2011-08-19 18:10:58 +0300226 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
227 lower_32_bits(evt->dma));
228 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
229 upper_32_bits(evt->dma));
230 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
Felipe Balbi68d6a012013-06-12 21:09:26 +0300231 DWC3_GEVNTSIZ_SIZE(evt->length));
Felipe Balbi72246da2011-08-19 18:10:58 +0300232 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
233 }
234
235 return 0;
236}
237
238static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
239{
240 struct dwc3_event_buffer *evt;
241 int n;
242
Felipe Balbi9f622b22011-10-12 10:31:04 +0300243 for (n = 0; n < dwc->num_event_buffers; n++) {
Felipe Balbi72246da2011-08-19 18:10:58 +0300244 evt = dwc->ev_buffs[n];
Paul Zimmerman7acd85e2012-04-27 14:28:02 +0300245
246 evt->lpos = 0;
247
Felipe Balbi72246da2011-08-19 18:10:58 +0300248 dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
249 dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
Felipe Balbi68d6a012013-06-12 21:09:26 +0300250 dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK
251 | DWC3_GEVNTSIZ_SIZE(0));
Felipe Balbi72246da2011-08-19 18:10:58 +0300252 dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
253 }
254}
255
Felipe Balbi0ffcaf32013-12-19 13:04:28 -0600256static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
257{
258 if (!dwc->has_hibernation)
259 return 0;
260
261 if (!dwc->nr_scratch)
262 return 0;
263
264 dwc->scratchbuf = kmalloc_array(dwc->nr_scratch,
265 DWC3_SCRATCHBUF_SIZE, GFP_KERNEL);
266 if (!dwc->scratchbuf)
267 return -ENOMEM;
268
269 return 0;
270}
271
272static int dwc3_setup_scratch_buffers(struct dwc3 *dwc)
273{
274 dma_addr_t scratch_addr;
275 u32 param;
276 int ret;
277
278 if (!dwc->has_hibernation)
279 return 0;
280
281 if (!dwc->nr_scratch)
282 return 0;
283
284 /* should never fall here */
285 if (!WARN_ON(dwc->scratchbuf))
286 return 0;
287
288 scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf,
289 dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE,
290 DMA_BIDIRECTIONAL);
291 if (dma_mapping_error(dwc->dev, scratch_addr)) {
292 dev_err(dwc->dev, "failed to map scratch buffer\n");
293 ret = -EFAULT;
294 goto err0;
295 }
296
297 dwc->scratch_addr = scratch_addr;
298
299 param = lower_32_bits(scratch_addr);
300
301 ret = dwc3_send_gadget_generic_command(dwc,
302 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param);
303 if (ret < 0)
304 goto err1;
305
306 param = upper_32_bits(scratch_addr);
307
308 ret = dwc3_send_gadget_generic_command(dwc,
309 DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param);
310 if (ret < 0)
311 goto err1;
312
313 return 0;
314
315err1:
316 dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
317 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
318
319err0:
320 return ret;
321}
322
323static void dwc3_free_scratch_buffers(struct dwc3 *dwc)
324{
325 if (!dwc->has_hibernation)
326 return;
327
328 if (!dwc->nr_scratch)
329 return;
330
331 /* should never fall here */
332 if (!WARN_ON(dwc->scratchbuf))
333 return;
334
335 dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch *
336 DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL);
337 kfree(dwc->scratchbuf);
338}
339
Felipe Balbi789451f62011-05-05 15:53:10 +0300340static void dwc3_core_num_eps(struct dwc3 *dwc)
341{
342 struct dwc3_hwparams *parms = &dwc->hwparams;
343
344 dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
345 dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
346
347 dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
348 dwc->num_in_eps, dwc->num_out_eps);
349}
350
Bill Pemberton41ac7b32012-11-19 13:21:48 -0500351static void dwc3_cache_hwparams(struct dwc3 *dwc)
Felipe Balbi26ceca92011-09-30 10:58:49 +0300352{
353 struct dwc3_hwparams *parms = &dwc->hwparams;
354
355 parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
356 parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
357 parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
358 parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
359 parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
360 parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
361 parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
362 parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
363 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
364}
365
Felipe Balbi72246da2011-08-19 18:10:58 +0300366/**
367 * dwc3_core_init - Low-level initialization of DWC3 Core
368 * @dwc: Pointer to our controller context structure
369 *
370 * Returns 0 on success otherwise negative errno.
371 */
Bill Pemberton41ac7b32012-11-19 13:21:48 -0500372static int dwc3_core_init(struct dwc3 *dwc)
Felipe Balbi72246da2011-08-19 18:10:58 +0300373{
374 unsigned long timeout;
Felipe Balbi0ffcaf32013-12-19 13:04:28 -0600375 u32 hwparams4 = dwc->hwparams.hwparams4;
Felipe Balbi72246da2011-08-19 18:10:58 +0300376 u32 reg;
377 int ret;
378
Sebastian Andrzej Siewior7650bd72011-08-29 13:56:36 +0200379 reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
380 /* This should read as U3 followed by revision number */
381 if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
382 dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
383 ret = -ENODEV;
384 goto err0;
385 }
Felipe Balbi248b1222011-12-14 21:59:30 +0200386 dwc->revision = reg;
Sebastian Andrzej Siewior7650bd72011-08-29 13:56:36 +0200387
Felipe Balbifa0ea132014-09-19 15:51:11 -0500388 /*
389 * Write Linux Version Code to our GUID register so it's easy to figure
390 * out which kernel version a bug was found.
391 */
392 dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE);
393
Paul Zimmerman0e1e5c42014-05-23 11:39:24 -0700394 /* Handle USB2.0-only core configuration */
395 if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
396 DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
397 if (dwc->maximum_speed == USB_SPEED_SUPER)
398 dwc->maximum_speed = USB_SPEED_HIGH;
399 }
400
Felipe Balbi72246da2011-08-19 18:10:58 +0300401 /* issue device SoftReset too */
402 timeout = jiffies + msecs_to_jiffies(500);
403 dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
404 do {
405 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
406 if (!(reg & DWC3_DCTL_CSFTRST))
407 break;
408
409 if (time_after(jiffies, timeout)) {
410 dev_err(dwc->dev, "Reset Timed Out\n");
411 ret = -ETIMEDOUT;
412 goto err0;
413 }
414
415 cpu_relax();
416 } while (true);
417
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530418 ret = dwc3_core_soft_reset(dwc);
419 if (ret)
420 goto err0;
Pratyush Anand58a0f232012-06-21 17:44:29 +0530421
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100422 reg = dwc3_readl(dwc->regs, DWC3_GCTL);
Paul Zimmerman3e87c422012-02-24 17:32:13 -0800423 reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100424 reg &= ~DWC3_GCTL_DISSCRAMBLE;
425
Sebastian Andrzej Siewior164d7732011-11-24 11:22:05 +0100426 switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100427 case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
Felipe Balbi32a4a132014-02-25 14:00:13 -0600428 /**
429 * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
430 * issue which would cause xHCI compliance tests to fail.
431 *
432 * Because of that we cannot enable clock gating on such
433 * configurations.
434 *
435 * Refers to:
436 *
437 * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
438 * SOF/ITP Mode Used
439 */
440 if ((dwc->dr_mode == USB_DR_MODE_HOST ||
441 dwc->dr_mode == USB_DR_MODE_OTG) &&
442 (dwc->revision >= DWC3_REVISION_210A &&
443 dwc->revision <= DWC3_REVISION_250A))
444 reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
445 else
446 reg &= ~DWC3_GCTL_DSBLCLKGTNG;
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100447 break;
Felipe Balbi0ffcaf32013-12-19 13:04:28 -0600448 case DWC3_GHWPARAMS1_EN_PWROPT_HIB:
449 /* enable hibernation here */
450 dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4);
451 break;
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100452 default:
453 dev_dbg(dwc->dev, "No power optimization available\n");
454 }
455
456 /*
457 * WORKAROUND: DWC3 revisions <1.90a have a bug
Paul Zimmerman1d046792012-02-15 18:56:56 -0800458 * where the device can fail to connect at SuperSpeed
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100459 * and falls back to high-speed mode which causes
Paul Zimmerman1d046792012-02-15 18:56:56 -0800460 * the device to enter a Connect/Disconnect loop
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100461 */
462 if (dwc->revision < DWC3_REVISION_190A)
463 reg |= DWC3_GCTL_U2RSTECN;
464
Felipe Balbi789451f62011-05-05 15:53:10 +0300465 dwc3_core_num_eps(dwc);
466
Sebastian Andrzej Siewior4878a022011-10-31 22:25:41 +0100467 dwc3_writel(dwc->regs, DWC3_GCTL, reg);
468
Felipe Balbi0ffcaf32013-12-19 13:04:28 -0600469 ret = dwc3_alloc_scratch_buffers(dwc);
470 if (ret)
471 goto err1;
472
473 ret = dwc3_setup_scratch_buffers(dwc);
474 if (ret)
475 goto err2;
476
Felipe Balbi72246da2011-08-19 18:10:58 +0300477 return 0;
478
Felipe Balbi0ffcaf32013-12-19 13:04:28 -0600479err2:
480 dwc3_free_scratch_buffers(dwc);
481
482err1:
483 usb_phy_shutdown(dwc->usb2_phy);
484 usb_phy_shutdown(dwc->usb3_phy);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530485 phy_exit(dwc->usb2_generic_phy);
486 phy_exit(dwc->usb3_generic_phy);
Felipe Balbi0ffcaf32013-12-19 13:04:28 -0600487
Felipe Balbi72246da2011-08-19 18:10:58 +0300488err0:
489 return ret;
490}
491
492static void dwc3_core_exit(struct dwc3 *dwc)
493{
Felipe Balbi0ffcaf32013-12-19 13:04:28 -0600494 dwc3_free_scratch_buffers(dwc);
Vivek Gautam01b8daf2012-10-13 19:20:18 +0530495 usb_phy_shutdown(dwc->usb2_phy);
496 usb_phy_shutdown(dwc->usb3_phy);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530497 phy_exit(dwc->usb2_generic_phy);
498 phy_exit(dwc->usb3_generic_phy);
Felipe Balbi72246da2011-08-19 18:10:58 +0300499}
500
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500501static int dwc3_core_get_phy(struct dwc3 *dwc)
Felipe Balbi72246da2011-08-19 18:10:58 +0300502{
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500503 struct device *dev = dwc->dev;
Felipe Balbi941ea362013-07-31 09:21:25 +0300504 struct device_node *node = dev->of_node;
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500505 int ret;
Felipe Balbi72246da2011-08-19 18:10:58 +0300506
Kishon Vijay Abraham I5088b6f2013-01-25 16:36:53 +0530507 if (node) {
508 dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
509 dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
Felipe Balbibb674902013-08-14 13:21:23 -0500510 } else {
511 dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
512 dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
Kishon Vijay Abraham I5088b6f2013-01-25 16:36:53 +0530513 }
514
Felipe Balbid105e7f2013-03-15 10:52:08 +0200515 if (IS_ERR(dwc->usb2_phy)) {
516 ret = PTR_ERR(dwc->usb2_phy);
Kishon Vijay Abraham I122f06e2014-03-03 17:08:10 +0530517 if (ret == -ENXIO || ret == -ENODEV) {
518 dwc->usb2_phy = NULL;
519 } else if (ret == -EPROBE_DEFER) {
Felipe Balbid105e7f2013-03-15 10:52:08 +0200520 return ret;
Kishon Vijay Abraham I122f06e2014-03-03 17:08:10 +0530521 } else {
522 dev_err(dev, "no usb2 phy configured\n");
523 return ret;
524 }
Felipe Balbi51e1e7b2012-07-19 14:09:48 +0300525 }
526
Felipe Balbid105e7f2013-03-15 10:52:08 +0200527 if (IS_ERR(dwc->usb3_phy)) {
Ruchika Kharwar315955d72013-07-04 00:59:34 -0500528 ret = PTR_ERR(dwc->usb3_phy);
Kishon Vijay Abraham I122f06e2014-03-03 17:08:10 +0530529 if (ret == -ENXIO || ret == -ENODEV) {
530 dwc->usb3_phy = NULL;
531 } else if (ret == -EPROBE_DEFER) {
Felipe Balbid105e7f2013-03-15 10:52:08 +0200532 return ret;
Kishon Vijay Abraham I122f06e2014-03-03 17:08:10 +0530533 } else {
534 dev_err(dev, "no usb3 phy configured\n");
535 return ret;
536 }
Felipe Balbi51e1e7b2012-07-19 14:09:48 +0300537 }
538
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530539 dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
540 if (IS_ERR(dwc->usb2_generic_phy)) {
541 ret = PTR_ERR(dwc->usb2_generic_phy);
542 if (ret == -ENOSYS || ret == -ENODEV) {
543 dwc->usb2_generic_phy = NULL;
544 } else if (ret == -EPROBE_DEFER) {
545 return ret;
546 } else {
547 dev_err(dev, "no usb2 phy configured\n");
548 return ret;
549 }
550 }
551
552 dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
553 if (IS_ERR(dwc->usb3_generic_phy)) {
554 ret = PTR_ERR(dwc->usb3_generic_phy);
555 if (ret == -ENOSYS || ret == -ENODEV) {
556 dwc->usb3_generic_phy = NULL;
557 } else if (ret == -EPROBE_DEFER) {
558 return ret;
559 } else {
560 dev_err(dev, "no usb3 phy configured\n");
561 return ret;
562 }
563 }
564
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500565 return 0;
566}
567
Felipe Balbi5f94adf2014-04-16 15:13:45 -0500568static int dwc3_core_init_mode(struct dwc3 *dwc)
569{
570 struct device *dev = dwc->dev;
571 int ret;
572
573 switch (dwc->dr_mode) {
574 case USB_DR_MODE_PERIPHERAL:
575 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
576 ret = dwc3_gadget_init(dwc);
577 if (ret) {
578 dev_err(dev, "failed to initialize gadget\n");
579 return ret;
580 }
581 break;
582 case USB_DR_MODE_HOST:
583 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
584 ret = dwc3_host_init(dwc);
585 if (ret) {
586 dev_err(dev, "failed to initialize host\n");
587 return ret;
588 }
589 break;
590 case USB_DR_MODE_OTG:
591 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
592 ret = dwc3_host_init(dwc);
593 if (ret) {
594 dev_err(dev, "failed to initialize host\n");
595 return ret;
596 }
597
598 ret = dwc3_gadget_init(dwc);
599 if (ret) {
600 dev_err(dev, "failed to initialize gadget\n");
601 return ret;
602 }
603 break;
604 default:
605 dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
606 return -EINVAL;
607 }
608
609 return 0;
610}
611
612static void dwc3_core_exit_mode(struct dwc3 *dwc)
613{
614 switch (dwc->dr_mode) {
615 case USB_DR_MODE_PERIPHERAL:
616 dwc3_gadget_exit(dwc);
617 break;
618 case USB_DR_MODE_HOST:
619 dwc3_host_exit(dwc);
620 break;
621 case USB_DR_MODE_OTG:
622 dwc3_host_exit(dwc);
623 dwc3_gadget_exit(dwc);
624 break;
625 default:
626 /* do nothing */
627 break;
628 }
629}
630
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500631#define DWC3_ALIGN_MASK (16 - 1)
632
633static int dwc3_probe(struct platform_device *pdev)
634{
635 struct device *dev = &pdev->dev;
636 struct dwc3_platform_data *pdata = dev_get_platdata(dev);
637 struct device_node *node = dev->of_node;
638 struct resource *res;
639 struct dwc3 *dwc;
640
Andy Shevchenkob09e99e2014-05-15 15:53:32 +0300641 int ret;
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500642
643 void __iomem *regs;
644 void *mem;
645
646 mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
Jingoo Han734d5a52014-07-17 12:45:11 +0900647 if (!mem)
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500648 return -ENOMEM;
Jingoo Han734d5a52014-07-17 12:45:11 +0900649
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500650 dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
651 dwc->mem = mem;
652 dwc->dev = dev;
653
654 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
655 if (!res) {
656 dev_err(dev, "missing IRQ\n");
657 return -ENODEV;
658 }
659 dwc->xhci_resources[1].start = res->start;
660 dwc->xhci_resources[1].end = res->end;
661 dwc->xhci_resources[1].flags = res->flags;
662 dwc->xhci_resources[1].name = res->name;
663
664 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
665 if (!res) {
666 dev_err(dev, "missing memory resource\n");
667 return -ENODEV;
668 }
669
Vivek Gautamf32a5e22014-06-04 14:34:52 +0530670 dwc->xhci_resources[0].start = res->start;
671 dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
672 DWC3_XHCI_REGS_END;
673 dwc->xhci_resources[0].flags = res->flags;
674 dwc->xhci_resources[0].name = res->name;
675
676 res->start += DWC3_GLOBALS_REGS_START;
677
678 /*
679 * Request memory region but exclude xHCI regs,
680 * since it will be requested by the xhci-plat driver.
681 */
682 regs = devm_ioremap_resource(dev, res);
683 if (IS_ERR(regs))
684 return PTR_ERR(regs);
685
686 dwc->regs = regs;
687 dwc->regs_size = resource_size(res);
688 /*
689 * restore res->start back to its original value so that,
690 * in case the probe is deferred, we don't end up getting error in
691 * request the memory region the next time probe is called.
692 */
693 res->start -= DWC3_GLOBALS_REGS_START;
694
Felipe Balbi3c9f94a2014-04-16 15:08:29 -0500695 if (node) {
696 dwc->maximum_speed = of_usb_get_maximum_speed(node);
697
698 dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
699 dwc->dr_mode = of_usb_get_dr_mode(node);
700 } else if (pdata) {
701 dwc->maximum_speed = pdata->maximum_speed;
702
703 dwc->needs_fifo_resize = pdata->tx_fifo_resize;
704 dwc->dr_mode = pdata->dr_mode;
705 }
706
707 /* default to superspeed if no maximum_speed passed */
708 if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
709 dwc->maximum_speed = USB_SPEED_SUPER;
710
711 ret = dwc3_core_get_phy(dwc);
712 if (ret)
713 return ret;
714
Felipe Balbi72246da2011-08-19 18:10:58 +0300715 spin_lock_init(&dwc->lock);
716 platform_set_drvdata(pdev, dwc);
717
Kishon Vijay Abraham Iddff14f2013-03-07 18:51:43 +0530718 dev->dma_mask = dev->parent->dma_mask;
719 dev->dma_parms = dev->parent->dma_parms;
720 dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
721
Chanho Park802ca852012-02-15 18:27:55 +0900722 pm_runtime_enable(dev);
723 pm_runtime_get_sync(dev);
724 pm_runtime_forbid(dev);
Felipe Balbi72246da2011-08-19 18:10:58 +0300725
Kishon Vijay Abraham I4fd24482012-11-16 12:07:54 +0530726 dwc3_cache_hwparams(dwc);
727
Felipe Balbi39214262012-10-11 13:54:36 +0300728 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
729 if (ret) {
730 dev_err(dwc->dev, "failed to allocate event buffers\n");
731 ret = -ENOMEM;
732 goto err0;
733 }
734
Felipe Balbi32a4a132014-02-25 14:00:13 -0600735 if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
736 dwc->dr_mode = USB_DR_MODE_HOST;
737 else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
738 dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
739
740 if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
741 dwc->dr_mode = USB_DR_MODE_OTG;
742
Felipe Balbi72246da2011-08-19 18:10:58 +0300743 ret = dwc3_core_init(dwc);
744 if (ret) {
Chanho Park802ca852012-02-15 18:27:55 +0900745 dev_err(dev, "failed to initialize core\n");
Felipe Balbi39214262012-10-11 13:54:36 +0300746 goto err0;
Felipe Balbi72246da2011-08-19 18:10:58 +0300747 }
748
Kishon Vijay Abraham I3088f102013-11-25 15:31:21 +0530749 usb_phy_set_suspend(dwc->usb2_phy, 0);
750 usb_phy_set_suspend(dwc->usb3_phy, 0);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530751 ret = phy_power_on(dwc->usb2_generic_phy);
752 if (ret < 0)
753 goto err1;
754
755 ret = phy_power_on(dwc->usb3_generic_phy);
756 if (ret < 0)
757 goto err_usb2phy_power;
Kishon Vijay Abraham I3088f102013-11-25 15:31:21 +0530758
Felipe Balbif122d332013-02-08 15:15:11 +0200759 ret = dwc3_event_buffers_setup(dwc);
760 if (ret) {
761 dev_err(dwc->dev, "failed to setup event buffers\n");
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530762 goto err_usb3phy_power;
Felipe Balbif122d332013-02-08 15:15:11 +0200763 }
764
Felipe Balbi5f94adf2014-04-16 15:13:45 -0500765 ret = dwc3_core_init_mode(dwc);
766 if (ret)
Felipe Balbif122d332013-02-08 15:15:11 +0200767 goto err2;
Felipe Balbi72246da2011-08-19 18:10:58 +0300768
769 ret = dwc3_debugfs_init(dwc);
770 if (ret) {
Chanho Park802ca852012-02-15 18:27:55 +0900771 dev_err(dev, "failed to initialize debugfs\n");
Felipe Balbif122d332013-02-08 15:15:11 +0200772 goto err3;
Felipe Balbi72246da2011-08-19 18:10:58 +0300773 }
774
Chanho Park802ca852012-02-15 18:27:55 +0900775 pm_runtime_allow(dev);
Felipe Balbi72246da2011-08-19 18:10:58 +0300776
777 return 0;
778
Felipe Balbif122d332013-02-08 15:15:11 +0200779err3:
Felipe Balbi5f94adf2014-04-16 15:13:45 -0500780 dwc3_core_exit_mode(dwc);
Felipe Balbi72246da2011-08-19 18:10:58 +0300781
Felipe Balbif122d332013-02-08 15:15:11 +0200782err2:
783 dwc3_event_buffers_cleanup(dwc);
784
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530785err_usb3phy_power:
786 phy_power_off(dwc->usb3_generic_phy);
787
788err_usb2phy_power:
789 phy_power_off(dwc->usb2_generic_phy);
790
Chanho Park802ca852012-02-15 18:27:55 +0900791err1:
Kishon Vijay Abraham I501fae52013-11-25 15:31:22 +0530792 usb_phy_set_suspend(dwc->usb2_phy, 1);
793 usb_phy_set_suspend(dwc->usb3_phy, 1);
Felipe Balbi72246da2011-08-19 18:10:58 +0300794 dwc3_core_exit(dwc);
795
Felipe Balbi39214262012-10-11 13:54:36 +0300796err0:
797 dwc3_free_event_buffers(dwc);
798
Felipe Balbi72246da2011-08-19 18:10:58 +0300799 return ret;
800}
801
Bill Pembertonfb4e98a2012-11-19 13:26:20 -0500802static int dwc3_remove(struct platform_device *pdev)
Felipe Balbi72246da2011-08-19 18:10:58 +0300803{
Felipe Balbi72246da2011-08-19 18:10:58 +0300804 struct dwc3 *dwc = platform_get_drvdata(pdev);
Felipe Balbi72246da2011-08-19 18:10:58 +0300805
Felipe Balbidc99f162014-09-03 16:13:37 -0500806 dwc3_debugfs_exit(dwc);
807 dwc3_core_exit_mode(dwc);
808 dwc3_event_buffers_cleanup(dwc);
809 dwc3_free_event_buffers(dwc);
810
Kishon Vijay Abraham I8ba007a2013-01-25 08:30:54 +0530811 usb_phy_set_suspend(dwc->usb2_phy, 1);
812 usb_phy_set_suspend(dwc->usb3_phy, 1);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530813 phy_power_off(dwc->usb2_generic_phy);
814 phy_power_off(dwc->usb3_generic_phy);
Kishon Vijay Abraham I8ba007a2013-01-25 08:30:54 +0530815
Felipe Balbi72246da2011-08-19 18:10:58 +0300816 dwc3_core_exit(dwc);
Felipe Balbi72246da2011-08-19 18:10:58 +0300817
Felipe Balbi7415f172012-04-30 14:56:33 +0300818 pm_runtime_put_sync(&pdev->dev);
819 pm_runtime_disable(&pdev->dev);
820
Felipe Balbi72246da2011-08-19 18:10:58 +0300821 return 0;
822}
823
Felipe Balbi7415f172012-04-30 14:56:33 +0300824#ifdef CONFIG_PM_SLEEP
825static int dwc3_prepare(struct device *dev)
826{
827 struct dwc3 *dwc = dev_get_drvdata(dev);
828 unsigned long flags;
829
830 spin_lock_irqsave(&dwc->lock, flags);
831
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500832 switch (dwc->dr_mode) {
833 case USB_DR_MODE_PERIPHERAL:
834 case USB_DR_MODE_OTG:
Felipe Balbi7415f172012-04-30 14:56:33 +0300835 dwc3_gadget_prepare(dwc);
836 /* FALLTHROUGH */
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500837 case USB_DR_MODE_HOST:
Felipe Balbi7415f172012-04-30 14:56:33 +0300838 default:
839 dwc3_event_buffers_cleanup(dwc);
840 break;
841 }
842
843 spin_unlock_irqrestore(&dwc->lock, flags);
844
845 return 0;
846}
847
848static void dwc3_complete(struct device *dev)
849{
850 struct dwc3 *dwc = dev_get_drvdata(dev);
851 unsigned long flags;
852
853 spin_lock_irqsave(&dwc->lock, flags);
854
Roger Quadrosf45e5f02014-03-26 11:43:09 +0200855 dwc3_event_buffers_setup(dwc);
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500856 switch (dwc->dr_mode) {
857 case USB_DR_MODE_PERIPHERAL:
858 case USB_DR_MODE_OTG:
Felipe Balbi7415f172012-04-30 14:56:33 +0300859 dwc3_gadget_complete(dwc);
860 /* FALLTHROUGH */
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500861 case USB_DR_MODE_HOST:
Felipe Balbi7415f172012-04-30 14:56:33 +0300862 default:
Felipe Balbi7415f172012-04-30 14:56:33 +0300863 break;
864 }
865
866 spin_unlock_irqrestore(&dwc->lock, flags);
867}
868
869static int dwc3_suspend(struct device *dev)
870{
871 struct dwc3 *dwc = dev_get_drvdata(dev);
872 unsigned long flags;
873
874 spin_lock_irqsave(&dwc->lock, flags);
875
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500876 switch (dwc->dr_mode) {
877 case USB_DR_MODE_PERIPHERAL:
878 case USB_DR_MODE_OTG:
Felipe Balbi7415f172012-04-30 14:56:33 +0300879 dwc3_gadget_suspend(dwc);
880 /* FALLTHROUGH */
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500881 case USB_DR_MODE_HOST:
Felipe Balbi7415f172012-04-30 14:56:33 +0300882 default:
883 /* do nothing */
884 break;
885 }
886
887 dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
888 spin_unlock_irqrestore(&dwc->lock, flags);
889
890 usb_phy_shutdown(dwc->usb3_phy);
891 usb_phy_shutdown(dwc->usb2_phy);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530892 phy_exit(dwc->usb2_generic_phy);
893 phy_exit(dwc->usb3_generic_phy);
Felipe Balbi7415f172012-04-30 14:56:33 +0300894
895 return 0;
896}
897
898static int dwc3_resume(struct device *dev)
899{
900 struct dwc3 *dwc = dev_get_drvdata(dev);
901 unsigned long flags;
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530902 int ret;
Felipe Balbi7415f172012-04-30 14:56:33 +0300903
904 usb_phy_init(dwc->usb3_phy);
905 usb_phy_init(dwc->usb2_phy);
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530906 ret = phy_init(dwc->usb2_generic_phy);
907 if (ret < 0)
908 return ret;
909
910 ret = phy_init(dwc->usb3_generic_phy);
911 if (ret < 0)
912 goto err_usb2phy_init;
Felipe Balbi7415f172012-04-30 14:56:33 +0300913
914 spin_lock_irqsave(&dwc->lock, flags);
915
916 dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
917
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500918 switch (dwc->dr_mode) {
919 case USB_DR_MODE_PERIPHERAL:
920 case USB_DR_MODE_OTG:
Felipe Balbi7415f172012-04-30 14:56:33 +0300921 dwc3_gadget_resume(dwc);
922 /* FALLTHROUGH */
Ruchika Kharwara45c82b82013-07-06 07:52:49 -0500923 case USB_DR_MODE_HOST:
Felipe Balbi7415f172012-04-30 14:56:33 +0300924 default:
925 /* do nothing */
926 break;
927 }
928
929 spin_unlock_irqrestore(&dwc->lock, flags);
930
931 pm_runtime_disable(dev);
932 pm_runtime_set_active(dev);
933 pm_runtime_enable(dev);
934
935 return 0;
Kishon Vijay Abraham I57303482014-03-03 17:08:11 +0530936
937err_usb2phy_init:
938 phy_exit(dwc->usb2_generic_phy);
939
940 return ret;
Felipe Balbi7415f172012-04-30 14:56:33 +0300941}
942
943static const struct dev_pm_ops dwc3_dev_pm_ops = {
944 .prepare = dwc3_prepare,
945 .complete = dwc3_complete,
946
947 SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
948};
949
950#define DWC3_PM_OPS &(dwc3_dev_pm_ops)
951#else
952#define DWC3_PM_OPS NULL
953#endif
954
Kishon Vijay Abraham I5088b6f2013-01-25 16:36:53 +0530955#ifdef CONFIG_OF
956static const struct of_device_id of_dwc3_match[] = {
957 {
Felipe Balbi22a5aa12013-07-02 21:20:24 +0300958 .compatible = "snps,dwc3"
959 },
960 {
Kishon Vijay Abraham I5088b6f2013-01-25 16:36:53 +0530961 .compatible = "synopsys,dwc3"
962 },
963 { },
964};
965MODULE_DEVICE_TABLE(of, of_dwc3_match);
966#endif
967
Felipe Balbi72246da2011-08-19 18:10:58 +0300968static struct platform_driver dwc3_driver = {
969 .probe = dwc3_probe,
Bill Pemberton76904172012-11-19 13:21:08 -0500970 .remove = dwc3_remove,
Felipe Balbi72246da2011-08-19 18:10:58 +0300971 .driver = {
972 .name = "dwc3",
Kishon Vijay Abraham I5088b6f2013-01-25 16:36:53 +0530973 .of_match_table = of_match_ptr(of_dwc3_match),
Felipe Balbi7415f172012-04-30 14:56:33 +0300974 .pm = DWC3_PM_OPS,
Felipe Balbi72246da2011-08-19 18:10:58 +0300975 },
Felipe Balbi72246da2011-08-19 18:10:58 +0300976};
977
Tobias Klauserb1116dc2012-02-28 12:57:20 +0100978module_platform_driver(dwc3_driver);
979
Sebastian Andrzej Siewior7ae4fc42011-10-19 19:39:50 +0200980MODULE_ALIAS("platform:dwc3");
Felipe Balbi72246da2011-08-19 18:10:58 +0300981MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
Felipe Balbi5945f782013-06-30 14:15:11 +0300982MODULE_LICENSE("GPL v2");
Felipe Balbi72246da2011-08-19 18:10:58 +0300983MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");