blob: 5a79caeb4977e425e73ffd84116972fdbebb2af3 [file] [log] [blame]
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <linux/platform_device.h>
18#include <linux/dma-mapping.h>
19#include <linux/ioport.h>
20#include <linux/io.h>
21#include <linux/module.h>
22#include <linux/types.h>
Ido Shayevitzef72ddd2012-03-28 18:55:55 +020023#include <linux/delay.h>
24#include <linux/of.h>
Ido Shayevitz9fb83452012-04-01 17:45:58 +030025#include <linux/list.h>
26#include <linux/usb/ch9.h>
27#include <linux/usb/gadget.h>
28#include <linux/usb/msm_hsusb.h>
Manu Gautam60e01352012-05-29 09:00:34 +053029#include <linux/regulator/consumer.h>
30
31#include <mach/rpm-regulator.h>
Ido Shayevitz9fb83452012-04-01 17:45:58 +030032
33#include "core.h"
34#include "gadget.h"
35
36/**
37 * USB DBM Hardware registers.
38 *
39 */
40#define DBM_EP_CFG(n) (0x00 + 4 * (n))
41#define DBM_DATA_FIFO(n) (0x10 + 4 * (n))
42#define DBM_DATA_FIFO_SIZE(n) (0x20 + 4 * (n))
43#define DBM_DATA_FIFO_EN (0x30)
44#define DBM_GEVNTADR (0x34)
45#define DBM_GEVNTSIZ (0x38)
46#define DBM_DBG_CNFG (0x3C)
47#define DBM_HW_TRB0_EP(n) (0x40 + 4 * (n))
48#define DBM_HW_TRB1_EP(n) (0x50 + 4 * (n))
49#define DBM_HW_TRB2_EP(n) (0x60 + 4 * (n))
50#define DBM_HW_TRB3_EP(n) (0x70 + 4 * (n))
51#define DBM_PIPE_CFG (0x80)
52#define DBM_SOFT_RESET (0x84)
53
54/**
55 * USB DBM Hardware registers bitmask.
56 *
57 */
58/* DBM_EP_CFG */
59#define DBM_EN_EP 0x00000000
60#define DBM_USB3_EP_NUM 0x0000003E
61#define DBM_BAM_PIPE_NUM 0x000000C0
62#define DBM_PRODUCER 0x00000100
63#define DBM_DISABLE_WB 0x00000200
64#define DBM_INT_RAM_ACC 0x00000400
65
66/* DBM_DATA_FIFO_SIZE */
67#define DBM_DATA_FIFO_SIZE_MASK 0x0000ffff
68
69/* DBM_GEVNTSIZ */
70#define DBM_GEVNTSIZ_MASK 0x0000ffff
71
72/* DBM_DBG_CNFG */
73#define DBM_ENABLE_IOC_MASK 0x0000000f
74
75/* DBM_SOFT_RESET */
76#define DBM_SFT_RST_EP0 0x00000001
77#define DBM_SFT_RST_EP1 0x00000002
78#define DBM_SFT_RST_EP2 0x00000004
79#define DBM_SFT_RST_EP3 0x00000008
80#define DBM_SFT_RST_EPS 0x0000000F
81#define DBM_SFT_RST 0x80000000
Ido Shayevitzef72ddd2012-03-28 18:55:55 +020082
83#define DBM_MAX_EPS 4
84
Ido Shayevitzfa65a582012-06-06 14:39:54 +030085/* DBM TRB configurations */
86#define DBM_TRB_BIT 0x80000000
87#define DBM_TRB_DATA_SRC 0x40000000
88#define DBM_TRB_DMA 0x20000000
89#define DBM_TRB_EP_NUM(ep) (ep<<24)
90
Ido Shayevitz9fb83452012-04-01 17:45:58 +030091struct dwc3_msm_req_complete {
92 struct list_head list_item;
93 struct usb_request *req;
94 void (*orig_complete)(struct usb_ep *ep,
95 struct usb_request *req);
96};
97
Ido Shayevitzef72ddd2012-03-28 18:55:55 +020098struct dwc3_msm {
99 struct platform_device *dwc3;
100 struct device *dev;
101 void __iomem *base;
102 u32 resource_size;
103 int dbm_num_eps;
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300104 u8 ep_num_mapping[DBM_MAX_EPS];
105 const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
106 struct list_head req_complete_list;
Manu Gautam60e01352012-05-29 09:00:34 +0530107 struct regulator *hsusb_3p3;
108 struct regulator *hsusb_1p8;
109 struct regulator *hsusb_vddcx;
110 struct regulator *ssusb_1p8;
111 struct regulator *ssusb_vddcx;
112 enum usb_vdd_type ss_vdd_type;
113 enum usb_vdd_type hs_vdd_type;
114};
115
116#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
117#define USB_HSPHY_3P3_VOL_MAX 3300000 /* uV */
118#define USB_HSPHY_3P3_HPM_LOAD 16000 /* uA */
119
120#define USB_HSPHY_1P8_VOL_MIN 1800000 /* uV */
121#define USB_HSPHY_1P8_VOL_MAX 1800000 /* uV */
122#define USB_HSPHY_1P8_HPM_LOAD 19000 /* uA */
123
124#define USB_SSPHY_1P8_VOL_MIN 1800000 /* uV */
125#define USB_SSPHY_1P8_VOL_MAX 1800000 /* uV */
126#define USB_SSPHY_1P8_HPM_LOAD 23000 /* uA */
127
128#define USB_PHY_VDD_DIG_VOL_NONE 0 /* uV */
129#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
130#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
131
132enum usb_vdd_value {
133 VDD_NONE = 0,
134 VDD_MIN,
135 VDD_MAX,
136 VDD_VAL_MAX,
137};
138
139static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
140 { /* VDD_CX CORNER Voting */
141 [VDD_NONE] = RPM_VREG_CORNER_NONE,
142 [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
143 [VDD_MAX] = RPM_VREG_CORNER_HIGH,
144 },
145 { /* VDD_CX Voltage Voting */
146 [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
147 [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
148 [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
149 },
Ido Shayevitzef72ddd2012-03-28 18:55:55 +0200150};
151
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300152static struct dwc3_msm *context;
153
154/**
155 *
156 * Read register with debug info.
157 *
158 * @base - DWC3 base virtual address.
159 * @offset - register offset.
160 *
161 * @return u32
162 */
163static inline u32 dwc3_msm_read_reg(void *base, u32 offset)
164{
165 u32 val = ioread32(base + offset);
166 return val;
167}
168
169/**
170 * Read register masked field with debug info.
171 *
172 * @base - DWC3 base virtual address.
173 * @offset - register offset.
174 * @mask - register bitmask.
175 *
176 * @return u32
177 */
178static inline u32 dwc3_msm_read_reg_field(void *base,
179 u32 offset,
180 const u32 mask)
181{
182 u32 shift = find_first_bit((void *)&mask, 32);
183 u32 val = ioread32(base + offset);
184 val &= mask; /* clear other bits */
185 val >>= shift;
186 return val;
187}
188
189/**
190 *
191 * Write register with debug info.
192 *
193 * @base - DWC3 base virtual address.
194 * @offset - register offset.
195 * @val - value to write.
196 *
197 */
198static inline void dwc3_msm_write_reg(void *base, u32 offset, u32 val)
199{
200 iowrite32(val, base + offset);
201}
202
203/**
204 * Write register masked field with debug info.
205 *
206 * @base - DWC3 base virtual address.
207 * @offset - register offset.
208 * @mask - register bitmask.
209 * @val - value to write.
210 *
211 */
212static inline void dwc3_msm_write_reg_field(void *base, u32 offset,
213 const u32 mask, u32 val)
214{
215 u32 shift = find_first_bit((void *)&mask, 32);
216 u32 tmp = ioread32(base + offset);
217
218 tmp &= ~mask; /* clear written bits */
219 val = tmp | (val << shift);
220 iowrite32(val, base + offset);
221}
222
223/**
224 * Return DBM EP number which is not already configured.
225 *
226 */
227static int dwc3_msm_find_avail_dbm_ep(void)
228{
229 int i;
230
231 for (i = 0; i < context->dbm_num_eps; i++)
232 if (!context->ep_num_mapping[i])
233 return i;
234
235 return -ENODEV; /* Not found */
236}
237
238/**
239 * Return DBM EP number according to usb endpoint number.
240 *
241 */
242static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
243{
244 int i;
245
246 for (i = 0; i < context->dbm_num_eps; i++)
247 if (context->ep_num_mapping[i] == usb_ep)
248 return i;
249
250 return -ENODEV; /* Not found */
251}
252
253/**
254 * Return number of configured DBM endpoints.
255 *
256 */
257static int dwc3_msm_configured_dbm_ep_num(void)
258{
259 int i;
260 int count = 0;
261
262 for (i = 0; i < context->dbm_num_eps; i++)
263 if (context->ep_num_mapping[i])
264 count++;
265
266 return count;
267}
268
269/**
270 * Configure the DBM with the USB3 core event buffer.
271 * This function is called by the SNPS UDC upon initialization.
272 *
273 * @addr - address of the event buffer.
274 * @size - size of the event buffer.
275 *
276 */
277static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
278{
279 dev_dbg(context->dev, "%s\n", __func__);
280
281 dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
282 dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
283 DBM_GEVNTSIZ_MASK, size);
284
285 return 0;
286}
287
288/**
289 * Reset the DBM registers upon initialization.
290 *
291 */
292static int dwc3_msm_dbm_soft_reset(void)
293{
294 dev_dbg(context->dev, "%s\n", __func__);
295
296 dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
297 DBM_SFT_RST, 1);
298
299 return 0;
300}
301
302/**
303 * Soft reset specific DBM ep.
304 * This function is called by the function driver upon events
305 * such as transfer aborting, USB re-enumeration and USB
306 * disconnection.
307 *
308 * @dbm_ep - DBM ep number.
309 * @enter_reset - should we enter a reset state or get out of it.
310 *
311 */
312static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
313{
314 dev_dbg(context->dev, "%s\n", __func__);
315
316 if (dbm_ep >= context->dbm_num_eps) {
317 dev_err(context->dev,
318 "%s: Invalid DBM ep index\n", __func__);
319 return -ENODEV;
320 }
321
322 if (enter_reset) {
323 dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
324 DBM_SFT_RST_EPS, 1 << dbm_ep);
325 } else {
326 dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
327 DBM_SFT_RST_EPS, 0);
328 }
329
330 return 0;
331}
332
333/**
334 * Configure a USB DBM ep to work in BAM mode.
335 *
336 *
337 * @usb_ep - USB physical EP number.
338 * @producer - producer/consumer.
339 * @disable_wb - disable write back to system memory.
340 * @internal_mem - use internal USB memory for data fifo.
341 * @ioc - enable interrupt on completion.
342 *
343 * @return int - DBM ep number.
344 */
345static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
346 bool producer, bool disable_wb,
347 bool internal_mem, bool ioc)
348{
349 u8 dbm_ep;
350 u8 ioc_mask;
351
352 dev_dbg(context->dev, "%s\n", __func__);
353
354 dbm_ep = dwc3_msm_find_avail_dbm_ep();
355 if (dbm_ep < 0) {
356 dev_err(context->dev, "%s: No more DBM eps\n", __func__);
357 return -ENODEV;
358 }
359
360 context->ep_num_mapping[dbm_ep] = usb_ep;
361
362 /* First, reset the dbm endpoint */
363 dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
364
365 ioc_mask = dwc3_msm_read_reg_field(context->base, DBM_DBG_CNFG,
366 DBM_ENABLE_IOC_MASK);
367 ioc_mask &= ~(ioc << dbm_ep); /* Clear ioc bit for dbm_ep */
368 /* Set ioc bit for dbm_ep if needed */
369 dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
370 DBM_ENABLE_IOC_MASK, ioc_mask | (ioc << dbm_ep));
371
372 dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep),
373 producer | disable_wb | internal_mem);
374 dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
375 DBM_USB3_EP_NUM, usb_ep);
376 dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
377 DBM_BAM_PIPE_NUM, bam_pipe);
378 dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
379 DBM_EN_EP, 1);
380
381 return dbm_ep;
382}
383
384/**
385 * Configure a USB DBM ep to work in normal mode.
386 *
387 * @usb_ep - USB ep number.
388 *
389 */
390static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
391{
392 u8 dbm_ep;
393
394 dev_dbg(context->dev, "%s\n", __func__);
395
396 dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
397
398 if (dbm_ep < 0) {
399 dev_err(context->dev,
400 "%s: Invalid usb ep index\n", __func__);
401 return -ENODEV;
402 }
403
404 context->ep_num_mapping[dbm_ep] = 0;
405
406 dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), 0);
407
408 /* Reset the dbm endpoint */
409 dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
410
411 return 0;
412}
413
414/**
415 * Configure the DBM with the BAM's data fifo.
416 * This function is called by the USB BAM Driver
417 * upon initialization.
418 *
419 * @ep - pointer to usb endpoint.
420 * @addr - address of data fifo.
421 * @size - size of data fifo.
422 *
423 */
424int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size)
425{
426 u8 dbm_ep;
427 struct dwc3_ep *dep = to_dwc3_ep(ep);
428
429 dev_dbg(context->dev, "%s\n", __func__);
430
431 dbm_ep = dwc3_msm_find_matching_dbm_ep(dep->number);
432
433 if (dbm_ep >= context->dbm_num_eps) {
434 dev_err(context->dev,
435 "%s: Invalid DBM ep index\n", __func__);
436 return -ENODEV;
437 }
438
439 dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
440 dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
441 DBM_DATA_FIFO_SIZE_MASK, size);
442
443 return 0;
444}
445
446/**
447* Cleanups for msm endpoint on request complete.
448*
449* Also call original request complete.
450*
451* @usb_ep - pointer to usb_ep instance.
452* @request - pointer to usb_request instance.
453*
454* @return int - 0 on success, negetive on error.
455*/
456static void dwc3_msm_req_complete_func(struct usb_ep *ep,
457 struct usb_request *request)
458{
459 struct dwc3_request *req = to_dwc3_request(request);
460 struct dwc3_ep *dep = to_dwc3_ep(ep);
461 struct dwc3_msm_req_complete *req_complete = NULL;
462
463 /* Find original request complete function and remove it from list */
464 list_for_each_entry(req_complete,
465 &context->req_complete_list,
466 list_item) {
467 if (req_complete->req == request)
468 break;
469 }
470 if (!req_complete || req_complete->req != request) {
471 dev_err(dep->dwc->dev, "%s: could not find the request\n",
472 __func__);
473 return;
474 }
475 list_del(&req_complete->list_item);
476
477 /*
478 * Release another one TRB to the pool since DBM queue took 2 TRBs
479 * (normal and link), and the dwc3/gadget.c :: dwc3_gadget_giveback
480 * released only one.
481 */
482 if (req->queued)
483 dep->busy_slot++;
484
485 /* Unconfigure dbm ep */
486 dwc3_msm_dbm_ep_unconfig(dep->number);
487
488 /*
489 * If this is the last endpoint we unconfigured, than reset also
490 * the event buffers.
491 */
492 if (0 == dwc3_msm_configured_dbm_ep_num())
493 dwc3_msm_event_buffer_config(0, 0);
494
495 /*
496 * Call original complete function, notice that dwc->lock is already
497 * taken by the caller of this function (dwc3_gadget_giveback()).
498 */
499 request->complete = req_complete->orig_complete;
500 request->complete(ep, request);
501
502 kfree(req_complete);
503}
504
505/**
506* Helper function.
507* See the header of the dwc3_msm_ep_queue function.
508*
509* @dwc3_ep - pointer to dwc3_ep instance.
510* @req - pointer to dwc3_request instance.
511*
512* @return int - 0 on success, negetive on error.
513*/
514static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
515{
Ido Shayevitzfa65a582012-06-06 14:39:54 +0300516 struct dwc3_trb *trb;
517 struct dwc3_trb *trb_link;
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300518 struct dwc3_gadget_ep_cmd_params params;
519 u32 cmd;
520 int ret = 0;
521
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300522 /* We push the request to the dep->req_queued list to indicate that
523 * this request is issued with start transfer. The request will be out
524 * from this list in 2 cases. The first is that the transfer will be
525 * completed (not if the transfer is endless using a circular TRBs with
526 * with link TRB). The second case is an option to do stop stransfer,
527 * this can be initiated by the function driver when calling dequeue.
528 */
529 req->queued = true;
530 list_add_tail(&req->list, &dep->req_queued);
531
532 /* First, prepare a normal TRB, point to the fake buffer */
Ido Shayevitzfa65a582012-06-06 14:39:54 +0300533 trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300534 dep->free_slot++;
Ido Shayevitzfa65a582012-06-06 14:39:54 +0300535 memset(trb, 0, sizeof(*trb));
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300536
Ido Shayevitzfa65a582012-06-06 14:39:54 +0300537 req->trb = trb;
538 req->trb_dma = dwc3_trb_dma_offset(dep, trb);
539 trb->bph = DBM_TRB_BIT | DBM_TRB_DATA_SRC |
540 DBM_TRB_DMA | DBM_TRB_EP_NUM(dep->number);
541 trb->size = DWC3_TRB_SIZE_LENGTH(req->request.length);
542 trb->ctrl = DWC3_TRBCTL_NORMAL | DWC3_TRB_CTRL_HWO | DWC3_TRB_CTRL_CHN;
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300543
544 /* Second, prepare a Link TRB that points to the first TRB*/
Ido Shayevitzfa65a582012-06-06 14:39:54 +0300545 trb_link = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300546 dep->free_slot++;
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300547
Ido Shayevitzfa65a582012-06-06 14:39:54 +0300548 trb_link->bpl = lower_32_bits(req->trb_dma);
549 trb_link->bph = DBM_TRB_BIT | DBM_TRB_DATA_SRC |
550 DBM_TRB_DMA | DBM_TRB_EP_NUM(dep->number);
551 trb_link->size = 0;
552 trb_link->ctrl = DWC3_TRBCTL_LINK_TRB | DWC3_TRB_CTRL_HWO;
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300553
554 /*
555 * Now start the transfer
556 */
557 memset(&params, 0, sizeof(params));
558 params.param0 = upper_32_bits(req->trb_dma);
559 params.param1 = lower_32_bits(req->trb_dma);
560 cmd = DWC3_DEPCMD_STARTTRANSFER;
561 ret = dwc3_send_gadget_ep_cmd(dep->dwc, dep->number, cmd, &params);
562 if (ret < 0) {
563 dev_dbg(dep->dwc->dev,
564 "%s: failed to send STARTTRANSFER command\n",
565 __func__);
566
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300567 list_del(&req->list);
568 return ret;
569 }
570
571 return ret;
572}
573
574/**
575* Queue a usb request to the DBM endpoint.
576* This function should be called after the endpoint
577* was enabled by the ep_enable.
578*
579* This function prepares special structure of TRBs which
580* is familier with the DBM HW, so it will possible to use
581* this endpoint in DBM mode.
582*
583* The TRBs prepared by this function, is one normal TRB
584* which point to a fake buffer, followed by a link TRB
585* that points to the first TRB.
586*
587* The API of this function follow the regular API of
588* usb_ep_queue (see usb_ep_ops in include/linuk/usb/gadget.h).
589*
590* @usb_ep - pointer to usb_ep instance.
591* @request - pointer to usb_request instance.
592* @gfp_flags - possible flags.
593*
594* @return int - 0 on success, negetive on error.
595*/
596static int dwc3_msm_ep_queue(struct usb_ep *ep,
597 struct usb_request *request, gfp_t gfp_flags)
598{
599 struct dwc3_request *req = to_dwc3_request(request);
600 struct dwc3_ep *dep = to_dwc3_ep(ep);
601 struct dwc3 *dwc = dep->dwc;
602 struct dwc3_msm_req_complete *req_complete;
603 unsigned long flags;
604 int ret = 0;
605 u8 bam_pipe;
606 bool producer;
607 bool disable_wb;
608 bool internal_mem;
609 bool ioc;
610
611 if (!(request->udc_priv & MSM_SPS_MODE)) {
612 /* Not SPS mode, call original queue */
613 dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
614 __func__);
615
616 return (context->original_ep_ops[dep->number])->queue(ep,
617 request,
618 gfp_flags);
619 }
620
621 if (!dep->endpoint.desc) {
622 dev_err(dwc->dev,
623 "%s: trying to queue request %p to disabled ep %s\n",
624 __func__, request, ep->name);
625 return -EPERM;
626 }
627
628 if (dep->number == 0 || dep->number == 1) {
629 dev_err(dwc->dev,
630 "%s: trying to queue dbm request %p to control ep %s\n",
631 __func__, request, ep->name);
632 return -EPERM;
633 }
634
635 if (dep->free_slot > 0 || dep->busy_slot > 0 ||
636 !list_empty(&dep->request_list) ||
637 !list_empty(&dep->req_queued)) {
638
639 dev_err(dwc->dev,
640 "%s: trying to queue dbm request %p tp ep %s\n",
641 __func__, request, ep->name);
642 return -EPERM;
643 }
644
645 /*
646 * Override req->complete function, but before doing that,
647 * store it's original pointer in the req_complete_list.
648 */
649 req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
650 if (!req_complete) {
651 dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
652 return -ENOMEM;
653 }
654 req_complete->req = request;
655 req_complete->orig_complete = request->complete;
656 list_add_tail(&req_complete->list_item, &context->req_complete_list);
657 request->complete = dwc3_msm_req_complete_func;
658
659 /*
660 * Configure dbm event buffers if this is the first
661 * dbm endpoint we about to configure.
662 */
663 if (0 == dwc3_msm_configured_dbm_ep_num())
664 dwc3_msm_event_buffer_config(dwc->ev_buffs[0]->dma,
665 dwc->ev_buffs[0]->length);
666
667 /*
668 * Configure the DBM endpoint
669 */
670 bam_pipe = (request->udc_priv & MSM_PIPE_ID_MASK);
671 producer = ((request->udc_priv & MSM_PRODUCER) ? true : false);
672 disable_wb = ((request->udc_priv & MSM_DISABLE_WB) ? true : false);
673 internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
674 ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
675
676 ret = dwc3_msm_dbm_ep_config(dep->number,
677 bam_pipe, producer,
678 disable_wb, internal_mem, ioc);
679 if (ret < 0) {
680 dev_err(context->dev,
681 "error %d after calling dwc3_msm_dbm_ep_config\n",
682 ret);
683 return ret;
684 }
685
686 dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n",
687 __func__, request, ep->name, request->length);
688
689 /*
690 * We must obtain the lock of the dwc3 core driver,
691 * including disabling interrupts, so we will be sure
692 * that we are the only ones that configure the HW device
693 * core and ensure that we queuing the request will finish
694 * as soon as possible so we will release back the lock.
695 */
696 spin_lock_irqsave(&dwc->lock, flags);
697 ret = __dwc3_msm_ep_queue(dep, req);
698 spin_unlock_irqrestore(&dwc->lock, flags);
699 if (ret < 0) {
700 dev_err(context->dev,
701 "error %d after calling __dwc3_msm_ep_queue\n", ret);
702 return ret;
703 }
704
705 return 0;
706}
707
708/**
709 * Configure MSM endpoint.
710 * This function do specific configurations
711 * to an endpoint which need specific implementaion
712 * in the MSM architecture.
713 *
714 * This function should be called by usb function/class
715 * layer which need a support from the specific MSM HW
716 * which wrap the USB3 core. (like DBM specific endpoints)
717 *
718 * @ep - a pointer to some usb_ep instance
719 *
720 * @return int - 0 on success, negetive on error.
721 */
722int msm_ep_config(struct usb_ep *ep)
723{
724 struct dwc3_ep *dep = to_dwc3_ep(ep);
725 struct usb_ep_ops *new_ep_ops;
726
727 /* Save original ep ops for future restore*/
728 if (context->original_ep_ops[dep->number]) {
729 dev_err(context->dev,
730 "ep [%s,%d] already configured as msm endpoint\n",
731 ep->name, dep->number);
732 return -EPERM;
733 }
734 context->original_ep_ops[dep->number] = ep->ops;
735
736 /* Set new usb ops as we like */
737 new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
738 if (!new_ep_ops) {
739 dev_err(context->dev,
740 "%s: unable to allocate mem for new usb ep ops\n",
741 __func__);
742 return -ENOMEM;
743 }
744 (*new_ep_ops) = (*ep->ops);
745 new_ep_ops->queue = dwc3_msm_ep_queue;
746 ep->ops = new_ep_ops;
747
748 /*
749 * Do HERE more usb endpoint configurations
750 * which are specific to MSM.
751 */
752
753 return 0;
754}
755EXPORT_SYMBOL(msm_ep_config);
756
757/**
758 * Un-configure MSM endpoint.
759 * Tear down configurations done in the
760 * dwc3_msm_ep_config function.
761 *
762 * @ep - a pointer to some usb_ep instance
763 *
764 * @return int - 0 on success, negetive on error.
765 */
766int msm_ep_unconfig(struct usb_ep *ep)
767{
768 struct dwc3_ep *dep = to_dwc3_ep(ep);
769 struct usb_ep_ops *old_ep_ops;
770
771 /* Restore original ep ops */
772 if (!context->original_ep_ops[dep->number]) {
773 dev_err(context->dev,
774 "ep [%s,%d] was not configured as msm endpoint\n",
775 ep->name, dep->number);
776 return -EINVAL;
777 }
778 old_ep_ops = (struct usb_ep_ops *)ep->ops;
779 ep->ops = context->original_ep_ops[dep->number];
780 context->original_ep_ops[dep->number] = NULL;
781 kfree(old_ep_ops);
782
783 /*
784 * Do HERE more usb endpoint un-configurations
785 * which are specific to MSM.
786 */
787
788 return 0;
789}
790EXPORT_SYMBOL(msm_ep_unconfig);
791
Manu Gautam60e01352012-05-29 09:00:34 +0530792/* HSPHY */
793static int dwc3_hsusb_config_vddcx(int high)
794{
795 int min_vol, ret;
796 struct dwc3_msm *dwc = context;
797 enum usb_vdd_type vdd_type = context->hs_vdd_type;
798 int max_vol = vdd_val[vdd_type][VDD_MAX];
799
800 min_vol = vdd_val[vdd_type][high ? VDD_MIN : VDD_NONE];
801 ret = regulator_set_voltage(dwc->hsusb_vddcx, min_vol, max_vol);
802 if (ret) {
803 dev_err(dwc->dev, "unable to set voltage for HSUSB_VDDCX\n");
804 return ret;
805 }
806
807 dev_dbg(dwc->dev, "%s: min_vol:%d max_vol:%d\n", __func__,
808 min_vol, max_vol);
809
810 return ret;
811}
812
813static int dwc3_hsusb_ldo_init(int init)
814{
815 int rc = 0;
816 struct dwc3_msm *dwc = context;
817
818 if (!init) {
819 regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
820 regulator_set_voltage(dwc->hsusb_3p3, 0, USB_HSPHY_3P3_VOL_MAX);
821 return 0;
822 }
823
824 dwc->hsusb_3p3 = devm_regulator_get(dwc->dev, "HSUSB_3p3");
825 if (IS_ERR(dwc->hsusb_3p3)) {
826 dev_err(dwc->dev, "unable to get hsusb 3p3\n");
827 return PTR_ERR(dwc->hsusb_3p3);
828 }
829
830 rc = regulator_set_voltage(dwc->hsusb_3p3,
831 USB_HSPHY_3P3_VOL_MIN, USB_HSPHY_3P3_VOL_MAX);
832 if (rc) {
833 dev_err(dwc->dev, "unable to set voltage for hsusb 3p3\n");
834 return rc;
835 }
836 dwc->hsusb_1p8 = devm_regulator_get(dwc->dev, "HSUSB_1p8");
837 if (IS_ERR(dwc->hsusb_1p8)) {
838 dev_err(dwc->dev, "unable to get hsusb 1p8\n");
839 rc = PTR_ERR(dwc->hsusb_1p8);
840 goto devote_3p3;
841 }
842 rc = regulator_set_voltage(dwc->hsusb_1p8,
843 USB_HSPHY_1P8_VOL_MIN, USB_HSPHY_1P8_VOL_MAX);
844 if (rc) {
845 dev_err(dwc->dev, "unable to set voltage for hsusb 1p8\n");
846 goto devote_3p3;
847 }
848
849 return 0;
850
851devote_3p3:
852 regulator_set_voltage(dwc->hsusb_3p3, 0, USB_HSPHY_3P3_VOL_MAX);
853
854 return rc;
855}
856
857static int dwc3_hsusb_ldo_enable(int on)
858{
859 int rc = 0;
860 struct dwc3_msm *dwc = context;
861
862 dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
863
864 if (!on)
865 goto disable_regulators;
866
867
868 rc = regulator_set_optimum_mode(dwc->hsusb_1p8, USB_HSPHY_1P8_HPM_LOAD);
869 if (rc < 0) {
870 dev_err(dwc->dev, "Unable to set HPM of regulator HSUSB_1p8\n");
871 return rc;
872 }
873
874 rc = regulator_enable(dwc->hsusb_1p8);
875 if (rc) {
876 dev_err(dwc->dev, "Unable to enable HSUSB_1p8\n");
877 goto put_1p8_lpm;
878 }
879
880 rc = regulator_set_optimum_mode(dwc->hsusb_3p3, USB_HSPHY_3P3_HPM_LOAD);
881 if (rc < 0) {
882 dev_err(dwc->dev, "Unable to set HPM of regulator HSUSB_3p3\n");
883 goto disable_1p8;
884 }
885
886 rc = regulator_enable(dwc->hsusb_3p3);
887 if (rc) {
888 dev_err(dwc->dev, "Unable to enable HSUSB_3p3\n");
889 goto put_3p3_lpm;
890 }
891
892 return 0;
893
894disable_regulators:
895 rc = regulator_disable(dwc->hsusb_3p3);
896 if (rc)
897 dev_err(dwc->dev, "Unable to disable HSUSB_3p3\n");
898
899put_3p3_lpm:
900 rc = regulator_set_optimum_mode(dwc->hsusb_3p3, 0);
901 if (rc < 0)
902 dev_err(dwc->dev, "Unable to set LPM of regulator HSUSB_3p3\n");
903
904disable_1p8:
905 rc = regulator_disable(dwc->hsusb_1p8);
906 if (rc)
907 dev_err(dwc->dev, "Unable to disable HSUSB_1p8\n");
908
909put_1p8_lpm:
910 rc = regulator_set_optimum_mode(dwc->hsusb_1p8, 0);
911 if (rc < 0)
912 dev_err(dwc->dev, "Unable to set LPM of regulator HSUSB_1p8\n");
913
914 return rc < 0 ? rc : 0;
915}
916
917/* SSPHY */
918static int dwc3_ssusb_config_vddcx(int high)
919{
920 int min_vol, ret;
921 struct dwc3_msm *dwc = context;
922 enum usb_vdd_type vdd_type = context->ss_vdd_type;
923 int max_vol = vdd_val[vdd_type][VDD_MAX];
924
925 min_vol = vdd_val[vdd_type][high ? VDD_MIN : VDD_NONE];
926 ret = regulator_set_voltage(dwc->ssusb_vddcx, min_vol, max_vol);
927 if (ret) {
928 dev_err(dwc->dev, "unable to set voltage for SSUSB_VDDCX\n");
929 return ret;
930 }
931
932 dev_dbg(dwc->dev, "%s: min_vol:%d max_vol:%d\n", __func__,
933 min_vol, max_vol);
934 return ret;
935}
936
937/* 3.3v supply not needed for SS PHY */
938static int dwc3_ssusb_ldo_init(int init)
939{
940 int rc = 0;
941 struct dwc3_msm *dwc = context;
942
943 if (!init) {
944 regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
945 return 0;
946 }
947
948 dwc->ssusb_1p8 = devm_regulator_get(dwc->dev, "SSUSB_1p8");
949 if (IS_ERR(dwc->ssusb_1p8)) {
950 dev_err(dwc->dev, "unable to get ssusb 1p8\n");
951 return PTR_ERR(dwc->ssusb_1p8);
952 }
953 rc = regulator_set_voltage(dwc->ssusb_1p8,
954 USB_SSPHY_1P8_VOL_MIN, USB_SSPHY_1P8_VOL_MAX);
955 if (rc)
956 dev_err(dwc->dev, "unable to set voltage for ssusb 1p8\n");
957
958 return rc;
959}
960
961static int dwc3_ssusb_ldo_enable(int on)
962{
963 int rc = 0;
964 struct dwc3_msm *dwc = context;
965
966 dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
967
968 if (!on)
969 goto disable_regulators;
970
971
972 rc = regulator_set_optimum_mode(dwc->ssusb_1p8, USB_SSPHY_1P8_HPM_LOAD);
973 if (rc < 0) {
974 dev_err(dwc->dev, "Unable to set HPM of SSUSB_1p8\n");
975 return rc;
976 }
977
978 rc = regulator_enable(dwc->ssusb_1p8);
979 if (rc) {
980 dev_err(dwc->dev, "Unable to enable SSUSB_1p8\n");
981 goto put_1p8_lpm;
982 }
983
984 return 0;
985
986disable_regulators:
987 rc = regulator_disable(dwc->ssusb_1p8);
988 if (rc)
989 dev_err(dwc->dev, "Unable to disable SSUSB_1p8\n");
990
991put_1p8_lpm:
992 rc = regulator_set_optimum_mode(dwc->ssusb_1p8, 0);
993 if (rc < 0)
994 dev_err(dwc->dev, "Unable to set LPM of SSUSB_1p8\n");
995
996 return rc < 0 ? rc : 0;
997}
998
Ido Shayevitzef72ddd2012-03-28 18:55:55 +0200999static int __devinit dwc3_msm_probe(struct platform_device *pdev)
1000{
1001 struct device_node *node = pdev->dev.of_node;
1002 struct platform_device *dwc3;
1003 struct dwc3_msm *msm;
1004 struct resource *res;
1005 int ret = 0;
1006
1007 msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
1008 if (!msm) {
1009 dev_err(&pdev->dev, "not enough memory\n");
1010 return -ENOMEM;
1011 }
1012
1013 platform_set_drvdata(pdev, msm);
Ido Shayevitz9fb83452012-04-01 17:45:58 +03001014 context = msm;
Manu Gautam60e01352012-05-29 09:00:34 +05301015 msm->dev = &pdev->dev;
Ido Shayevitz9fb83452012-04-01 17:45:58 +03001016
1017 INIT_LIST_HEAD(&msm->req_complete_list);
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001018
Manu Gautam60e01352012-05-29 09:00:34 +05301019 /* SS PHY */
1020 msm->ss_vdd_type = VDDCX_CORNER;
1021 msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
1022 if (IS_ERR(msm->ssusb_vddcx)) {
1023 msm->ssusb_vddcx = devm_regulator_get(&pdev->dev,
1024 "SSUSB_VDDCX");
1025 if (IS_ERR(msm->ssusb_vddcx)) {
1026 dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
1027 return PTR_ERR(msm->ssusb_vddcx);
1028 }
1029 msm->ss_vdd_type = VDDCX;
1030 dev_dbg(&pdev->dev, "ss_vdd_type: VDDCX\n");
1031 }
1032
1033 ret = dwc3_ssusb_config_vddcx(1);
1034 if (ret) {
1035 dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
1036 return ret;
1037 }
1038
1039 ret = regulator_enable(context->ssusb_vddcx);
1040 if (ret) {
1041 dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
1042 goto unconfig_ss_vddcx;
1043 }
1044
1045 ret = dwc3_ssusb_ldo_init(1);
1046 if (ret) {
1047 dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
1048 goto disable_ss_vddcx;
1049 }
1050
1051 ret = dwc3_ssusb_ldo_enable(1);
1052 if (ret) {
1053 dev_err(&pdev->dev, "ssusb vreg enable failed\n");
1054 goto free_ss_ldo_init;
1055 }
1056
1057 /* HS PHY */
1058 msm->hs_vdd_type = VDDCX_CORNER;
1059 msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
1060 if (IS_ERR(msm->hsusb_vddcx)) {
1061 msm->hsusb_vddcx = devm_regulator_get(&pdev->dev,
1062 "HSUSB_VDDCX");
1063 if (IS_ERR(msm->hsusb_vddcx)) {
1064 dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
1065 ret = PTR_ERR(msm->ssusb_vddcx);
1066 goto disable_ss_ldo;
1067 }
1068 msm->hs_vdd_type = VDDCX;
1069 dev_dbg(&pdev->dev, "hs_vdd_type: VDDCX\n");
1070 }
1071
1072 ret = dwc3_hsusb_config_vddcx(1);
1073 if (ret) {
1074 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1075 goto disable_ss_ldo;
1076 }
1077
1078 ret = regulator_enable(context->hsusb_vddcx);
1079 if (ret) {
1080 dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
1081 goto unconfig_hs_vddcx;
1082 }
1083
1084 ret = dwc3_hsusb_ldo_init(1);
1085 if (ret) {
1086 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
1087 goto disable_hs_vddcx;
1088 }
1089
1090 ret = dwc3_hsusb_ldo_enable(1);
1091 if (ret) {
1092 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
1093 goto free_hs_ldo_init;
1094 }
1095
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001096 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1097 if (!res) {
1098 dev_err(&pdev->dev, "missing memory base resource\n");
Manu Gautam60e01352012-05-29 09:00:34 +05301099 ret = -ENODEV;
1100 goto disable_hs_ldo;
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001101 }
1102
1103 msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
1104 resource_size(res));
1105 if (!msm->base) {
1106 dev_err(&pdev->dev, "ioremap failed\n");
Manu Gautam60e01352012-05-29 09:00:34 +05301107 ret = -ENODEV;
1108 goto disable_hs_ldo;
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001109 }
1110
Ido Shayevitzca2691e2012-04-17 15:54:53 +03001111 dwc3 = platform_device_alloc("dwc3", -1);
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001112 if (!dwc3) {
1113 dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
Manu Gautam60e01352012-05-29 09:00:34 +05301114 ret = -ENODEV;
1115 goto disable_hs_ldo;
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001116 }
1117
1118 dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
1119
1120 dwc3->dev.parent = &pdev->dev;
1121 dwc3->dev.dma_mask = pdev->dev.dma_mask;
1122 dwc3->dev.dma_parms = pdev->dev.dma_parms;
1123 msm->resource_size = resource_size(res);
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001124 msm->dwc3 = dwc3;
1125
1126 if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
1127 &msm->dbm_num_eps)) {
1128 dev_err(&pdev->dev,
1129 "unable to read platform data num of dbm eps\n");
1130 msm->dbm_num_eps = DBM_MAX_EPS;
1131 }
1132
1133 if (msm->dbm_num_eps > DBM_MAX_EPS) {
1134 dev_err(&pdev->dev,
1135 "Driver doesn't support number of DBM EPs. "
1136 "max: %d, dbm_num_eps: %d\n",
1137 DBM_MAX_EPS, msm->dbm_num_eps);
1138 ret = -ENODEV;
Manu Gautam60e01352012-05-29 09:00:34 +05301139 goto put_pdev;
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001140 }
1141
1142 ret = platform_device_add_resources(dwc3, pdev->resource,
1143 pdev->num_resources);
1144 if (ret) {
1145 dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
Manu Gautam60e01352012-05-29 09:00:34 +05301146 goto put_pdev;
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001147 }
1148
1149 ret = platform_device_add(dwc3);
1150 if (ret) {
1151 dev_err(&pdev->dev, "failed to register dwc3 device\n");
Manu Gautam60e01352012-05-29 09:00:34 +05301152 goto put_pdev;
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001153 }
1154
Ido Shayevitz9fb83452012-04-01 17:45:58 +03001155 /* Reset the DBM */
1156 dwc3_msm_dbm_soft_reset();
1157
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001158 return 0;
1159
Manu Gautam60e01352012-05-29 09:00:34 +05301160put_pdev:
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001161 platform_device_put(dwc3);
Manu Gautam60e01352012-05-29 09:00:34 +05301162disable_hs_ldo:
1163 dwc3_hsusb_ldo_enable(0);
1164free_hs_ldo_init:
1165 dwc3_hsusb_ldo_init(0);
1166disable_hs_vddcx:
1167 regulator_disable(context->hsusb_vddcx);
1168unconfig_hs_vddcx:
1169 dwc3_hsusb_config_vddcx(0);
1170disable_ss_ldo:
1171 dwc3_ssusb_ldo_enable(0);
1172free_ss_ldo_init:
1173 dwc3_ssusb_ldo_init(0);
1174disable_ss_vddcx:
1175 regulator_disable(context->ssusb_vddcx);
1176unconfig_ss_vddcx:
1177 dwc3_ssusb_config_vddcx(0);
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001178
1179 return ret;
1180}
1181
1182static int __devexit dwc3_msm_remove(struct platform_device *pdev)
1183{
1184 struct dwc3_msm *msm = platform_get_drvdata(pdev);
1185
1186 platform_device_unregister(msm->dwc3);
1187
Manu Gautam60e01352012-05-29 09:00:34 +05301188 dwc3_hsusb_ldo_enable(0);
1189 dwc3_hsusb_ldo_init(0);
1190 regulator_disable(msm->hsusb_vddcx);
1191 dwc3_hsusb_config_vddcx(0);
1192 dwc3_ssusb_ldo_enable(0);
1193 dwc3_ssusb_ldo_init(0);
1194 regulator_disable(msm->ssusb_vddcx);
1195 dwc3_ssusb_config_vddcx(0);
1196
Ido Shayevitzef72ddd2012-03-28 18:55:55 +02001197 return 0;
1198}
1199
1200static const struct of_device_id of_dwc3_matach[] = {
1201 {
1202 .compatible = "qcom,dwc-usb3-msm",
1203 },
1204 { },
1205};
1206MODULE_DEVICE_TABLE(of, of_dwc3_matach);
1207
1208static struct platform_driver dwc3_msm_driver = {
1209 .probe = dwc3_msm_probe,
1210 .remove = __devexit_p(dwc3_msm_remove),
1211 .driver = {
1212 .name = "msm-dwc3",
1213 .of_match_table = of_dwc3_matach,
1214 },
1215};
1216
1217MODULE_LICENSE("GPLV2");
1218MODULE_DESCRIPTION("DesignWare USB3 MSM Glue Layer");
1219
1220static int __devinit dwc3_msm_init(void)
1221{
1222 return platform_driver_register(&dwc3_msm_driver);
1223}
1224module_init(dwc3_msm_init);
1225
1226static void __exit dwc3_msm_exit(void)
1227{
1228 platform_driver_unregister(&dwc3_msm_driver);
1229}
1230module_exit(dwc3_msm_exit);