aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavankumar Kondeti <pkondeti@codeaurora.org>2010-12-07 07:24:03 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-12-10 17:23:33 -0500
commit33f82f387b9cb27bc903e1368fce88b73213910a (patch)
treee2bc5671dd364c489fccbfd9f4f7d975fbb4ecde
parentf01ef5748f4c4dcd2e49ccb7d75dc113219559d2 (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/Kconfig21
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/ci13xxx_msm.c130
-rw-r--r--drivers/usb/gadget/gadget_chips.h8
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
534config 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
549config 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
27obj-$(CONFIG_USB_EG20T) += pch_udc.o 27obj-$(CONFIG_USB_EG20T) += pch_udc.o
28obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o 28obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o
29mv_udc-y := mv_udc_core.o mv_udc_phy.o 29mv_udc-y := mv_udc_core.o mv_udc_phy.o
30obj-$(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
28static irqreturn_t msm_udc_irq(int irq, void *data)
29{
30 return udc_irq();
31}
32
33static 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
61static 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
71static 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
113udc_remove:
114 udc_remove();
115iounmap:
116 iounmap(regs);
117
118 return ret;
119}
120
121static struct platform_driver ci13xxx_msm_driver = {
122 .probe = ci13xxx_msm_probe,
123 .driver = { .name = "msm_hsusb", },
124};
125
126static int __init ci13xxx_msm_init(void)
127{
128 return platform_driver_register(&ci13xxx_msm_driver);
129}
130module_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