diff options
author | Pavankumar Kondeti <pkondeti@codeaurora.org> | 2010-12-07 07:24:03 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-10 17:23:33 -0500 |
commit | 33f82f387b9cb27bc903e1368fce88b73213910a (patch) | |
tree | e2bc5671dd364c489fccbfd9f4f7d975fbb4ecde | |
parent | f01ef5748f4c4dcd2e49ccb7d75dc113219559d2 (diff) |
USB: gadget: Add USB controller driver for MSM SoC
MSM SoC has chipidea USB controller. So use ci13xxx_udc core.
This driver depends on transceiver driver for clock control,
PHY initialization, VBUS detection. Register for notify_event
callback to perform MSM specific quirks after controller is reset
and stopped.
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/gadget/Kconfig | 21 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/ci13xxx_msm.c | 130 | ||||
-rw-r--r-- | drivers/usb/gadget/gadget_chips.h | 8 |
4 files changed, 160 insertions, 0 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 6bcbcb073e56..7201b4e32778 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -531,6 +531,27 @@ config USB_EG20T | |||
531 | default USB_GADGET | 531 | default USB_GADGET |
532 | select USB_GADGET_SELECTED | 532 | select USB_GADGET_SELECTED |
533 | 533 | ||
534 | config USB_GADGET_CI13XXX_MSM | ||
535 | boolean "MIPS USB CI13xxx for MSM" | ||
536 | depends on ARCH_MSM | ||
537 | select USB_GADGET_DUALSPEED | ||
538 | select USB_MSM_OTG_72K | ||
539 | help | ||
540 | MSM SoC has chipidea USB controller. This driver uses | ||
541 | ci13xxx_udc core. | ||
542 | This driver depends on OTG driver for PHY initialization, | ||
543 | clock management, powering up VBUS, and power management. | ||
544 | |||
545 | Say "y" to link the driver statically, or "m" to build a | ||
546 | dynamically linked module called "ci13xxx_msm" and force all | ||
547 | gadget drivers to also be dynamically linked. | ||
548 | |||
549 | config USB_CI13XXX_MSM | ||
550 | tristate | ||
551 | depends on USB_GADGET_CI13XXX_MSM | ||
552 | default USB_GADGET | ||
553 | select USB_GADGET_SELECTED | ||
554 | |||
534 | # | 555 | # |
535 | # LAST -- dummy/emulated controller | 556 | # LAST -- dummy/emulated controller |
536 | # | 557 | # |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index f53fda7c2558..fbf5db4d456d 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o | |||
27 | obj-$(CONFIG_USB_EG20T) += pch_udc.o | 27 | obj-$(CONFIG_USB_EG20T) += pch_udc.o |
28 | obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o | 28 | obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o |
29 | mv_udc-y := mv_udc_core.o mv_udc_phy.o | 29 | mv_udc-y := mv_udc_core.o mv_udc_phy.o |
30 | obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o | ||
30 | 31 | ||
31 | # | 32 | # |
32 | # USB gadget drivers | 33 | # USB gadget drivers |
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c new file mode 100644 index 000000000000..c497337bb72b --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_msm.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* Copyright (c) 2010, 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 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/usb/msm_hsusb_hw.h> | ||
22 | #include <linux/usb/ulpi.h> | ||
23 | |||
24 | #include "ci13xxx_udc.c" | ||
25 | |||
26 | #define MSM_USB_BASE (udc->regs) | ||
27 | |||
28 | static irqreturn_t msm_udc_irq(int irq, void *data) | ||
29 | { | ||
30 | return udc_irq(); | ||
31 | } | ||
32 | |||
33 | static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event) | ||
34 | { | ||
35 | struct device *dev = udc->gadget.dev.parent; | ||
36 | int val; | ||
37 | |||
38 | switch (event) { | ||
39 | case CI13XXX_CONTROLLER_RESET_EVENT: | ||
40 | dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n"); | ||
41 | writel(0, USB_AHBBURST); | ||
42 | writel(0, USB_AHBMODE); | ||
43 | break; | ||
44 | case CI13XXX_CONTROLLER_STOPPED_EVENT: | ||
45 | dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n"); | ||
46 | /* | ||
47 | * Put the transceiver in non-driving mode. Otherwise host | ||
48 | * may not detect soft-disconnection. | ||
49 | */ | ||
50 | val = otg_io_read(udc->transceiver, ULPI_FUNC_CTRL); | ||
51 | val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; | ||
52 | val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; | ||
53 | otg_io_write(udc->transceiver, val, ULPI_FUNC_CTRL); | ||
54 | break; | ||
55 | default: | ||
56 | dev_dbg(dev, "unknown ci13xxx_udc event\n"); | ||
57 | break; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = { | ||
62 | .name = "ci13xxx_msm", | ||
63 | .flags = CI13XXX_REGS_SHARED | | ||
64 | CI13XXX_REQUIRE_TRANSCEIVER | | ||
65 | CI13XXX_PULLUP_ON_VBUS | | ||
66 | CI13XXX_DISABLE_STREAMING, | ||
67 | |||
68 | .notify_event = ci13xxx_msm_notify_event, | ||
69 | }; | ||
70 | |||
71 | static int ci13xxx_msm_probe(struct platform_device *pdev) | ||
72 | { | ||
73 | struct resource *res; | ||
74 | void __iomem *regs; | ||
75 | int irq; | ||
76 | int ret; | ||
77 | |||
78 | dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); | ||
79 | |||
80 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
81 | if (!res) { | ||
82 | dev_err(&pdev->dev, "failed to get platform resource mem\n"); | ||
83 | return -ENXIO; | ||
84 | } | ||
85 | |||
86 | regs = ioremap(res->start, resource_size(res)); | ||
87 | if (!regs) { | ||
88 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
89 | return -ENOMEM; | ||
90 | } | ||
91 | |||
92 | ret = udc_probe(&ci13xxx_msm_udc_driver, &pdev->dev, regs); | ||
93 | if (ret < 0) { | ||
94 | dev_err(&pdev->dev, "udc_probe failed\n"); | ||
95 | goto iounmap; | ||
96 | } | ||
97 | |||
98 | irq = platform_get_irq(pdev, 0); | ||
99 | if (irq < 0) { | ||
100 | dev_err(&pdev->dev, "IRQ not found\n"); | ||
101 | ret = -ENXIO; | ||
102 | goto udc_remove; | ||
103 | } | ||
104 | |||
105 | ret = request_irq(irq, msm_udc_irq, IRQF_SHARED, pdev->name, pdev); | ||
106 | if (ret < 0) { | ||
107 | dev_err(&pdev->dev, "request_irq failed\n"); | ||
108 | goto udc_remove; | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | |||
113 | udc_remove: | ||
114 | udc_remove(); | ||
115 | iounmap: | ||
116 | iounmap(regs); | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static struct platform_driver ci13xxx_msm_driver = { | ||
122 | .probe = ci13xxx_msm_probe, | ||
123 | .driver = { .name = "msm_hsusb", }, | ||
124 | }; | ||
125 | |||
126 | static int __init ci13xxx_msm_init(void) | ||
127 | { | ||
128 | return platform_driver_register(&ci13xxx_msm_driver); | ||
129 | } | ||
130 | module_init(ci13xxx_msm_init); | ||
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 3093ebbea731..ad2114e87511 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h | |||
@@ -148,6 +148,12 @@ | |||
148 | #define gadget_is_pch(g) 0 | 148 | #define gadget_is_pch(g) 0 |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | #ifdef CONFIG_USB_GADGET_CI13XXX_MSM | ||
152 | #define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name)) | ||
153 | #else | ||
154 | #define gadget_is_ci13xxx_msm(g) 0 | ||
155 | #endif | ||
156 | |||
151 | /** | 157 | /** |
152 | * usb_gadget_controller_number - support bcdDevice id convention | 158 | * usb_gadget_controller_number - support bcdDevice id convention |
153 | * @gadget: the controller being driven | 159 | * @gadget: the controller being driven |
@@ -207,6 +213,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) | |||
207 | return 0x26; | 213 | return 0x26; |
208 | else if (gadget_is_pch(gadget)) | 214 | else if (gadget_is_pch(gadget)) |
209 | return 0x27; | 215 | return 0x27; |
216 | else if (gadget_is_ci13xxx_msm(gadget)) | ||
217 | return 0x28; | ||
210 | return -ENOENT; | 218 | return -ENOENT; |
211 | } | 219 | } |
212 | 220 | ||