aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-10-12 07:08:26 -0400
committerFelipe Balbi <balbi@ti.com>2011-12-12 04:48:12 -0500
commitd07e8819a03dc2d1f03f725194ae56544e6c680b (patch)
tree0715634a05d360ef7939fd0c23befaf11c40919a /drivers/usb/dwc3
parent0949e99b05736946cf0ac78e37194be0807e497e (diff)
usb: dwc3: add xHCI Host support
The Designware USB3 IP can be configured with an internal xHCI. If we're running on such a version, let's start the xHCI stack. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/Kconfig1
-rw-r--r--drivers/usb/dwc3/Makefile2
-rw-r--r--drivers/usb/dwc3/core.c39
-rw-r--r--drivers/usb/dwc3/core.h9
-rw-r--r--drivers/usb/dwc3/host.c116
5 files changed, 164 insertions, 3 deletions
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 3c1d67d324fd..2c05ec9cf352 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -2,6 +2,7 @@ config USB_DWC3
2 tristate "DesignWare USB3 DRD Core Support" 2 tristate "DesignWare USB3 DRD Core Support"
3 depends on (USB || USB_GADGET) 3 depends on (USB || USB_GADGET)
4 select USB_OTG_UTILS 4 select USB_OTG_UTILS
5 select USB_XHCI_PLATFORM
5 help 6 help
6 Say Y or M here if your system has a Dual Role SuperSpeed 7 Say Y or M here if your system has a Dual Role SuperSpeed
7 USB controller based on the DesignWare USB3 IP Core. 8 USB controller based on the DesignWare USB3 IP Core.
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 593d1dbc465b..0926e71142b9 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -4,11 +4,13 @@ ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG
4obj-$(CONFIG_USB_DWC3) += dwc3.o 4obj-$(CONFIG_USB_DWC3) += dwc3.o
5 5
6dwc3-y := core.o 6dwc3-y := core.o
7dwc3-y += host.o
7 8
8ifneq ($(CONFIG_USB_GADGET_DWC3),) 9ifneq ($(CONFIG_USB_GADGET_DWC3),)
9 dwc3-y += gadget.o ep0.o 10 dwc3-y += gadget.o ep0.o
10endif 11endif
11 12
13
12ifneq ($(CONFIG_DEBUG_FS),) 14ifneq ($(CONFIG_DEBUG_FS),)
13 dwc3-y += debugfs.o 15 dwc3-y += debugfs.o
14endif 16endif
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index df151992e49d..410835e28cf6 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -350,6 +350,8 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
350 goto err1; 350 goto err1;
351 } 351 }
352 352
353 dwc->res = res;
354
353 res = request_mem_region(res->start, resource_size(res), 355 res = request_mem_region(res->start, resource_size(res),
354 dev_name(&pdev->dev)); 356 dev_name(&pdev->dev));
355 if (!res) { 357 if (!res) {
@@ -401,7 +403,6 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
401 mode = DWC3_MODE(dwc->hwparams.hwparams0); 403 mode = DWC3_MODE(dwc->hwparams.hwparams0);
402 404
403 switch (mode) { 405 switch (mode) {
404 case DWC3_MODE_DRD:
405 case DWC3_MODE_DEVICE: 406 case DWC3_MODE_DEVICE:
406 ret = dwc3_gadget_init(dwc); 407 ret = dwc3_gadget_init(dwc);
407 if (ret) { 408 if (ret) {
@@ -409,6 +410,26 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
409 goto err4; 410 goto err4;
410 } 411 }
411 break; 412 break;
413 case DWC3_MODE_HOST:
414 ret = dwc3_host_init(dwc);
415 if (ret) {
416 dev_err(&pdev->dev, "failed to initialize host\n");
417 goto err4;
418 }
419 break;
420 case DWC3_MODE_DRD:
421 ret = dwc3_host_init(dwc);
422 if (ret) {
423 dev_err(&pdev->dev, "failed to initialize host\n");
424 goto err4;
425 }
426
427 ret = dwc3_gadget_init(dwc);
428 if (ret) {
429 dev_err(&pdev->dev, "failed to initialize gadget\n");
430 goto err4;
431 }
432 break;
412 default: 433 default:
413 dev_err(&pdev->dev, "Unsupported mode of operation %d\n", mode); 434 dev_err(&pdev->dev, "Unsupported mode of operation %d\n", mode);
414 goto err4; 435 goto err4;
@@ -427,10 +448,16 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
427 448
428err5: 449err5:
429 switch (mode) { 450 switch (mode) {
430 case DWC3_MODE_DRD:
431 case DWC3_MODE_DEVICE: 451 case DWC3_MODE_DEVICE:
432 dwc3_gadget_exit(dwc); 452 dwc3_gadget_exit(dwc);
433 break; 453 break;
454 case DWC3_MODE_HOST:
455 dwc3_host_exit(dwc);
456 break;
457 case DWC3_MODE_DRD:
458 dwc3_host_exit(dwc);
459 dwc3_gadget_exit(dwc);
460 break;
434 default: 461 default:
435 /* do nothing */ 462 /* do nothing */
436 break; 463 break;
@@ -465,10 +492,16 @@ static int __devexit dwc3_remove(struct platform_device *pdev)
465 dwc3_debugfs_exit(dwc); 492 dwc3_debugfs_exit(dwc);
466 493
467 switch (dwc->mode) { 494 switch (dwc->mode) {
468 case DWC3_MODE_DRD:
469 case DWC3_MODE_DEVICE: 495 case DWC3_MODE_DEVICE:
470 dwc3_gadget_exit(dwc); 496 dwc3_gadget_exit(dwc);
471 break; 497 break;
498 case DWC3_MODE_HOST:
499 dwc3_host_exit(dwc);
500 break;
501 case DWC3_MODE_DRD:
502 dwc3_host_exit(dwc);
503 dwc3_gadget_exit(dwc);
504 break;
472 default: 505 default:
473 /* do nothing */ 506 /* do nothing */
474 break; 507 break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index a3ef8f34bf77..a77554373224 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -41,6 +41,7 @@
41 41
42#include <linux/device.h> 42#include <linux/device.h>
43#include <linux/spinlock.h> 43#include <linux/spinlock.h>
44#include <linux/ioport.h>
44#include <linux/list.h> 45#include <linux/list.h>
45#include <linux/dma-mapping.h> 46#include <linux/dma-mapping.h>
46#include <linux/mm.h> 47#include <linux/mm.h>
@@ -560,6 +561,7 @@ struct dwc3_hwparams {
560 * @ep0_bounce_addr: dma address of ep0_bounce 561 * @ep0_bounce_addr: dma address of ep0_bounce
561 * @lock: for synchronizing 562 * @lock: for synchronizing
562 * @dev: pointer to our struct device 563 * @dev: pointer to our struct device
564 * @xhci: pointer to our xHCI child
563 * @event_buffer_list: a list of event buffers 565 * @event_buffer_list: a list of event buffers
564 * @gadget: device side representation of the peripheral controller 566 * @gadget: device side representation of the peripheral controller
565 * @gadget_driver: pointer to the gadget driver 567 * @gadget_driver: pointer to the gadget driver
@@ -598,6 +600,9 @@ struct dwc3 {
598 spinlock_t lock; 600 spinlock_t lock;
599 struct device *dev; 601 struct device *dev;
600 602
603 struct platform_device *xhci;
604 struct resource *res;
605
601 struct dwc3_event_buffer *ev_buffs[DWC3_EVENT_BUFFERS_MAX]; 606 struct dwc3_event_buffer *ev_buffs[DWC3_EVENT_BUFFERS_MAX];
602 struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; 607 struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
603 608
@@ -782,4 +787,8 @@ union dwc3_event {
782#define DWC3_HAS_XHCI BIT(1) 787#define DWC3_HAS_XHCI BIT(1)
783#define DWC3_HAS_OTG BIT(3) 788#define DWC3_HAS_OTG BIT(3)
784 789
790/* prototypes */
791int dwc3_host_init(struct dwc3 *dwc);
792void dwc3_host_exit(struct dwc3 *dwc);
793
785#endif /* __DRIVERS_USB_DWC3_CORE_H */ 794#endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
new file mode 100644
index 000000000000..9b300a26fceb
--- /dev/null
+++ b/drivers/usb/dwc3/host.c
@@ -0,0 +1,116 @@
1/**
2 * host.c - DesignWare USB3 DRD Controller Host Glue
3 *
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
5 *
6 * Authors: Felipe Balbi <balbi@ti.com>,
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions, and the following disclaimer,
13 * without modification.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The names of the above-listed copyright holders may not be used
18 * to endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * ALTERNATIVELY, this software may be distributed under the terms of the
22 * GNU General Public License ("GPL") version 2, as published by the Free
23 * Software Foundation.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
26 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <linux/module.h>
39#include <linux/kernel.h>
40#include <linux/slab.h>
41#include <linux/spinlock.h>
42#include <linux/platform_device.h>
43#include <linux/pm_runtime.h>
44#include <linux/interrupt.h>
45#include <linux/ioport.h>
46#include <linux/io.h>
47#include <linux/list.h>
48#include <linux/delay.h>
49#include <linux/dma-mapping.h>
50
51#include "core.h"
52#include "io.h"
53
54#include "debug.h"
55
56static struct resource generic_resources[] = {
57 {
58 .flags = IORESOURCE_IRQ,
59 },
60 {
61 .flags = IORESOURCE_MEM,
62 },
63};
64
65int dwc3_host_init(struct dwc3 *dwc)
66{
67 struct platform_device *xhci;
68 int ret;
69
70 xhci = platform_device_alloc("xhci", -1);
71 if (!xhci) {
72 dev_err(dwc->dev, "couldn't allocate xHCI device\n");
73 ret = -ENOMEM;
74 goto err0;
75 }
76
77 dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);
78
79 xhci->dev.parent = dwc->dev;
80 xhci->dev.dma_mask = dwc->dev->dma_mask;
81 xhci->dev.dma_parms = dwc->dev->dma_parms;
82
83 dwc->xhci = xhci;
84
85 /* setup resources */
86 generic_resources[0].start = dwc->irq;
87
88 generic_resources[1].start = dwc->res->start;
89 generic_resources[1].end = dwc->res->start + 0x7fff;
90
91 ret = platform_device_add_resources(xhci, generic_resources,
92 ARRAY_SIZE(generic_resources));
93 if (ret) {
94 dev_err(dwc->dev, "couldn't add resources to xHCI device\n");
95 goto err1;
96 }
97
98 ret = platform_device_add(xhci);
99 if (ret) {
100 dev_err(dwc->dev, "failed to register xHCI device\n");
101 goto err1;
102 }
103
104 return 0;
105
106err1:
107 platform_device_put(xhci);
108
109err0:
110 return ret;
111}
112
113void dwc3_host_exit(struct dwc3 *dwc)
114{
115 platform_device_unregister(dwc->xhci);
116}