blob: 4e6091e8a55a1b7a95cd61e20133303575fbbb22 [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>
29
30#include "core.h"
31#include "gadget.h"
32
33/**
34 * USB DBM Hardware registers.
35 *
36 */
37#define DBM_EP_CFG(n) (0x00 + 4 * (n))
38#define DBM_DATA_FIFO(n) (0x10 + 4 * (n))
39#define DBM_DATA_FIFO_SIZE(n) (0x20 + 4 * (n))
40#define DBM_DATA_FIFO_EN (0x30)
41#define DBM_GEVNTADR (0x34)
42#define DBM_GEVNTSIZ (0x38)
43#define DBM_DBG_CNFG (0x3C)
44#define DBM_HW_TRB0_EP(n) (0x40 + 4 * (n))
45#define DBM_HW_TRB1_EP(n) (0x50 + 4 * (n))
46#define DBM_HW_TRB2_EP(n) (0x60 + 4 * (n))
47#define DBM_HW_TRB3_EP(n) (0x70 + 4 * (n))
48#define DBM_PIPE_CFG (0x80)
49#define DBM_SOFT_RESET (0x84)
50
51/**
52 * USB DBM Hardware registers bitmask.
53 *
54 */
55/* DBM_EP_CFG */
56#define DBM_EN_EP 0x00000000
57#define DBM_USB3_EP_NUM 0x0000003E
58#define DBM_BAM_PIPE_NUM 0x000000C0
59#define DBM_PRODUCER 0x00000100
60#define DBM_DISABLE_WB 0x00000200
61#define DBM_INT_RAM_ACC 0x00000400
62
63/* DBM_DATA_FIFO_SIZE */
64#define DBM_DATA_FIFO_SIZE_MASK 0x0000ffff
65
66/* DBM_GEVNTSIZ */
67#define DBM_GEVNTSIZ_MASK 0x0000ffff
68
69/* DBM_DBG_CNFG */
70#define DBM_ENABLE_IOC_MASK 0x0000000f
71
72/* DBM_SOFT_RESET */
73#define DBM_SFT_RST_EP0 0x00000001
74#define DBM_SFT_RST_EP1 0x00000002
75#define DBM_SFT_RST_EP2 0x00000004
76#define DBM_SFT_RST_EP3 0x00000008
77#define DBM_SFT_RST_EPS 0x0000000F
78#define DBM_SFT_RST 0x80000000
Ido Shayevitzef72ddd2012-03-28 18:55:55 +020079
80#define DBM_MAX_EPS 4
81
Ido Shayevitz9fb83452012-04-01 17:45:58 +030082struct dwc3_msm_req_complete {
83 struct list_head list_item;
84 struct usb_request *req;
85 void (*orig_complete)(struct usb_ep *ep,
86 struct usb_request *req);
87};
88
Ido Shayevitzef72ddd2012-03-28 18:55:55 +020089struct dwc3_msm {
90 struct platform_device *dwc3;
91 struct device *dev;
92 void __iomem *base;
93 u32 resource_size;
94 int dbm_num_eps;
Ido Shayevitz9fb83452012-04-01 17:45:58 +030095 u8 ep_num_mapping[DBM_MAX_EPS];
96 const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
97 struct list_head req_complete_list;
Ido Shayevitzef72ddd2012-03-28 18:55:55 +020098};
99
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300100static struct dwc3_msm *context;
101
102/**
103 *
104 * Read register with debug info.
105 *
106 * @base - DWC3 base virtual address.
107 * @offset - register offset.
108 *
109 * @return u32
110 */
111static inline u32 dwc3_msm_read_reg(void *base, u32 offset)
112{
113 u32 val = ioread32(base + offset);
114 return val;
115}
116
117/**
118 * Read register masked field with debug info.
119 *
120 * @base - DWC3 base virtual address.
121 * @offset - register offset.
122 * @mask - register bitmask.
123 *
124 * @return u32
125 */
126static inline u32 dwc3_msm_read_reg_field(void *base,
127 u32 offset,
128 const u32 mask)
129{
130 u32 shift = find_first_bit((void *)&mask, 32);
131 u32 val = ioread32(base + offset);
132 val &= mask; /* clear other bits */
133 val >>= shift;
134 return val;
135}
136
137/**
138 *
139 * Write register with debug info.
140 *
141 * @base - DWC3 base virtual address.
142 * @offset - register offset.
143 * @val - value to write.
144 *
145 */
146static inline void dwc3_msm_write_reg(void *base, u32 offset, u32 val)
147{
148 iowrite32(val, base + offset);
149}
150
151/**
152 * Write register masked field with debug info.
153 *
154 * @base - DWC3 base virtual address.
155 * @offset - register offset.
156 * @mask - register bitmask.
157 * @val - value to write.
158 *
159 */
160static inline void dwc3_msm_write_reg_field(void *base, u32 offset,
161 const u32 mask, u32 val)
162{
163 u32 shift = find_first_bit((void *)&mask, 32);
164 u32 tmp = ioread32(base + offset);
165
166 tmp &= ~mask; /* clear written bits */
167 val = tmp | (val << shift);
168 iowrite32(val, base + offset);
169}
170
171/**
172 * Return DBM EP number which is not already configured.
173 *
174 */
175static int dwc3_msm_find_avail_dbm_ep(void)
176{
177 int i;
178
179 for (i = 0; i < context->dbm_num_eps; i++)
180 if (!context->ep_num_mapping[i])
181 return i;
182
183 return -ENODEV; /* Not found */
184}
185
186/**
187 * Return DBM EP number according to usb endpoint number.
188 *
189 */
190static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
191{
192 int i;
193
194 for (i = 0; i < context->dbm_num_eps; i++)
195 if (context->ep_num_mapping[i] == usb_ep)
196 return i;
197
198 return -ENODEV; /* Not found */
199}
200
201/**
202 * Return number of configured DBM endpoints.
203 *
204 */
205static int dwc3_msm_configured_dbm_ep_num(void)
206{
207 int i;
208 int count = 0;
209
210 for (i = 0; i < context->dbm_num_eps; i++)
211 if (context->ep_num_mapping[i])
212 count++;
213
214 return count;
215}
216
217/**
218 * Configure the DBM with the USB3 core event buffer.
219 * This function is called by the SNPS UDC upon initialization.
220 *
221 * @addr - address of the event buffer.
222 * @size - size of the event buffer.
223 *
224 */
225static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
226{
227 dev_dbg(context->dev, "%s\n", __func__);
228
229 dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
230 dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
231 DBM_GEVNTSIZ_MASK, size);
232
233 return 0;
234}
235
236/**
237 * Reset the DBM registers upon initialization.
238 *
239 */
240static int dwc3_msm_dbm_soft_reset(void)
241{
242 dev_dbg(context->dev, "%s\n", __func__);
243
244 dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
245 DBM_SFT_RST, 1);
246
247 return 0;
248}
249
250/**
251 * Soft reset specific DBM ep.
252 * This function is called by the function driver upon events
253 * such as transfer aborting, USB re-enumeration and USB
254 * disconnection.
255 *
256 * @dbm_ep - DBM ep number.
257 * @enter_reset - should we enter a reset state or get out of it.
258 *
259 */
260static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
261{
262 dev_dbg(context->dev, "%s\n", __func__);
263
264 if (dbm_ep >= context->dbm_num_eps) {
265 dev_err(context->dev,
266 "%s: Invalid DBM ep index\n", __func__);
267 return -ENODEV;
268 }
269
270 if (enter_reset) {
271 dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
272 DBM_SFT_RST_EPS, 1 << dbm_ep);
273 } else {
274 dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
275 DBM_SFT_RST_EPS, 0);
276 }
277
278 return 0;
279}
280
281/**
282 * Configure a USB DBM ep to work in BAM mode.
283 *
284 *
285 * @usb_ep - USB physical EP number.
286 * @producer - producer/consumer.
287 * @disable_wb - disable write back to system memory.
288 * @internal_mem - use internal USB memory for data fifo.
289 * @ioc - enable interrupt on completion.
290 *
291 * @return int - DBM ep number.
292 */
293static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
294 bool producer, bool disable_wb,
295 bool internal_mem, bool ioc)
296{
297 u8 dbm_ep;
298 u8 ioc_mask;
299
300 dev_dbg(context->dev, "%s\n", __func__);
301
302 dbm_ep = dwc3_msm_find_avail_dbm_ep();
303 if (dbm_ep < 0) {
304 dev_err(context->dev, "%s: No more DBM eps\n", __func__);
305 return -ENODEV;
306 }
307
308 context->ep_num_mapping[dbm_ep] = usb_ep;
309
310 /* First, reset the dbm endpoint */
311 dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
312
313 ioc_mask = dwc3_msm_read_reg_field(context->base, DBM_DBG_CNFG,
314 DBM_ENABLE_IOC_MASK);
315 ioc_mask &= ~(ioc << dbm_ep); /* Clear ioc bit for dbm_ep */
316 /* Set ioc bit for dbm_ep if needed */
317 dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
318 DBM_ENABLE_IOC_MASK, ioc_mask | (ioc << dbm_ep));
319
320 dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep),
321 producer | disable_wb | internal_mem);
322 dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
323 DBM_USB3_EP_NUM, usb_ep);
324 dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
325 DBM_BAM_PIPE_NUM, bam_pipe);
326 dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
327 DBM_EN_EP, 1);
328
329 return dbm_ep;
330}
331
332/**
333 * Configure a USB DBM ep to work in normal mode.
334 *
335 * @usb_ep - USB ep number.
336 *
337 */
338static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
339{
340 u8 dbm_ep;
341
342 dev_dbg(context->dev, "%s\n", __func__);
343
344 dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
345
346 if (dbm_ep < 0) {
347 dev_err(context->dev,
348 "%s: Invalid usb ep index\n", __func__);
349 return -ENODEV;
350 }
351
352 context->ep_num_mapping[dbm_ep] = 0;
353
354 dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), 0);
355
356 /* Reset the dbm endpoint */
357 dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
358
359 return 0;
360}
361
362/**
363 * Configure the DBM with the BAM's data fifo.
364 * This function is called by the USB BAM Driver
365 * upon initialization.
366 *
367 * @ep - pointer to usb endpoint.
368 * @addr - address of data fifo.
369 * @size - size of data fifo.
370 *
371 */
372int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size)
373{
374 u8 dbm_ep;
375 struct dwc3_ep *dep = to_dwc3_ep(ep);
376
377 dev_dbg(context->dev, "%s\n", __func__);
378
379 dbm_ep = dwc3_msm_find_matching_dbm_ep(dep->number);
380
381 if (dbm_ep >= context->dbm_num_eps) {
382 dev_err(context->dev,
383 "%s: Invalid DBM ep index\n", __func__);
384 return -ENODEV;
385 }
386
387 dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
388 dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
389 DBM_DATA_FIFO_SIZE_MASK, size);
390
391 return 0;
392}
393
394/**
395* Cleanups for msm endpoint on request complete.
396*
397* Also call original request complete.
398*
399* @usb_ep - pointer to usb_ep instance.
400* @request - pointer to usb_request instance.
401*
402* @return int - 0 on success, negetive on error.
403*/
404static void dwc3_msm_req_complete_func(struct usb_ep *ep,
405 struct usb_request *request)
406{
407 struct dwc3_request *req = to_dwc3_request(request);
408 struct dwc3_ep *dep = to_dwc3_ep(ep);
409 struct dwc3_msm_req_complete *req_complete = NULL;
410
411 /* Find original request complete function and remove it from list */
412 list_for_each_entry(req_complete,
413 &context->req_complete_list,
414 list_item) {
415 if (req_complete->req == request)
416 break;
417 }
418 if (!req_complete || req_complete->req != request) {
419 dev_err(dep->dwc->dev, "%s: could not find the request\n",
420 __func__);
421 return;
422 }
423 list_del(&req_complete->list_item);
424
425 /*
426 * Release another one TRB to the pool since DBM queue took 2 TRBs
427 * (normal and link), and the dwc3/gadget.c :: dwc3_gadget_giveback
428 * released only one.
429 */
430 if (req->queued)
431 dep->busy_slot++;
432
433 /* Unconfigure dbm ep */
434 dwc3_msm_dbm_ep_unconfig(dep->number);
435
436 /*
437 * If this is the last endpoint we unconfigured, than reset also
438 * the event buffers.
439 */
440 if (0 == dwc3_msm_configured_dbm_ep_num())
441 dwc3_msm_event_buffer_config(0, 0);
442
443 /*
444 * Call original complete function, notice that dwc->lock is already
445 * taken by the caller of this function (dwc3_gadget_giveback()).
446 */
447 request->complete = req_complete->orig_complete;
448 request->complete(ep, request);
449
450 kfree(req_complete);
451}
452
453/**
454* Helper function.
455* See the header of the dwc3_msm_ep_queue function.
456*
457* @dwc3_ep - pointer to dwc3_ep instance.
458* @req - pointer to dwc3_request instance.
459*
460* @return int - 0 on success, negetive on error.
461*/
462static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
463{
464 struct dwc3_trb_hw *trb_hw;
465 struct dwc3_trb_hw *trb_link_hw;
466 struct dwc3_trb trb;
467 struct dwc3_gadget_ep_cmd_params params;
468 u32 cmd;
469 int ret = 0;
470
471 if ((req->request.udc_priv & MSM_IS_FINITE_TRANSFER) &&
472 (req->request.length > 0)) {
473 /* Map the request to a DMA. */
474 dwc3_map_buffer_to_dma(req);
475 }
476
477 /* We push the request to the dep->req_queued list to indicate that
478 * this request is issued with start transfer. The request will be out
479 * from this list in 2 cases. The first is that the transfer will be
480 * completed (not if the transfer is endless using a circular TRBs with
481 * with link TRB). The second case is an option to do stop stransfer,
482 * this can be initiated by the function driver when calling dequeue.
483 */
484 req->queued = true;
485 list_add_tail(&req->list, &dep->req_queued);
486
487 /* First, prepare a normal TRB, point to the fake buffer */
488 trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
489 dep->free_slot++;
490 memset(&trb, 0, sizeof(trb));
491
492 req->trb = trb_hw;
493
494 trb.bplh = req->request.dma;
495 trb.lst = 0;
496 trb.trbctl = DWC3_TRBCTL_NORMAL;
497 trb.length = req->request.length;
498 trb.hwo = true;
499
500 dwc3_trb_to_hw(&trb, trb_hw);
501 req->trb_dma = dep->trb_pool_dma;
502
503 /* Second, prepare a Link TRB that points to the first TRB*/
504 trb_link_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
505 dep->free_slot++;
506 memset(&trb, 0, sizeof(trb));
507
508 trb.bplh = dep->trb_pool_dma;
509 trb.trbctl = DWC3_TRBCTL_LINK_TRB;
510 trb.hwo = true;
511
512 dwc3_trb_to_hw(&trb, trb_link_hw);
513
514 /*
515 * Now start the transfer
516 */
517 memset(&params, 0, sizeof(params));
518 params.param0 = upper_32_bits(req->trb_dma);
519 params.param1 = lower_32_bits(req->trb_dma);
520 cmd = DWC3_DEPCMD_STARTTRANSFER;
521 ret = dwc3_send_gadget_ep_cmd(dep->dwc, dep->number, cmd, &params);
522 if (ret < 0) {
523 dev_dbg(dep->dwc->dev,
524 "%s: failed to send STARTTRANSFER command\n",
525 __func__);
526
527 dwc3_unmap_buffer_from_dma(req);
528 list_del(&req->list);
529 return ret;
530 }
531
532 return ret;
533}
534
535/**
536* Queue a usb request to the DBM endpoint.
537* This function should be called after the endpoint
538* was enabled by the ep_enable.
539*
540* This function prepares special structure of TRBs which
541* is familier with the DBM HW, so it will possible to use
542* this endpoint in DBM mode.
543*
544* The TRBs prepared by this function, is one normal TRB
545* which point to a fake buffer, followed by a link TRB
546* that points to the first TRB.
547*
548* The API of this function follow the regular API of
549* usb_ep_queue (see usb_ep_ops in include/linuk/usb/gadget.h).
550*
551* @usb_ep - pointer to usb_ep instance.
552* @request - pointer to usb_request instance.
553* @gfp_flags - possible flags.
554*
555* @return int - 0 on success, negetive on error.
556*/
557static int dwc3_msm_ep_queue(struct usb_ep *ep,
558 struct usb_request *request, gfp_t gfp_flags)
559{
560 struct dwc3_request *req = to_dwc3_request(request);
561 struct dwc3_ep *dep = to_dwc3_ep(ep);
562 struct dwc3 *dwc = dep->dwc;
563 struct dwc3_msm_req_complete *req_complete;
564 unsigned long flags;
565 int ret = 0;
566 u8 bam_pipe;
567 bool producer;
568 bool disable_wb;
569 bool internal_mem;
570 bool ioc;
571
572 if (!(request->udc_priv & MSM_SPS_MODE)) {
573 /* Not SPS mode, call original queue */
574 dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
575 __func__);
576
577 return (context->original_ep_ops[dep->number])->queue(ep,
578 request,
579 gfp_flags);
580 }
581
582 if (!dep->endpoint.desc) {
583 dev_err(dwc->dev,
584 "%s: trying to queue request %p to disabled ep %s\n",
585 __func__, request, ep->name);
586 return -EPERM;
587 }
588
589 if (dep->number == 0 || dep->number == 1) {
590 dev_err(dwc->dev,
591 "%s: trying to queue dbm request %p to control ep %s\n",
592 __func__, request, ep->name);
593 return -EPERM;
594 }
595
596 if (dep->free_slot > 0 || dep->busy_slot > 0 ||
597 !list_empty(&dep->request_list) ||
598 !list_empty(&dep->req_queued)) {
599
600 dev_err(dwc->dev,
601 "%s: trying to queue dbm request %p tp ep %s\n",
602 __func__, request, ep->name);
603 return -EPERM;
604 }
605
606 /*
607 * Override req->complete function, but before doing that,
608 * store it's original pointer in the req_complete_list.
609 */
610 req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
611 if (!req_complete) {
612 dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
613 return -ENOMEM;
614 }
615 req_complete->req = request;
616 req_complete->orig_complete = request->complete;
617 list_add_tail(&req_complete->list_item, &context->req_complete_list);
618 request->complete = dwc3_msm_req_complete_func;
619
620 /*
621 * Configure dbm event buffers if this is the first
622 * dbm endpoint we about to configure.
623 */
624 if (0 == dwc3_msm_configured_dbm_ep_num())
625 dwc3_msm_event_buffer_config(dwc->ev_buffs[0]->dma,
626 dwc->ev_buffs[0]->length);
627
628 /*
629 * Configure the DBM endpoint
630 */
631 bam_pipe = (request->udc_priv & MSM_PIPE_ID_MASK);
632 producer = ((request->udc_priv & MSM_PRODUCER) ? true : false);
633 disable_wb = ((request->udc_priv & MSM_DISABLE_WB) ? true : false);
634 internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
635 ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
636
637 ret = dwc3_msm_dbm_ep_config(dep->number,
638 bam_pipe, producer,
639 disable_wb, internal_mem, ioc);
640 if (ret < 0) {
641 dev_err(context->dev,
642 "error %d after calling dwc3_msm_dbm_ep_config\n",
643 ret);
644 return ret;
645 }
646
647 dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n",
648 __func__, request, ep->name, request->length);
649
650 /*
651 * We must obtain the lock of the dwc3 core driver,
652 * including disabling interrupts, so we will be sure
653 * that we are the only ones that configure the HW device
654 * core and ensure that we queuing the request will finish
655 * as soon as possible so we will release back the lock.
656 */
657 spin_lock_irqsave(&dwc->lock, flags);
658 ret = __dwc3_msm_ep_queue(dep, req);
659 spin_unlock_irqrestore(&dwc->lock, flags);
660 if (ret < 0) {
661 dev_err(context->dev,
662 "error %d after calling __dwc3_msm_ep_queue\n", ret);
663 return ret;
664 }
665
666 return 0;
667}
668
669/**
670 * Configure MSM endpoint.
671 * This function do specific configurations
672 * to an endpoint which need specific implementaion
673 * in the MSM architecture.
674 *
675 * This function should be called by usb function/class
676 * layer which need a support from the specific MSM HW
677 * which wrap the USB3 core. (like DBM specific endpoints)
678 *
679 * @ep - a pointer to some usb_ep instance
680 *
681 * @return int - 0 on success, negetive on error.
682 */
683int msm_ep_config(struct usb_ep *ep)
684{
685 struct dwc3_ep *dep = to_dwc3_ep(ep);
686 struct usb_ep_ops *new_ep_ops;
687
688 /* Save original ep ops for future restore*/
689 if (context->original_ep_ops[dep->number]) {
690 dev_err(context->dev,
691 "ep [%s,%d] already configured as msm endpoint\n",
692 ep->name, dep->number);
693 return -EPERM;
694 }
695 context->original_ep_ops[dep->number] = ep->ops;
696
697 /* Set new usb ops as we like */
698 new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
699 if (!new_ep_ops) {
700 dev_err(context->dev,
701 "%s: unable to allocate mem for new usb ep ops\n",
702 __func__);
703 return -ENOMEM;
704 }
705 (*new_ep_ops) = (*ep->ops);
706 new_ep_ops->queue = dwc3_msm_ep_queue;
707 ep->ops = new_ep_ops;
708
709 /*
710 * Do HERE more usb endpoint configurations
711 * which are specific to MSM.
712 */
713
714 return 0;
715}
716EXPORT_SYMBOL(msm_ep_config);
717
718/**
719 * Un-configure MSM endpoint.
720 * Tear down configurations done in the
721 * dwc3_msm_ep_config function.
722 *
723 * @ep - a pointer to some usb_ep instance
724 *
725 * @return int - 0 on success, negetive on error.
726 */
727int msm_ep_unconfig(struct usb_ep *ep)
728{
729 struct dwc3_ep *dep = to_dwc3_ep(ep);
730 struct usb_ep_ops *old_ep_ops;
731
732 /* Restore original ep ops */
733 if (!context->original_ep_ops[dep->number]) {
734 dev_err(context->dev,
735 "ep [%s,%d] was not configured as msm endpoint\n",
736 ep->name, dep->number);
737 return -EINVAL;
738 }
739 old_ep_ops = (struct usb_ep_ops *)ep->ops;
740 ep->ops = context->original_ep_ops[dep->number];
741 context->original_ep_ops[dep->number] = NULL;
742 kfree(old_ep_ops);
743
744 /*
745 * Do HERE more usb endpoint un-configurations
746 * which are specific to MSM.
747 */
748
749 return 0;
750}
751EXPORT_SYMBOL(msm_ep_unconfig);
752
Ido Shayevitzef72ddd2012-03-28 18:55:55 +0200753static int __devinit dwc3_msm_probe(struct platform_device *pdev)
754{
755 struct device_node *node = pdev->dev.of_node;
756 struct platform_device *dwc3;
757 struct dwc3_msm *msm;
758 struct resource *res;
759 int ret = 0;
760
761 msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
762 if (!msm) {
763 dev_err(&pdev->dev, "not enough memory\n");
764 return -ENOMEM;
765 }
766
767 platform_set_drvdata(pdev, msm);
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300768 context = msm;
769
770 INIT_LIST_HEAD(&msm->req_complete_list);
Ido Shayevitzef72ddd2012-03-28 18:55:55 +0200771
772 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
773 if (!res) {
774 dev_err(&pdev->dev, "missing memory base resource\n");
775 return -ENODEV;
776 }
777
778 msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
779 resource_size(res));
780 if (!msm->base) {
781 dev_err(&pdev->dev, "ioremap failed\n");
782 return -ENODEV;
783 }
784
785 dwc3 = platform_device_alloc("dwc3-msm", -1);
786 if (!dwc3) {
787 dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
788 return -ENOMEM;
789 }
790
791 dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
792
793 dwc3->dev.parent = &pdev->dev;
794 dwc3->dev.dma_mask = pdev->dev.dma_mask;
795 dwc3->dev.dma_parms = pdev->dev.dma_parms;
796 msm->resource_size = resource_size(res);
797 msm->dev = &pdev->dev;
798 msm->dwc3 = dwc3;
799
800 if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
801 &msm->dbm_num_eps)) {
802 dev_err(&pdev->dev,
803 "unable to read platform data num of dbm eps\n");
804 msm->dbm_num_eps = DBM_MAX_EPS;
805 }
806
807 if (msm->dbm_num_eps > DBM_MAX_EPS) {
808 dev_err(&pdev->dev,
809 "Driver doesn't support number of DBM EPs. "
810 "max: %d, dbm_num_eps: %d\n",
811 DBM_MAX_EPS, msm->dbm_num_eps);
812 ret = -ENODEV;
813 goto err1;
814 }
815
816 ret = platform_device_add_resources(dwc3, pdev->resource,
817 pdev->num_resources);
818 if (ret) {
819 dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
820 goto err1;
821 }
822
823 ret = platform_device_add(dwc3);
824 if (ret) {
825 dev_err(&pdev->dev, "failed to register dwc3 device\n");
826 goto err1;
827 }
828
Ido Shayevitz9fb83452012-04-01 17:45:58 +0300829 /* Reset the DBM */
830 dwc3_msm_dbm_soft_reset();
831
Ido Shayevitzef72ddd2012-03-28 18:55:55 +0200832 return 0;
833
834err1:
835 platform_device_put(dwc3);
836
837 return ret;
838}
839
840static int __devexit dwc3_msm_remove(struct platform_device *pdev)
841{
842 struct dwc3_msm *msm = platform_get_drvdata(pdev);
843
844 platform_device_unregister(msm->dwc3);
845
846 return 0;
847}
848
849static const struct of_device_id of_dwc3_matach[] = {
850 {
851 .compatible = "qcom,dwc-usb3-msm",
852 },
853 { },
854};
855MODULE_DEVICE_TABLE(of, of_dwc3_matach);
856
857static struct platform_driver dwc3_msm_driver = {
858 .probe = dwc3_msm_probe,
859 .remove = __devexit_p(dwc3_msm_remove),
860 .driver = {
861 .name = "msm-dwc3",
862 .of_match_table = of_dwc3_matach,
863 },
864};
865
866MODULE_LICENSE("GPLV2");
867MODULE_DESCRIPTION("DesignWare USB3 MSM Glue Layer");
868
869static int __devinit dwc3_msm_init(void)
870{
871 return platform_driver_register(&dwc3_msm_driver);
872}
873module_init(dwc3_msm_init);
874
875static void __exit dwc3_msm_exit(void)
876{
877 platform_driver_unregister(&dwc3_msm_driver);
878}
879module_exit(dwc3_msm_exit);