diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:09:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 15:09:47 -0500 |
commit | 55b81e6f2795484ea8edf5805c95c007cacfa736 (patch) | |
tree | c3724975107857fcc03b5dd649c462e4f72397be /drivers/usb/otg | |
parent | 5983faf942f260023e547f3c5f38c1033c35cc9b (diff) | |
parent | 08e87d0d773dc9ca5faf4c3306e238ed0ea129b0 (diff) |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (232 commits)
USB: Add USB-ID for Multiplex RC serial adapter to cp210x.c
xhci: Clean up 32-bit build warnings.
USB: update documentation for usbmon
usb: usb-storage doesn't support dynamic id currently, the patch disables the feature to fix an oops
drivers/usb/class/cdc-acm.c: clear dangling pointer
drivers/usb/dwc3/dwc3-pci.c: introduce missing kfree
drivers/usb/host/isp1760-if.c: introduce missing kfree
usb: option: add ZD Incorporated HSPA modem
usb: ch9: fix up MaxStreams helper
USB: usb-skeleton.c: cleanup open_count
USB: usb-skeleton.c: fix open/disconnect race
xhci: Properly handle COMP_2ND_BW_ERR
USB: remove dead code from suspend/resume path
USB: add quirk for another camera
drivers: usb: wusbcore: Fix dependency for USB_WUSB
xhci: Better debugging for critical host errors.
xhci: Be less verbose during URB cancellation.
xhci: Remove debugging about ring structure allocation.
xhci: Remove debugging about toggling cycle bits.
xhci: Remove debugging for individual transfers.
...
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r-- | drivers/usb/otg/Kconfig | 32 | ||||
-rw-r--r-- | drivers/usb/otg/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/otg/fsl_otg.c | 13 | ||||
-rw-r--r-- | drivers/usb/otg/mv_otg.c | 957 | ||||
-rw-r--r-- | drivers/usb/otg/mv_otg.h | 165 |
5 files changed, 1146 insertions, 22 deletions
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index c66481ad98d7..2a25955881fc 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -82,9 +82,9 @@ config NOP_USB_XCEIV | |||
82 | tristate "NOP USB Transceiver Driver" | 82 | tristate "NOP USB Transceiver Driver" |
83 | select USB_OTG_UTILS | 83 | select USB_OTG_UTILS |
84 | help | 84 | help |
85 | this driver is to be used by all the usb transceiver which are either | 85 | This driver is to be used by all the usb transceiver which are either |
86 | built-in with usb ip or which are autonomous and doesn't require any | 86 | built-in with usb ip or which are autonomous and doesn't require any |
87 | phy programming such as ISP1x04 etc. | 87 | phy programming such as ISP1x04 etc. |
88 | 88 | ||
89 | config USB_LANGWELL_OTG | 89 | config USB_LANGWELL_OTG |
90 | tristate "Intel Langwell USB OTG dual-role support" | 90 | tristate "Intel Langwell USB OTG dual-role support" |
@@ -114,13 +114,13 @@ config USB_MSM_OTG | |||
114 | has an external PHY. | 114 | has an external PHY. |
115 | 115 | ||
116 | config AB8500_USB | 116 | config AB8500_USB |
117 | tristate "AB8500 USB Transceiver Driver" | 117 | tristate "AB8500 USB Transceiver Driver" |
118 | depends on AB8500_CORE | 118 | depends on AB8500_CORE |
119 | select USB_OTG_UTILS | 119 | select USB_OTG_UTILS |
120 | help | 120 | help |
121 | Enable this to support the USB OTG transceiver in AB8500 chip. | 121 | Enable this to support the USB OTG transceiver in AB8500 chip. |
122 | This transceiver supports high and full speed devices plus, | 122 | This transceiver supports high and full speed devices plus, |
123 | in host mode, low speed. | 123 | in host mode, low speed. |
124 | 124 | ||
125 | config FSL_USB2_OTG | 125 | config FSL_USB2_OTG |
126 | bool "Freescale USB OTG Transceiver Driver" | 126 | bool "Freescale USB OTG Transceiver Driver" |
@@ -130,4 +130,16 @@ config FSL_USB2_OTG | |||
130 | help | 130 | help |
131 | Enable this to support Freescale USB OTG transceiver. | 131 | Enable this to support Freescale USB OTG transceiver. |
132 | 132 | ||
133 | config USB_MV_OTG | ||
134 | tristate "Marvell USB OTG support" | ||
135 | depends on USB_MV_UDC | ||
136 | select USB_OTG | ||
137 | select USB_OTG_UTILS | ||
138 | help | ||
139 | Say Y here if you want to build Marvell USB OTG transciever | ||
140 | driver in kernel (including PXA and MMP series). This driver | ||
141 | implements role switch between EHCI host driver and gadget driver. | ||
142 | |||
143 | To compile this driver as a module, choose M here. | ||
144 | |||
133 | endif # USB || OTG | 145 | endif # USB || OTG |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 566655c53331..b2c5a9598637 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
@@ -21,3 +21,4 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o | |||
21 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o | 21 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o |
22 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o | 22 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o |
23 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o | 23 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o |
24 | obj-$(CONFIG_USB_MV_OTG) += mv_otg.o | ||
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index 2d9cc445fc73..a190850d2d3b 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c | |||
@@ -1151,18 +1151,7 @@ struct platform_driver fsl_otg_driver = { | |||
1151 | }, | 1151 | }, |
1152 | }; | 1152 | }; |
1153 | 1153 | ||
1154 | static int __init fsl_usb_otg_init(void) | 1154 | module_platform_driver(fsl_otg_driver); |
1155 | { | ||
1156 | pr_info(DRIVER_INFO "\n"); | ||
1157 | return platform_driver_register(&fsl_otg_driver); | ||
1158 | } | ||
1159 | module_init(fsl_usb_otg_init); | ||
1160 | |||
1161 | static void __exit fsl_usb_otg_exit(void) | ||
1162 | { | ||
1163 | platform_driver_unregister(&fsl_otg_driver); | ||
1164 | } | ||
1165 | module_exit(fsl_usb_otg_exit); | ||
1166 | 1155 | ||
1167 | MODULE_DESCRIPTION(DRIVER_INFO); | 1156 | MODULE_DESCRIPTION(DRIVER_INFO); |
1168 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1157 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c new file mode 100644 index 000000000000..db0d4fcdc8e2 --- /dev/null +++ b/drivers/usb/otg/mv_otg.c | |||
@@ -0,0 +1,957 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Marvell International Ltd. All rights reserved. | ||
3 | * Author: Chao Xie <chao.xie@marvell.com> | ||
4 | * Neil Zhang <zhangwm@marvell.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/uaccess.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/proc_fs.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <linux/usb.h> | ||
24 | #include <linux/usb/ch9.h> | ||
25 | #include <linux/usb/otg.h> | ||
26 | #include <linux/usb/gadget.h> | ||
27 | #include <linux/usb/hcd.h> | ||
28 | #include <linux/platform_data/mv_usb.h> | ||
29 | |||
30 | #include "mv_otg.h" | ||
31 | |||
32 | #define DRIVER_DESC "Marvell USB OTG transceiver driver" | ||
33 | #define DRIVER_VERSION "Jan 20, 2010" | ||
34 | |||
35 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
36 | MODULE_VERSION(DRIVER_VERSION); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | static const char driver_name[] = "mv-otg"; | ||
40 | |||
41 | static char *state_string[] = { | ||
42 | "undefined", | ||
43 | "b_idle", | ||
44 | "b_srp_init", | ||
45 | "b_peripheral", | ||
46 | "b_wait_acon", | ||
47 | "b_host", | ||
48 | "a_idle", | ||
49 | "a_wait_vrise", | ||
50 | "a_wait_bcon", | ||
51 | "a_host", | ||
52 | "a_suspend", | ||
53 | "a_peripheral", | ||
54 | "a_wait_vfall", | ||
55 | "a_vbus_err" | ||
56 | }; | ||
57 | |||
58 | static int mv_otg_set_vbus(struct otg_transceiver *otg, bool on) | ||
59 | { | ||
60 | struct mv_otg *mvotg = container_of(otg, struct mv_otg, otg); | ||
61 | if (mvotg->pdata->set_vbus == NULL) | ||
62 | return -ENODEV; | ||
63 | |||
64 | return mvotg->pdata->set_vbus(on); | ||
65 | } | ||
66 | |||
67 | static int mv_otg_set_host(struct otg_transceiver *otg, | ||
68 | struct usb_bus *host) | ||
69 | { | ||
70 | otg->host = host; | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int mv_otg_set_peripheral(struct otg_transceiver *otg, | ||
76 | struct usb_gadget *gadget) | ||
77 | { | ||
78 | otg->gadget = gadget; | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void mv_otg_run_state_machine(struct mv_otg *mvotg, | ||
84 | unsigned long delay) | ||
85 | { | ||
86 | dev_dbg(&mvotg->pdev->dev, "transceiver is updated\n"); | ||
87 | if (!mvotg->qwork) | ||
88 | return; | ||
89 | |||
90 | queue_delayed_work(mvotg->qwork, &mvotg->work, delay); | ||
91 | } | ||
92 | |||
93 | static void mv_otg_timer_await_bcon(unsigned long data) | ||
94 | { | ||
95 | struct mv_otg *mvotg = (struct mv_otg *) data; | ||
96 | |||
97 | mvotg->otg_ctrl.a_wait_bcon_timeout = 1; | ||
98 | |||
99 | dev_info(&mvotg->pdev->dev, "B Device No Response!\n"); | ||
100 | |||
101 | if (spin_trylock(&mvotg->wq_lock)) { | ||
102 | mv_otg_run_state_machine(mvotg, 0); | ||
103 | spin_unlock(&mvotg->wq_lock); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id) | ||
108 | { | ||
109 | struct timer_list *timer; | ||
110 | |||
111 | if (id >= OTG_TIMER_NUM) | ||
112 | return -EINVAL; | ||
113 | |||
114 | timer = &mvotg->otg_ctrl.timer[id]; | ||
115 | |||
116 | if (timer_pending(timer)) | ||
117 | del_timer(timer); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id, | ||
123 | unsigned long interval, | ||
124 | void (*callback) (unsigned long)) | ||
125 | { | ||
126 | struct timer_list *timer; | ||
127 | |||
128 | if (id >= OTG_TIMER_NUM) | ||
129 | return -EINVAL; | ||
130 | |||
131 | timer = &mvotg->otg_ctrl.timer[id]; | ||
132 | if (timer_pending(timer)) { | ||
133 | dev_err(&mvotg->pdev->dev, "Timer%d is already running\n", id); | ||
134 | return -EBUSY; | ||
135 | } | ||
136 | |||
137 | init_timer(timer); | ||
138 | timer->data = (unsigned long) mvotg; | ||
139 | timer->function = callback; | ||
140 | timer->expires = jiffies + interval; | ||
141 | add_timer(timer); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int mv_otg_reset(struct mv_otg *mvotg) | ||
147 | { | ||
148 | unsigned int loops; | ||
149 | u32 tmp; | ||
150 | |||
151 | /* Stop the controller */ | ||
152 | tmp = readl(&mvotg->op_regs->usbcmd); | ||
153 | tmp &= ~USBCMD_RUN_STOP; | ||
154 | writel(tmp, &mvotg->op_regs->usbcmd); | ||
155 | |||
156 | /* Reset the controller to get default values */ | ||
157 | writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd); | ||
158 | |||
159 | loops = 500; | ||
160 | while (readl(&mvotg->op_regs->usbcmd) & USBCMD_CTRL_RESET) { | ||
161 | if (loops == 0) { | ||
162 | dev_err(&mvotg->pdev->dev, | ||
163 | "Wait for RESET completed TIMEOUT\n"); | ||
164 | return -ETIMEDOUT; | ||
165 | } | ||
166 | loops--; | ||
167 | udelay(20); | ||
168 | } | ||
169 | |||
170 | writel(0x0, &mvotg->op_regs->usbintr); | ||
171 | tmp = readl(&mvotg->op_regs->usbsts); | ||
172 | writel(tmp, &mvotg->op_regs->usbsts); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static void mv_otg_init_irq(struct mv_otg *mvotg) | ||
178 | { | ||
179 | u32 otgsc; | ||
180 | |||
181 | mvotg->irq_en = OTGSC_INTR_A_SESSION_VALID | ||
182 | | OTGSC_INTR_A_VBUS_VALID; | ||
183 | mvotg->irq_status = OTGSC_INTSTS_A_SESSION_VALID | ||
184 | | OTGSC_INTSTS_A_VBUS_VALID; | ||
185 | |||
186 | if (mvotg->pdata->vbus == NULL) { | ||
187 | mvotg->irq_en |= OTGSC_INTR_B_SESSION_VALID | ||
188 | | OTGSC_INTR_B_SESSION_END; | ||
189 | mvotg->irq_status |= OTGSC_INTSTS_B_SESSION_VALID | ||
190 | | OTGSC_INTSTS_B_SESSION_END; | ||
191 | } | ||
192 | |||
193 | if (mvotg->pdata->id == NULL) { | ||
194 | mvotg->irq_en |= OTGSC_INTR_USB_ID; | ||
195 | mvotg->irq_status |= OTGSC_INTSTS_USB_ID; | ||
196 | } | ||
197 | |||
198 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
199 | otgsc |= mvotg->irq_en; | ||
200 | writel(otgsc, &mvotg->op_regs->otgsc); | ||
201 | } | ||
202 | |||
203 | static void mv_otg_start_host(struct mv_otg *mvotg, int on) | ||
204 | { | ||
205 | struct otg_transceiver *otg = &mvotg->otg; | ||
206 | struct usb_hcd *hcd; | ||
207 | |||
208 | if (!otg->host) | ||
209 | return; | ||
210 | |||
211 | dev_info(&mvotg->pdev->dev, "%s host\n", on ? "start" : "stop"); | ||
212 | |||
213 | hcd = bus_to_hcd(otg->host); | ||
214 | |||
215 | if (on) | ||
216 | usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); | ||
217 | else | ||
218 | usb_remove_hcd(hcd); | ||
219 | } | ||
220 | |||
221 | static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) | ||
222 | { | ||
223 | struct otg_transceiver *otg = &mvotg->otg; | ||
224 | |||
225 | if (!otg->gadget) | ||
226 | return; | ||
227 | |||
228 | dev_info(otg->dev, "gadget %s\n", on ? "on" : "off"); | ||
229 | |||
230 | if (on) | ||
231 | usb_gadget_vbus_connect(otg->gadget); | ||
232 | else | ||
233 | usb_gadget_vbus_disconnect(otg->gadget); | ||
234 | } | ||
235 | |||
236 | static void otg_clock_enable(struct mv_otg *mvotg) | ||
237 | { | ||
238 | unsigned int i; | ||
239 | |||
240 | for (i = 0; i < mvotg->clknum; i++) | ||
241 | clk_enable(mvotg->clk[i]); | ||
242 | } | ||
243 | |||
244 | static void otg_clock_disable(struct mv_otg *mvotg) | ||
245 | { | ||
246 | unsigned int i; | ||
247 | |||
248 | for (i = 0; i < mvotg->clknum; i++) | ||
249 | clk_disable(mvotg->clk[i]); | ||
250 | } | ||
251 | |||
252 | static int mv_otg_enable_internal(struct mv_otg *mvotg) | ||
253 | { | ||
254 | int retval = 0; | ||
255 | |||
256 | if (mvotg->active) | ||
257 | return 0; | ||
258 | |||
259 | dev_dbg(&mvotg->pdev->dev, "otg enabled\n"); | ||
260 | |||
261 | otg_clock_enable(mvotg); | ||
262 | if (mvotg->pdata->phy_init) { | ||
263 | retval = mvotg->pdata->phy_init(mvotg->phy_regs); | ||
264 | if (retval) { | ||
265 | dev_err(&mvotg->pdev->dev, | ||
266 | "init phy error %d\n", retval); | ||
267 | otg_clock_disable(mvotg); | ||
268 | return retval; | ||
269 | } | ||
270 | } | ||
271 | mvotg->active = 1; | ||
272 | |||
273 | return 0; | ||
274 | |||
275 | } | ||
276 | |||
277 | static int mv_otg_enable(struct mv_otg *mvotg) | ||
278 | { | ||
279 | if (mvotg->clock_gating) | ||
280 | return mv_otg_enable_internal(mvotg); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static void mv_otg_disable_internal(struct mv_otg *mvotg) | ||
286 | { | ||
287 | if (mvotg->active) { | ||
288 | dev_dbg(&mvotg->pdev->dev, "otg disabled\n"); | ||
289 | if (mvotg->pdata->phy_deinit) | ||
290 | mvotg->pdata->phy_deinit(mvotg->phy_regs); | ||
291 | otg_clock_disable(mvotg); | ||
292 | mvotg->active = 0; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static void mv_otg_disable(struct mv_otg *mvotg) | ||
297 | { | ||
298 | if (mvotg->clock_gating) | ||
299 | mv_otg_disable_internal(mvotg); | ||
300 | } | ||
301 | |||
302 | static void mv_otg_update_inputs(struct mv_otg *mvotg) | ||
303 | { | ||
304 | struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl; | ||
305 | u32 otgsc; | ||
306 | |||
307 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
308 | |||
309 | if (mvotg->pdata->vbus) { | ||
310 | if (mvotg->pdata->vbus->poll() == VBUS_HIGH) { | ||
311 | otg_ctrl->b_sess_vld = 1; | ||
312 | otg_ctrl->b_sess_end = 0; | ||
313 | } else { | ||
314 | otg_ctrl->b_sess_vld = 0; | ||
315 | otg_ctrl->b_sess_end = 1; | ||
316 | } | ||
317 | } else { | ||
318 | otg_ctrl->b_sess_vld = !!(otgsc & OTGSC_STS_B_SESSION_VALID); | ||
319 | otg_ctrl->b_sess_end = !!(otgsc & OTGSC_STS_B_SESSION_END); | ||
320 | } | ||
321 | |||
322 | if (mvotg->pdata->id) | ||
323 | otg_ctrl->id = !!mvotg->pdata->id->poll(); | ||
324 | else | ||
325 | otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID); | ||
326 | |||
327 | if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id) | ||
328 | otg_ctrl->a_bus_req = 1; | ||
329 | |||
330 | otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID); | ||
331 | otg_ctrl->a_vbus_vld = !!(otgsc & OTGSC_STS_A_VBUS_VALID); | ||
332 | |||
333 | dev_dbg(&mvotg->pdev->dev, "%s: ", __func__); | ||
334 | dev_dbg(&mvotg->pdev->dev, "id %d\n", otg_ctrl->id); | ||
335 | dev_dbg(&mvotg->pdev->dev, "b_sess_vld %d\n", otg_ctrl->b_sess_vld); | ||
336 | dev_dbg(&mvotg->pdev->dev, "b_sess_end %d\n", otg_ctrl->b_sess_end); | ||
337 | dev_dbg(&mvotg->pdev->dev, "a_vbus_vld %d\n", otg_ctrl->a_vbus_vld); | ||
338 | dev_dbg(&mvotg->pdev->dev, "a_sess_vld %d\n", otg_ctrl->a_sess_vld); | ||
339 | } | ||
340 | |||
341 | static void mv_otg_update_state(struct mv_otg *mvotg) | ||
342 | { | ||
343 | struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl; | ||
344 | struct otg_transceiver *otg = &mvotg->otg; | ||
345 | int old_state = otg->state; | ||
346 | |||
347 | switch (old_state) { | ||
348 | case OTG_STATE_UNDEFINED: | ||
349 | otg->state = OTG_STATE_B_IDLE; | ||
350 | /* FALL THROUGH */ | ||
351 | case OTG_STATE_B_IDLE: | ||
352 | if (otg_ctrl->id == 0) | ||
353 | otg->state = OTG_STATE_A_IDLE; | ||
354 | else if (otg_ctrl->b_sess_vld) | ||
355 | otg->state = OTG_STATE_B_PERIPHERAL; | ||
356 | break; | ||
357 | case OTG_STATE_B_PERIPHERAL: | ||
358 | if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0) | ||
359 | otg->state = OTG_STATE_B_IDLE; | ||
360 | break; | ||
361 | case OTG_STATE_A_IDLE: | ||
362 | if (otg_ctrl->id) | ||
363 | otg->state = OTG_STATE_B_IDLE; | ||
364 | else if (!(otg_ctrl->a_bus_drop) && | ||
365 | (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det)) | ||
366 | otg->state = OTG_STATE_A_WAIT_VRISE; | ||
367 | break; | ||
368 | case OTG_STATE_A_WAIT_VRISE: | ||
369 | if (otg_ctrl->a_vbus_vld) | ||
370 | otg->state = OTG_STATE_A_WAIT_BCON; | ||
371 | break; | ||
372 | case OTG_STATE_A_WAIT_BCON: | ||
373 | if (otg_ctrl->id || otg_ctrl->a_bus_drop | ||
374 | || otg_ctrl->a_wait_bcon_timeout) { | ||
375 | mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); | ||
376 | mvotg->otg_ctrl.a_wait_bcon_timeout = 0; | ||
377 | otg->state = OTG_STATE_A_WAIT_VFALL; | ||
378 | otg_ctrl->a_bus_req = 0; | ||
379 | } else if (!otg_ctrl->a_vbus_vld) { | ||
380 | mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); | ||
381 | mvotg->otg_ctrl.a_wait_bcon_timeout = 0; | ||
382 | otg->state = OTG_STATE_A_VBUS_ERR; | ||
383 | } else if (otg_ctrl->b_conn) { | ||
384 | mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER); | ||
385 | mvotg->otg_ctrl.a_wait_bcon_timeout = 0; | ||
386 | otg->state = OTG_STATE_A_HOST; | ||
387 | } | ||
388 | break; | ||
389 | case OTG_STATE_A_HOST: | ||
390 | if (otg_ctrl->id || !otg_ctrl->b_conn | ||
391 | || otg_ctrl->a_bus_drop) | ||
392 | otg->state = OTG_STATE_A_WAIT_BCON; | ||
393 | else if (!otg_ctrl->a_vbus_vld) | ||
394 | otg->state = OTG_STATE_A_VBUS_ERR; | ||
395 | break; | ||
396 | case OTG_STATE_A_WAIT_VFALL: | ||
397 | if (otg_ctrl->id | ||
398 | || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld) | ||
399 | || otg_ctrl->a_bus_req) | ||
400 | otg->state = OTG_STATE_A_IDLE; | ||
401 | break; | ||
402 | case OTG_STATE_A_VBUS_ERR: | ||
403 | if (otg_ctrl->id || otg_ctrl->a_clr_err | ||
404 | || otg_ctrl->a_bus_drop) { | ||
405 | otg_ctrl->a_clr_err = 0; | ||
406 | otg->state = OTG_STATE_A_WAIT_VFALL; | ||
407 | } | ||
408 | break; | ||
409 | default: | ||
410 | break; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | static void mv_otg_work(struct work_struct *work) | ||
415 | { | ||
416 | struct mv_otg *mvotg; | ||
417 | struct otg_transceiver *otg; | ||
418 | int old_state; | ||
419 | |||
420 | mvotg = container_of((struct delayed_work *)work, struct mv_otg, work); | ||
421 | |||
422 | run: | ||
423 | /* work queue is single thread, or we need spin_lock to protect */ | ||
424 | otg = &mvotg->otg; | ||
425 | old_state = otg->state; | ||
426 | |||
427 | if (!mvotg->active) | ||
428 | return; | ||
429 | |||
430 | mv_otg_update_inputs(mvotg); | ||
431 | mv_otg_update_state(mvotg); | ||
432 | |||
433 | if (old_state != otg->state) { | ||
434 | dev_info(&mvotg->pdev->dev, "change from state %s to %s\n", | ||
435 | state_string[old_state], | ||
436 | state_string[otg->state]); | ||
437 | |||
438 | switch (otg->state) { | ||
439 | case OTG_STATE_B_IDLE: | ||
440 | mvotg->otg.default_a = 0; | ||
441 | if (old_state == OTG_STATE_B_PERIPHERAL) | ||
442 | mv_otg_start_periphrals(mvotg, 0); | ||
443 | mv_otg_reset(mvotg); | ||
444 | mv_otg_disable(mvotg); | ||
445 | break; | ||
446 | case OTG_STATE_B_PERIPHERAL: | ||
447 | mv_otg_enable(mvotg); | ||
448 | mv_otg_start_periphrals(mvotg, 1); | ||
449 | break; | ||
450 | case OTG_STATE_A_IDLE: | ||
451 | mvotg->otg.default_a = 1; | ||
452 | mv_otg_enable(mvotg); | ||
453 | if (old_state == OTG_STATE_A_WAIT_VFALL) | ||
454 | mv_otg_start_host(mvotg, 0); | ||
455 | mv_otg_reset(mvotg); | ||
456 | break; | ||
457 | case OTG_STATE_A_WAIT_VRISE: | ||
458 | mv_otg_set_vbus(&mvotg->otg, 1); | ||
459 | break; | ||
460 | case OTG_STATE_A_WAIT_BCON: | ||
461 | if (old_state != OTG_STATE_A_HOST) | ||
462 | mv_otg_start_host(mvotg, 1); | ||
463 | mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER, | ||
464 | T_A_WAIT_BCON, | ||
465 | mv_otg_timer_await_bcon); | ||
466 | /* | ||
467 | * Now, we directly enter A_HOST. So set b_conn = 1 | ||
468 | * here. In fact, it need host driver to notify us. | ||
469 | */ | ||
470 | mvotg->otg_ctrl.b_conn = 1; | ||
471 | break; | ||
472 | case OTG_STATE_A_HOST: | ||
473 | break; | ||
474 | case OTG_STATE_A_WAIT_VFALL: | ||
475 | /* | ||
476 | * Now, we has exited A_HOST. So set b_conn = 0 | ||
477 | * here. In fact, it need host driver to notify us. | ||
478 | */ | ||
479 | mvotg->otg_ctrl.b_conn = 0; | ||
480 | mv_otg_set_vbus(&mvotg->otg, 0); | ||
481 | break; | ||
482 | case OTG_STATE_A_VBUS_ERR: | ||
483 | break; | ||
484 | default: | ||
485 | break; | ||
486 | } | ||
487 | goto run; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | static irqreturn_t mv_otg_irq(int irq, void *dev) | ||
492 | { | ||
493 | struct mv_otg *mvotg = dev; | ||
494 | u32 otgsc; | ||
495 | |||
496 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
497 | writel(otgsc, &mvotg->op_regs->otgsc); | ||
498 | |||
499 | /* | ||
500 | * if we have vbus, then the vbus detection for B-device | ||
501 | * will be done by mv_otg_inputs_irq(). | ||
502 | */ | ||
503 | if (mvotg->pdata->vbus) | ||
504 | if ((otgsc & OTGSC_STS_USB_ID) && | ||
505 | !(otgsc & OTGSC_INTSTS_USB_ID)) | ||
506 | return IRQ_NONE; | ||
507 | |||
508 | if ((otgsc & mvotg->irq_status) == 0) | ||
509 | return IRQ_NONE; | ||
510 | |||
511 | mv_otg_run_state_machine(mvotg, 0); | ||
512 | |||
513 | return IRQ_HANDLED; | ||
514 | } | ||
515 | |||
516 | static irqreturn_t mv_otg_inputs_irq(int irq, void *dev) | ||
517 | { | ||
518 | struct mv_otg *mvotg = dev; | ||
519 | |||
520 | /* The clock may disabled at this time */ | ||
521 | if (!mvotg->active) { | ||
522 | mv_otg_enable(mvotg); | ||
523 | mv_otg_init_irq(mvotg); | ||
524 | } | ||
525 | |||
526 | mv_otg_run_state_machine(mvotg, 0); | ||
527 | |||
528 | return IRQ_HANDLED; | ||
529 | } | ||
530 | |||
531 | static ssize_t | ||
532 | get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf) | ||
533 | { | ||
534 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
535 | return scnprintf(buf, PAGE_SIZE, "%d\n", | ||
536 | mvotg->otg_ctrl.a_bus_req); | ||
537 | } | ||
538 | |||
539 | static ssize_t | ||
540 | set_a_bus_req(struct device *dev, struct device_attribute *attr, | ||
541 | const char *buf, size_t count) | ||
542 | { | ||
543 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
544 | |||
545 | if (count > 2) | ||
546 | return -1; | ||
547 | |||
548 | /* We will use this interface to change to A device */ | ||
549 | if (mvotg->otg.state != OTG_STATE_B_IDLE | ||
550 | && mvotg->otg.state != OTG_STATE_A_IDLE) | ||
551 | return -1; | ||
552 | |||
553 | /* The clock may disabled and we need to set irq for ID detected */ | ||
554 | mv_otg_enable(mvotg); | ||
555 | mv_otg_init_irq(mvotg); | ||
556 | |||
557 | if (buf[0] == '1') { | ||
558 | mvotg->otg_ctrl.a_bus_req = 1; | ||
559 | mvotg->otg_ctrl.a_bus_drop = 0; | ||
560 | dev_dbg(&mvotg->pdev->dev, | ||
561 | "User request: a_bus_req = 1\n"); | ||
562 | |||
563 | if (spin_trylock(&mvotg->wq_lock)) { | ||
564 | mv_otg_run_state_machine(mvotg, 0); | ||
565 | spin_unlock(&mvotg->wq_lock); | ||
566 | } | ||
567 | } | ||
568 | |||
569 | return count; | ||
570 | } | ||
571 | |||
572 | static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, | ||
573 | set_a_bus_req); | ||
574 | |||
575 | static ssize_t | ||
576 | set_a_clr_err(struct device *dev, struct device_attribute *attr, | ||
577 | const char *buf, size_t count) | ||
578 | { | ||
579 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
580 | if (!mvotg->otg.default_a) | ||
581 | return -1; | ||
582 | |||
583 | if (count > 2) | ||
584 | return -1; | ||
585 | |||
586 | if (buf[0] == '1') { | ||
587 | mvotg->otg_ctrl.a_clr_err = 1; | ||
588 | dev_dbg(&mvotg->pdev->dev, | ||
589 | "User request: a_clr_err = 1\n"); | ||
590 | } | ||
591 | |||
592 | if (spin_trylock(&mvotg->wq_lock)) { | ||
593 | mv_otg_run_state_machine(mvotg, 0); | ||
594 | spin_unlock(&mvotg->wq_lock); | ||
595 | } | ||
596 | |||
597 | return count; | ||
598 | } | ||
599 | |||
600 | static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err); | ||
601 | |||
602 | static ssize_t | ||
603 | get_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
604 | char *buf) | ||
605 | { | ||
606 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
607 | return scnprintf(buf, PAGE_SIZE, "%d\n", | ||
608 | mvotg->otg_ctrl.a_bus_drop); | ||
609 | } | ||
610 | |||
611 | static ssize_t | ||
612 | set_a_bus_drop(struct device *dev, struct device_attribute *attr, | ||
613 | const char *buf, size_t count) | ||
614 | { | ||
615 | struct mv_otg *mvotg = dev_get_drvdata(dev); | ||
616 | if (!mvotg->otg.default_a) | ||
617 | return -1; | ||
618 | |||
619 | if (count > 2) | ||
620 | return -1; | ||
621 | |||
622 | if (buf[0] == '0') { | ||
623 | mvotg->otg_ctrl.a_bus_drop = 0; | ||
624 | dev_dbg(&mvotg->pdev->dev, | ||
625 | "User request: a_bus_drop = 0\n"); | ||
626 | } else if (buf[0] == '1') { | ||
627 | mvotg->otg_ctrl.a_bus_drop = 1; | ||
628 | mvotg->otg_ctrl.a_bus_req = 0; | ||
629 | dev_dbg(&mvotg->pdev->dev, | ||
630 | "User request: a_bus_drop = 1\n"); | ||
631 | dev_dbg(&mvotg->pdev->dev, | ||
632 | "User request: and a_bus_req = 0\n"); | ||
633 | } | ||
634 | |||
635 | if (spin_trylock(&mvotg->wq_lock)) { | ||
636 | mv_otg_run_state_machine(mvotg, 0); | ||
637 | spin_unlock(&mvotg->wq_lock); | ||
638 | } | ||
639 | |||
640 | return count; | ||
641 | } | ||
642 | |||
643 | static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, | ||
644 | get_a_bus_drop, set_a_bus_drop); | ||
645 | |||
646 | static struct attribute *inputs_attrs[] = { | ||
647 | &dev_attr_a_bus_req.attr, | ||
648 | &dev_attr_a_clr_err.attr, | ||
649 | &dev_attr_a_bus_drop.attr, | ||
650 | NULL, | ||
651 | }; | ||
652 | |||
653 | static struct attribute_group inputs_attr_group = { | ||
654 | .name = "inputs", | ||
655 | .attrs = inputs_attrs, | ||
656 | }; | ||
657 | |||
658 | int mv_otg_remove(struct platform_device *pdev) | ||
659 | { | ||
660 | struct mv_otg *mvotg = platform_get_drvdata(pdev); | ||
661 | int clk_i; | ||
662 | |||
663 | sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group); | ||
664 | |||
665 | if (mvotg->irq) | ||
666 | free_irq(mvotg->irq, mvotg); | ||
667 | |||
668 | if (mvotg->pdata->vbus) | ||
669 | free_irq(mvotg->pdata->vbus->irq, mvotg); | ||
670 | if (mvotg->pdata->id) | ||
671 | free_irq(mvotg->pdata->id->irq, mvotg); | ||
672 | |||
673 | if (mvotg->qwork) { | ||
674 | flush_workqueue(mvotg->qwork); | ||
675 | destroy_workqueue(mvotg->qwork); | ||
676 | } | ||
677 | |||
678 | mv_otg_disable(mvotg); | ||
679 | |||
680 | if (mvotg->cap_regs) | ||
681 | iounmap(mvotg->cap_regs); | ||
682 | |||
683 | if (mvotg->phy_regs) | ||
684 | iounmap(mvotg->phy_regs); | ||
685 | |||
686 | for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) | ||
687 | clk_put(mvotg->clk[clk_i]); | ||
688 | |||
689 | otg_set_transceiver(NULL); | ||
690 | platform_set_drvdata(pdev, NULL); | ||
691 | |||
692 | kfree(mvotg); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int mv_otg_probe(struct platform_device *pdev) | ||
698 | { | ||
699 | struct mv_usb_platform_data *pdata = pdev->dev.platform_data; | ||
700 | struct mv_otg *mvotg; | ||
701 | struct resource *r; | ||
702 | int retval = 0, clk_i, i; | ||
703 | size_t size; | ||
704 | |||
705 | if (pdata == NULL) { | ||
706 | dev_err(&pdev->dev, "failed to get platform data\n"); | ||
707 | return -ENODEV; | ||
708 | } | ||
709 | |||
710 | size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum; | ||
711 | mvotg = kzalloc(size, GFP_KERNEL); | ||
712 | if (!mvotg) { | ||
713 | dev_err(&pdev->dev, "failed to allocate memory!\n"); | ||
714 | return -ENOMEM; | ||
715 | } | ||
716 | |||
717 | platform_set_drvdata(pdev, mvotg); | ||
718 | |||
719 | mvotg->pdev = pdev; | ||
720 | mvotg->pdata = pdata; | ||
721 | |||
722 | mvotg->clknum = pdata->clknum; | ||
723 | for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) { | ||
724 | mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]); | ||
725 | if (IS_ERR(mvotg->clk[clk_i])) { | ||
726 | retval = PTR_ERR(mvotg->clk[clk_i]); | ||
727 | goto err_put_clk; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | mvotg->qwork = create_singlethread_workqueue("mv_otg_queue"); | ||
732 | if (!mvotg->qwork) { | ||
733 | dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n"); | ||
734 | retval = -ENOMEM; | ||
735 | goto err_put_clk; | ||
736 | } | ||
737 | |||
738 | INIT_DELAYED_WORK(&mvotg->work, mv_otg_work); | ||
739 | |||
740 | /* OTG common part */ | ||
741 | mvotg->pdev = pdev; | ||
742 | mvotg->otg.dev = &pdev->dev; | ||
743 | mvotg->otg.label = driver_name; | ||
744 | mvotg->otg.set_host = mv_otg_set_host; | ||
745 | mvotg->otg.set_peripheral = mv_otg_set_peripheral; | ||
746 | mvotg->otg.set_vbus = mv_otg_set_vbus; | ||
747 | mvotg->otg.state = OTG_STATE_UNDEFINED; | ||
748 | |||
749 | for (i = 0; i < OTG_TIMER_NUM; i++) | ||
750 | init_timer(&mvotg->otg_ctrl.timer[i]); | ||
751 | |||
752 | r = platform_get_resource_byname(mvotg->pdev, | ||
753 | IORESOURCE_MEM, "phyregs"); | ||
754 | if (r == NULL) { | ||
755 | dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); | ||
756 | retval = -ENODEV; | ||
757 | goto err_destroy_workqueue; | ||
758 | } | ||
759 | |||
760 | mvotg->phy_regs = ioremap(r->start, resource_size(r)); | ||
761 | if (mvotg->phy_regs == NULL) { | ||
762 | dev_err(&pdev->dev, "failed to map phy I/O memory\n"); | ||
763 | retval = -EFAULT; | ||
764 | goto err_destroy_workqueue; | ||
765 | } | ||
766 | |||
767 | r = platform_get_resource_byname(mvotg->pdev, | ||
768 | IORESOURCE_MEM, "capregs"); | ||
769 | if (r == NULL) { | ||
770 | dev_err(&pdev->dev, "no I/O memory resource defined\n"); | ||
771 | retval = -ENODEV; | ||
772 | goto err_unmap_phyreg; | ||
773 | } | ||
774 | |||
775 | mvotg->cap_regs = ioremap(r->start, resource_size(r)); | ||
776 | if (mvotg->cap_regs == NULL) { | ||
777 | dev_err(&pdev->dev, "failed to map I/O memory\n"); | ||
778 | retval = -EFAULT; | ||
779 | goto err_unmap_phyreg; | ||
780 | } | ||
781 | |||
782 | /* we will acces controller register, so enable the udc controller */ | ||
783 | retval = mv_otg_enable_internal(mvotg); | ||
784 | if (retval) { | ||
785 | dev_err(&pdev->dev, "mv otg enable error %d\n", retval); | ||
786 | goto err_unmap_capreg; | ||
787 | } | ||
788 | |||
789 | mvotg->op_regs = | ||
790 | (struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs | ||
791 | + (readl(mvotg->cap_regs) & CAPLENGTH_MASK)); | ||
792 | |||
793 | if (pdata->id) { | ||
794 | retval = request_threaded_irq(pdata->id->irq, NULL, | ||
795 | mv_otg_inputs_irq, | ||
796 | IRQF_ONESHOT, "id", mvotg); | ||
797 | if (retval) { | ||
798 | dev_info(&pdev->dev, | ||
799 | "Failed to request irq for ID\n"); | ||
800 | pdata->id = NULL; | ||
801 | } | ||
802 | } | ||
803 | |||
804 | if (pdata->vbus) { | ||
805 | mvotg->clock_gating = 1; | ||
806 | retval = request_threaded_irq(pdata->vbus->irq, NULL, | ||
807 | mv_otg_inputs_irq, | ||
808 | IRQF_ONESHOT, "vbus", mvotg); | ||
809 | if (retval) { | ||
810 | dev_info(&pdev->dev, | ||
811 | "Failed to request irq for VBUS, " | ||
812 | "disable clock gating\n"); | ||
813 | mvotg->clock_gating = 0; | ||
814 | pdata->vbus = NULL; | ||
815 | } | ||
816 | } | ||
817 | |||
818 | if (pdata->disable_otg_clock_gating) | ||
819 | mvotg->clock_gating = 0; | ||
820 | |||
821 | mv_otg_reset(mvotg); | ||
822 | mv_otg_init_irq(mvotg); | ||
823 | |||
824 | r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0); | ||
825 | if (r == NULL) { | ||
826 | dev_err(&pdev->dev, "no IRQ resource defined\n"); | ||
827 | retval = -ENODEV; | ||
828 | goto err_disable_clk; | ||
829 | } | ||
830 | |||
831 | mvotg->irq = r->start; | ||
832 | if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED, | ||
833 | driver_name, mvotg)) { | ||
834 | dev_err(&pdev->dev, "Request irq %d for OTG failed\n", | ||
835 | mvotg->irq); | ||
836 | mvotg->irq = 0; | ||
837 | retval = -ENODEV; | ||
838 | goto err_disable_clk; | ||
839 | } | ||
840 | |||
841 | retval = otg_set_transceiver(&mvotg->otg); | ||
842 | if (retval < 0) { | ||
843 | dev_err(&pdev->dev, "can't register transceiver, %d\n", | ||
844 | retval); | ||
845 | goto err_free_irq; | ||
846 | } | ||
847 | |||
848 | retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group); | ||
849 | if (retval < 0) { | ||
850 | dev_dbg(&pdev->dev, | ||
851 | "Can't register sysfs attr group: %d\n", retval); | ||
852 | goto err_set_transceiver; | ||
853 | } | ||
854 | |||
855 | spin_lock_init(&mvotg->wq_lock); | ||
856 | if (spin_trylock(&mvotg->wq_lock)) { | ||
857 | mv_otg_run_state_machine(mvotg, 2 * HZ); | ||
858 | spin_unlock(&mvotg->wq_lock); | ||
859 | } | ||
860 | |||
861 | dev_info(&pdev->dev, | ||
862 | "successful probe OTG device %s clock gating.\n", | ||
863 | mvotg->clock_gating ? "with" : "without"); | ||
864 | |||
865 | return 0; | ||
866 | |||
867 | err_set_transceiver: | ||
868 | otg_set_transceiver(NULL); | ||
869 | err_free_irq: | ||
870 | free_irq(mvotg->irq, mvotg); | ||
871 | err_disable_clk: | ||
872 | if (pdata->vbus) | ||
873 | free_irq(pdata->vbus->irq, mvotg); | ||
874 | if (pdata->id) | ||
875 | free_irq(pdata->id->irq, mvotg); | ||
876 | mv_otg_disable_internal(mvotg); | ||
877 | err_unmap_capreg: | ||
878 | iounmap(mvotg->cap_regs); | ||
879 | err_unmap_phyreg: | ||
880 | iounmap(mvotg->phy_regs); | ||
881 | err_destroy_workqueue: | ||
882 | flush_workqueue(mvotg->qwork); | ||
883 | destroy_workqueue(mvotg->qwork); | ||
884 | err_put_clk: | ||
885 | for (clk_i--; clk_i >= 0; clk_i--) | ||
886 | clk_put(mvotg->clk[clk_i]); | ||
887 | |||
888 | platform_set_drvdata(pdev, NULL); | ||
889 | kfree(mvotg); | ||
890 | |||
891 | return retval; | ||
892 | } | ||
893 | |||
894 | #ifdef CONFIG_PM | ||
895 | static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state) | ||
896 | { | ||
897 | struct mv_otg *mvotg = platform_get_drvdata(pdev); | ||
898 | |||
899 | if (mvotg->otg.state != OTG_STATE_B_IDLE) { | ||
900 | dev_info(&pdev->dev, | ||
901 | "OTG state is not B_IDLE, it is %d!\n", | ||
902 | mvotg->otg.state); | ||
903 | return -EAGAIN; | ||
904 | } | ||
905 | |||
906 | if (!mvotg->clock_gating) | ||
907 | mv_otg_disable_internal(mvotg); | ||
908 | |||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | static int mv_otg_resume(struct platform_device *pdev) | ||
913 | { | ||
914 | struct mv_otg *mvotg = platform_get_drvdata(pdev); | ||
915 | u32 otgsc; | ||
916 | |||
917 | if (!mvotg->clock_gating) { | ||
918 | mv_otg_enable_internal(mvotg); | ||
919 | |||
920 | otgsc = readl(&mvotg->op_regs->otgsc); | ||
921 | otgsc |= mvotg->irq_en; | ||
922 | writel(otgsc, &mvotg->op_regs->otgsc); | ||
923 | |||
924 | if (spin_trylock(&mvotg->wq_lock)) { | ||
925 | mv_otg_run_state_machine(mvotg, 0); | ||
926 | spin_unlock(&mvotg->wq_lock); | ||
927 | } | ||
928 | } | ||
929 | return 0; | ||
930 | } | ||
931 | #endif | ||
932 | |||
933 | static struct platform_driver mv_otg_driver = { | ||
934 | .probe = mv_otg_probe, | ||
935 | .remove = __exit_p(mv_otg_remove), | ||
936 | .driver = { | ||
937 | .owner = THIS_MODULE, | ||
938 | .name = driver_name, | ||
939 | }, | ||
940 | #ifdef CONFIG_PM | ||
941 | .suspend = mv_otg_suspend, | ||
942 | .resume = mv_otg_resume, | ||
943 | #endif | ||
944 | }; | ||
945 | |||
946 | static int __init mv_otg_init(void) | ||
947 | { | ||
948 | return platform_driver_register(&mv_otg_driver); | ||
949 | } | ||
950 | |||
951 | static void __exit mv_otg_exit(void) | ||
952 | { | ||
953 | platform_driver_unregister(&mv_otg_driver); | ||
954 | } | ||
955 | |||
956 | module_init(mv_otg_init); | ||
957 | module_exit(mv_otg_exit); | ||
diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/otg/mv_otg.h new file mode 100644 index 000000000000..be6ca1437645 --- /dev/null +++ b/drivers/usb/otg/mv_otg.h | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Marvell International Ltd. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef __MV_USB_OTG_CONTROLLER__ | ||
11 | #define __MV_USB_OTG_CONTROLLER__ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | |||
15 | /* Command Register Bit Masks */ | ||
16 | #define USBCMD_RUN_STOP (0x00000001) | ||
17 | #define USBCMD_CTRL_RESET (0x00000002) | ||
18 | |||
19 | /* otgsc Register Bit Masks */ | ||
20 | #define OTGSC_CTRL_VUSB_DISCHARGE 0x00000001 | ||
21 | #define OTGSC_CTRL_VUSB_CHARGE 0x00000002 | ||
22 | #define OTGSC_CTRL_OTG_TERM 0x00000008 | ||
23 | #define OTGSC_CTRL_DATA_PULSING 0x00000010 | ||
24 | #define OTGSC_STS_USB_ID 0x00000100 | ||
25 | #define OTGSC_STS_A_VBUS_VALID 0x00000200 | ||
26 | #define OTGSC_STS_A_SESSION_VALID 0x00000400 | ||
27 | #define OTGSC_STS_B_SESSION_VALID 0x00000800 | ||
28 | #define OTGSC_STS_B_SESSION_END 0x00001000 | ||
29 | #define OTGSC_STS_1MS_TOGGLE 0x00002000 | ||
30 | #define OTGSC_STS_DATA_PULSING 0x00004000 | ||
31 | #define OTGSC_INTSTS_USB_ID 0x00010000 | ||
32 | #define OTGSC_INTSTS_A_VBUS_VALID 0x00020000 | ||
33 | #define OTGSC_INTSTS_A_SESSION_VALID 0x00040000 | ||
34 | #define OTGSC_INTSTS_B_SESSION_VALID 0x00080000 | ||
35 | #define OTGSC_INTSTS_B_SESSION_END 0x00100000 | ||
36 | #define OTGSC_INTSTS_1MS 0x00200000 | ||
37 | #define OTGSC_INTSTS_DATA_PULSING 0x00400000 | ||
38 | #define OTGSC_INTR_USB_ID 0x01000000 | ||
39 | #define OTGSC_INTR_A_VBUS_VALID 0x02000000 | ||
40 | #define OTGSC_INTR_A_SESSION_VALID 0x04000000 | ||
41 | #define OTGSC_INTR_B_SESSION_VALID 0x08000000 | ||
42 | #define OTGSC_INTR_B_SESSION_END 0x10000000 | ||
43 | #define OTGSC_INTR_1MS_TIMER 0x20000000 | ||
44 | #define OTGSC_INTR_DATA_PULSING 0x40000000 | ||
45 | |||
46 | #define CAPLENGTH_MASK (0xff) | ||
47 | |||
48 | /* Timer's interval, unit 10ms */ | ||
49 | #define T_A_WAIT_VRISE 100 | ||
50 | #define T_A_WAIT_BCON 2000 | ||
51 | #define T_A_AIDL_BDIS 100 | ||
52 | #define T_A_BIDL_ADIS 20 | ||
53 | #define T_B_ASE0_BRST 400 | ||
54 | #define T_B_SE0_SRP 300 | ||
55 | #define T_B_SRP_FAIL 2000 | ||
56 | #define T_B_DATA_PLS 10 | ||
57 | #define T_B_SRP_INIT 100 | ||
58 | #define T_A_SRP_RSPNS 10 | ||
59 | #define T_A_DRV_RSM 5 | ||
60 | |||
61 | enum otg_function { | ||
62 | OTG_B_DEVICE = 0, | ||
63 | OTG_A_DEVICE | ||
64 | }; | ||
65 | |||
66 | enum mv_otg_timer { | ||
67 | A_WAIT_BCON_TIMER = 0, | ||
68 | OTG_TIMER_NUM | ||
69 | }; | ||
70 | |||
71 | /* PXA OTG state machine */ | ||
72 | struct mv_otg_ctrl { | ||
73 | /* internal variables */ | ||
74 | u8 a_set_b_hnp_en; /* A-Device set b_hnp_en */ | ||
75 | u8 b_srp_done; | ||
76 | u8 b_hnp_en; | ||
77 | |||
78 | /* OTG inputs */ | ||
79 | u8 a_bus_drop; | ||
80 | u8 a_bus_req; | ||
81 | u8 a_clr_err; | ||
82 | u8 a_bus_resume; | ||
83 | u8 a_bus_suspend; | ||
84 | u8 a_conn; | ||
85 | u8 a_sess_vld; | ||
86 | u8 a_srp_det; | ||
87 | u8 a_vbus_vld; | ||
88 | u8 b_bus_req; /* B-Device Require Bus */ | ||
89 | u8 b_bus_resume; | ||
90 | u8 b_bus_suspend; | ||
91 | u8 b_conn; | ||
92 | u8 b_se0_srp; | ||
93 | u8 b_sess_end; | ||
94 | u8 b_sess_vld; | ||
95 | u8 id; | ||
96 | u8 a_suspend_req; | ||
97 | |||
98 | /*Timer event */ | ||
99 | u8 a_aidl_bdis_timeout; | ||
100 | u8 b_ase0_brst_timeout; | ||
101 | u8 a_bidl_adis_timeout; | ||
102 | u8 a_wait_bcon_timeout; | ||
103 | |||
104 | struct timer_list timer[OTG_TIMER_NUM]; | ||
105 | }; | ||
106 | |||
107 | #define VUSBHS_MAX_PORTS 8 | ||
108 | |||
109 | struct mv_otg_regs { | ||
110 | u32 usbcmd; /* Command register */ | ||
111 | u32 usbsts; /* Status register */ | ||
112 | u32 usbintr; /* Interrupt enable */ | ||
113 | u32 frindex; /* Frame index */ | ||
114 | u32 reserved1[1]; | ||
115 | u32 deviceaddr; /* Device Address */ | ||
116 | u32 eplistaddr; /* Endpoint List Address */ | ||
117 | u32 ttctrl; /* HOST TT status and control */ | ||
118 | u32 burstsize; /* Programmable Burst Size */ | ||
119 | u32 txfilltuning; /* Host Transmit Pre-Buffer Packet Tuning */ | ||
120 | u32 reserved[4]; | ||
121 | u32 epnak; /* Endpoint NAK */ | ||
122 | u32 epnaken; /* Endpoint NAK Enable */ | ||
123 | u32 configflag; /* Configured Flag register */ | ||
124 | u32 portsc[VUSBHS_MAX_PORTS]; /* Port Status/Control x, x = 1..8 */ | ||
125 | u32 otgsc; | ||
126 | u32 usbmode; /* USB Host/Device mode */ | ||
127 | u32 epsetupstat; /* Endpoint Setup Status */ | ||
128 | u32 epprime; /* Endpoint Initialize */ | ||
129 | u32 epflush; /* Endpoint De-initialize */ | ||
130 | u32 epstatus; /* Endpoint Status */ | ||
131 | u32 epcomplete; /* Endpoint Interrupt On Complete */ | ||
132 | u32 epctrlx[16]; /* Endpoint Control, where x = 0.. 15 */ | ||
133 | u32 mcr; /* Mux Control */ | ||
134 | u32 isr; /* Interrupt Status */ | ||
135 | u32 ier; /* Interrupt Enable */ | ||
136 | }; | ||
137 | |||
138 | struct mv_otg { | ||
139 | struct otg_transceiver otg; | ||
140 | struct mv_otg_ctrl otg_ctrl; | ||
141 | |||
142 | /* base address */ | ||
143 | void __iomem *phy_regs; | ||
144 | void __iomem *cap_regs; | ||
145 | struct mv_otg_regs __iomem *op_regs; | ||
146 | |||
147 | struct platform_device *pdev; | ||
148 | int irq; | ||
149 | u32 irq_status; | ||
150 | u32 irq_en; | ||
151 | |||
152 | struct delayed_work work; | ||
153 | struct workqueue_struct *qwork; | ||
154 | |||
155 | spinlock_t wq_lock; | ||
156 | |||
157 | struct mv_usb_platform_data *pdata; | ||
158 | |||
159 | unsigned int active; | ||
160 | unsigned int clock_gating; | ||
161 | unsigned int clknum; | ||
162 | struct clk *clk[0]; | ||
163 | }; | ||
164 | |||
165 | #endif | ||