diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-19 08:50:26 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-19 08:50:38 -0400 |
commit | 50ee9339c7347c2b16fa79d43777f72e9f41ef5a (patch) | |
tree | ce09aa147e5c8bb74c72c46cebfdbffeece6678f /drivers/usb | |
parent | f0e615c3cb72b42191b558c130409335812621d8 (diff) | |
parent | 98346f7db014614a4814eb60639f651f8bbc591d (diff) |
Merge 2.6.39-rc4 into usb-next
This is needed to help resolve some xhci issues and other minor
differences.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
39 files changed, 4277 insertions, 650 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 006489d82dc3..a1b3750cadb3 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -65,6 +65,7 @@ config USB_ARCH_HAS_EHCI | |||
65 | default y if ARCH_CNS3XXX | 65 | default y if ARCH_CNS3XXX |
66 | default y if ARCH_VT8500 | 66 | default y if ARCH_VT8500 |
67 | default y if PLAT_SPEAR | 67 | default y if PLAT_SPEAR |
68 | default y if PLAT_S5P | ||
68 | default y if ARCH_MSM | 69 | default y if ARCH_MSM |
69 | default y if MICROBLAZE | 70 | default y if MICROBLAZE |
70 | default PCI | 71 | default PCI |
@@ -116,6 +117,8 @@ source "drivers/usb/host/Kconfig" | |||
116 | 117 | ||
117 | source "drivers/usb/musb/Kconfig" | 118 | source "drivers/usb/musb/Kconfig" |
118 | 119 | ||
120 | source "drivers/usb/renesas_usbhs/Kconfig" | ||
121 | |||
119 | source "drivers/usb/class/Kconfig" | 122 | source "drivers/usb/class/Kconfig" |
120 | 123 | ||
121 | source "drivers/usb/storage/Kconfig" | 124 | source "drivers/usb/storage/Kconfig" |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 239f050efa35..9bc8aeb3c96f 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -45,3 +45,8 @@ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ | |||
45 | 45 | ||
46 | obj-$(CONFIG_USB_ATM) += atm/ | 46 | obj-$(CONFIG_USB_ATM) += atm/ |
47 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ | 47 | obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ |
48 | |||
49 | obj-$(CONFIG_USB_MUSB_HDRC) += musb/ | ||
50 | obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/ | ||
51 | obj-$(CONFIG_USB_OTG_UTILS) += otg/ | ||
52 | obj-$(CONFIG_USB_GADGET) += gadget/ | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e057e5381465..58754b508a0f 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -7,35 +7,12 @@ | |||
7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> |
8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> | 8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> |
9 | * Copyright (c) 2005 David Kubicek <dave@awk.cz> | 9 | * Copyright (c) 2005 David Kubicek <dave@awk.cz> |
10 | * Copyright (c) 2011 Johan Hovold <jhovold@gmail.com> | ||
10 | * | 11 | * |
11 | * USB Abstract Control Model driver for USB modems and ISDN adapters | 12 | * USB Abstract Control Model driver for USB modems and ISDN adapters |
12 | * | 13 | * |
13 | * Sponsored by SuSE | 14 | * Sponsored by SuSE |
14 | * | 15 | * |
15 | * ChangeLog: | ||
16 | * v0.9 - thorough cleaning, URBification, almost a rewrite | ||
17 | * v0.10 - some more cleanups | ||
18 | * v0.11 - fixed flow control, read error doesn't stop reads | ||
19 | * v0.12 - added TIOCM ioctls, added break handling, made struct acm | ||
20 | * kmalloced | ||
21 | * v0.13 - added termios, added hangup | ||
22 | * v0.14 - sized down struct acm | ||
23 | * v0.15 - fixed flow control again - characters could be lost | ||
24 | * v0.16 - added code for modems with swapped data and control interfaces | ||
25 | * v0.17 - added new style probing | ||
26 | * v0.18 - fixed new style probing for devices with more configurations | ||
27 | * v0.19 - fixed CLOCAL handling (thanks to Richard Shih-Ping Chan) | ||
28 | * v0.20 - switched to probing on interface (rather than device) class | ||
29 | * v0.21 - revert to probing on device for devices with multiple configs | ||
30 | * v0.22 - probe only the control interface. if usbcore doesn't choose the | ||
31 | * config we want, sysadmin changes bConfigurationValue in sysfs. | ||
32 | * v0.23 - use softirq for rx processing, as needed by tty layer | ||
33 | * v0.24 - change probe method to evaluate CDC union descriptor | ||
34 | * v0.25 - downstream tasks paralelized to maximize throughput | ||
35 | * v0.26 - multiple write urbs, writesize increased | ||
36 | */ | ||
37 | |||
38 | /* | ||
39 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
40 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
41 | * the Free Software Foundation; either version 2 of the License, or | 18 | * the Free Software Foundation; either version 2 of the License, or |
@@ -74,13 +51,7 @@ | |||
74 | #include "cdc-acm.h" | 51 | #include "cdc-acm.h" |
75 | 52 | ||
76 | 53 | ||
77 | #define ACM_CLOSE_TIMEOUT 15 /* seconds to let writes drain */ | 54 | #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek, Johan Hovold" |
78 | |||
79 | /* | ||
80 | * Version Information | ||
81 | */ | ||
82 | #define DRIVER_VERSION "v0.26" | ||
83 | #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" | ||
84 | #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" | 55 | #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" |
85 | 56 | ||
86 | static struct usb_driver acm_driver; | 57 | static struct usb_driver acm_driver; |
@@ -94,12 +65,6 @@ static DEFINE_MUTEX(open_mutex); | |||
94 | static const struct tty_port_operations acm_port_ops = { | 65 | static const struct tty_port_operations acm_port_ops = { |
95 | }; | 66 | }; |
96 | 67 | ||
97 | #ifdef VERBOSE_DEBUG | ||
98 | #define verbose 1 | ||
99 | #else | ||
100 | #define verbose 0 | ||
101 | #endif | ||
102 | |||
103 | /* | 68 | /* |
104 | * Functions for ACM control messages. | 69 | * Functions for ACM control messages. |
105 | */ | 70 | */ |
@@ -111,8 +76,9 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value, | |||
111 | request, USB_RT_ACM, value, | 76 | request, USB_RT_ACM, value, |
112 | acm->control->altsetting[0].desc.bInterfaceNumber, | 77 | acm->control->altsetting[0].desc.bInterfaceNumber, |
113 | buf, len, 5000); | 78 | buf, len, 5000); |
114 | dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", | 79 | dev_dbg(&acm->control->dev, |
115 | request, value, len, retval); | 80 | "%s - rq 0x%02x, val %#x, len %#x, result %d\n", |
81 | __func__, request, value, len, retval); | ||
116 | return retval < 0 ? retval : 0; | 82 | return retval < 0 ? retval : 0; |
117 | } | 83 | } |
118 | 84 | ||
@@ -192,7 +158,9 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) | |||
192 | 158 | ||
193 | rc = usb_submit_urb(wb->urb, GFP_ATOMIC); | 159 | rc = usb_submit_urb(wb->urb, GFP_ATOMIC); |
194 | if (rc < 0) { | 160 | if (rc < 0) { |
195 | dbg("usb_submit_urb(write bulk) failed: %d", rc); | 161 | dev_err(&acm->data->dev, |
162 | "%s - usb_submit_urb(write bulk) failed: %d\n", | ||
163 | __func__, rc); | ||
196 | acm_write_done(acm, wb); | 164 | acm_write_done(acm, wb); |
197 | } | 165 | } |
198 | return rc; | 166 | return rc; |
@@ -211,7 +179,8 @@ static int acm_write_start(struct acm *acm, int wbn) | |||
211 | return -ENODEV; | 179 | return -ENODEV; |
212 | } | 180 | } |
213 | 181 | ||
214 | dbg("%s susp_count: %d", __func__, acm->susp_count); | 182 | dev_vdbg(&acm->data->dev, "%s - susp_count %d\n", __func__, |
183 | acm->susp_count); | ||
215 | usb_autopm_get_interface_async(acm->control); | 184 | usb_autopm_get_interface_async(acm->control); |
216 | if (acm->susp_count) { | 185 | if (acm->susp_count) { |
217 | if (!acm->delayed_wb) | 186 | if (!acm->delayed_wb) |
@@ -287,10 +256,14 @@ static void acm_ctrl_irq(struct urb *urb) | |||
287 | case -ENOENT: | 256 | case -ENOENT: |
288 | case -ESHUTDOWN: | 257 | case -ESHUTDOWN: |
289 | /* this urb is terminated, clean up */ | 258 | /* this urb is terminated, clean up */ |
290 | dbg("%s - urb shutting down with status: %d", __func__, status); | 259 | dev_dbg(&acm->control->dev, |
260 | "%s - urb shutting down with status: %d\n", | ||
261 | __func__, status); | ||
291 | return; | 262 | return; |
292 | default: | 263 | default: |
293 | dbg("%s - nonzero urb status received: %d", __func__, status); | 264 | dev_dbg(&acm->control->dev, |
265 | "%s - nonzero urb status received: %d\n", | ||
266 | __func__, status); | ||
294 | goto exit; | 267 | goto exit; |
295 | } | 268 | } |
296 | 269 | ||
@@ -302,8 +275,8 @@ static void acm_ctrl_irq(struct urb *urb) | |||
302 | data = (unsigned char *)(dr + 1); | 275 | data = (unsigned char *)(dr + 1); |
303 | switch (dr->bNotificationType) { | 276 | switch (dr->bNotificationType) { |
304 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | 277 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: |
305 | dbg("%s network", dr->wValue ? | 278 | dev_dbg(&acm->control->dev, "%s - network connection: %d\n", |
306 | "connected to" : "disconnected from"); | 279 | __func__, dr->wValue); |
307 | break; | 280 | break; |
308 | 281 | ||
309 | case USB_CDC_NOTIFY_SERIAL_STATE: | 282 | case USB_CDC_NOTIFY_SERIAL_STATE: |
@@ -313,7 +286,8 @@ static void acm_ctrl_irq(struct urb *urb) | |||
313 | if (tty) { | 286 | if (tty) { |
314 | if (!acm->clocal && | 287 | if (!acm->clocal && |
315 | (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { | 288 | (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { |
316 | dbg("calling hangup"); | 289 | dev_dbg(&acm->control->dev, |
290 | "%s - calling hangup\n", __func__); | ||
317 | tty_hangup(tty); | 291 | tty_hangup(tty); |
318 | } | 292 | } |
319 | tty_kref_put(tty); | 293 | tty_kref_put(tty); |
@@ -321,7 +295,10 @@ static void acm_ctrl_irq(struct urb *urb) | |||
321 | 295 | ||
322 | acm->ctrlin = newctrl; | 296 | acm->ctrlin = newctrl; |
323 | 297 | ||
324 | dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c", | 298 | dev_dbg(&acm->control->dev, |
299 | "%s - input control lines: dcd%c dsr%c break%c " | ||
300 | "ring%c framing%c parity%c overrun%c\n", | ||
301 | __func__, | ||
325 | acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', | 302 | acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', |
326 | acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', | 303 | acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', |
327 | acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', | 304 | acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', |
@@ -332,7 +309,10 @@ static void acm_ctrl_irq(struct urb *urb) | |||
332 | break; | 309 | break; |
333 | 310 | ||
334 | default: | 311 | default: |
335 | dbg("unknown notification %d received: index %d len %d data0 %d data1 %d", | 312 | dev_dbg(&acm->control->dev, |
313 | "%s - unknown notification %d received: index %d " | ||
314 | "len %d data0 %d data1 %d\n", | ||
315 | __func__, | ||
336 | dr->bNotificationType, dr->wIndex, | 316 | dr->bNotificationType, dr->wIndex, |
337 | dr->wLength, data[0], data[1]); | 317 | dr->wLength, data[0], data[1]); |
338 | break; | 318 | break; |
@@ -340,166 +320,96 @@ static void acm_ctrl_irq(struct urb *urb) | |||
340 | exit: | 320 | exit: |
341 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 321 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
342 | if (retval) | 322 | if (retval) |
343 | dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " | 323 | dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n", |
344 | "result %d", __func__, retval); | 324 | __func__, retval); |
345 | } | 325 | } |
346 | 326 | ||
347 | /* data interface returns incoming bytes, or we got unthrottled */ | 327 | static int acm_submit_read_urb(struct acm *acm, int index, gfp_t mem_flags) |
348 | static void acm_read_bulk(struct urb *urb) | ||
349 | { | 328 | { |
350 | struct acm_rb *buf; | 329 | int res; |
351 | struct acm_ru *rcv = urb->context; | 330 | |
352 | struct acm *acm = rcv->instance; | 331 | if (!test_and_clear_bit(index, &acm->read_urbs_free)) |
353 | int status = urb->status; | 332 | return 0; |
354 | 333 | ||
355 | dbg("Entering acm_read_bulk with status %d", status); | 334 | dev_vdbg(&acm->data->dev, "%s - urb %d\n", __func__, index); |
356 | 335 | ||
357 | if (!ACM_READY(acm)) { | 336 | res = usb_submit_urb(acm->read_urbs[index], mem_flags); |
358 | dev_dbg(&acm->data->dev, "Aborting, acm not ready"); | 337 | if (res) { |
359 | return; | 338 | if (res != -EPERM) { |
339 | dev_err(&acm->data->dev, | ||
340 | "%s - usb_submit_urb failed: %d\n", | ||
341 | __func__, res); | ||
342 | } | ||
343 | set_bit(index, &acm->read_urbs_free); | ||
344 | return res; | ||
360 | } | 345 | } |
361 | usb_mark_last_busy(acm->dev); | ||
362 | 346 | ||
363 | if (status) | 347 | return 0; |
364 | dev_dbg(&acm->data->dev, "bulk rx status %d\n", status); | 348 | } |
365 | 349 | ||
366 | buf = rcv->buffer; | 350 | static int acm_submit_read_urbs(struct acm *acm, gfp_t mem_flags) |
367 | buf->size = urb->actual_length; | 351 | { |
352 | int res; | ||
353 | int i; | ||
368 | 354 | ||
369 | if (likely(status == 0)) { | 355 | for (i = 0; i < acm->rx_buflimit; ++i) { |
370 | spin_lock(&acm->read_lock); | 356 | res = acm_submit_read_urb(acm, i, mem_flags); |
371 | acm->processing++; | 357 | if (res) |
372 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | 358 | return res; |
373 | list_add_tail(&buf->list, &acm->filled_read_bufs); | ||
374 | spin_unlock(&acm->read_lock); | ||
375 | } else { | ||
376 | /* we drop the buffer due to an error */ | ||
377 | spin_lock(&acm->read_lock); | ||
378 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | ||
379 | list_add(&buf->list, &acm->spare_read_bufs); | ||
380 | spin_unlock(&acm->read_lock); | ||
381 | /* nevertheless the tasklet must be kicked unconditionally | ||
382 | so the queue cannot dry up */ | ||
383 | } | 359 | } |
384 | if (likely(!acm->susp_count)) | 360 | |
385 | tasklet_schedule(&acm->urb_task); | 361 | return 0; |
386 | } | 362 | } |
387 | 363 | ||
388 | static void acm_rx_tasklet(unsigned long _acm) | 364 | static void acm_process_read_urb(struct acm *acm, struct urb *urb) |
389 | { | 365 | { |
390 | struct acm *acm = (void *)_acm; | ||
391 | struct acm_rb *buf; | ||
392 | struct tty_struct *tty; | 366 | struct tty_struct *tty; |
393 | struct acm_ru *rcv; | ||
394 | unsigned long flags; | ||
395 | unsigned char throttled; | ||
396 | |||
397 | dbg("Entering acm_rx_tasklet"); | ||
398 | 367 | ||
399 | if (!ACM_READY(acm)) { | 368 | if (!urb->actual_length) |
400 | dbg("acm_rx_tasklet: ACM not ready"); | ||
401 | return; | 369 | return; |
402 | } | ||
403 | |||
404 | spin_lock_irqsave(&acm->throttle_lock, flags); | ||
405 | throttled = acm->throttle; | ||
406 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | ||
407 | if (throttled) { | ||
408 | dbg("acm_rx_tasklet: throttled"); | ||
409 | return; | ||
410 | } | ||
411 | 370 | ||
412 | tty = tty_port_tty_get(&acm->port); | 371 | tty = tty_port_tty_get(&acm->port); |
372 | if (!tty) | ||
373 | return; | ||
413 | 374 | ||
414 | next_buffer: | 375 | tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); |
415 | spin_lock_irqsave(&acm->read_lock, flags); | 376 | tty_flip_buffer_push(tty); |
416 | if (list_empty(&acm->filled_read_bufs)) { | ||
417 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
418 | goto urbs; | ||
419 | } | ||
420 | buf = list_entry(acm->filled_read_bufs.next, | ||
421 | struct acm_rb, list); | ||
422 | list_del(&buf->list); | ||
423 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
424 | |||
425 | dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); | ||
426 | |||
427 | if (tty) { | ||
428 | spin_lock_irqsave(&acm->throttle_lock, flags); | ||
429 | throttled = acm->throttle; | ||
430 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | ||
431 | if (!throttled) { | ||
432 | tty_insert_flip_string(tty, buf->base, buf->size); | ||
433 | tty_flip_buffer_push(tty); | ||
434 | } else { | ||
435 | tty_kref_put(tty); | ||
436 | dbg("Throttling noticed"); | ||
437 | spin_lock_irqsave(&acm->read_lock, flags); | ||
438 | list_add(&buf->list, &acm->filled_read_bufs); | ||
439 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
440 | return; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | spin_lock_irqsave(&acm->read_lock, flags); | ||
445 | list_add(&buf->list, &acm->spare_read_bufs); | ||
446 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
447 | goto next_buffer; | ||
448 | 377 | ||
449 | urbs: | ||
450 | tty_kref_put(tty); | 378 | tty_kref_put(tty); |
379 | } | ||
451 | 380 | ||
452 | while (!list_empty(&acm->spare_read_bufs)) { | 381 | static void acm_read_bulk_callback(struct urb *urb) |
453 | spin_lock_irqsave(&acm->read_lock, flags); | 382 | { |
454 | if (list_empty(&acm->spare_read_urbs)) { | 383 | struct acm_rb *rb = urb->context; |
455 | acm->processing = 0; | 384 | struct acm *acm = rb->instance; |
456 | spin_unlock_irqrestore(&acm->read_lock, flags); | 385 | unsigned long flags; |
457 | return; | ||
458 | } | ||
459 | rcv = list_entry(acm->spare_read_urbs.next, | ||
460 | struct acm_ru, list); | ||
461 | list_del(&rcv->list); | ||
462 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
463 | 386 | ||
464 | buf = list_entry(acm->spare_read_bufs.next, | 387 | dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__, |
465 | struct acm_rb, list); | 388 | rb->index, urb->actual_length); |
466 | list_del(&buf->list); | 389 | set_bit(rb->index, &acm->read_urbs_free); |
467 | 390 | ||
468 | rcv->buffer = buf; | 391 | if (!acm->dev) { |
392 | dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); | ||
393 | return; | ||
394 | } | ||
395 | usb_mark_last_busy(acm->dev); | ||
469 | 396 | ||
470 | if (acm->is_int_ep) | 397 | if (urb->status) { |
471 | usb_fill_int_urb(rcv->urb, acm->dev, | 398 | dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", |
472 | acm->rx_endpoint, | 399 | __func__, urb->status); |
473 | buf->base, | 400 | return; |
474 | acm->readsize, | ||
475 | acm_read_bulk, rcv, acm->bInterval); | ||
476 | else | ||
477 | usb_fill_bulk_urb(rcv->urb, acm->dev, | ||
478 | acm->rx_endpoint, | ||
479 | buf->base, | ||
480 | acm->readsize, | ||
481 | acm_read_bulk, rcv); | ||
482 | rcv->urb->transfer_dma = buf->dma; | ||
483 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
484 | |||
485 | /* This shouldn't kill the driver as unsuccessful URBs are | ||
486 | returned to the free-urbs-pool and resubmited ASAP */ | ||
487 | spin_lock_irqsave(&acm->read_lock, flags); | ||
488 | if (acm->susp_count || | ||
489 | usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { | ||
490 | list_add(&buf->list, &acm->spare_read_bufs); | ||
491 | list_add(&rcv->list, &acm->spare_read_urbs); | ||
492 | acm->processing = 0; | ||
493 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
494 | return; | ||
495 | } else { | ||
496 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
497 | dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf); | ||
498 | } | ||
499 | } | 401 | } |
402 | acm_process_read_urb(acm, urb); | ||
403 | |||
404 | /* throttle device if requested by tty */ | ||
500 | spin_lock_irqsave(&acm->read_lock, flags); | 405 | spin_lock_irqsave(&acm->read_lock, flags); |
501 | acm->processing = 0; | 406 | acm->throttled = acm->throttle_req; |
502 | spin_unlock_irqrestore(&acm->read_lock, flags); | 407 | if (!acm->throttled && !acm->susp_count) { |
408 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
409 | acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); | ||
410 | } else { | ||
411 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
412 | } | ||
503 | } | 413 | } |
504 | 414 | ||
505 | /* data interface wrote those outgoing bytes */ | 415 | /* data interface wrote those outgoing bytes */ |
@@ -509,9 +419,9 @@ static void acm_write_bulk(struct urb *urb) | |||
509 | struct acm *acm = wb->instance; | 419 | struct acm *acm = wb->instance; |
510 | unsigned long flags; | 420 | unsigned long flags; |
511 | 421 | ||
512 | if (verbose || urb->status | 422 | if (urb->status || (urb->actual_length != urb->transfer_buffer_length)) |
513 | || (urb->actual_length != urb->transfer_buffer_length)) | 423 | dev_vdbg(&acm->data->dev, "%s - len %d/%d, status %d\n", |
514 | dev_dbg(&acm->data->dev, "tx %d/%d bytes -- > %d\n", | 424 | __func__, |
515 | urb->actual_length, | 425 | urb->actual_length, |
516 | urb->transfer_buffer_length, | 426 | urb->transfer_buffer_length, |
517 | urb->status); | 427 | urb->status); |
@@ -521,8 +431,6 @@ static void acm_write_bulk(struct urb *urb) | |||
521 | spin_unlock_irqrestore(&acm->write_lock, flags); | 431 | spin_unlock_irqrestore(&acm->write_lock, flags); |
522 | if (ACM_READY(acm)) | 432 | if (ACM_READY(acm)) |
523 | schedule_work(&acm->work); | 433 | schedule_work(&acm->work); |
524 | else | ||
525 | wake_up_interruptible(&acm->drain_wait); | ||
526 | } | 434 | } |
527 | 435 | ||
528 | static void acm_softint(struct work_struct *work) | 436 | static void acm_softint(struct work_struct *work) |
@@ -530,7 +438,8 @@ static void acm_softint(struct work_struct *work) | |||
530 | struct acm *acm = container_of(work, struct acm, work); | 438 | struct acm *acm = container_of(work, struct acm, work); |
531 | struct tty_struct *tty; | 439 | struct tty_struct *tty; |
532 | 440 | ||
533 | dev_vdbg(&acm->data->dev, "tx work\n"); | 441 | dev_vdbg(&acm->data->dev, "%s\n", __func__); |
442 | |||
534 | if (!ACM_READY(acm)) | 443 | if (!ACM_READY(acm)) |
535 | return; | 444 | return; |
536 | tty = tty_port_tty_get(&acm->port); | 445 | tty = tty_port_tty_get(&acm->port); |
@@ -548,8 +457,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
548 | { | 457 | { |
549 | struct acm *acm; | 458 | struct acm *acm; |
550 | int rv = -ENODEV; | 459 | int rv = -ENODEV; |
551 | int i; | ||
552 | dbg("Entering acm_tty_open."); | ||
553 | 460 | ||
554 | mutex_lock(&open_mutex); | 461 | mutex_lock(&open_mutex); |
555 | 462 | ||
@@ -559,6 +466,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
559 | else | 466 | else |
560 | rv = 0; | 467 | rv = 0; |
561 | 468 | ||
469 | dev_dbg(&acm->control->dev, "%s\n", __func__); | ||
470 | |||
562 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); | 471 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); |
563 | 472 | ||
564 | tty->driver_data = acm; | 473 | tty->driver_data = acm; |
@@ -578,38 +487,28 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
578 | 487 | ||
579 | acm->ctrlurb->dev = acm->dev; | 488 | acm->ctrlurb->dev = acm->dev; |
580 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { | 489 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { |
581 | dbg("usb_submit_urb(ctrl irq) failed"); | 490 | dev_err(&acm->control->dev, |
491 | "%s - usb_submit_urb(ctrl irq) failed\n", __func__); | ||
582 | goto bail_out; | 492 | goto bail_out; |
583 | } | 493 | } |
584 | 494 | ||
585 | if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && | 495 | if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && |
586 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) | 496 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) |
587 | goto full_bailout; | 497 | goto bail_out; |
588 | 498 | ||
589 | usb_autopm_put_interface(acm->control); | 499 | usb_autopm_put_interface(acm->control); |
590 | 500 | ||
591 | INIT_LIST_HEAD(&acm->spare_read_urbs); | 501 | if (acm_submit_read_urbs(acm, GFP_KERNEL)) |
592 | INIT_LIST_HEAD(&acm->spare_read_bufs); | 502 | goto bail_out; |
593 | INIT_LIST_HEAD(&acm->filled_read_bufs); | ||
594 | |||
595 | for (i = 0; i < acm->rx_buflimit; i++) | ||
596 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); | ||
597 | for (i = 0; i < acm->rx_buflimit; i++) | ||
598 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); | ||
599 | |||
600 | acm->throttle = 0; | ||
601 | 503 | ||
602 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); | 504 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); |
603 | rv = tty_port_block_til_ready(&acm->port, tty, filp); | 505 | rv = tty_port_block_til_ready(&acm->port, tty, filp); |
604 | tasklet_schedule(&acm->urb_task); | ||
605 | 506 | ||
606 | mutex_unlock(&acm->mutex); | 507 | mutex_unlock(&acm->mutex); |
607 | out: | 508 | out: |
608 | mutex_unlock(&open_mutex); | 509 | mutex_unlock(&open_mutex); |
609 | return rv; | 510 | return rv; |
610 | 511 | ||
611 | full_bailout: | ||
612 | usb_kill_urb(acm->ctrlurb); | ||
613 | bail_out: | 512 | bail_out: |
614 | acm->port.count--; | 513 | acm->port.count--; |
615 | mutex_unlock(&acm->mutex); | 514 | mutex_unlock(&acm->mutex); |
@@ -622,26 +521,24 @@ early_bail: | |||
622 | 521 | ||
623 | static void acm_tty_unregister(struct acm *acm) | 522 | static void acm_tty_unregister(struct acm *acm) |
624 | { | 523 | { |
625 | int i, nr; | 524 | int i; |
626 | 525 | ||
627 | nr = acm->rx_buflimit; | ||
628 | tty_unregister_device(acm_tty_driver, acm->minor); | 526 | tty_unregister_device(acm_tty_driver, acm->minor); |
629 | usb_put_intf(acm->control); | 527 | usb_put_intf(acm->control); |
630 | acm_table[acm->minor] = NULL; | 528 | acm_table[acm->minor] = NULL; |
631 | usb_free_urb(acm->ctrlurb); | 529 | usb_free_urb(acm->ctrlurb); |
632 | for (i = 0; i < ACM_NW; i++) | 530 | for (i = 0; i < ACM_NW; i++) |
633 | usb_free_urb(acm->wb[i].urb); | 531 | usb_free_urb(acm->wb[i].urb); |
634 | for (i = 0; i < nr; i++) | 532 | for (i = 0; i < acm->rx_buflimit; i++) |
635 | usb_free_urb(acm->ru[i].urb); | 533 | usb_free_urb(acm->read_urbs[i]); |
636 | kfree(acm->country_codes); | 534 | kfree(acm->country_codes); |
637 | kfree(acm); | 535 | kfree(acm); |
638 | } | 536 | } |
639 | 537 | ||
640 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); | ||
641 | |||
642 | static void acm_port_down(struct acm *acm) | 538 | static void acm_port_down(struct acm *acm) |
643 | { | 539 | { |
644 | int i, nr = acm->rx_buflimit; | 540 | int i; |
541 | |||
645 | mutex_lock(&open_mutex); | 542 | mutex_lock(&open_mutex); |
646 | if (acm->dev) { | 543 | if (acm->dev) { |
647 | usb_autopm_get_interface(acm->control); | 544 | usb_autopm_get_interface(acm->control); |
@@ -649,10 +546,8 @@ static void acm_port_down(struct acm *acm) | |||
649 | usb_kill_urb(acm->ctrlurb); | 546 | usb_kill_urb(acm->ctrlurb); |
650 | for (i = 0; i < ACM_NW; i++) | 547 | for (i = 0; i < ACM_NW; i++) |
651 | usb_kill_urb(acm->wb[i].urb); | 548 | usb_kill_urb(acm->wb[i].urb); |
652 | tasklet_disable(&acm->urb_task); | 549 | for (i = 0; i < acm->rx_buflimit; i++) |
653 | for (i = 0; i < nr; i++) | 550 | usb_kill_urb(acm->read_urbs[i]); |
654 | usb_kill_urb(acm->ru[i].urb); | ||
655 | tasklet_enable(&acm->urb_task); | ||
656 | acm->control->needs_remote_wakeup = 0; | 551 | acm->control->needs_remote_wakeup = 0; |
657 | usb_autopm_put_interface(acm->control); | 552 | usb_autopm_put_interface(acm->control); |
658 | } | 553 | } |
@@ -698,13 +593,13 @@ static int acm_tty_write(struct tty_struct *tty, | |||
698 | int wbn; | 593 | int wbn; |
699 | struct acm_wb *wb; | 594 | struct acm_wb *wb; |
700 | 595 | ||
701 | dbg("Entering acm_tty_write to write %d bytes,", count); | ||
702 | |||
703 | if (!ACM_READY(acm)) | 596 | if (!ACM_READY(acm)) |
704 | return -EINVAL; | 597 | return -EINVAL; |
705 | if (!count) | 598 | if (!count) |
706 | return 0; | 599 | return 0; |
707 | 600 | ||
601 | dev_vdbg(&acm->data->dev, "%s - count %d\n", __func__, count); | ||
602 | |||
708 | spin_lock_irqsave(&acm->write_lock, flags); | 603 | spin_lock_irqsave(&acm->write_lock, flags); |
709 | wbn = acm_wb_alloc(acm); | 604 | wbn = acm_wb_alloc(acm); |
710 | if (wbn < 0) { | 605 | if (wbn < 0) { |
@@ -714,7 +609,7 @@ static int acm_tty_write(struct tty_struct *tty, | |||
714 | wb = &acm->wb[wbn]; | 609 | wb = &acm->wb[wbn]; |
715 | 610 | ||
716 | count = (count > acm->writesize) ? acm->writesize : count; | 611 | count = (count > acm->writesize) ? acm->writesize : count; |
717 | dbg("Get %d bytes...", count); | 612 | dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count); |
718 | memcpy(wb->buf, buf, count); | 613 | memcpy(wb->buf, buf, count); |
719 | wb->len = count; | 614 | wb->len = count; |
720 | spin_unlock_irqrestore(&acm->write_lock, flags); | 615 | spin_unlock_irqrestore(&acm->write_lock, flags); |
@@ -751,22 +646,31 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty) | |||
751 | static void acm_tty_throttle(struct tty_struct *tty) | 646 | static void acm_tty_throttle(struct tty_struct *tty) |
752 | { | 647 | { |
753 | struct acm *acm = tty->driver_data; | 648 | struct acm *acm = tty->driver_data; |
649 | |||
754 | if (!ACM_READY(acm)) | 650 | if (!ACM_READY(acm)) |
755 | return; | 651 | return; |
756 | spin_lock_bh(&acm->throttle_lock); | 652 | |
757 | acm->throttle = 1; | 653 | spin_lock_irq(&acm->read_lock); |
758 | spin_unlock_bh(&acm->throttle_lock); | 654 | acm->throttle_req = 1; |
655 | spin_unlock_irq(&acm->read_lock); | ||
759 | } | 656 | } |
760 | 657 | ||
761 | static void acm_tty_unthrottle(struct tty_struct *tty) | 658 | static void acm_tty_unthrottle(struct tty_struct *tty) |
762 | { | 659 | { |
763 | struct acm *acm = tty->driver_data; | 660 | struct acm *acm = tty->driver_data; |
661 | unsigned int was_throttled; | ||
662 | |||
764 | if (!ACM_READY(acm)) | 663 | if (!ACM_READY(acm)) |
765 | return; | 664 | return; |
766 | spin_lock_bh(&acm->throttle_lock); | 665 | |
767 | acm->throttle = 0; | 666 | spin_lock_irq(&acm->read_lock); |
768 | spin_unlock_bh(&acm->throttle_lock); | 667 | was_throttled = acm->throttled; |
769 | tasklet_schedule(&acm->urb_task); | 668 | acm->throttled = 0; |
669 | acm->throttle_req = 0; | ||
670 | spin_unlock_irq(&acm->read_lock); | ||
671 | |||
672 | if (was_throttled) | ||
673 | acm_submit_read_urbs(acm, GFP_KERNEL); | ||
770 | } | 674 | } |
771 | 675 | ||
772 | static int acm_tty_break_ctl(struct tty_struct *tty, int state) | 676 | static int acm_tty_break_ctl(struct tty_struct *tty, int state) |
@@ -777,7 +681,8 @@ static int acm_tty_break_ctl(struct tty_struct *tty, int state) | |||
777 | return -EINVAL; | 681 | return -EINVAL; |
778 | retval = acm_send_break(acm, state ? 0xffff : 0); | 682 | retval = acm_send_break(acm, state ? 0xffff : 0); |
779 | if (retval < 0) | 683 | if (retval < 0) |
780 | dbg("send break failed"); | 684 | dev_dbg(&acm->control->dev, "%s - send break failed\n", |
685 | __func__); | ||
781 | return retval; | 686 | return retval; |
782 | } | 687 | } |
783 | 688 | ||
@@ -872,7 +777,9 @@ static void acm_tty_set_termios(struct tty_struct *tty, | |||
872 | 777 | ||
873 | if (memcmp(&acm->line, &newline, sizeof newline)) { | 778 | if (memcmp(&acm->line, &newline, sizeof newline)) { |
874 | memcpy(&acm->line, &newline, sizeof newline); | 779 | memcpy(&acm->line, &newline, sizeof newline); |
875 | dbg("set line: %d %d %d %d", le32_to_cpu(newline.dwDTERate), | 780 | dev_dbg(&acm->control->dev, "%s - set line: %d %d %d %d\n", |
781 | __func__, | ||
782 | le32_to_cpu(newline.dwDTERate), | ||
876 | newline.bCharFormat, newline.bParityType, | 783 | newline.bCharFormat, newline.bParityType, |
877 | newline.bDataBits); | 784 | newline.bDataBits); |
878 | acm_set_line(acm, &acm->line); | 785 | acm_set_line(acm, &acm->line); |
@@ -897,11 +804,11 @@ static void acm_write_buffers_free(struct acm *acm) | |||
897 | static void acm_read_buffers_free(struct acm *acm) | 804 | static void acm_read_buffers_free(struct acm *acm) |
898 | { | 805 | { |
899 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); | 806 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); |
900 | int i, n = acm->rx_buflimit; | 807 | int i; |
901 | 808 | ||
902 | for (i = 0; i < n; i++) | 809 | for (i = 0; i < acm->rx_buflimit; i++) |
903 | usb_free_coherent(usb_dev, acm->readsize, | 810 | usb_free_coherent(usb_dev, acm->readsize, |
904 | acm->rb[i].base, acm->rb[i].dma); | 811 | acm->read_buffers[i].base, acm->read_buffers[i].dma); |
905 | } | 812 | } |
906 | 813 | ||
907 | /* Little helper: write buffers allocate */ | 814 | /* Little helper: write buffers allocate */ |
@@ -1133,7 +1040,7 @@ skip_normal_probe: | |||
1133 | epwrite = t; | 1040 | epwrite = t; |
1134 | } | 1041 | } |
1135 | made_compressed_probe: | 1042 | made_compressed_probe: |
1136 | dbg("interfaces are valid"); | 1043 | dev_dbg(&intf->dev, "interfaces are valid\n"); |
1137 | for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); | 1044 | for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); |
1138 | 1045 | ||
1139 | if (minor == ACM_TTY_MINORS) { | 1046 | if (minor == ACM_TTY_MINORS) { |
@@ -1143,7 +1050,7 @@ made_compressed_probe: | |||
1143 | 1050 | ||
1144 | acm = kzalloc(sizeof(struct acm), GFP_KERNEL); | 1051 | acm = kzalloc(sizeof(struct acm), GFP_KERNEL); |
1145 | if (acm == NULL) { | 1052 | if (acm == NULL) { |
1146 | dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n"); | 1053 | dev_err(&intf->dev, "out of memory (acm kzalloc)\n"); |
1147 | goto alloc_fail; | 1054 | goto alloc_fail; |
1148 | } | 1055 | } |
1149 | 1056 | ||
@@ -1162,11 +1069,7 @@ made_compressed_probe: | |||
1162 | acm->ctrlsize = ctrlsize; | 1069 | acm->ctrlsize = ctrlsize; |
1163 | acm->readsize = readsize; | 1070 | acm->readsize = readsize; |
1164 | acm->rx_buflimit = num_rx_buf; | 1071 | acm->rx_buflimit = num_rx_buf; |
1165 | acm->urb_task.func = acm_rx_tasklet; | ||
1166 | acm->urb_task.data = (unsigned long) acm; | ||
1167 | INIT_WORK(&acm->work, acm_softint); | 1072 | INIT_WORK(&acm->work, acm_softint); |
1168 | init_waitqueue_head(&acm->drain_wait); | ||
1169 | spin_lock_init(&acm->throttle_lock); | ||
1170 | spin_lock_init(&acm->write_lock); | 1073 | spin_lock_init(&acm->write_lock); |
1171 | spin_lock_init(&acm->read_lock); | 1074 | spin_lock_init(&acm->read_lock); |
1172 | mutex_init(&acm->mutex); | 1075 | mutex_init(&acm->mutex); |
@@ -1179,53 +1082,69 @@ made_compressed_probe: | |||
1179 | 1082 | ||
1180 | buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); | 1083 | buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
1181 | if (!buf) { | 1084 | if (!buf) { |
1182 | dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n"); | 1085 | dev_err(&intf->dev, "out of memory (ctrl buffer alloc)\n"); |
1183 | goto alloc_fail2; | 1086 | goto alloc_fail2; |
1184 | } | 1087 | } |
1185 | acm->ctrl_buffer = buf; | 1088 | acm->ctrl_buffer = buf; |
1186 | 1089 | ||
1187 | if (acm_write_buffers_alloc(acm) < 0) { | 1090 | if (acm_write_buffers_alloc(acm) < 0) { |
1188 | dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); | 1091 | dev_err(&intf->dev, "out of memory (write buffer alloc)\n"); |
1189 | goto alloc_fail4; | 1092 | goto alloc_fail4; |
1190 | } | 1093 | } |
1191 | 1094 | ||
1192 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); | 1095 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); |
1193 | if (!acm->ctrlurb) { | 1096 | if (!acm->ctrlurb) { |
1194 | dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); | 1097 | dev_err(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); |
1195 | goto alloc_fail5; | 1098 | goto alloc_fail5; |
1196 | } | 1099 | } |
1197 | for (i = 0; i < num_rx_buf; i++) { | 1100 | for (i = 0; i < num_rx_buf; i++) { |
1198 | struct acm_ru *rcv = &(acm->ru[i]); | 1101 | struct acm_rb *rb = &(acm->read_buffers[i]); |
1102 | struct urb *urb; | ||
1199 | 1103 | ||
1200 | rcv->urb = usb_alloc_urb(0, GFP_KERNEL); | 1104 | rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, |
1201 | if (rcv->urb == NULL) { | 1105 | &rb->dma); |
1202 | dev_dbg(&intf->dev, | 1106 | if (!rb->base) { |
1203 | "out of memory (read urbs usb_alloc_urb)\n"); | 1107 | dev_err(&intf->dev, "out of memory " |
1108 | "(read bufs usb_alloc_coherent)\n"); | ||
1204 | goto alloc_fail6; | 1109 | goto alloc_fail6; |
1205 | } | 1110 | } |
1111 | rb->index = i; | ||
1112 | rb->instance = acm; | ||
1206 | 1113 | ||
1207 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1114 | urb = usb_alloc_urb(0, GFP_KERNEL); |
1208 | rcv->instance = acm; | 1115 | if (!urb) { |
1209 | } | 1116 | dev_err(&intf->dev, |
1210 | for (i = 0; i < num_rx_buf; i++) { | 1117 | "out of memory (read urbs usb_alloc_urb)\n"); |
1211 | struct acm_rb *rb = &(acm->rb[i]); | 1118 | goto alloc_fail6; |
1212 | 1119 | } | |
1213 | rb->base = usb_alloc_coherent(acm->dev, readsize, | 1120 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
1214 | GFP_KERNEL, &rb->dma); | 1121 | urb->transfer_dma = rb->dma; |
1215 | if (!rb->base) { | 1122 | if (acm->is_int_ep) { |
1216 | dev_dbg(&intf->dev, | 1123 | usb_fill_int_urb(urb, acm->dev, |
1217 | "out of memory (read bufs usb_alloc_coherent)\n"); | 1124 | acm->rx_endpoint, |
1218 | goto alloc_fail7; | 1125 | rb->base, |
1126 | acm->readsize, | ||
1127 | acm_read_bulk_callback, rb, | ||
1128 | acm->bInterval); | ||
1129 | } else { | ||
1130 | usb_fill_bulk_urb(urb, acm->dev, | ||
1131 | acm->rx_endpoint, | ||
1132 | rb->base, | ||
1133 | acm->readsize, | ||
1134 | acm_read_bulk_callback, rb); | ||
1219 | } | 1135 | } |
1136 | |||
1137 | acm->read_urbs[i] = urb; | ||
1138 | __set_bit(i, &acm->read_urbs_free); | ||
1220 | } | 1139 | } |
1221 | for (i = 0; i < ACM_NW; i++) { | 1140 | for (i = 0; i < ACM_NW; i++) { |
1222 | struct acm_wb *snd = &(acm->wb[i]); | 1141 | struct acm_wb *snd = &(acm->wb[i]); |
1223 | 1142 | ||
1224 | snd->urb = usb_alloc_urb(0, GFP_KERNEL); | 1143 | snd->urb = usb_alloc_urb(0, GFP_KERNEL); |
1225 | if (snd->urb == NULL) { | 1144 | if (snd->urb == NULL) { |
1226 | dev_dbg(&intf->dev, | 1145 | dev_err(&intf->dev, |
1227 | "out of memory (write urbs usb_alloc_urb)"); | 1146 | "out of memory (write urbs usb_alloc_urb)\n"); |
1228 | goto alloc_fail8; | 1147 | goto alloc_fail7; |
1229 | } | 1148 | } |
1230 | 1149 | ||
1231 | if (usb_endpoint_xfer_int(epwrite)) | 1150 | if (usb_endpoint_xfer_int(epwrite)) |
@@ -1244,7 +1163,7 @@ made_compressed_probe: | |||
1244 | 1163 | ||
1245 | i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); | 1164 | i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); |
1246 | if (i < 0) | 1165 | if (i < 0) |
1247 | goto alloc_fail8; | 1166 | goto alloc_fail7; |
1248 | 1167 | ||
1249 | if (cfd) { /* export the country data */ | 1168 | if (cfd) { /* export the country data */ |
1250 | acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); | 1169 | acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); |
@@ -1296,14 +1215,13 @@ skip_countries: | |||
1296 | acm_table[minor] = acm; | 1215 | acm_table[minor] = acm; |
1297 | 1216 | ||
1298 | return 0; | 1217 | return 0; |
1299 | alloc_fail8: | 1218 | alloc_fail7: |
1300 | for (i = 0; i < ACM_NW; i++) | 1219 | for (i = 0; i < ACM_NW; i++) |
1301 | usb_free_urb(acm->wb[i].urb); | 1220 | usb_free_urb(acm->wb[i].urb); |
1302 | alloc_fail7: | ||
1303 | acm_read_buffers_free(acm); | ||
1304 | alloc_fail6: | 1221 | alloc_fail6: |
1305 | for (i = 0; i < num_rx_buf; i++) | 1222 | for (i = 0; i < num_rx_buf; i++) |
1306 | usb_free_urb(acm->ru[i].urb); | 1223 | usb_free_urb(acm->read_urbs[i]); |
1224 | acm_read_buffers_free(acm); | ||
1307 | usb_free_urb(acm->ctrlurb); | 1225 | usb_free_urb(acm->ctrlurb); |
1308 | alloc_fail5: | 1226 | alloc_fail5: |
1309 | acm_write_buffers_free(acm); | 1227 | acm_write_buffers_free(acm); |
@@ -1318,17 +1236,14 @@ alloc_fail: | |||
1318 | static void stop_data_traffic(struct acm *acm) | 1236 | static void stop_data_traffic(struct acm *acm) |
1319 | { | 1237 | { |
1320 | int i; | 1238 | int i; |
1321 | dbg("Entering stop_data_traffic"); | ||
1322 | 1239 | ||
1323 | tasklet_disable(&acm->urb_task); | 1240 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
1324 | 1241 | ||
1325 | usb_kill_urb(acm->ctrlurb); | 1242 | usb_kill_urb(acm->ctrlurb); |
1326 | for (i = 0; i < ACM_NW; i++) | 1243 | for (i = 0; i < ACM_NW; i++) |
1327 | usb_kill_urb(acm->wb[i].urb); | 1244 | usb_kill_urb(acm->wb[i].urb); |
1328 | for (i = 0; i < acm->rx_buflimit; i++) | 1245 | for (i = 0; i < acm->rx_buflimit; i++) |
1329 | usb_kill_urb(acm->ru[i].urb); | 1246 | usb_kill_urb(acm->read_urbs[i]); |
1330 | |||
1331 | tasklet_enable(&acm->urb_task); | ||
1332 | 1247 | ||
1333 | cancel_work_sync(&acm->work); | 1248 | cancel_work_sync(&acm->work); |
1334 | } | 1249 | } |
@@ -1389,11 +1304,9 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1389 | if (message.event & PM_EVENT_AUTO) { | 1304 | if (message.event & PM_EVENT_AUTO) { |
1390 | int b; | 1305 | int b; |
1391 | 1306 | ||
1392 | spin_lock_irq(&acm->read_lock); | 1307 | spin_lock_irq(&acm->write_lock); |
1393 | spin_lock(&acm->write_lock); | 1308 | b = acm->transmitting; |
1394 | b = acm->processing + acm->transmitting; | 1309 | spin_unlock_irq(&acm->write_lock); |
1395 | spin_unlock(&acm->write_lock); | ||
1396 | spin_unlock_irq(&acm->read_lock); | ||
1397 | if (b) | 1310 | if (b) |
1398 | return -EBUSY; | 1311 | return -EBUSY; |
1399 | } | 1312 | } |
@@ -1455,7 +1368,7 @@ static int acm_resume(struct usb_interface *intf) | |||
1455 | if (rv < 0) | 1368 | if (rv < 0) |
1456 | goto err_out; | 1369 | goto err_out; |
1457 | 1370 | ||
1458 | tasklet_schedule(&acm->urb_task); | 1371 | rv = acm_submit_read_urbs(acm, GFP_NOIO); |
1459 | } | 1372 | } |
1460 | 1373 | ||
1461 | err_out: | 1374 | err_out: |
@@ -1716,8 +1629,7 @@ static int __init acm_init(void) | |||
1716 | return retval; | 1629 | return retval; |
1717 | } | 1630 | } |
1718 | 1631 | ||
1719 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | 1632 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); |
1720 | DRIVER_DESC "\n"); | ||
1721 | 1633 | ||
1722 | return 0; | 1634 | return 0; |
1723 | } | 1635 | } |
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index b4ea54dbf323..7b5c0bd07f80 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h | |||
@@ -72,16 +72,10 @@ struct acm_wb { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct acm_rb { | 74 | struct acm_rb { |
75 | struct list_head list; | ||
76 | int size; | 75 | int size; |
77 | unsigned char *base; | 76 | unsigned char *base; |
78 | dma_addr_t dma; | 77 | dma_addr_t dma; |
79 | }; | 78 | int index; |
80 | |||
81 | struct acm_ru { | ||
82 | struct list_head list; | ||
83 | struct acm_rb *buffer; | ||
84 | struct urb *urb; | ||
85 | struct acm *instance; | 79 | struct acm *instance; |
86 | }; | 80 | }; |
87 | 81 | ||
@@ -97,35 +91,30 @@ struct acm { | |||
97 | unsigned int country_code_size; /* size of this buffer */ | 91 | unsigned int country_code_size; /* size of this buffer */ |
98 | unsigned int country_rel_date; /* release date of version */ | 92 | unsigned int country_rel_date; /* release date of version */ |
99 | struct acm_wb wb[ACM_NW]; | 93 | struct acm_wb wb[ACM_NW]; |
100 | struct acm_ru ru[ACM_NR]; | 94 | unsigned long read_urbs_free; |
101 | struct acm_rb rb[ACM_NR]; | 95 | struct urb *read_urbs[ACM_NR]; |
96 | struct acm_rb read_buffers[ACM_NR]; | ||
102 | int rx_buflimit; | 97 | int rx_buflimit; |
103 | int rx_endpoint; | 98 | int rx_endpoint; |
104 | spinlock_t read_lock; | 99 | spinlock_t read_lock; |
105 | struct list_head spare_read_urbs; | ||
106 | struct list_head spare_read_bufs; | ||
107 | struct list_head filled_read_bufs; | ||
108 | int write_used; /* number of non-empty write buffers */ | 100 | int write_used; /* number of non-empty write buffers */ |
109 | int processing; | ||
110 | int transmitting; | 101 | int transmitting; |
111 | spinlock_t write_lock; | 102 | spinlock_t write_lock; |
112 | struct mutex mutex; | 103 | struct mutex mutex; |
113 | struct usb_cdc_line_coding line; /* bits, stop, parity */ | 104 | struct usb_cdc_line_coding line; /* bits, stop, parity */ |
114 | struct work_struct work; /* work queue entry for line discipline waking up */ | 105 | struct work_struct work; /* work queue entry for line discipline waking up */ |
115 | wait_queue_head_t drain_wait; /* close processing */ | ||
116 | struct tasklet_struct urb_task; /* rx processing */ | ||
117 | spinlock_t throttle_lock; /* synchronize throtteling and read callback */ | ||
118 | unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ | 106 | unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ |
119 | unsigned int ctrlout; /* output control lines (DTR, RTS) */ | 107 | unsigned int ctrlout; /* output control lines (DTR, RTS) */ |
120 | unsigned int writesize; /* max packet size for the output bulk endpoint */ | 108 | unsigned int writesize; /* max packet size for the output bulk endpoint */ |
121 | unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ | 109 | unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ |
122 | unsigned int minor; /* acm minor number */ | 110 | unsigned int minor; /* acm minor number */ |
123 | unsigned char throttle; /* throttled by tty layer */ | ||
124 | unsigned char clocal; /* termios CLOCAL */ | 111 | unsigned char clocal; /* termios CLOCAL */ |
125 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ | 112 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ |
126 | unsigned int susp_count; /* number of suspended interfaces */ | 113 | unsigned int susp_count; /* number of suspended interfaces */ |
127 | unsigned int combined_interfaces:1; /* control and data collapsed */ | 114 | unsigned int combined_interfaces:1; /* control and data collapsed */ |
128 | unsigned int is_int_ep:1; /* interrupt endpoints contrary to spec used */ | 115 | unsigned int is_int_ep:1; /* interrupt endpoints contrary to spec used */ |
116 | unsigned int throttled:1; /* actually throttled */ | ||
117 | unsigned int throttle_req:1; /* throttle requested */ | ||
129 | u8 bInterval; | 118 | u8 bInterval; |
130 | struct acm_wb *delayed_wb; /* write queued for a device about to be woken */ | 119 | struct acm_wb *delayed_wb; /* write queued for a device about to be woken */ |
131 | }; | 120 | }; |
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 96fdfb815f89..0149c0976e9c 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
@@ -64,49 +64,49 @@ | |||
64 | /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ | 64 | /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ |
65 | #define ALLOW_SERIAL_NUMBER | 65 | #define ALLOW_SERIAL_NUMBER |
66 | 66 | ||
67 | static const char *format_topo = | 67 | static const char format_topo[] = |
68 | /* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */ | 68 | /* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */ |
69 | "\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n"; | 69 | "\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n"; |
70 | 70 | ||
71 | static const char *format_string_manufacturer = | 71 | static const char format_string_manufacturer[] = |
72 | /* S: Manufacturer=xxxx */ | 72 | /* S: Manufacturer=xxxx */ |
73 | "S: Manufacturer=%.100s\n"; | 73 | "S: Manufacturer=%.100s\n"; |
74 | 74 | ||
75 | static const char *format_string_product = | 75 | static const char format_string_product[] = |
76 | /* S: Product=xxxx */ | 76 | /* S: Product=xxxx */ |
77 | "S: Product=%.100s\n"; | 77 | "S: Product=%.100s\n"; |
78 | 78 | ||
79 | #ifdef ALLOW_SERIAL_NUMBER | 79 | #ifdef ALLOW_SERIAL_NUMBER |
80 | static const char *format_string_serialnumber = | 80 | static const char format_string_serialnumber[] = |
81 | /* S: SerialNumber=xxxx */ | 81 | /* S: SerialNumber=xxxx */ |
82 | "S: SerialNumber=%.100s\n"; | 82 | "S: SerialNumber=%.100s\n"; |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | static const char *format_bandwidth = | 85 | static const char format_bandwidth[] = |
86 | /* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */ | 86 | /* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */ |
87 | "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n"; | 87 | "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n"; |
88 | 88 | ||
89 | static const char *format_device1 = | 89 | static const char format_device1[] = |
90 | /* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */ | 90 | /* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */ |
91 | "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n"; | 91 | "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n"; |
92 | 92 | ||
93 | static const char *format_device2 = | 93 | static const char format_device2[] = |
94 | /* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */ | 94 | /* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */ |
95 | "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n"; | 95 | "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n"; |
96 | 96 | ||
97 | static const char *format_config = | 97 | static const char format_config[] = |
98 | /* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */ | 98 | /* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */ |
99 | "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n"; | 99 | "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n"; |
100 | 100 | ||
101 | static const char *format_iad = | 101 | static const char format_iad[] = |
102 | /* A: FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */ | 102 | /* A: FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */ |
103 | "A: FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n"; | 103 | "A: FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n"; |
104 | 104 | ||
105 | static const char *format_iface = | 105 | static const char format_iface[] = |
106 | /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/ | 106 | /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/ |
107 | "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; | 107 | "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; |
108 | 108 | ||
109 | static const char *format_endpt = | 109 | static const char format_endpt[] = |
110 | /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ | 110 | /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ |
111 | "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; | 111 | "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; |
112 | 112 | ||
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index cf6a5423de09..99458c843d60 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
@@ -236,13 +236,6 @@ EXPORT_SYMBOL_GPL(usb_register_dev); | |||
236 | void usb_deregister_dev(struct usb_interface *intf, | 236 | void usb_deregister_dev(struct usb_interface *intf, |
237 | struct usb_class_driver *class_driver) | 237 | struct usb_class_driver *class_driver) |
238 | { | 238 | { |
239 | int minor_base = class_driver->minor_base; | ||
240 | char name[20]; | ||
241 | |||
242 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
243 | minor_base = 0; | ||
244 | #endif | ||
245 | |||
246 | if (intf->minor == -1) | 239 | if (intf->minor == -1) |
247 | return; | 240 | return; |
248 | 241 | ||
@@ -252,7 +245,6 @@ void usb_deregister_dev(struct usb_interface *intf, | |||
252 | usb_minors[intf->minor] = NULL; | 245 | usb_minors[intf->minor] = NULL; |
253 | up_write(&minor_rwsem); | 246 | up_write(&minor_rwsem); |
254 | 247 | ||
255 | snprintf(name, sizeof(name), class_driver->name, intf->minor - minor_base); | ||
256 | device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); | 248 | device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); |
257 | intf->usb_dev = NULL; | 249 | intf->usb_dev = NULL; |
258 | intf->minor = -1; | 250 | intf->minor = -1; |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index bc5123cf41c2..4c02b9f1597e 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -260,6 +260,24 @@ config USB_R8A66597 | |||
260 | default USB_GADGET | 260 | default USB_GADGET |
261 | select USB_GADGET_SELECTED | 261 | select USB_GADGET_SELECTED |
262 | 262 | ||
263 | config USB_GADGET_RENESAS_USBHS | ||
264 | boolean "Renesas USBHS" | ||
265 | depends on USB_RENESAS_USBHS | ||
266 | select USB_GADGET_DUALSPEED | ||
267 | help | ||
268 | Renesas USBHS is a discrete USB host and peripheral controller | ||
269 | chip that supports both full and high speed USB 2.0 data transfers. | ||
270 | platform is able to configure endpoint (pipe) style | ||
271 | |||
272 | Say "y" to enable the gadget specific portion of the USBHS driver. | ||
273 | |||
274 | |||
275 | config USB_RENESAS_USBHS_UDC | ||
276 | tristate | ||
277 | depends on USB_GADGET_RENESAS_USBHS | ||
278 | default USB_GADGET | ||
279 | select USB_GADGET_SELECTED | ||
280 | |||
263 | config USB_GADGET_PXA27X | 281 | config USB_GADGET_PXA27X |
264 | boolean "PXA 27x" | 282 | boolean "PXA 27x" |
265 | depends on ARCH_PXA && (PXA27x || PXA3xx) | 283 | depends on ARCH_PXA && (PXA27x || PXA3xx) |
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6d8e533949eb..01ae27b60d4c 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -613,6 +613,11 @@ static int fsg_setup(struct usb_function *f, | |||
613 | if (!fsg_is_set(fsg->common)) | 613 | if (!fsg_is_set(fsg->common)) |
614 | return -EOPNOTSUPP; | 614 | return -EOPNOTSUPP; |
615 | 615 | ||
616 | ++fsg->common->ep0_req_tag; /* Record arrival of a new request */ | ||
617 | req->context = NULL; | ||
618 | req->length = 0; | ||
619 | dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); | ||
620 | |||
616 | switch (ctrl->bRequest) { | 621 | switch (ctrl->bRequest) { |
617 | 622 | ||
618 | case USB_BULK_RESET_REQUEST: | 623 | case USB_BULK_RESET_REQUEST: |
@@ -1584,37 +1589,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) | |||
1584 | return rc; | 1589 | return rc; |
1585 | } | 1590 | } |
1586 | 1591 | ||
1587 | static int pad_with_zeros(struct fsg_dev *fsg) | ||
1588 | { | ||
1589 | struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; | ||
1590 | u32 nkeep = bh->inreq->length; | ||
1591 | u32 nsend; | ||
1592 | int rc; | ||
1593 | |||
1594 | bh->state = BUF_STATE_EMPTY; /* For the first iteration */ | ||
1595 | fsg->common->usb_amount_left = nkeep + fsg->common->residue; | ||
1596 | while (fsg->common->usb_amount_left > 0) { | ||
1597 | |||
1598 | /* Wait for the next buffer to be free */ | ||
1599 | while (bh->state != BUF_STATE_EMPTY) { | ||
1600 | rc = sleep_thread(fsg->common); | ||
1601 | if (rc) | ||
1602 | return rc; | ||
1603 | } | ||
1604 | |||
1605 | nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); | ||
1606 | memset(bh->buf + nkeep, 0, nsend - nkeep); | ||
1607 | bh->inreq->length = nsend; | ||
1608 | bh->inreq->zero = 0; | ||
1609 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
1610 | &bh->inreq_busy, &bh->state); | ||
1611 | bh = fsg->common->next_buffhd_to_fill = bh->next; | ||
1612 | fsg->common->usb_amount_left -= nsend; | ||
1613 | nkeep = 0; | ||
1614 | } | ||
1615 | return 0; | ||
1616 | } | ||
1617 | |||
1618 | static int throw_away_data(struct fsg_common *common) | 1592 | static int throw_away_data(struct fsg_common *common) |
1619 | { | 1593 | { |
1620 | struct fsg_buffhd *bh; | 1594 | struct fsg_buffhd *bh; |
@@ -1702,6 +1676,10 @@ static int finish_reply(struct fsg_common *common) | |||
1702 | if (common->data_size == 0) { | 1676 | if (common->data_size == 0) { |
1703 | /* Nothing to send */ | 1677 | /* Nothing to send */ |
1704 | 1678 | ||
1679 | /* Don't know what to do if common->fsg is NULL */ | ||
1680 | } else if (!fsg_is_set(common)) { | ||
1681 | rc = -EIO; | ||
1682 | |||
1705 | /* If there's no residue, simply send the last buffer */ | 1683 | /* If there's no residue, simply send the last buffer */ |
1706 | } else if (common->residue == 0) { | 1684 | } else if (common->residue == 0) { |
1707 | bh->inreq->zero = 0; | 1685 | bh->inreq->zero = 0; |
@@ -1710,24 +1688,19 @@ static int finish_reply(struct fsg_common *common) | |||
1710 | common->next_buffhd_to_fill = bh->next; | 1688 | common->next_buffhd_to_fill = bh->next; |
1711 | 1689 | ||
1712 | /* | 1690 | /* |
1713 | * For Bulk-only, if we're allowed to stall then send the | 1691 | * For Bulk-only, mark the end of the data with a short |
1714 | * short packet and halt the bulk-in endpoint. If we can't | 1692 | * packet. If we are allowed to stall, halt the bulk-in |
1715 | * stall, pad out the remaining data with 0's. | 1693 | * endpoint. (Note: This violates the Bulk-Only Transport |
1694 | * specification, which requires us to pad the data if we | ||
1695 | * don't halt the endpoint. Presumably nobody will mind.) | ||
1716 | */ | 1696 | */ |
1717 | } else if (common->can_stall) { | 1697 | } else { |
1718 | bh->inreq->zero = 1; | 1698 | bh->inreq->zero = 1; |
1719 | if (!start_in_transfer(common, bh)) | 1699 | if (!start_in_transfer(common, bh)) |
1720 | /* Don't know what to do if | ||
1721 | * common->fsg is NULL */ | ||
1722 | rc = -EIO; | 1700 | rc = -EIO; |
1723 | common->next_buffhd_to_fill = bh->next; | 1701 | common->next_buffhd_to_fill = bh->next; |
1724 | if (common->fsg) | 1702 | if (common->can_stall) |
1725 | rc = halt_bulk_in_endpoint(common->fsg); | 1703 | rc = halt_bulk_in_endpoint(common->fsg); |
1726 | } else if (fsg_is_set(common)) { | ||
1727 | rc = pad_with_zeros(common->fsg); | ||
1728 | } else { | ||
1729 | /* Don't know what to do if common->fsg is NULL */ | ||
1730 | rc = -EIO; | ||
1731 | } | 1704 | } |
1732 | break; | 1705 | break; |
1733 | 1706 | ||
@@ -2800,6 +2773,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2800 | for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { | 2773 | for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { |
2801 | curlun->cdrom = !!lcfg->cdrom; | 2774 | curlun->cdrom = !!lcfg->cdrom; |
2802 | curlun->ro = lcfg->cdrom || lcfg->ro; | 2775 | curlun->ro = lcfg->cdrom || lcfg->ro; |
2776 | curlun->initially_ro = curlun->ro; | ||
2803 | curlun->removable = lcfg->removable; | 2777 | curlun->removable = lcfg->removable; |
2804 | curlun->dev.release = fsg_lun_release; | 2778 | curlun->dev.release = fsg_lun_release; |
2805 | curlun->dev.parent = &gadget->dev; | 2779 | curlun->dev.parent = &gadget->dev; |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a6eacb59571b..fcfc77c7ad70 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -1947,37 +1947,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) | |||
1947 | return rc; | 1947 | return rc; |
1948 | } | 1948 | } |
1949 | 1949 | ||
1950 | static int pad_with_zeros(struct fsg_dev *fsg) | ||
1951 | { | ||
1952 | struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; | ||
1953 | u32 nkeep = bh->inreq->length; | ||
1954 | u32 nsend; | ||
1955 | int rc; | ||
1956 | |||
1957 | bh->state = BUF_STATE_EMPTY; // For the first iteration | ||
1958 | fsg->usb_amount_left = nkeep + fsg->residue; | ||
1959 | while (fsg->usb_amount_left > 0) { | ||
1960 | |||
1961 | /* Wait for the next buffer to be free */ | ||
1962 | while (bh->state != BUF_STATE_EMPTY) { | ||
1963 | rc = sleep_thread(fsg); | ||
1964 | if (rc) | ||
1965 | return rc; | ||
1966 | } | ||
1967 | |||
1968 | nsend = min(fsg->usb_amount_left, (u32) mod_data.buflen); | ||
1969 | memset(bh->buf + nkeep, 0, nsend - nkeep); | ||
1970 | bh->inreq->length = nsend; | ||
1971 | bh->inreq->zero = 0; | ||
1972 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
1973 | &bh->inreq_busy, &bh->state); | ||
1974 | bh = fsg->next_buffhd_to_fill = bh->next; | ||
1975 | fsg->usb_amount_left -= nsend; | ||
1976 | nkeep = 0; | ||
1977 | } | ||
1978 | return 0; | ||
1979 | } | ||
1980 | |||
1981 | static int throw_away_data(struct fsg_dev *fsg) | 1950 | static int throw_away_data(struct fsg_dev *fsg) |
1982 | { | 1951 | { |
1983 | struct fsg_buffhd *bh; | 1952 | struct fsg_buffhd *bh; |
@@ -2082,18 +2051,20 @@ static int finish_reply(struct fsg_dev *fsg) | |||
2082 | } | 2051 | } |
2083 | } | 2052 | } |
2084 | 2053 | ||
2085 | /* For Bulk-only, if we're allowed to stall then send the | 2054 | /* |
2086 | * short packet and halt the bulk-in endpoint. If we can't | 2055 | * For Bulk-only, mark the end of the data with a short |
2087 | * stall, pad out the remaining data with 0's. */ | 2056 | * packet. If we are allowed to stall, halt the bulk-in |
2057 | * endpoint. (Note: This violates the Bulk-Only Transport | ||
2058 | * specification, which requires us to pad the data if we | ||
2059 | * don't halt the endpoint. Presumably nobody will mind.) | ||
2060 | */ | ||
2088 | else { | 2061 | else { |
2089 | if (mod_data.can_stall) { | 2062 | bh->inreq->zero = 1; |
2090 | bh->inreq->zero = 1; | 2063 | start_transfer(fsg, fsg->bulk_in, bh->inreq, |
2091 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | 2064 | &bh->inreq_busy, &bh->state); |
2092 | &bh->inreq_busy, &bh->state); | 2065 | fsg->next_buffhd_to_fill = bh->next; |
2093 | fsg->next_buffhd_to_fill = bh->next; | 2066 | if (mod_data.can_stall) |
2094 | rc = halt_bulk_in_endpoint(fsg); | 2067 | rc = halt_bulk_in_endpoint(fsg); |
2095 | } else | ||
2096 | rc = pad_with_zeros(fsg); | ||
2097 | } | 2068 | } |
2098 | break; | 2069 | break; |
2099 | 2070 | ||
diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h index e35e24fd64bb..1da5fb03d218 100644 --- a/drivers/usb/gadget/fsl_qe_udc.h +++ b/drivers/usb/gadget/fsl_qe_udc.h | |||
@@ -207,7 +207,7 @@ struct qe_frame{ | |||
207 | 207 | ||
208 | /* Frame status field */ | 208 | /* Frame status field */ |
209 | /* Receive side */ | 209 | /* Receive side */ |
210 | #define FRAME_OK 0x00000000 /* Frame tranmitted or received OK */ | 210 | #define FRAME_OK 0x00000000 /* Frame transmitted or received OK */ |
211 | #define FRAME_ERROR 0x80000000 /* Error occurred on frame */ | 211 | #define FRAME_ERROR 0x80000000 /* Error occurred on frame */ |
212 | #define START_FRAME_LOST 0x40000000 /* START_FRAME_LOST */ | 212 | #define START_FRAME_LOST 0x40000000 /* START_FRAME_LOST */ |
213 | #define END_FRAME_LOST 0x20000000 /* END_FRAME_LOST */ | 213 | #define END_FRAME_LOST 0x20000000 /* END_FRAME_LOST */ |
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index e896f6359dfe..ec3fd979c71d 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h | |||
@@ -148,6 +148,12 @@ | |||
148 | #define gadget_is_ci13xxx_msm(g) 0 | 148 | #define gadget_is_ci13xxx_msm(g) 0 |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | #ifdef CONFIG_USB_GADGET_RENESAS_USBHS | ||
152 | #define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name)) | ||
153 | #else | ||
154 | #define gadget_is_renesas_usbhs(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,9 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) | |||
207 | return 0x27; | 213 | return 0x27; |
208 | else if (gadget_is_ci13xxx_msm(gadget)) | 214 | else if (gadget_is_ci13xxx_msm(gadget)) |
209 | return 0x28; | 215 | return 0x28; |
216 | else if (gadget_is_renesas_usbhs(gadget)) | ||
217 | return 0x29; | ||
218 | |||
210 | return -ENOENT; | 219 | return -ENOENT; |
211 | } | 220 | } |
212 | 221 | ||
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index b015561fd602..109635a84888 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c | |||
@@ -711,10 +711,11 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, | |||
711 | ssize_t rc = count; | 711 | ssize_t rc = count; |
712 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | 712 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); |
713 | struct rw_semaphore *filesem = dev_get_drvdata(dev); | 713 | struct rw_semaphore *filesem = dev_get_drvdata(dev); |
714 | unsigned long ro; | 714 | unsigned ro; |
715 | 715 | ||
716 | if (strict_strtoul(buf, 2, &ro)) | 716 | rc = kstrtouint(buf, 2, &ro); |
717 | return -EINVAL; | 717 | if (rc) |
718 | return rc; | ||
718 | 719 | ||
719 | /* | 720 | /* |
720 | * Allow the write-enable status to change only while the | 721 | * Allow the write-enable status to change only while the |
@@ -738,10 +739,12 @@ static ssize_t fsg_store_nofua(struct device *dev, | |||
738 | const char *buf, size_t count) | 739 | const char *buf, size_t count) |
739 | { | 740 | { |
740 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | 741 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); |
741 | unsigned long nofua; | 742 | unsigned nofua; |
743 | int ret; | ||
742 | 744 | ||
743 | if (strict_strtoul(buf, 2, &nofua)) | 745 | ret = kstrtouint(buf, 2, &nofua); |
744 | return -EINVAL; | 746 | if (ret) |
747 | return ret; | ||
745 | 748 | ||
746 | /* Sync data when switching from async mode to sync */ | 749 | /* Sync data when switching from async mode to sync */ |
747 | if (!nofua && curlun->nofua) | 750 | if (!nofua && curlun->nofua) |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index e0e0787b724b..fe4beca00009 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -188,6 +188,12 @@ config USB_EHCI_SH | |||
188 | Enables support for the on-chip EHCI controller on the SuperH. | 188 | Enables support for the on-chip EHCI controller on the SuperH. |
189 | If you use the PCI EHCI controller, this option is not necessary. | 189 | If you use the PCI EHCI controller, this option is not necessary. |
190 | 190 | ||
191 | config USB_EHCI_S5P | ||
192 | boolean "S5P EHCI support" | ||
193 | depends on USB_EHCI_HCD && PLAT_S5P | ||
194 | help | ||
195 | Enable support for the S5P SOC's on-chip EHCI controller. | ||
196 | |||
191 | config USB_W90X900_EHCI | 197 | config USB_W90X900_EHCI |
192 | bool "W90X900(W90P910) EHCI support" | 198 | bool "W90X900(W90P910) EHCI support" |
193 | depends on USB_EHCI_HCD && ARCH_W90X900 | 199 | depends on USB_EHCI_HCD && ARCH_W90X900 |
@@ -202,6 +208,15 @@ config USB_CNS3XXX_EHCI | |||
202 | It is needed for high-speed (480Mbit/sec) USB 2.0 device | 208 | It is needed for high-speed (480Mbit/sec) USB 2.0 device |
203 | support. | 209 | support. |
204 | 210 | ||
211 | config USB_EHCI_ATH79 | ||
212 | bool "EHCI support for AR7XXX/AR9XXX SoCs" | ||
213 | depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X) | ||
214 | select USB_EHCI_ROOT_HUB_TT | ||
215 | default y | ||
216 | ---help--- | ||
217 | Enables support for the built-in EHCI controller present | ||
218 | on the Atheros AR7XXX/AR9XXX SoCs. | ||
219 | |||
205 | config USB_OXU210HP_HCD | 220 | config USB_OXU210HP_HCD |
206 | tristate "OXU210HP HCD support" | 221 | tristate "OXU210HP HCD support" |
207 | depends on USB | 222 | depends on USB |
@@ -287,6 +302,14 @@ config USB_OHCI_HCD_OMAP3 | |||
287 | Enables support for the on-chip OHCI controller on | 302 | Enables support for the on-chip OHCI controller on |
288 | OMAP3 and later chips. | 303 | OMAP3 and later chips. |
289 | 304 | ||
305 | config USB_OHCI_ATH79 | ||
306 | bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs" | ||
307 | depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X) | ||
308 | default y | ||
309 | help | ||
310 | Enables support for the built-in OHCI controller present on the | ||
311 | Atheros AR71XX/AR7240 SoCs. | ||
312 | |||
290 | config USB_OHCI_HCD_PPC_SOC | 313 | config USB_OHCI_HCD_PPC_SOC |
291 | bool "OHCI support for on-chip PPC USB controller" | 314 | bool "OHCI support for on-chip PPC USB controller" |
292 | depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) | 315 | depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) |
@@ -444,6 +467,16 @@ config USB_SL811_HCD | |||
444 | To compile this driver as a module, choose M here: the | 467 | To compile this driver as a module, choose M here: the |
445 | module will be called sl811-hcd. | 468 | module will be called sl811-hcd. |
446 | 469 | ||
470 | config USB_SL811_HCD_ISO | ||
471 | bool "partial ISO support" | ||
472 | depends on USB_SL811_HCD | ||
473 | help | ||
474 | The driver doesn't support iso_frame_desc (yet), but for some simple | ||
475 | devices that just queue one ISO frame per URB, then ISO transfers | ||
476 | "should" work using the normal urb status fields. | ||
477 | |||
478 | If unsure, say N. | ||
479 | |||
447 | config USB_SL811_CS | 480 | config USB_SL811_CS |
448 | tristate "CF/PCMCIA support for SL811HS HCD" | 481 | tristate "CF/PCMCIA support for SL811HS HCD" |
449 | depends on USB_SL811_HCD && PCMCIA | 482 | depends on USB_SL811_HCD && PCMCIA |
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c new file mode 100644 index 000000000000..7ea23b50f5d8 --- /dev/null +++ b/drivers/usb/host/ehci-ath79.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Bus Glue for Atheros AR7XXX/AR9XXX built-in EHCI controller. | ||
3 | * | ||
4 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
5 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||
6 | * | ||
7 | * Parts of this file are based on Atheros' 2.6.15 BSP | ||
8 | * Copyright (C) 2007 Atheros Communications, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/platform_device.h> | ||
16 | |||
17 | enum { | ||
18 | EHCI_ATH79_IP_V1 = 0, | ||
19 | EHCI_ATH79_IP_V2, | ||
20 | }; | ||
21 | |||
22 | static const struct platform_device_id ehci_ath79_id_table[] = { | ||
23 | { | ||
24 | .name = "ar71xx-ehci", | ||
25 | .driver_data = EHCI_ATH79_IP_V1, | ||
26 | }, | ||
27 | { | ||
28 | .name = "ar724x-ehci", | ||
29 | .driver_data = EHCI_ATH79_IP_V2, | ||
30 | }, | ||
31 | { | ||
32 | .name = "ar913x-ehci", | ||
33 | .driver_data = EHCI_ATH79_IP_V2, | ||
34 | }, | ||
35 | { | ||
36 | /* terminating entry */ | ||
37 | }, | ||
38 | }; | ||
39 | |||
40 | MODULE_DEVICE_TABLE(platform, ehci_ath79_id_table); | ||
41 | |||
42 | static int ehci_ath79_init(struct usb_hcd *hcd) | ||
43 | { | ||
44 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
45 | struct platform_device *pdev = to_platform_device(hcd->self.controller); | ||
46 | const struct platform_device_id *id; | ||
47 | int ret; | ||
48 | |||
49 | id = platform_get_device_id(pdev); | ||
50 | if (!id) { | ||
51 | dev_err(hcd->self.controller, "missing device id\n"); | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | |||
55 | switch (id->driver_data) { | ||
56 | case EHCI_ATH79_IP_V1: | ||
57 | ehci->has_synopsys_hc_bug = 1; | ||
58 | |||
59 | ehci->caps = hcd->regs; | ||
60 | ehci->regs = hcd->regs + | ||
61 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
62 | break; | ||
63 | |||
64 | case EHCI_ATH79_IP_V2: | ||
65 | hcd->has_tt = 1; | ||
66 | |||
67 | ehci->caps = hcd->regs + 0x100; | ||
68 | ehci->regs = hcd->regs + 0x100 + | ||
69 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
70 | break; | ||
71 | |||
72 | default: | ||
73 | BUG(); | ||
74 | } | ||
75 | |||
76 | dbg_hcs_params(ehci, "reset"); | ||
77 | dbg_hcc_params(ehci, "reset"); | ||
78 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
79 | ehci->sbrn = 0x20; | ||
80 | |||
81 | ehci_reset(ehci); | ||
82 | |||
83 | ret = ehci_init(hcd); | ||
84 | if (ret) | ||
85 | return ret; | ||
86 | |||
87 | ehci_port_power(ehci, 0); | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static const struct hc_driver ehci_ath79_hc_driver = { | ||
93 | .description = hcd_name, | ||
94 | .product_desc = "Atheros built-in EHCI controller", | ||
95 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
96 | .irq = ehci_irq, | ||
97 | .flags = HCD_MEMORY | HCD_USB2, | ||
98 | |||
99 | .reset = ehci_ath79_init, | ||
100 | .start = ehci_run, | ||
101 | .stop = ehci_stop, | ||
102 | .shutdown = ehci_shutdown, | ||
103 | |||
104 | .urb_enqueue = ehci_urb_enqueue, | ||
105 | .urb_dequeue = ehci_urb_dequeue, | ||
106 | .endpoint_disable = ehci_endpoint_disable, | ||
107 | .endpoint_reset = ehci_endpoint_reset, | ||
108 | |||
109 | .get_frame_number = ehci_get_frame, | ||
110 | |||
111 | .hub_status_data = ehci_hub_status_data, | ||
112 | .hub_control = ehci_hub_control, | ||
113 | |||
114 | .relinquish_port = ehci_relinquish_port, | ||
115 | .port_handed_over = ehci_port_handed_over, | ||
116 | |||
117 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
118 | }; | ||
119 | |||
120 | static int ehci_ath79_probe(struct platform_device *pdev) | ||
121 | { | ||
122 | struct usb_hcd *hcd; | ||
123 | struct resource *res; | ||
124 | int irq; | ||
125 | int ret; | ||
126 | |||
127 | if (usb_disabled()) | ||
128 | return -ENODEV; | ||
129 | |||
130 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
131 | if (!res) { | ||
132 | dev_dbg(&pdev->dev, "no IRQ specified\n"); | ||
133 | return -ENODEV; | ||
134 | } | ||
135 | irq = res->start; | ||
136 | |||
137 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
138 | if (!res) { | ||
139 | dev_dbg(&pdev->dev, "no base address specified\n"); | ||
140 | return -ENODEV; | ||
141 | } | ||
142 | |||
143 | hcd = usb_create_hcd(&ehci_ath79_hc_driver, &pdev->dev, | ||
144 | dev_name(&pdev->dev)); | ||
145 | if (!hcd) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | hcd->rsrc_start = res->start; | ||
149 | hcd->rsrc_len = res->end - res->start + 1; | ||
150 | |||
151 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
152 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
153 | ret = -EBUSY; | ||
154 | goto err_put_hcd; | ||
155 | } | ||
156 | |||
157 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
158 | if (!hcd->regs) { | ||
159 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
160 | ret = -EFAULT; | ||
161 | goto err_release_region; | ||
162 | } | ||
163 | |||
164 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | ||
165 | if (ret) | ||
166 | goto err_iounmap; | ||
167 | |||
168 | return 0; | ||
169 | |||
170 | err_iounmap: | ||
171 | iounmap(hcd->regs); | ||
172 | |||
173 | err_release_region: | ||
174 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
175 | err_put_hcd: | ||
176 | usb_put_hcd(hcd); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static int ehci_ath79_remove(struct platform_device *pdev) | ||
181 | { | ||
182 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
183 | |||
184 | usb_remove_hcd(hcd); | ||
185 | iounmap(hcd->regs); | ||
186 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
187 | usb_put_hcd(hcd); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static struct platform_driver ehci_ath79_driver = { | ||
193 | .probe = ehci_ath79_probe, | ||
194 | .remove = ehci_ath79_remove, | ||
195 | .id_table = ehci_ath79_id_table, | ||
196 | .driver = { | ||
197 | .owner = THIS_MODULE, | ||
198 | .name = "ath79-ehci", | ||
199 | } | ||
200 | }; | ||
201 | |||
202 | MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ehci"); | ||
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 78561d112c04..83b7d5f02a15 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1265,6 +1265,16 @@ MODULE_LICENSE ("GPL"); | |||
1265 | #define PLATFORM_DRIVER tegra_ehci_driver | 1265 | #define PLATFORM_DRIVER tegra_ehci_driver |
1266 | #endif | 1266 | #endif |
1267 | 1267 | ||
1268 | #ifdef CONFIG_USB_EHCI_S5P | ||
1269 | #include "ehci-s5p.c" | ||
1270 | #define PLATFORM_DRIVER s5p_ehci_driver | ||
1271 | #endif | ||
1272 | |||
1273 | #ifdef CONFIG_USB_EHCI_ATH79 | ||
1274 | #include "ehci-ath79.c" | ||
1275 | #define PLATFORM_DRIVER ehci_ath79_driver | ||
1276 | #endif | ||
1277 | |||
1268 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1278 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
1269 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ | 1279 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ |
1270 | !defined(XILINX_OF_PLATFORM_DRIVER) | 1280 | !defined(XILINX_OF_PLATFORM_DRIVER) |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d05ea03cfb4d..1a21799195af 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -127,7 +127,7 @@ static int ehci_port_change(struct ehci_hcd *ehci) | |||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | 130 | static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, |
131 | bool suspending, bool do_wakeup) | 131 | bool suspending, bool do_wakeup) |
132 | { | 132 | { |
133 | int port; | 133 | int port; |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 42abd0f603bf..a46d6a1388c9 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -1183,6 +1183,10 @@ static void end_unlink_async (struct ehci_hcd *ehci) | |||
1183 | ehci->reclaim = NULL; | 1183 | ehci->reclaim = NULL; |
1184 | start_unlink_async (ehci, next); | 1184 | start_unlink_async (ehci, next); |
1185 | } | 1185 | } |
1186 | |||
1187 | if (ehci->has_synopsys_hc_bug) | ||
1188 | ehci_writel(ehci, (u32) ehci->async->qh_dma, | ||
1189 | &ehci->regs->async_next); | ||
1186 | } | 1190 | } |
1187 | 1191 | ||
1188 | /* makes sure the async qh will become idle */ | 1192 | /* makes sure the async qh will become idle */ |
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c new file mode 100644 index 000000000000..0c18f280bf4c --- /dev/null +++ b/drivers/usb/host/ehci-s5p.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * SAMSUNG S5P USB HOST EHCI Controller | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
5 | * Author: Jingoo Han <jg1.han@samsung.com> | ||
6 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <mach/regs-pmu.h> | ||
18 | #include <plat/cpu.h> | ||
19 | #include <plat/ehci.h> | ||
20 | #include <plat/usb-phy.h> | ||
21 | |||
22 | struct s5p_ehci_hcd { | ||
23 | struct device *dev; | ||
24 | struct usb_hcd *hcd; | ||
25 | struct clk *clk; | ||
26 | }; | ||
27 | |||
28 | static const struct hc_driver s5p_ehci_hc_driver = { | ||
29 | .description = hcd_name, | ||
30 | .product_desc = "S5P EHCI Host Controller", | ||
31 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
32 | |||
33 | .irq = ehci_irq, | ||
34 | .flags = HCD_MEMORY | HCD_USB2, | ||
35 | |||
36 | .reset = ehci_init, | ||
37 | .start = ehci_run, | ||
38 | .stop = ehci_stop, | ||
39 | .shutdown = ehci_shutdown, | ||
40 | |||
41 | .get_frame_number = ehci_get_frame, | ||
42 | |||
43 | .urb_enqueue = ehci_urb_enqueue, | ||
44 | .urb_dequeue = ehci_urb_dequeue, | ||
45 | .endpoint_disable = ehci_endpoint_disable, | ||
46 | .endpoint_reset = ehci_endpoint_reset, | ||
47 | |||
48 | .hub_status_data = ehci_hub_status_data, | ||
49 | .hub_control = ehci_hub_control, | ||
50 | .bus_suspend = ehci_bus_suspend, | ||
51 | .bus_resume = ehci_bus_resume, | ||
52 | |||
53 | .relinquish_port = ehci_relinquish_port, | ||
54 | .port_handed_over = ehci_port_handed_over, | ||
55 | |||
56 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
57 | }; | ||
58 | |||
59 | static int s5p_ehci_probe(struct platform_device *pdev) | ||
60 | { | ||
61 | struct s5p_ehci_platdata *pdata; | ||
62 | struct s5p_ehci_hcd *s5p_ehci; | ||
63 | struct usb_hcd *hcd; | ||
64 | struct ehci_hcd *ehci; | ||
65 | struct resource *res; | ||
66 | int irq; | ||
67 | int err; | ||
68 | |||
69 | pdata = pdev->dev.platform_data; | ||
70 | if (!pdata) { | ||
71 | dev_err(&pdev->dev, "No platform data defined\n"); | ||
72 | return -EINVAL; | ||
73 | } | ||
74 | |||
75 | s5p_ehci = kzalloc(sizeof(struct s5p_ehci_hcd), GFP_KERNEL); | ||
76 | if (!s5p_ehci) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | s5p_ehci->dev = &pdev->dev; | ||
80 | |||
81 | hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev, | ||
82 | dev_name(&pdev->dev)); | ||
83 | if (!hcd) { | ||
84 | dev_err(&pdev->dev, "Unable to create HCD\n"); | ||
85 | err = -ENOMEM; | ||
86 | goto fail_hcd; | ||
87 | } | ||
88 | |||
89 | s5p_ehci->clk = clk_get(&pdev->dev, "usbhost"); | ||
90 | |||
91 | if (IS_ERR(s5p_ehci->clk)) { | ||
92 | dev_err(&pdev->dev, "Failed to get usbhost clock\n"); | ||
93 | err = PTR_ERR(s5p_ehci->clk); | ||
94 | goto fail_clk; | ||
95 | } | ||
96 | |||
97 | err = clk_enable(s5p_ehci->clk); | ||
98 | if (err) | ||
99 | goto fail_clken; | ||
100 | |||
101 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
102 | if (!res) { | ||
103 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); | ||
104 | err = -ENXIO; | ||
105 | goto fail_io; | ||
106 | } | ||
107 | |||
108 | hcd->rsrc_start = res->start; | ||
109 | hcd->rsrc_len = resource_size(res); | ||
110 | hcd->regs = ioremap(res->start, resource_size(res)); | ||
111 | if (!hcd->regs) { | ||
112 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); | ||
113 | err = -ENOMEM; | ||
114 | goto fail_io; | ||
115 | } | ||
116 | |||
117 | irq = platform_get_irq(pdev, 0); | ||
118 | if (!irq) { | ||
119 | dev_err(&pdev->dev, "Failed to get IRQ\n"); | ||
120 | err = -ENODEV; | ||
121 | goto fail; | ||
122 | } | ||
123 | |||
124 | if (pdata->phy_init) | ||
125 | pdata->phy_init(pdev, S5P_USB_PHY_HOST); | ||
126 | |||
127 | ehci = hcd_to_ehci(hcd); | ||
128 | ehci->caps = hcd->regs; | ||
129 | ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); | ||
130 | |||
131 | dbg_hcs_params(ehci, "reset"); | ||
132 | dbg_hcc_params(ehci, "reset"); | ||
133 | |||
134 | /* cache this readonly data; minimize chip reads */ | ||
135 | ehci->hcs_params = readl(&ehci->caps->hcs_params); | ||
136 | |||
137 | err = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | ||
138 | if (err) { | ||
139 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); | ||
140 | goto fail; | ||
141 | } | ||
142 | |||
143 | platform_set_drvdata(pdev, s5p_ehci); | ||
144 | |||
145 | return 0; | ||
146 | |||
147 | fail: | ||
148 | iounmap(hcd->regs); | ||
149 | fail_io: | ||
150 | clk_disable(s5p_ehci->clk); | ||
151 | fail_clken: | ||
152 | clk_put(s5p_ehci->clk); | ||
153 | fail_clk: | ||
154 | usb_put_hcd(hcd); | ||
155 | fail_hcd: | ||
156 | kfree(s5p_ehci); | ||
157 | return err; | ||
158 | } | ||
159 | |||
160 | static int s5p_ehci_remove(struct platform_device *pdev) | ||
161 | { | ||
162 | struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; | ||
163 | struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); | ||
164 | struct usb_hcd *hcd = s5p_ehci->hcd; | ||
165 | |||
166 | usb_remove_hcd(hcd); | ||
167 | |||
168 | if (pdata && pdata->phy_exit) | ||
169 | pdata->phy_exit(pdev, S5P_USB_PHY_HOST); | ||
170 | |||
171 | iounmap(hcd->regs); | ||
172 | |||
173 | clk_disable(s5p_ehci->clk); | ||
174 | clk_put(s5p_ehci->clk); | ||
175 | |||
176 | usb_put_hcd(hcd); | ||
177 | kfree(s5p_ehci); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static void s5p_ehci_shutdown(struct platform_device *pdev) | ||
183 | { | ||
184 | struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); | ||
185 | struct usb_hcd *hcd = s5p_ehci->hcd; | ||
186 | |||
187 | if (hcd->driver->shutdown) | ||
188 | hcd->driver->shutdown(hcd); | ||
189 | } | ||
190 | |||
191 | static struct platform_driver s5p_ehci_driver = { | ||
192 | .probe = s5p_ehci_probe, | ||
193 | .remove = s5p_ehci_remove, | ||
194 | .shutdown = s5p_ehci_shutdown, | ||
195 | .driver = { | ||
196 | .name = "s5p-ehci", | ||
197 | .owner = THIS_MODULE, | ||
198 | } | ||
199 | }; | ||
200 | |||
201 | MODULE_ALIAS("platform:s5p-ehci"); | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 333ddc156919..168f1a88c4d0 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -134,6 +134,7 @@ struct ehci_hcd { /* one per controller */ | |||
134 | unsigned amd_pll_fix:1; | 134 | unsigned amd_pll_fix:1; |
135 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ | 135 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ |
136 | unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ | 136 | unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ |
137 | unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ | ||
137 | 138 | ||
138 | /* required for usb32 quirk */ | 139 | /* required for usb32 quirk */ |
139 | #define OHCI_CTRL_HCFS (3 << 6) | 140 | #define OHCI_CTRL_HCFS (3 << 6) |
diff --git a/drivers/usb/host/ohci-ath79.c b/drivers/usb/host/ohci-ath79.c new file mode 100644 index 000000000000..ffea3e7cb0a8 --- /dev/null +++ b/drivers/usb/host/ohci-ath79.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * OHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * Bus Glue for Atheros AR71XX/AR724X built-in OHCI controller. | ||
5 | * | ||
6 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
7 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||
8 | * | ||
9 | * Parts of this file are based on Atheros' 2.6.15 BSP | ||
10 | * Copyright (C) 2007 Atheros Communications, Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License version 2 as published | ||
14 | * by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | static int __devinit ohci_ath79_start(struct usb_hcd *hcd) | ||
20 | { | ||
21 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
22 | int ret; | ||
23 | |||
24 | ret = ohci_init(ohci); | ||
25 | if (ret < 0) | ||
26 | return ret; | ||
27 | |||
28 | ret = ohci_run(ohci); | ||
29 | if (ret < 0) | ||
30 | goto err; | ||
31 | |||
32 | return 0; | ||
33 | |||
34 | err: | ||
35 | ohci_stop(hcd); | ||
36 | return ret; | ||
37 | } | ||
38 | |||
39 | static const struct hc_driver ohci_ath79_hc_driver = { | ||
40 | .description = hcd_name, | ||
41 | .product_desc = "Atheros built-in OHCI controller", | ||
42 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
43 | |||
44 | .irq = ohci_irq, | ||
45 | .flags = HCD_USB11 | HCD_MEMORY, | ||
46 | |||
47 | .start = ohci_ath79_start, | ||
48 | .stop = ohci_stop, | ||
49 | .shutdown = ohci_shutdown, | ||
50 | |||
51 | .urb_enqueue = ohci_urb_enqueue, | ||
52 | .urb_dequeue = ohci_urb_dequeue, | ||
53 | .endpoint_disable = ohci_endpoint_disable, | ||
54 | |||
55 | /* | ||
56 | * scheduling support | ||
57 | */ | ||
58 | .get_frame_number = ohci_get_frame, | ||
59 | |||
60 | /* | ||
61 | * root hub support | ||
62 | */ | ||
63 | .hub_status_data = ohci_hub_status_data, | ||
64 | .hub_control = ohci_hub_control, | ||
65 | .start_port_reset = ohci_start_port_reset, | ||
66 | }; | ||
67 | |||
68 | static int ohci_ath79_probe(struct platform_device *pdev) | ||
69 | { | ||
70 | struct usb_hcd *hcd; | ||
71 | struct resource *res; | ||
72 | int irq; | ||
73 | int ret; | ||
74 | |||
75 | if (usb_disabled()) | ||
76 | return -ENODEV; | ||
77 | |||
78 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
79 | if (!res) { | ||
80 | dev_dbg(&pdev->dev, "no IRQ specified\n"); | ||
81 | return -ENODEV; | ||
82 | } | ||
83 | irq = res->start; | ||
84 | |||
85 | hcd = usb_create_hcd(&ohci_ath79_hc_driver, &pdev->dev, | ||
86 | dev_name(&pdev->dev)); | ||
87 | if (!hcd) | ||
88 | return -ENOMEM; | ||
89 | |||
90 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
91 | if (!res) { | ||
92 | dev_dbg(&pdev->dev, "no base address specified\n"); | ||
93 | ret = -ENODEV; | ||
94 | goto err_put_hcd; | ||
95 | } | ||
96 | hcd->rsrc_start = res->start; | ||
97 | hcd->rsrc_len = res->end - res->start + 1; | ||
98 | |||
99 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
100 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
101 | ret = -EBUSY; | ||
102 | goto err_put_hcd; | ||
103 | } | ||
104 | |||
105 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
106 | if (!hcd->regs) { | ||
107 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
108 | ret = -EFAULT; | ||
109 | goto err_release_region; | ||
110 | } | ||
111 | |||
112 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
113 | |||
114 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | ||
115 | if (ret) | ||
116 | goto err_stop_hcd; | ||
117 | |||
118 | return 0; | ||
119 | |||
120 | err_stop_hcd: | ||
121 | iounmap(hcd->regs); | ||
122 | err_release_region: | ||
123 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
124 | err_put_hcd: | ||
125 | usb_put_hcd(hcd); | ||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | static int ohci_ath79_remove(struct platform_device *pdev) | ||
130 | { | ||
131 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
132 | |||
133 | usb_remove_hcd(hcd); | ||
134 | iounmap(hcd->regs); | ||
135 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
136 | usb_put_hcd(hcd); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static struct platform_driver ohci_hcd_ath79_driver = { | ||
142 | .probe = ohci_ath79_probe, | ||
143 | .remove = ohci_ath79_remove, | ||
144 | .shutdown = usb_hcd_platform_shutdown, | ||
145 | .driver = { | ||
146 | .name = "ath79-ohci", | ||
147 | .owner = THIS_MODULE, | ||
148 | }, | ||
149 | }; | ||
150 | |||
151 | MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ohci"); | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index d55723514860..8c8dc6559ac7 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -1105,6 +1105,11 @@ MODULE_LICENSE ("GPL"); | |||
1105 | #define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver | 1105 | #define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver |
1106 | #endif | 1106 | #endif |
1107 | 1107 | ||
1108 | #ifdef CONFIG_USB_OHCI_ATH79 | ||
1109 | #include "ohci-ath79.c" | ||
1110 | #define PLATFORM_DRIVER ohci_hcd_ath79_driver | ||
1111 | #endif | ||
1112 | |||
1108 | #if !defined(PCI_DRIVER) && \ | 1113 | #if !defined(PCI_DRIVER) && \ |
1109 | !defined(PLATFORM_DRIVER) && \ | 1114 | !defined(PLATFORM_DRIVER) && \ |
1110 | !defined(OMAP1_PLATFORM_DRIVER) && \ | 1115 | !defined(OMAP1_PLATFORM_DRIVER) && \ |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 18b7099a8125..5adcba016fcf 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -71,12 +71,6 @@ MODULE_ALIAS("platform:sl811-hcd"); | |||
71 | /* for now, use only one transfer register bank */ | 71 | /* for now, use only one transfer register bank */ |
72 | #undef USE_B | 72 | #undef USE_B |
73 | 73 | ||
74 | /* this doesn't understand urb->iso_frame_desc[], but if you had a driver | ||
75 | * that just queued one ISO frame per URB then iso transfers "should" work | ||
76 | * using the normal urb status fields. | ||
77 | */ | ||
78 | #define DISABLE_ISO | ||
79 | |||
80 | // #define QUIRK2 | 74 | // #define QUIRK2 |
81 | #define QUIRK3 | 75 | #define QUIRK3 |
82 | 76 | ||
@@ -807,7 +801,7 @@ static int sl811h_urb_enqueue( | |||
807 | int retval; | 801 | int retval; |
808 | struct usb_host_endpoint *hep = urb->ep; | 802 | struct usb_host_endpoint *hep = urb->ep; |
809 | 803 | ||
810 | #ifdef DISABLE_ISO | 804 | #ifndef CONFIG_USB_SL811_HCD_ISO |
811 | if (type == PIPE_ISOCHRONOUS) | 805 | if (type == PIPE_ISOCHRONOUS) |
812 | return -ENOSPC; | 806 | return -ENOSPC; |
813 | #endif | 807 | #endif |
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index b4785934e091..533d12cca371 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c | |||
@@ -3230,8 +3230,7 @@ static int __init u132_hcd_init(void) | |||
3230 | mutex_init(&u132_module_lock); | 3230 | mutex_init(&u132_module_lock); |
3231 | if (usb_disabled()) | 3231 | if (usb_disabled()) |
3232 | return -ENODEV; | 3232 | return -ENODEV; |
3233 | printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__, | 3233 | printk(KERN_INFO "driver %s\n", hcd_name); |
3234 | __DATE__); | ||
3235 | workqueue = create_singlethread_workqueue("u132"); | 3234 | workqueue = create_singlethread_workqueue("u132"); |
3236 | retval = platform_driver_register(&u132_platform_driver); | 3235 | retval = platform_driver_register(&u132_platform_driver); |
3237 | return retval; | 3236 | return retval; |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4f65b14e5e08..83344d688ff0 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -139,10 +139,7 @@ static void finish_reset(struct uhci_hcd *uhci) | |||
139 | uhci->port_c_suspend = uhci->resuming_ports = 0; | 139 | uhci->port_c_suspend = uhci->resuming_ports = 0; |
140 | uhci->rh_state = UHCI_RH_RESET; | 140 | uhci->rh_state = UHCI_RH_RESET; |
141 | uhci->is_stopped = UHCI_IS_STOPPED; | 141 | uhci->is_stopped = UHCI_IS_STOPPED; |
142 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; | ||
143 | clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); | 142 | clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); |
144 | |||
145 | uhci->dead = 0; /* Full reset resurrects the controller */ | ||
146 | } | 143 | } |
147 | 144 | ||
148 | /* | 145 | /* |
@@ -188,10 +185,6 @@ static void configure_hc(struct uhci_hcd *uhci) | |||
188 | outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, | 185 | outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, |
189 | uhci->io_addr + USBFRNUM); | 186 | uhci->io_addr + USBFRNUM); |
190 | 187 | ||
191 | /* Mark controller as not halted before we enable interrupts */ | ||
192 | uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; | ||
193 | mb(); | ||
194 | |||
195 | /* Enable PIRQ */ | 188 | /* Enable PIRQ */ |
196 | pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT); | 189 | pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT); |
197 | 190 | ||
@@ -360,7 +353,6 @@ __acquires(uhci->lock) | |||
360 | 353 | ||
361 | static void start_rh(struct uhci_hcd *uhci) | 354 | static void start_rh(struct uhci_hcd *uhci) |
362 | { | 355 | { |
363 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | ||
364 | uhci->is_stopped = 0; | 356 | uhci->is_stopped = 0; |
365 | 357 | ||
366 | /* Mark it configured and running with a 64-byte max packet. | 358 | /* Mark it configured and running with a 64-byte max packet. |
@@ -449,6 +441,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) | |||
449 | lprintk(errbuf); | 441 | lprintk(errbuf); |
450 | } | 442 | } |
451 | uhci_hc_died(uhci); | 443 | uhci_hc_died(uhci); |
444 | usb_hc_died(hcd); | ||
452 | 445 | ||
453 | /* Force a callback in case there are | 446 | /* Force a callback in case there are |
454 | * pending unlinks */ | 447 | * pending unlinks */ |
@@ -842,16 +835,17 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) | |||
842 | spin_lock_irq(&uhci->lock); | 835 | spin_lock_irq(&uhci->lock); |
843 | 836 | ||
844 | /* Make sure resume from hibernation re-enumerates everything */ | 837 | /* Make sure resume from hibernation re-enumerates everything */ |
845 | if (hibernated) | 838 | if (hibernated) { |
846 | uhci_hc_died(uhci); | 839 | uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); |
840 | finish_reset(uhci); | ||
841 | } | ||
847 | 842 | ||
848 | /* The firmware or a boot kernel may have changed the controller | 843 | /* The firmware may have changed the controller settings during |
849 | * settings during a system wakeup. Check it and reconfigure | 844 | * a system wakeup. Check it and reconfigure to avoid problems. |
850 | * to avoid problems. | ||
851 | */ | 845 | */ |
852 | check_and_reset_hc(uhci); | 846 | else { |
853 | 847 | check_and_reset_hc(uhci); | |
854 | /* If the controller was dead before, it's back alive now */ | 848 | } |
855 | configure_hc(uhci); | 849 | configure_hc(uhci); |
856 | 850 | ||
857 | /* Tell the core if the controller had to be reset */ | 851 | /* Tell the core if the controller had to be reset */ |
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 7839c98fa742..b16bd3ce3915 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c | |||
@@ -2889,8 +2889,7 @@ static struct usb_driver ftdi_elan_driver = { | |||
2889 | static int __init ftdi_elan_init(void) | 2889 | static int __init ftdi_elan_init(void) |
2890 | { | 2890 | { |
2891 | int result; | 2891 | int result; |
2892 | printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, | 2892 | printk(KERN_INFO "driver %s\n", ftdi_elan_driver.name); |
2893 | __TIME__, __DATE__); | ||
2894 | mutex_init(&ftdi_module_lock); | 2893 | mutex_init(&ftdi_module_lock); |
2895 | INIT_LIST_HEAD(&ftdi_static_list); | 2894 | INIT_LIST_HEAD(&ftdi_static_list); |
2896 | status_queue = create_singlethread_workqueue("ftdi-status-control"); | 2895 | status_queue = create_singlethread_workqueue("ftdi-status-control"); |
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index e01b073cc489..efeb4d1517ff 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -160,6 +160,7 @@ struct twl4030_usb { | |||
160 | 160 | ||
161 | int irq; | 161 | int irq; |
162 | u8 linkstat; | 162 | u8 linkstat; |
163 | bool vbus_supplied; | ||
163 | u8 asleep; | 164 | u8 asleep; |
164 | bool irq_enabled; | 165 | bool irq_enabled; |
165 | }; | 166 | }; |
@@ -250,6 +251,8 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
250 | int status; | 251 | int status; |
251 | int linkstat = USB_EVENT_NONE; | 252 | int linkstat = USB_EVENT_NONE; |
252 | 253 | ||
254 | twl->vbus_supplied = false; | ||
255 | |||
253 | /* | 256 | /* |
254 | * For ID/VBUS sensing, see manual section 15.4.8 ... | 257 | * For ID/VBUS sensing, see manual section 15.4.8 ... |
255 | * except when using only battery backup power, two | 258 | * except when using only battery backup power, two |
@@ -265,6 +268,9 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
265 | if (status < 0) | 268 | if (status < 0) |
266 | dev_err(twl->dev, "USB link status err %d\n", status); | 269 | dev_err(twl->dev, "USB link status err %d\n", status); |
267 | else if (status & (BIT(7) | BIT(2))) { | 270 | else if (status & (BIT(7) | BIT(2))) { |
271 | if (status & (BIT(7))) | ||
272 | twl->vbus_supplied = true; | ||
273 | |||
268 | if (status & BIT(2)) | 274 | if (status & BIT(2)) |
269 | linkstat = USB_EVENT_ID; | 275 | linkstat = USB_EVENT_ID; |
270 | else | 276 | else |
@@ -484,7 +490,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev, | |||
484 | 490 | ||
485 | spin_lock_irqsave(&twl->lock, flags); | 491 | spin_lock_irqsave(&twl->lock, flags); |
486 | ret = sprintf(buf, "%s\n", | 492 | ret = sprintf(buf, "%s\n", |
487 | (twl->linkstat == USB_EVENT_VBUS) ? "on" : "off"); | 493 | twl->vbus_supplied ? "on" : "off"); |
488 | spin_unlock_irqrestore(&twl->lock, flags); | 494 | spin_unlock_irqrestore(&twl->lock, flags); |
489 | 495 | ||
490 | return ret; | 496 | return ret; |
@@ -608,6 +614,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
608 | twl->otg.set_peripheral = twl4030_set_peripheral; | 614 | twl->otg.set_peripheral = twl4030_set_peripheral; |
609 | twl->otg.set_suspend = twl4030_set_suspend; | 615 | twl->otg.set_suspend = twl4030_set_suspend; |
610 | twl->usb_mode = pdata->usb_mode; | 616 | twl->usb_mode = pdata->usb_mode; |
617 | twl->vbus_supplied = false; | ||
611 | twl->asleep = 1; | 618 | twl->asleep = 1; |
612 | 619 | ||
613 | /* init spinlock for workqueue */ | 620 | /* init spinlock for workqueue */ |
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 8a91b4b832a1..6e920de64ef6 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -101,7 +101,7 @@ struct twl6030_usb { | |||
101 | bool irq_enabled; | 101 | bool irq_enabled; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg); | 104 | #define xceiv_to_twl(x) container_of((x), struct twl6030_usb, otg) |
105 | 105 | ||
106 | /*-------------------------------------------------------------------------*/ | 106 | /*-------------------------------------------------------------------------*/ |
107 | 107 | ||
diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig new file mode 100644 index 000000000000..481490e5500a --- /dev/null +++ b/drivers/usb/renesas_usbhs/Kconfig | |||
@@ -0,0 +1,15 @@ | |||
1 | # | ||
2 | # Renesas USB Controller Drivers | ||
3 | # | ||
4 | |||
5 | config USB_RENESAS_USBHS | ||
6 | tristate 'Renesas USBHS controller' | ||
7 | default n | ||
8 | help | ||
9 | Renesas USBHS is a discrete USB host and peripheral controller chip | ||
10 | that supports both full and high speed USB 2.0 data transfers. | ||
11 | It has nine or more configurable endpoints, and endpoint zero. | ||
12 | |||
13 | Say "y" to link the driver statically, or "m" to build a | ||
14 | dynamically linked module called "renesas_usbhs" and force all | ||
15 | gadget drivers to also be dynamically linked. | ||
diff --git a/drivers/usb/renesas_usbhs/Makefile b/drivers/usb/renesas_usbhs/Makefile new file mode 100644 index 000000000000..b8798ad16278 --- /dev/null +++ b/drivers/usb/renesas_usbhs/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # | ||
2 | # for Renesas USB | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o | ||
6 | |||
7 | renesas_usbhs-y := common.o mod.o pipe.o | ||
8 | |||
9 | renesas_usbhs-$(CONFIG_USB_RENESAS_USBHS_UDC) += mod_gadget.o | ||
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c new file mode 100644 index 000000000000..d9ad60d1c156 --- /dev/null +++ b/drivers/usb/renesas_usbhs/common.c | |||
@@ -0,0 +1,394 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
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 St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/sysfs.h> | ||
22 | #include "./common.h" | ||
23 | |||
24 | /* | ||
25 | * platform call back | ||
26 | * | ||
27 | * renesas usb support platform callback function. | ||
28 | * Below macro call it. | ||
29 | * if platform doesn't have callback, it return 0 (no error) | ||
30 | */ | ||
31 | #define usbhs_platform_call(priv, func, args...)\ | ||
32 | (!(priv) ? -ENODEV : \ | ||
33 | !((priv)->pfunc->func) ? 0 : \ | ||
34 | (priv)->pfunc->func(args)) | ||
35 | |||
36 | /* | ||
37 | * common functions | ||
38 | */ | ||
39 | u16 usbhs_read(struct usbhs_priv *priv, u32 reg) | ||
40 | { | ||
41 | return ioread16(priv->base + reg); | ||
42 | } | ||
43 | |||
44 | void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data) | ||
45 | { | ||
46 | iowrite16(data, priv->base + reg); | ||
47 | } | ||
48 | |||
49 | void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data) | ||
50 | { | ||
51 | u16 val = usbhs_read(priv, reg); | ||
52 | |||
53 | val &= ~mask; | ||
54 | val |= data & mask; | ||
55 | |||
56 | usbhs_write(priv, reg, val); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * syscfg functions | ||
61 | */ | ||
62 | void usbhs_sys_clock_ctrl(struct usbhs_priv *priv, int enable) | ||
63 | { | ||
64 | usbhs_bset(priv, SYSCFG, SCKE, enable ? SCKE : 0); | ||
65 | } | ||
66 | |||
67 | void usbhs_sys_hispeed_ctrl(struct usbhs_priv *priv, int enable) | ||
68 | { | ||
69 | usbhs_bset(priv, SYSCFG, HSE, enable ? HSE : 0); | ||
70 | } | ||
71 | |||
72 | void usbhs_sys_usb_ctrl(struct usbhs_priv *priv, int enable) | ||
73 | { | ||
74 | usbhs_bset(priv, SYSCFG, USBE, enable ? USBE : 0); | ||
75 | } | ||
76 | |||
77 | void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable) | ||
78 | { | ||
79 | u16 mask = DCFM | DRPD | DPRPU; | ||
80 | u16 val = DCFM | DRPD; | ||
81 | |||
82 | /* | ||
83 | * if enable | ||
84 | * | ||
85 | * - select Host mode | ||
86 | * - D+ Line/D- Line Pull-down | ||
87 | */ | ||
88 | usbhs_bset(priv, SYSCFG, mask, enable ? val : 0); | ||
89 | } | ||
90 | |||
91 | void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable) | ||
92 | { | ||
93 | u16 mask = DCFM | DRPD | DPRPU; | ||
94 | u16 val = DPRPU; | ||
95 | |||
96 | /* | ||
97 | * if enable | ||
98 | * | ||
99 | * - select Function mode | ||
100 | * - D+ Line Pull-up | ||
101 | */ | ||
102 | usbhs_bset(priv, SYSCFG, mask, enable ? val : 0); | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * frame functions | ||
107 | */ | ||
108 | int usbhs_frame_get_num(struct usbhs_priv *priv) | ||
109 | { | ||
110 | return usbhs_read(priv, FRMNUM) & FRNM_MASK; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * local functions | ||
115 | */ | ||
116 | static struct usbhs_priv *usbhsc_pdev_to_priv(struct platform_device *pdev) | ||
117 | { | ||
118 | return dev_get_drvdata(&pdev->dev); | ||
119 | } | ||
120 | |||
121 | static void usbhsc_bus_ctrl(struct usbhs_priv *priv, int enable) | ||
122 | { | ||
123 | int wait = usbhs_get_dparam(priv, buswait_bwait); | ||
124 | u16 data = 0; | ||
125 | |||
126 | if (enable) { | ||
127 | /* set bus wait if platform have */ | ||
128 | if (wait) | ||
129 | usbhs_bset(priv, BUSWAIT, 0x000F, wait); | ||
130 | } | ||
131 | usbhs_write(priv, DVSTCTR, data); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * platform default param | ||
136 | */ | ||
137 | static u32 usbhsc_default_pipe_type[] = { | ||
138 | USB_ENDPOINT_XFER_CONTROL, | ||
139 | USB_ENDPOINT_XFER_ISOC, | ||
140 | USB_ENDPOINT_XFER_ISOC, | ||
141 | USB_ENDPOINT_XFER_BULK, | ||
142 | USB_ENDPOINT_XFER_BULK, | ||
143 | USB_ENDPOINT_XFER_BULK, | ||
144 | USB_ENDPOINT_XFER_INT, | ||
145 | USB_ENDPOINT_XFER_INT, | ||
146 | USB_ENDPOINT_XFER_INT, | ||
147 | USB_ENDPOINT_XFER_INT, | ||
148 | }; | ||
149 | |||
150 | /* | ||
151 | * driver callback functions | ||
152 | */ | ||
153 | static void usbhsc_notify_hotplug(struct work_struct *work) | ||
154 | { | ||
155 | struct usbhs_priv *priv = container_of(work, | ||
156 | struct usbhs_priv, | ||
157 | notify_hotplug_work); | ||
158 | struct platform_device *pdev = usbhs_priv_to_pdev(priv); | ||
159 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
160 | int id; | ||
161 | int enable; | ||
162 | int ret; | ||
163 | |||
164 | /* | ||
165 | * get vbus status from platform | ||
166 | */ | ||
167 | enable = usbhs_platform_call(priv, get_vbus, pdev); | ||
168 | |||
169 | /* | ||
170 | * get id from platform | ||
171 | */ | ||
172 | id = usbhs_platform_call(priv, get_id, pdev); | ||
173 | |||
174 | if (enable && !mod) { | ||
175 | ret = usbhs_mod_change(priv, id); | ||
176 | if (ret < 0) | ||
177 | return; | ||
178 | |||
179 | dev_dbg(&pdev->dev, "%s enable\n", __func__); | ||
180 | |||
181 | /* enable PM */ | ||
182 | pm_runtime_get_sync(&pdev->dev); | ||
183 | |||
184 | /* USB on */ | ||
185 | usbhs_sys_clock_ctrl(priv, enable); | ||
186 | usbhsc_bus_ctrl(priv, enable); | ||
187 | |||
188 | /* module start */ | ||
189 | usbhs_mod_call(priv, start, priv); | ||
190 | |||
191 | } else if (!enable && mod) { | ||
192 | dev_dbg(&pdev->dev, "%s disable\n", __func__); | ||
193 | |||
194 | /* module stop */ | ||
195 | usbhs_mod_call(priv, stop, priv); | ||
196 | |||
197 | /* USB off */ | ||
198 | usbhsc_bus_ctrl(priv, enable); | ||
199 | usbhs_sys_clock_ctrl(priv, enable); | ||
200 | |||
201 | /* disable PM */ | ||
202 | pm_runtime_put_sync(&pdev->dev); | ||
203 | |||
204 | usbhs_mod_change(priv, -1); | ||
205 | |||
206 | /* reset phy for next connection */ | ||
207 | usbhs_platform_call(priv, phy_reset, pdev); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) | ||
212 | { | ||
213 | struct usbhs_priv *priv = usbhsc_pdev_to_priv(pdev); | ||
214 | |||
215 | /* | ||
216 | * This functions will be called in interrupt. | ||
217 | * To make sure safety context, | ||
218 | * use workqueue for usbhs_notify_hotplug | ||
219 | */ | ||
220 | schedule_work(&priv->notify_hotplug_work); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * platform functions | ||
226 | */ | ||
227 | static int __devinit usbhs_probe(struct platform_device *pdev) | ||
228 | { | ||
229 | struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; | ||
230 | struct renesas_usbhs_driver_callback *dfunc; | ||
231 | struct usbhs_priv *priv; | ||
232 | struct resource *res; | ||
233 | unsigned int irq; | ||
234 | int ret; | ||
235 | |||
236 | /* check platform information */ | ||
237 | if (!info || | ||
238 | !info->platform_callback.get_id || | ||
239 | !info->platform_callback.get_vbus) { | ||
240 | dev_err(&pdev->dev, "no platform information\n"); | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | |||
244 | /* platform data */ | ||
245 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
246 | irq = platform_get_irq(pdev, 0); | ||
247 | if (!res || (int)irq <= 0) { | ||
248 | dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n"); | ||
249 | return -ENODEV; | ||
250 | } | ||
251 | |||
252 | /* usb private data */ | ||
253 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
254 | if (!priv) { | ||
255 | dev_err(&pdev->dev, "Could not allocate priv\n"); | ||
256 | return -ENOMEM; | ||
257 | } | ||
258 | |||
259 | priv->base = ioremap_nocache(res->start, resource_size(res)); | ||
260 | if (!priv->base) { | ||
261 | dev_err(&pdev->dev, "ioremap error.\n"); | ||
262 | ret = -ENOMEM; | ||
263 | goto probe_end_kfree; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * care platform info | ||
268 | */ | ||
269 | priv->pfunc = &info->platform_callback; | ||
270 | priv->dparam = &info->driver_param; | ||
271 | |||
272 | /* set driver callback functions for platform */ | ||
273 | dfunc = &info->driver_callback; | ||
274 | dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug; | ||
275 | |||
276 | /* set default param if platform doesn't have */ | ||
277 | if (!priv->dparam->pipe_type) { | ||
278 | priv->dparam->pipe_type = usbhsc_default_pipe_type; | ||
279 | priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * priv settings | ||
284 | */ | ||
285 | priv->irq = irq; | ||
286 | priv->pdev = pdev; | ||
287 | INIT_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug); | ||
288 | spin_lock_init(usbhs_priv_to_lock(priv)); | ||
289 | |||
290 | /* call pipe and module init */ | ||
291 | ret = usbhs_pipe_probe(priv); | ||
292 | if (ret < 0) | ||
293 | goto probe_end_mod_exit; | ||
294 | |||
295 | ret = usbhs_mod_probe(priv); | ||
296 | if (ret < 0) | ||
297 | goto probe_end_iounmap; | ||
298 | |||
299 | /* dev_set_drvdata should be called after usbhs_mod_init */ | ||
300 | dev_set_drvdata(&pdev->dev, priv); | ||
301 | |||
302 | /* | ||
303 | * deviece reset here because | ||
304 | * USB device might be used in boot loader. | ||
305 | */ | ||
306 | usbhs_sys_clock_ctrl(priv, 0); | ||
307 | |||
308 | /* | ||
309 | * platform call | ||
310 | * | ||
311 | * USB phy setup might depend on CPU/Board. | ||
312 | * If platform has its callback functions, | ||
313 | * call it here. | ||
314 | */ | ||
315 | ret = usbhs_platform_call(priv, hardware_init, pdev); | ||
316 | if (ret < 0) { | ||
317 | dev_err(&pdev->dev, "platform prove failed.\n"); | ||
318 | goto probe_end_pipe_exit; | ||
319 | } | ||
320 | |||
321 | /* reset phy for connection */ | ||
322 | usbhs_platform_call(priv, phy_reset, pdev); | ||
323 | |||
324 | /* | ||
325 | * manual call notify_hotplug for cold plug | ||
326 | */ | ||
327 | pm_runtime_enable(&pdev->dev); | ||
328 | ret = usbhsc_drvcllbck_notify_hotplug(pdev); | ||
329 | if (ret < 0) | ||
330 | goto probe_end_call_remove; | ||
331 | |||
332 | dev_info(&pdev->dev, "probed\n"); | ||
333 | |||
334 | return ret; | ||
335 | |||
336 | probe_end_call_remove: | ||
337 | usbhs_platform_call(priv, hardware_exit, pdev); | ||
338 | probe_end_pipe_exit: | ||
339 | usbhs_pipe_remove(priv); | ||
340 | probe_end_mod_exit: | ||
341 | usbhs_mod_remove(priv); | ||
342 | probe_end_iounmap: | ||
343 | iounmap(priv->base); | ||
344 | probe_end_kfree: | ||
345 | kfree(priv); | ||
346 | |||
347 | dev_info(&pdev->dev, "probe failed\n"); | ||
348 | |||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static int __devexit usbhs_remove(struct platform_device *pdev) | ||
353 | { | ||
354 | struct usbhs_priv *priv = usbhsc_pdev_to_priv(pdev); | ||
355 | |||
356 | dev_dbg(&pdev->dev, "usb remove\n"); | ||
357 | |||
358 | pm_runtime_disable(&pdev->dev); | ||
359 | |||
360 | usbhsc_bus_ctrl(priv, 0); | ||
361 | |||
362 | usbhs_platform_call(priv, hardware_exit, pdev); | ||
363 | usbhs_pipe_remove(priv); | ||
364 | usbhs_mod_remove(priv); | ||
365 | iounmap(priv->base); | ||
366 | kfree(priv); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static struct platform_driver renesas_usbhs_driver = { | ||
372 | .driver = { | ||
373 | .name = "renesas_usbhs", | ||
374 | }, | ||
375 | .probe = usbhs_probe, | ||
376 | .remove = __devexit_p(usbhs_remove), | ||
377 | }; | ||
378 | |||
379 | static int __init usbhs_init(void) | ||
380 | { | ||
381 | return platform_driver_register(&renesas_usbhs_driver); | ||
382 | } | ||
383 | |||
384 | static void __exit usbhs_exit(void) | ||
385 | { | ||
386 | platform_driver_unregister(&renesas_usbhs_driver); | ||
387 | } | ||
388 | |||
389 | module_init(usbhs_init); | ||
390 | module_exit(usbhs_exit); | ||
391 | |||
392 | MODULE_LICENSE("GPL"); | ||
393 | MODULE_DESCRIPTION("Renesas USB driver"); | ||
394 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | ||
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h new file mode 100644 index 000000000000..f1a2b62f93f9 --- /dev/null +++ b/drivers/usb/renesas_usbhs/common.h | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
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 St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #ifndef RENESAS_USB_DRIVER_H | ||
18 | #define RENESAS_USB_DRIVER_H | ||
19 | |||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/usb/renesas_usbhs.h> | ||
22 | |||
23 | struct usbhs_priv; | ||
24 | |||
25 | #include "./mod.h" | ||
26 | #include "./pipe.h" | ||
27 | |||
28 | /* | ||
29 | * | ||
30 | * register define | ||
31 | * | ||
32 | */ | ||
33 | #define SYSCFG 0x0000 | ||
34 | #define BUSWAIT 0x0002 | ||
35 | #define DVSTCTR 0x0008 | ||
36 | #define CFIFO 0x0014 | ||
37 | #define CFIFOSEL 0x0020 | ||
38 | #define CFIFOCTR 0x0022 | ||
39 | #define INTENB0 0x0030 | ||
40 | #define INTENB1 0x0032 | ||
41 | #define BRDYENB 0x0036 | ||
42 | #define NRDYENB 0x0038 | ||
43 | #define BEMPENB 0x003A | ||
44 | #define INTSTS0 0x0040 | ||
45 | #define INTSTS1 0x0042 | ||
46 | #define BRDYSTS 0x0046 | ||
47 | #define NRDYSTS 0x0048 | ||
48 | #define BEMPSTS 0x004A | ||
49 | #define FRMNUM 0x004C | ||
50 | #define USBREQ 0x0054 /* USB request type register */ | ||
51 | #define USBVAL 0x0056 /* USB request value register */ | ||
52 | #define USBINDX 0x0058 /* USB request index register */ | ||
53 | #define USBLENG 0x005A /* USB request length register */ | ||
54 | #define DCPCFG 0x005C | ||
55 | #define DCPMAXP 0x005E | ||
56 | #define DCPCTR 0x0060 | ||
57 | #define PIPESEL 0x0064 | ||
58 | #define PIPECFG 0x0068 | ||
59 | #define PIPEBUF 0x006A | ||
60 | #define PIPEMAXP 0x006C | ||
61 | #define PIPEPERI 0x006E | ||
62 | #define PIPEnCTR 0x0070 | ||
63 | |||
64 | /* SYSCFG */ | ||
65 | #define SCKE (1 << 10) /* USB Module Clock Enable */ | ||
66 | #define HSE (1 << 7) /* High-Speed Operation Enable */ | ||
67 | #define DCFM (1 << 6) /* Controller Function Select */ | ||
68 | #define DRPD (1 << 5) /* D+ Line/D- Line Resistance Control */ | ||
69 | #define DPRPU (1 << 4) /* D+ Line Resistance Control */ | ||
70 | #define USBE (1 << 0) /* USB Module Operation Enable */ | ||
71 | |||
72 | /* DVSTCTR */ | ||
73 | #define EXTLP (1 << 10) /* Controls the EXTLP pin output state */ | ||
74 | #define PWEN (1 << 9) /* Controls the PWEN pin output state */ | ||
75 | #define RHST (0x7) /* Reset Handshake */ | ||
76 | #define RHST_LOW_SPEED 1 /* Low-speed connection */ | ||
77 | #define RHST_FULL_SPEED 2 /* Full-speed connection */ | ||
78 | #define RHST_HIGH_SPEED 3 /* High-speed connection */ | ||
79 | |||
80 | /* CFIFOSEL */ | ||
81 | #define MBW_32 (0x2 << 10) /* CFIFO Port Access Bit Width */ | ||
82 | |||
83 | /* CFIFOCTR */ | ||
84 | #define BVAL (1 << 15) /* Buffer Memory Enable Flag */ | ||
85 | #define BCLR (1 << 14) /* CPU buffer clear */ | ||
86 | #define FRDY (1 << 13) /* FIFO Port Ready */ | ||
87 | #define DTLN_MASK (0x0FFF) /* Receive Data Length */ | ||
88 | |||
89 | /* INTENB0 */ | ||
90 | #define VBSE (1 << 15) /* Enable IRQ VBUS_0 and VBUSIN_0 */ | ||
91 | #define RSME (1 << 14) /* Enable IRQ Resume */ | ||
92 | #define SOFE (1 << 13) /* Enable IRQ Frame Number Update */ | ||
93 | #define DVSE (1 << 12) /* Enable IRQ Device State Transition */ | ||
94 | #define CTRE (1 << 11) /* Enable IRQ Control Stage Transition */ | ||
95 | #define BEMPE (1 << 10) /* Enable IRQ Buffer Empty */ | ||
96 | #define NRDYE (1 << 9) /* Enable IRQ Buffer Not Ready Response */ | ||
97 | #define BRDYE (1 << 8) /* Enable IRQ Buffer Ready */ | ||
98 | |||
99 | /* INTENB1 */ | ||
100 | #define BCHGE (1 << 14) /* USB Bus Change Interrupt Enable */ | ||
101 | #define DTCHE (1 << 12) /* Disconnection Detect Interrupt Enable */ | ||
102 | #define ATTCHE (1 << 11) /* Connection Detect Interrupt Enable */ | ||
103 | #define EOFERRE (1 << 6) /* EOF Error Detect Interrupt Enable */ | ||
104 | #define SIGNE (1 << 5) /* Setup Transaction Error Interrupt Enable */ | ||
105 | #define SACKE (1 << 4) /* Setup Transaction ACK Interrupt Enable */ | ||
106 | |||
107 | /* INTSTS0 */ | ||
108 | #define DVST (1 << 12) /* Device State Transition Interrupt Status */ | ||
109 | #define CTRT (1 << 11) /* Control Stage Interrupt Status */ | ||
110 | #define BEMP (1 << 10) /* Buffer Empty Interrupt Status */ | ||
111 | #define BRDY (1 << 8) /* Buffer Ready Interrupt Status */ | ||
112 | #define VBSTS (1 << 7) /* VBUS_0 and VBUSIN_0 Input Status */ | ||
113 | #define VALID (1 << 3) /* USB Request Receive */ | ||
114 | |||
115 | #define DVSQ_MASK (0x3 << 4) /* Device State */ | ||
116 | #define POWER_STATE (0 << 4) | ||
117 | #define DEFAULT_STATE (1 << 4) | ||
118 | #define ADDRESS_STATE (2 << 4) | ||
119 | #define CONFIGURATION_STATE (3 << 4) | ||
120 | |||
121 | #define CTSQ_MASK (0x7) /* Control Transfer Stage */ | ||
122 | #define IDLE_SETUP_STAGE 0 /* Idle stage or setup stage */ | ||
123 | #define READ_DATA_STAGE 1 /* Control read data stage */ | ||
124 | #define READ_STATUS_STAGE 2 /* Control read status stage */ | ||
125 | #define WRITE_DATA_STAGE 3 /* Control write data stage */ | ||
126 | #define WRITE_STATUS_STAGE 4 /* Control write status stage */ | ||
127 | #define NODATA_STATUS_STAGE 5 /* Control write NoData status stage */ | ||
128 | #define SEQUENCE_ERROR 6 /* Control transfer sequence error */ | ||
129 | |||
130 | /* PIPECFG */ | ||
131 | /* DCPCFG */ | ||
132 | #define TYPE_NONE (0 << 14) /* Transfer Type */ | ||
133 | #define TYPE_BULK (1 << 14) | ||
134 | #define TYPE_INT (2 << 14) | ||
135 | #define TYPE_ISO (3 << 14) | ||
136 | #define DBLB (1 << 9) /* Double Buffer Mode */ | ||
137 | #define SHTNAK (1 << 7) /* Pipe Disable in Transfer End */ | ||
138 | #define DIR_OUT (1 << 4) /* Transfer Direction */ | ||
139 | |||
140 | /* PIPEMAXP */ | ||
141 | /* DCPMAXP */ | ||
142 | #define DEVSEL_MASK (0xF << 12) /* Device Select */ | ||
143 | #define DCP_MAXP_MASK (0x7F) | ||
144 | #define PIPE_MAXP_MASK (0x7FF) | ||
145 | |||
146 | /* PIPEBUF */ | ||
147 | #define BUFSIZE_SHIFT 10 | ||
148 | #define BUFSIZE_MASK (0x1F << BUFSIZE_SHIFT) | ||
149 | #define BUFNMB_MASK (0xFF) | ||
150 | |||
151 | /* PIPEnCTR */ | ||
152 | /* DCPCTR */ | ||
153 | #define BSTS (1 << 15) /* Buffer Status */ | ||
154 | #define CSSTS (1 << 12) /* CSSTS Status */ | ||
155 | #define SQCLR (1 << 8) /* Toggle Bit Clear */ | ||
156 | #define ACLRM (1 << 9) /* Buffer Auto-Clear Mode */ | ||
157 | #define PBUSY (1 << 5) /* Pipe Busy */ | ||
158 | #define PID_MASK (0x3) /* Response PID */ | ||
159 | #define PID_NAK 0 | ||
160 | #define PID_BUF 1 | ||
161 | #define PID_STALL10 2 | ||
162 | #define PID_STALL11 3 | ||
163 | |||
164 | #define CCPL (1 << 2) /* Control Transfer End Enable */ | ||
165 | |||
166 | /* FRMNUM */ | ||
167 | #define FRNM_MASK (0x7FF) | ||
168 | |||
169 | /* | ||
170 | * struct | ||
171 | */ | ||
172 | struct usbhs_priv { | ||
173 | |||
174 | void __iomem *base; | ||
175 | unsigned int irq; | ||
176 | |||
177 | struct renesas_usbhs_platform_callback *pfunc; | ||
178 | struct renesas_usbhs_driver_param *dparam; | ||
179 | |||
180 | struct work_struct notify_hotplug_work; | ||
181 | struct platform_device *pdev; | ||
182 | |||
183 | spinlock_t lock; | ||
184 | |||
185 | /* | ||
186 | * module control | ||
187 | */ | ||
188 | struct usbhs_mod_info mod_info; | ||
189 | |||
190 | /* | ||
191 | * pipe control | ||
192 | */ | ||
193 | struct usbhs_pipe_info pipe_info; | ||
194 | }; | ||
195 | |||
196 | /* | ||
197 | * common | ||
198 | */ | ||
199 | u16 usbhs_read(struct usbhs_priv *priv, u32 reg); | ||
200 | void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data); | ||
201 | void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data); | ||
202 | |||
203 | /* | ||
204 | * sysconfig | ||
205 | */ | ||
206 | void usbhs_sys_clock_ctrl(struct usbhs_priv *priv, int enable); | ||
207 | void usbhs_sys_hispeed_ctrl(struct usbhs_priv *priv, int enable); | ||
208 | void usbhs_sys_usb_ctrl(struct usbhs_priv *priv, int enable); | ||
209 | void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable); | ||
210 | void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable); | ||
211 | |||
212 | /* | ||
213 | * frame | ||
214 | */ | ||
215 | int usbhs_frame_get_num(struct usbhs_priv *priv); | ||
216 | |||
217 | /* | ||
218 | * data | ||
219 | */ | ||
220 | #define usbhs_get_dparam(priv, param) (priv->dparam->param) | ||
221 | #define usbhs_priv_to_pdev(priv) (priv->pdev) | ||
222 | #define usbhs_priv_to_dev(priv) (&priv->pdev->dev) | ||
223 | #define usbhs_priv_to_lock(priv) (&priv->lock) | ||
224 | |||
225 | #endif /* RENESAS_USB_DRIVER_H */ | ||
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c new file mode 100644 index 000000000000..73604a1d6843 --- /dev/null +++ b/drivers/usb/renesas_usbhs/mod.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
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 St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/interrupt.h> | ||
18 | |||
19 | #include "./common.h" | ||
20 | #include "./mod.h" | ||
21 | |||
22 | #define usbhs_priv_to_modinfo(priv) (&priv->mod_info) | ||
23 | |||
24 | /* | ||
25 | * host / gadget functions | ||
26 | * | ||
27 | * renesas_usbhs host/gadget can register itself by below functions. | ||
28 | * these functions are called when probe | ||
29 | * | ||
30 | */ | ||
31 | void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id) | ||
32 | { | ||
33 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | ||
34 | |||
35 | info->mod[id] = mod; | ||
36 | mod->priv = priv; | ||
37 | } | ||
38 | |||
39 | struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id) | ||
40 | { | ||
41 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | ||
42 | struct usbhs_mod *ret = NULL; | ||
43 | |||
44 | switch (id) { | ||
45 | case USBHS_HOST: | ||
46 | case USBHS_GADGET: | ||
47 | ret = info->mod[id]; | ||
48 | break; | ||
49 | } | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | int usbhs_mod_is_host(struct usbhs_priv *priv, struct usbhs_mod *mod) | ||
55 | { | ||
56 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | ||
57 | |||
58 | if (!mod) | ||
59 | return -EINVAL; | ||
60 | |||
61 | return info->mod[USBHS_HOST] == mod; | ||
62 | } | ||
63 | |||
64 | struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv) | ||
65 | { | ||
66 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | ||
67 | |||
68 | return info->curt; | ||
69 | } | ||
70 | |||
71 | int usbhs_mod_change(struct usbhs_priv *priv, int id) | ||
72 | { | ||
73 | struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); | ||
74 | struct usbhs_mod *mod = NULL; | ||
75 | int ret = 0; | ||
76 | |||
77 | /* id < 0 mean no current */ | ||
78 | switch (id) { | ||
79 | case USBHS_HOST: | ||
80 | case USBHS_GADGET: | ||
81 | mod = info->mod[id]; | ||
82 | break; | ||
83 | default: | ||
84 | ret = -EINVAL; | ||
85 | } | ||
86 | info->curt = mod; | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | static irqreturn_t usbhs_interrupt(int irq, void *data); | ||
92 | int usbhs_mod_probe(struct usbhs_priv *priv) | ||
93 | { | ||
94 | struct device *dev = usbhs_priv_to_dev(priv); | ||
95 | int ret; | ||
96 | |||
97 | /* | ||
98 | * install host/gadget driver | ||
99 | */ | ||
100 | ret = usbhs_mod_gadget_probe(priv); | ||
101 | if (ret < 0) | ||
102 | return ret; | ||
103 | |||
104 | /* irq settings */ | ||
105 | ret = request_irq(priv->irq, usbhs_interrupt, | ||
106 | IRQF_DISABLED, dev_name(dev), priv); | ||
107 | if (ret) { | ||
108 | dev_err(dev, "irq request err\n"); | ||
109 | goto mod_init_gadget_err; | ||
110 | } | ||
111 | |||
112 | return ret; | ||
113 | |||
114 | mod_init_gadget_err: | ||
115 | usbhs_mod_gadget_remove(priv); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | void usbhs_mod_remove(struct usbhs_priv *priv) | ||
121 | { | ||
122 | usbhs_mod_gadget_remove(priv); | ||
123 | free_irq(priv->irq, priv); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * status functions | ||
128 | */ | ||
129 | int usbhs_status_get_usb_speed(struct usbhs_irq_state *irq_state) | ||
130 | { | ||
131 | switch (irq_state->dvstctr & RHST) { | ||
132 | case RHST_LOW_SPEED: | ||
133 | return USB_SPEED_LOW; | ||
134 | case RHST_FULL_SPEED: | ||
135 | return USB_SPEED_FULL; | ||
136 | case RHST_HIGH_SPEED: | ||
137 | return USB_SPEED_HIGH; | ||
138 | } | ||
139 | |||
140 | return USB_SPEED_UNKNOWN; | ||
141 | } | ||
142 | |||
143 | int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state) | ||
144 | { | ||
145 | int state = irq_state->intsts0 & DVSQ_MASK; | ||
146 | |||
147 | switch (state) { | ||
148 | case POWER_STATE: | ||
149 | case DEFAULT_STATE: | ||
150 | case ADDRESS_STATE: | ||
151 | case CONFIGURATION_STATE: | ||
152 | return state; | ||
153 | } | ||
154 | |||
155 | return -EIO; | ||
156 | } | ||
157 | |||
158 | int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state) | ||
159 | { | ||
160 | /* | ||
161 | * return value | ||
162 | * | ||
163 | * IDLE_SETUP_STAGE | ||
164 | * READ_DATA_STAGE | ||
165 | * READ_STATUS_STAGE | ||
166 | * WRITE_DATA_STAGE | ||
167 | * WRITE_STATUS_STAGE | ||
168 | * NODATA_STATUS_STAGE | ||
169 | * SEQUENCE_ERROR | ||
170 | */ | ||
171 | return (int)irq_state->intsts0 & CTSQ_MASK; | ||
172 | } | ||
173 | |||
174 | static void usbhs_status_get_each_irq(struct usbhs_priv *priv, | ||
175 | struct usbhs_irq_state *state) | ||
176 | { | ||
177 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
178 | |||
179 | state->intsts0 = usbhs_read(priv, INTSTS0); | ||
180 | state->intsts1 = usbhs_read(priv, INTSTS1); | ||
181 | |||
182 | state->brdysts = usbhs_read(priv, BRDYSTS); | ||
183 | state->nrdysts = usbhs_read(priv, NRDYSTS); | ||
184 | state->bempsts = usbhs_read(priv, BEMPSTS); | ||
185 | |||
186 | state->dvstctr = usbhs_read(priv, DVSTCTR); | ||
187 | |||
188 | /* mask */ | ||
189 | state->bempsts &= mod->irq_bempsts; | ||
190 | state->brdysts &= mod->irq_brdysts; | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * interrupt | ||
195 | */ | ||
196 | #define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */ | ||
197 | #define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */ | ||
198 | static irqreturn_t usbhs_interrupt(int irq, void *data) | ||
199 | { | ||
200 | struct usbhs_priv *priv = data; | ||
201 | struct usbhs_irq_state irq_state; | ||
202 | |||
203 | usbhs_status_get_each_irq(priv, &irq_state); | ||
204 | |||
205 | /* | ||
206 | * clear interrupt | ||
207 | * | ||
208 | * The hardware is _very_ picky to clear interrupt bit. | ||
209 | * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value. | ||
210 | * | ||
211 | * see | ||
212 | * "Operation" | ||
213 | * - "Control Transfer (DCP)" | ||
214 | * - Function :: VALID bit should 0 | ||
215 | */ | ||
216 | usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC); | ||
217 | usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC); | ||
218 | |||
219 | usbhs_write(priv, BRDYSTS, 0); | ||
220 | usbhs_write(priv, NRDYSTS, 0); | ||
221 | usbhs_write(priv, BEMPSTS, 0); | ||
222 | |||
223 | /* | ||
224 | * call irq callback functions | ||
225 | * see also | ||
226 | * usbhs_irq_setting_update | ||
227 | */ | ||
228 | if (irq_state.intsts0 & DVST) | ||
229 | usbhs_mod_call(priv, irq_dev_state, priv, &irq_state); | ||
230 | |||
231 | if (irq_state.intsts0 & CTRT) | ||
232 | usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state); | ||
233 | |||
234 | if (irq_state.intsts0 & BEMP) | ||
235 | usbhs_mod_call(priv, irq_empty, priv, &irq_state); | ||
236 | |||
237 | if (irq_state.intsts0 & BRDY) | ||
238 | usbhs_mod_call(priv, irq_ready, priv, &irq_state); | ||
239 | |||
240 | return IRQ_HANDLED; | ||
241 | } | ||
242 | |||
243 | void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) | ||
244 | { | ||
245 | u16 intenb0 = 0; | ||
246 | |||
247 | usbhs_write(priv, INTENB0, 0); | ||
248 | |||
249 | usbhs_write(priv, BEMPENB, 0); | ||
250 | usbhs_write(priv, BRDYENB, 0); | ||
251 | |||
252 | /* | ||
253 | * see also | ||
254 | * usbhs_interrupt | ||
255 | */ | ||
256 | |||
257 | /* | ||
258 | * it don't enable DVSE (intenb0) here | ||
259 | * but "mod->irq_dev_state" will be called. | ||
260 | */ | ||
261 | |||
262 | if (mod->irq_ctrl_stage) | ||
263 | intenb0 |= CTRE; | ||
264 | |||
265 | if (mod->irq_empty && mod->irq_bempsts) { | ||
266 | usbhs_write(priv, BEMPENB, mod->irq_bempsts); | ||
267 | intenb0 |= BEMPE; | ||
268 | } | ||
269 | |||
270 | if (mod->irq_ready && mod->irq_brdysts) { | ||
271 | usbhs_write(priv, BRDYENB, mod->irq_brdysts); | ||
272 | intenb0 |= BRDYE; | ||
273 | } | ||
274 | |||
275 | usbhs_write(priv, INTENB0, intenb0); | ||
276 | } | ||
diff --git a/drivers/usb/renesas_usbhs/mod.h b/drivers/usb/renesas_usbhs/mod.h new file mode 100644 index 000000000000..8644191e164f --- /dev/null +++ b/drivers/usb/renesas_usbhs/mod.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
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 St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #ifndef RENESAS_USB_MOD_H | ||
18 | #define RENESAS_USB_MOD_H | ||
19 | |||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/usb/renesas_usbhs.h> | ||
22 | #include "./common.h" | ||
23 | |||
24 | /* | ||
25 | * struct | ||
26 | */ | ||
27 | struct usbhs_irq_state { | ||
28 | u16 intsts0; | ||
29 | u16 intsts1; | ||
30 | u16 brdysts; | ||
31 | u16 nrdysts; | ||
32 | u16 bempsts; | ||
33 | u16 dvstctr; | ||
34 | }; | ||
35 | |||
36 | struct usbhs_mod { | ||
37 | char *name; | ||
38 | |||
39 | /* | ||
40 | * entry point from common.c | ||
41 | */ | ||
42 | int (*start)(struct usbhs_priv *priv); | ||
43 | int (*stop)(struct usbhs_priv *priv); | ||
44 | |||
45 | /* INTSTS0 :: DVST (DVSQ) */ | ||
46 | int (*irq_dev_state)(struct usbhs_priv *priv, | ||
47 | struct usbhs_irq_state *irq_state); | ||
48 | |||
49 | /* INTSTS0 :: CTRT (CTSQ) */ | ||
50 | int (*irq_ctrl_stage)(struct usbhs_priv *priv, | ||
51 | struct usbhs_irq_state *irq_state); | ||
52 | |||
53 | /* INTSTS0 :: BEMP */ | ||
54 | /* BEMPSTS */ | ||
55 | int (*irq_empty)(struct usbhs_priv *priv, | ||
56 | struct usbhs_irq_state *irq_state); | ||
57 | u16 irq_bempsts; | ||
58 | |||
59 | /* INTSTS0 :: BRDY */ | ||
60 | /* BRDYSTS */ | ||
61 | int (*irq_ready)(struct usbhs_priv *priv, | ||
62 | struct usbhs_irq_state *irq_state); | ||
63 | u16 irq_brdysts; | ||
64 | |||
65 | struct usbhs_priv *priv; | ||
66 | }; | ||
67 | |||
68 | struct usbhs_mod_info { | ||
69 | struct usbhs_mod *mod[USBHS_MAX]; | ||
70 | struct usbhs_mod *curt; /* current mod */ | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * for host/gadget module | ||
75 | */ | ||
76 | struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id); | ||
77 | struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv); | ||
78 | void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *usb, int id); | ||
79 | int usbhs_mod_is_host(struct usbhs_priv *priv, struct usbhs_mod *mod); | ||
80 | int usbhs_mod_change(struct usbhs_priv *priv, int id); | ||
81 | int usbhs_mod_probe(struct usbhs_priv *priv); | ||
82 | void usbhs_mod_remove(struct usbhs_priv *priv); | ||
83 | |||
84 | /* | ||
85 | * status functions | ||
86 | */ | ||
87 | int usbhs_status_get_usb_speed(struct usbhs_irq_state *irq_state); | ||
88 | int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state); | ||
89 | int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state); | ||
90 | |||
91 | /* | ||
92 | * callback functions | ||
93 | */ | ||
94 | void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod); | ||
95 | |||
96 | |||
97 | #define usbhs_mod_call(priv, func, param...) \ | ||
98 | ({ \ | ||
99 | struct usbhs_mod *mod; \ | ||
100 | mod = usbhs_mod_get_current(priv); \ | ||
101 | !mod ? -ENODEV : \ | ||
102 | !mod->func ? 0 : \ | ||
103 | mod->func(param); \ | ||
104 | }) | ||
105 | |||
106 | /* | ||
107 | * gadget control | ||
108 | */ | ||
109 | #ifdef CONFIG_USB_RENESAS_USBHS_UDC | ||
110 | extern int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv); | ||
111 | extern void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv); | ||
112 | #else | ||
113 | static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv) | ||
114 | { | ||
115 | return 0; | ||
116 | } | ||
117 | static inline void usbhs_mod_gadget_remove(struct usbhs_priv *priv) | ||
118 | { | ||
119 | } | ||
120 | #endif | ||
121 | |||
122 | #endif /* RENESAS_USB_MOD_H */ | ||
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c new file mode 100644 index 000000000000..9a5ac02077b9 --- /dev/null +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -0,0 +1,1341 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
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 St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/usb/ch9.h> | ||
21 | #include <linux/usb/gadget.h> | ||
22 | #include "common.h" | ||
23 | |||
24 | /* | ||
25 | * struct | ||
26 | */ | ||
27 | struct usbhsg_request { | ||
28 | struct usb_request req; | ||
29 | struct list_head node; | ||
30 | }; | ||
31 | |||
32 | #define EP_NAME_SIZE 8 | ||
33 | struct usbhsg_gpriv; | ||
34 | struct usbhsg_pipe_handle; | ||
35 | struct usbhsg_uep { | ||
36 | struct usb_ep ep; | ||
37 | struct usbhs_pipe *pipe; | ||
38 | struct list_head list; | ||
39 | |||
40 | char ep_name[EP_NAME_SIZE]; | ||
41 | |||
42 | struct usbhsg_gpriv *gpriv; | ||
43 | struct usbhsg_pipe_handle *handler; | ||
44 | }; | ||
45 | |||
46 | struct usbhsg_gpriv { | ||
47 | struct usb_gadget gadget; | ||
48 | struct usbhs_mod mod; | ||
49 | |||
50 | struct usbhsg_uep *uep; | ||
51 | int uep_size; | ||
52 | |||
53 | struct usb_gadget_driver *driver; | ||
54 | |||
55 | u32 status; | ||
56 | #define USBHSG_STATUS_STARTED (1 << 0) | ||
57 | #define USBHSG_STATUS_REGISTERD (1 << 1) | ||
58 | #define USBHSG_STATUS_WEDGE (1 << 2) | ||
59 | }; | ||
60 | |||
61 | struct usbhsg_pipe_handle { | ||
62 | int (*prepare)(struct usbhsg_uep *uep, struct usbhsg_request *ureq); | ||
63 | int (*try_run)(struct usbhsg_uep *uep, struct usbhsg_request *ureq); | ||
64 | void (*irq_mask)(struct usbhsg_uep *uep, int enable); | ||
65 | }; | ||
66 | |||
67 | struct usbhsg_recip_handle { | ||
68 | char *name; | ||
69 | int (*device)(struct usbhs_priv *priv, struct usbhsg_uep *uep, | ||
70 | struct usb_ctrlrequest *ctrl); | ||
71 | int (*interface)(struct usbhs_priv *priv, struct usbhsg_uep *uep, | ||
72 | struct usb_ctrlrequest *ctrl); | ||
73 | int (*endpoint)(struct usbhs_priv *priv, struct usbhsg_uep *uep, | ||
74 | struct usb_ctrlrequest *ctrl); | ||
75 | }; | ||
76 | |||
77 | /* | ||
78 | * macro | ||
79 | */ | ||
80 | #define usbhsg_priv_to_gpriv(priv) \ | ||
81 | container_of( \ | ||
82 | usbhs_mod_get(priv, USBHS_GADGET), \ | ||
83 | struct usbhsg_gpriv, mod) | ||
84 | |||
85 | #define __usbhsg_for_each_uep(start, pos, g, i) \ | ||
86 | for (i = start, pos = (g)->uep; \ | ||
87 | i < (g)->uep_size; \ | ||
88 | i++, pos = (g)->uep + i) | ||
89 | |||
90 | #define usbhsg_for_each_uep(pos, gpriv, i) \ | ||
91 | __usbhsg_for_each_uep(1, pos, gpriv, i) | ||
92 | |||
93 | #define usbhsg_for_each_uep_with_dcp(pos, gpriv, i) \ | ||
94 | __usbhsg_for_each_uep(0, pos, gpriv, i) | ||
95 | |||
96 | #define usbhsg_gadget_to_gpriv(g)\ | ||
97 | container_of(g, struct usbhsg_gpriv, gadget) | ||
98 | |||
99 | #define usbhsg_req_to_ureq(r)\ | ||
100 | container_of(r, struct usbhsg_request, req) | ||
101 | |||
102 | #define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep) | ||
103 | #define usbhsg_gpriv_to_lock(gp) usbhs_priv_to_lock((gp)->mod.priv) | ||
104 | #define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv) | ||
105 | #define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv) | ||
106 | #define usbhsg_gpriv_to_dcp(gp) ((gp)->uep) | ||
107 | #define usbhsg_gpriv_to_nth_uep(gp, i) ((gp)->uep + i) | ||
108 | #define usbhsg_uep_to_gpriv(u) ((u)->gpriv) | ||
109 | #define usbhsg_uep_to_pipe(u) ((u)->pipe) | ||
110 | #define usbhsg_pipe_to_uep(p) ((p)->mod_private) | ||
111 | #define usbhsg_is_dcp(u) ((u) == usbhsg_gpriv_to_dcp((u)->gpriv)) | ||
112 | |||
113 | #define usbhsg_is_not_connected(gp) ((gp)->gadget.speed == USB_SPEED_UNKNOWN) | ||
114 | |||
115 | /* status */ | ||
116 | #define usbhsg_status_init(gp) do {(gp)->status = 0; } while (0) | ||
117 | #define usbhsg_status_set(gp, b) (gp->status |= b) | ||
118 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) | ||
119 | #define usbhsg_status_has(gp, b) (gp->status & b) | ||
120 | |||
121 | /* | ||
122 | * list push/pop | ||
123 | */ | ||
124 | static void usbhsg_queue_push(struct usbhsg_uep *uep, | ||
125 | struct usbhsg_request *ureq) | ||
126 | { | ||
127 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
128 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
129 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
130 | |||
131 | /* | ||
132 | ********* assume under spin lock ********* | ||
133 | */ | ||
134 | list_del_init(&ureq->node); | ||
135 | list_add_tail(&ureq->node, &uep->list); | ||
136 | ureq->req.actual = 0; | ||
137 | ureq->req.status = -EINPROGRESS; | ||
138 | |||
139 | dev_dbg(dev, "pipe %d : queue push (%d)\n", | ||
140 | usbhs_pipe_number(pipe), | ||
141 | ureq->req.length); | ||
142 | } | ||
143 | |||
144 | static struct usbhsg_request *usbhsg_queue_get(struct usbhsg_uep *uep) | ||
145 | { | ||
146 | /* | ||
147 | ********* assume under spin lock ********* | ||
148 | */ | ||
149 | if (list_empty(&uep->list)) | ||
150 | return NULL; | ||
151 | |||
152 | return list_entry(uep->list.next, struct usbhsg_request, node); | ||
153 | } | ||
154 | |||
155 | #define usbhsg_queue_prepare(uep) __usbhsg_queue_handler(uep, 1); | ||
156 | #define usbhsg_queue_handle(uep) __usbhsg_queue_handler(uep, 0); | ||
157 | static int __usbhsg_queue_handler(struct usbhsg_uep *uep, int prepare) | ||
158 | { | ||
159 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
160 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
161 | struct usbhsg_request *ureq; | ||
162 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
163 | unsigned long flags; | ||
164 | int is_locked; | ||
165 | int ret = 0; | ||
166 | |||
167 | if (!uep->handler) { | ||
168 | dev_err(dev, "no handler function\n"); | ||
169 | return -EIO; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * CAUTION [*queue handler*] | ||
174 | * | ||
175 | * This function will be called for start/restart queue operation. | ||
176 | * OTOH the most much worry for USB driver is spinlock nest. | ||
177 | * Specially it are | ||
178 | * - usb_ep_ops :: queue | ||
179 | * - usb_request :: complete | ||
180 | * | ||
181 | * But the caller of this function need not care about spinlock. | ||
182 | * This function is using spin_trylock_irqsave for it. | ||
183 | * if "is_locked" is 1, this mean this function lock it. | ||
184 | * but if it is 0, this mean it is already under spin lock. | ||
185 | * see also | ||
186 | * CAUTION [*endpoint queue*] | ||
187 | * CAUTION [*request complete*] | ||
188 | */ | ||
189 | |||
190 | /****************** spin try lock *******************/ | ||
191 | is_locked = spin_trylock_irqsave(lock, flags); | ||
192 | ureq = usbhsg_queue_get(uep); | ||
193 | if (ureq) { | ||
194 | if (prepare) | ||
195 | ret = uep->handler->prepare(uep, ureq); | ||
196 | else | ||
197 | ret = uep->handler->try_run(uep, ureq); | ||
198 | } | ||
199 | if (is_locked) | ||
200 | spin_unlock_irqrestore(lock, flags); | ||
201 | /******************** spin unlock ******************/ | ||
202 | |||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | static void usbhsg_queue_pop(struct usbhsg_uep *uep, | ||
207 | struct usbhsg_request *ureq, | ||
208 | int status) | ||
209 | { | ||
210 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
211 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
212 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
213 | |||
214 | /* | ||
215 | ********* assume under spin lock ********* | ||
216 | */ | ||
217 | |||
218 | /* | ||
219 | * CAUTION [*request complete*] | ||
220 | * | ||
221 | * There is a possibility not to be called in correct order | ||
222 | * if "complete" is called without spinlock. | ||
223 | * | ||
224 | * So, this function assume it is under spinlock, | ||
225 | * and call usb_request :: complete. | ||
226 | * | ||
227 | * But this "complete" will push next usb_request. | ||
228 | * It mean "usb_ep_ops :: queue" which is using spinlock is called | ||
229 | * under spinlock. | ||
230 | * | ||
231 | * To avoid dead-lock, this driver is using spin_trylock. | ||
232 | * CAUTION [*endpoint queue*] | ||
233 | * CAUTION [*queue handler*] | ||
234 | */ | ||
235 | |||
236 | dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); | ||
237 | |||
238 | list_del_init(&ureq->node); | ||
239 | |||
240 | ureq->req.status = status; | ||
241 | ureq->req.complete(&uep->ep, &ureq->req); | ||
242 | |||
243 | /* more request ? */ | ||
244 | if (0 == status) | ||
245 | usbhsg_queue_prepare(uep); | ||
246 | } | ||
247 | |||
248 | /* | ||
249 | * irq enable/disable function | ||
250 | */ | ||
251 | #define usbhsg_irq_callback_ctrl(uep, status, enable) \ | ||
252 | ({ \ | ||
253 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); \ | ||
254 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); \ | ||
255 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); \ | ||
256 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); \ | ||
257 | if (!mod) \ | ||
258 | return; \ | ||
259 | if (enable) \ | ||
260 | mod->irq_##status |= (1 << usbhs_pipe_number(pipe)); \ | ||
261 | else \ | ||
262 | mod->irq_##status &= ~(1 << usbhs_pipe_number(pipe)); \ | ||
263 | usbhs_irq_callback_update(priv, mod); \ | ||
264 | }) | ||
265 | |||
266 | static void usbhsg_irq_empty_ctrl(struct usbhsg_uep *uep, int enable) | ||
267 | { | ||
268 | usbhsg_irq_callback_ctrl(uep, bempsts, enable); | ||
269 | } | ||
270 | |||
271 | static void usbhsg_irq_ready_ctrl(struct usbhsg_uep *uep, int enable) | ||
272 | { | ||
273 | usbhsg_irq_callback_ctrl(uep, brdysts, enable); | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * handler function | ||
278 | */ | ||
279 | static int usbhsg_try_run_ctrl_stage_end(struct usbhsg_uep *uep, | ||
280 | struct usbhsg_request *ureq) | ||
281 | { | ||
282 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
283 | |||
284 | /* | ||
285 | ********* assume under spin lock ********* | ||
286 | */ | ||
287 | |||
288 | usbhs_dcp_control_transfer_done(pipe); | ||
289 | usbhsg_queue_pop(uep, ureq, 0); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep, | ||
295 | struct usbhsg_request *ureq) | ||
296 | { | ||
297 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
298 | struct usb_request *req = &ureq->req; | ||
299 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
300 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
301 | void *buf; | ||
302 | int remainder, send; | ||
303 | int is_done = 0; | ||
304 | int enable; | ||
305 | int maxp; | ||
306 | |||
307 | /* | ||
308 | ********* assume under spin lock ********* | ||
309 | */ | ||
310 | |||
311 | maxp = usbhs_pipe_get_maxpacket(pipe); | ||
312 | buf = req->buf + req->actual; | ||
313 | remainder = req->length - req->actual; | ||
314 | |||
315 | send = usbhs_fifo_write(pipe, buf, remainder); | ||
316 | |||
317 | /* | ||
318 | * send < 0 : pipe busy | ||
319 | * send = 0 : send zero packet | ||
320 | * send > 0 : send data | ||
321 | * | ||
322 | * send <= max_packet | ||
323 | */ | ||
324 | if (send > 0) | ||
325 | req->actual += send; | ||
326 | |||
327 | /* send all packet ? */ | ||
328 | if (send < remainder) | ||
329 | is_done = 0; /* there are remainder data */ | ||
330 | else if (send < maxp) | ||
331 | is_done = 1; /* short packet */ | ||
332 | else | ||
333 | is_done = !req->zero; /* send zero packet ? */ | ||
334 | |||
335 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", | ||
336 | usbhs_pipe_number(pipe), | ||
337 | remainder, send, is_done, req->zero); | ||
338 | |||
339 | /* | ||
340 | * enable interrupt and send again in irq handler | ||
341 | * if it still have remainder data which should be sent. | ||
342 | */ | ||
343 | enable = !is_done; | ||
344 | uep->handler->irq_mask(uep, enable); | ||
345 | |||
346 | /* | ||
347 | * usbhs_fifo_enable execute | ||
348 | * - after callback_update, | ||
349 | * - before queue_pop / stage_end | ||
350 | */ | ||
351 | usbhs_fifo_enable(pipe); | ||
352 | |||
353 | /* | ||
354 | * all data were sent ? | ||
355 | */ | ||
356 | if (is_done) { | ||
357 | /* it care below call in | ||
358 | "function mode" */ | ||
359 | if (usbhsg_is_dcp(uep)) | ||
360 | usbhs_dcp_control_transfer_done(pipe); | ||
361 | |||
362 | usbhsg_queue_pop(uep, ureq, 0); | ||
363 | } | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static int usbhsg_prepare_send_packet(struct usbhsg_uep *uep, | ||
369 | struct usbhsg_request *ureq) | ||
370 | { | ||
371 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
372 | |||
373 | /* | ||
374 | ********* assume under spin lock ********* | ||
375 | */ | ||
376 | |||
377 | usbhs_fifo_prepare_write(pipe); | ||
378 | usbhsg_try_run_send_packet(uep, ureq); | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep, | ||
384 | struct usbhsg_request *ureq) | ||
385 | { | ||
386 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
387 | struct usb_request *req = &ureq->req; | ||
388 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
389 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
390 | void *buf; | ||
391 | int maxp; | ||
392 | int remainder, recv; | ||
393 | int is_done = 0; | ||
394 | |||
395 | /* | ||
396 | ********* assume under spin lock ********* | ||
397 | */ | ||
398 | |||
399 | maxp = usbhs_pipe_get_maxpacket(pipe); | ||
400 | buf = req->buf + req->actual; | ||
401 | remainder = req->length - req->actual; | ||
402 | |||
403 | recv = usbhs_fifo_read(pipe, buf, remainder); | ||
404 | /* | ||
405 | * recv < 0 : pipe busy | ||
406 | * recv >= 0 : receive data | ||
407 | * | ||
408 | * recv <= max_packet | ||
409 | */ | ||
410 | if (recv < 0) | ||
411 | return -EBUSY; | ||
412 | |||
413 | /* update parameters */ | ||
414 | req->actual += recv; | ||
415 | |||
416 | if ((recv == remainder) || /* receive all data */ | ||
417 | (recv < maxp)) /* short packet */ | ||
418 | is_done = 1; | ||
419 | |||
420 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", | ||
421 | usbhs_pipe_number(pipe), | ||
422 | remainder, recv, is_done, req->zero); | ||
423 | |||
424 | /* read all data ? */ | ||
425 | if (is_done) { | ||
426 | int disable = 0; | ||
427 | |||
428 | uep->handler->irq_mask(uep, disable); | ||
429 | usbhs_fifo_disable(pipe); | ||
430 | usbhsg_queue_pop(uep, ureq, 0); | ||
431 | } | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int usbhsg_prepare_receive_packet(struct usbhsg_uep *uep, | ||
437 | struct usbhsg_request *ureq) | ||
438 | { | ||
439 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
440 | int enable = 1; | ||
441 | int ret; | ||
442 | |||
443 | /* | ||
444 | ********* assume under spin lock ********* | ||
445 | */ | ||
446 | |||
447 | ret = usbhs_fifo_prepare_read(pipe); | ||
448 | if (ret < 0) | ||
449 | return ret; | ||
450 | |||
451 | /* | ||
452 | * data will be read in interrupt handler | ||
453 | */ | ||
454 | uep->handler->irq_mask(uep, enable); | ||
455 | |||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | static struct usbhsg_pipe_handle usbhsg_handler_send_by_empty = { | ||
460 | .prepare = usbhsg_prepare_send_packet, | ||
461 | .try_run = usbhsg_try_run_send_packet, | ||
462 | .irq_mask = usbhsg_irq_empty_ctrl, | ||
463 | }; | ||
464 | |||
465 | static struct usbhsg_pipe_handle usbhsg_handler_send_by_ready = { | ||
466 | .prepare = usbhsg_prepare_send_packet, | ||
467 | .try_run = usbhsg_try_run_send_packet, | ||
468 | .irq_mask = usbhsg_irq_ready_ctrl, | ||
469 | }; | ||
470 | |||
471 | static struct usbhsg_pipe_handle usbhsg_handler_recv_by_ready = { | ||
472 | .prepare = usbhsg_prepare_receive_packet, | ||
473 | .try_run = usbhsg_try_run_receive_packet, | ||
474 | .irq_mask = usbhsg_irq_ready_ctrl, | ||
475 | }; | ||
476 | |||
477 | static struct usbhsg_pipe_handle usbhsg_handler_ctrl_stage_end = { | ||
478 | .prepare = usbhsg_try_run_ctrl_stage_end, | ||
479 | .try_run = usbhsg_try_run_ctrl_stage_end, | ||
480 | }; | ||
481 | |||
482 | /* | ||
483 | * DCP pipe can NOT use "ready interrupt" for "send" | ||
484 | * it should use "empty" interrupt. | ||
485 | * see | ||
486 | * "Operation" - "Interrupt Function" - "BRDY Interrupt" | ||
487 | * | ||
488 | * on the other hand, normal pipe can use "ready interrupt" for "send" | ||
489 | * even though it is single/double buffer | ||
490 | */ | ||
491 | #define usbhsg_handler_send_ctrl usbhsg_handler_send_by_empty | ||
492 | #define usbhsg_handler_recv_ctrl usbhsg_handler_recv_by_ready | ||
493 | |||
494 | #define usbhsg_handler_send_packet usbhsg_handler_send_by_ready | ||
495 | #define usbhsg_handler_recv_packet usbhsg_handler_recv_by_ready | ||
496 | |||
497 | /* | ||
498 | * USB_TYPE_STANDARD / clear feature functions | ||
499 | */ | ||
500 | static int usbhsg_recip_handler_std_control_done(struct usbhs_priv *priv, | ||
501 | struct usbhsg_uep *uep, | ||
502 | struct usb_ctrlrequest *ctrl) | ||
503 | { | ||
504 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
505 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | ||
506 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); | ||
507 | |||
508 | usbhs_dcp_control_transfer_done(pipe); | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv, | ||
514 | struct usbhsg_uep *uep, | ||
515 | struct usb_ctrlrequest *ctrl) | ||
516 | { | ||
517 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
518 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
519 | |||
520 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_WEDGE)) { | ||
521 | usbhs_fifo_disable(pipe); | ||
522 | usbhs_pipe_clear_sequence(pipe); | ||
523 | usbhs_fifo_enable(pipe); | ||
524 | } | ||
525 | |||
526 | usbhsg_recip_handler_std_control_done(priv, uep, ctrl); | ||
527 | |||
528 | usbhsg_queue_prepare(uep); | ||
529 | |||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | struct usbhsg_recip_handle req_clear_feature = { | ||
534 | .name = "clear feature", | ||
535 | .device = usbhsg_recip_handler_std_control_done, | ||
536 | .interface = usbhsg_recip_handler_std_control_done, | ||
537 | .endpoint = usbhsg_recip_handler_std_clear_endpoint, | ||
538 | }; | ||
539 | |||
540 | /* | ||
541 | * USB_TYPE handler | ||
542 | */ | ||
543 | static int usbhsg_recip_run_handle(struct usbhs_priv *priv, | ||
544 | struct usbhsg_recip_handle *handler, | ||
545 | struct usb_ctrlrequest *ctrl) | ||
546 | { | ||
547 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
548 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
549 | struct usbhsg_uep *uep; | ||
550 | int recip = ctrl->bRequestType & USB_RECIP_MASK; | ||
551 | int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; | ||
552 | int ret; | ||
553 | int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep, | ||
554 | struct usb_ctrlrequest *ctrl); | ||
555 | char *msg; | ||
556 | |||
557 | uep = usbhsg_gpriv_to_nth_uep(gpriv, nth); | ||
558 | |||
559 | switch (recip) { | ||
560 | case USB_RECIP_DEVICE: | ||
561 | msg = "DEVICE"; | ||
562 | func = handler->device; | ||
563 | break; | ||
564 | case USB_RECIP_INTERFACE: | ||
565 | msg = "INTERFACE"; | ||
566 | func = handler->interface; | ||
567 | break; | ||
568 | case USB_RECIP_ENDPOINT: | ||
569 | msg = "ENDPOINT"; | ||
570 | func = handler->endpoint; | ||
571 | break; | ||
572 | default: | ||
573 | dev_warn(dev, "unsupported RECIP(%d)\n", recip); | ||
574 | func = NULL; | ||
575 | ret = -EINVAL; | ||
576 | } | ||
577 | |||
578 | if (func) { | ||
579 | dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg); | ||
580 | ret = func(priv, uep, ctrl); | ||
581 | } | ||
582 | |||
583 | return ret; | ||
584 | } | ||
585 | |||
586 | /* | ||
587 | * irq functions | ||
588 | * | ||
589 | * it will be called from usbhs_interrupt | ||
590 | */ | ||
591 | static int usbhsg_irq_dev_state(struct usbhs_priv *priv, | ||
592 | struct usbhs_irq_state *irq_state) | ||
593 | { | ||
594 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
595 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
596 | |||
597 | gpriv->gadget.speed = usbhs_status_get_usb_speed(irq_state); | ||
598 | |||
599 | dev_dbg(dev, "state = %x : speed : %d\n", | ||
600 | usbhs_status_get_device_state(irq_state), | ||
601 | gpriv->gadget.speed); | ||
602 | |||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, | ||
607 | struct usbhs_irq_state *irq_state) | ||
608 | { | ||
609 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
610 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | ||
611 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); | ||
612 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
613 | struct usb_ctrlrequest ctrl; | ||
614 | struct usbhsg_recip_handle *recip_handler = NULL; | ||
615 | int stage = usbhs_status_get_ctrl_stage(irq_state); | ||
616 | int ret = 0; | ||
617 | |||
618 | dev_dbg(dev, "stage = %d\n", stage); | ||
619 | |||
620 | /* | ||
621 | * see Manual | ||
622 | * | ||
623 | * "Operation" | ||
624 | * - "Interrupt Function" | ||
625 | * - "Control Transfer Stage Transition Interrupt" | ||
626 | * - Fig. "Control Transfer Stage Transitions" | ||
627 | */ | ||
628 | |||
629 | switch (stage) { | ||
630 | case READ_DATA_STAGE: | ||
631 | dcp->handler = &usbhsg_handler_send_ctrl; | ||
632 | break; | ||
633 | case WRITE_DATA_STAGE: | ||
634 | dcp->handler = &usbhsg_handler_recv_ctrl; | ||
635 | break; | ||
636 | case NODATA_STATUS_STAGE: | ||
637 | dcp->handler = &usbhsg_handler_ctrl_stage_end; | ||
638 | break; | ||
639 | default: | ||
640 | return ret; | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * get usb request | ||
645 | */ | ||
646 | usbhs_usbreq_get_val(priv, &ctrl); | ||
647 | |||
648 | switch (ctrl.bRequestType & USB_TYPE_MASK) { | ||
649 | case USB_TYPE_STANDARD: | ||
650 | switch (ctrl.bRequest) { | ||
651 | case USB_REQ_CLEAR_FEATURE: | ||
652 | recip_handler = &req_clear_feature; | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | |||
657 | /* | ||
658 | * setup stage / run recip | ||
659 | */ | ||
660 | if (recip_handler) | ||
661 | ret = usbhsg_recip_run_handle(priv, recip_handler, &ctrl); | ||
662 | else | ||
663 | ret = gpriv->driver->setup(&gpriv->gadget, &ctrl); | ||
664 | |||
665 | if (ret < 0) | ||
666 | usbhs_fifo_stall(pipe); | ||
667 | |||
668 | return ret; | ||
669 | } | ||
670 | |||
671 | static int usbhsg_irq_empty(struct usbhs_priv *priv, | ||
672 | struct usbhs_irq_state *irq_state) | ||
673 | { | ||
674 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
675 | struct usbhsg_uep *uep; | ||
676 | struct usbhs_pipe *pipe; | ||
677 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
678 | int i, ret; | ||
679 | |||
680 | if (!irq_state->bempsts) { | ||
681 | dev_err(dev, "debug %s !!\n", __func__); | ||
682 | return -EIO; | ||
683 | } | ||
684 | |||
685 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); | ||
686 | |||
687 | /* | ||
688 | * search interrupted "pipe" | ||
689 | * not "uep". | ||
690 | */ | ||
691 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
692 | if (!(irq_state->bempsts & (1 << i))) | ||
693 | continue; | ||
694 | |||
695 | uep = usbhsg_pipe_to_uep(pipe); | ||
696 | ret = usbhsg_queue_handle(uep); | ||
697 | if (ret < 0) | ||
698 | dev_err(dev, "send error %d : %d\n", i, ret); | ||
699 | } | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | static int usbhsg_irq_ready(struct usbhs_priv *priv, | ||
705 | struct usbhs_irq_state *irq_state) | ||
706 | { | ||
707 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
708 | struct usbhsg_uep *uep; | ||
709 | struct usbhs_pipe *pipe; | ||
710 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
711 | int i, ret; | ||
712 | |||
713 | if (!irq_state->brdysts) { | ||
714 | dev_err(dev, "debug %s !!\n", __func__); | ||
715 | return -EIO; | ||
716 | } | ||
717 | |||
718 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); | ||
719 | |||
720 | /* | ||
721 | * search interrupted "pipe" | ||
722 | * not "uep". | ||
723 | */ | ||
724 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
725 | if (!(irq_state->brdysts & (1 << i))) | ||
726 | continue; | ||
727 | |||
728 | uep = usbhsg_pipe_to_uep(pipe); | ||
729 | ret = usbhsg_queue_handle(uep); | ||
730 | if (ret < 0) | ||
731 | dev_err(dev, "receive error %d : %d\n", i, ret); | ||
732 | } | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | /* | ||
738 | * | ||
739 | * usb_dcp_ops | ||
740 | * | ||
741 | */ | ||
742 | static int usbhsg_dcp_enable(struct usbhsg_uep *uep) | ||
743 | { | ||
744 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
745 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | ||
746 | struct usbhs_pipe *pipe; | ||
747 | |||
748 | /* | ||
749 | ********* assume under spin lock ********* | ||
750 | */ | ||
751 | |||
752 | pipe = usbhs_dcp_malloc(priv); | ||
753 | if (!pipe) | ||
754 | return -EIO; | ||
755 | |||
756 | uep->pipe = pipe; | ||
757 | uep->pipe->mod_private = uep; | ||
758 | INIT_LIST_HEAD(&uep->list); | ||
759 | |||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | #define usbhsg_dcp_disable usbhsg_pipe_disable | ||
764 | static int usbhsg_pipe_disable(struct usbhsg_uep *uep) | ||
765 | { | ||
766 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
767 | struct usbhsg_request *ureq; | ||
768 | int disable = 0; | ||
769 | |||
770 | /* | ||
771 | ********* assume under spin lock ********* | ||
772 | */ | ||
773 | |||
774 | usbhs_fifo_disable(pipe); | ||
775 | |||
776 | /* | ||
777 | * disable pipe irq | ||
778 | */ | ||
779 | usbhsg_irq_empty_ctrl(uep, disable); | ||
780 | usbhsg_irq_ready_ctrl(uep, disable); | ||
781 | |||
782 | while (1) { | ||
783 | ureq = usbhsg_queue_get(uep); | ||
784 | if (!ureq) | ||
785 | break; | ||
786 | |||
787 | usbhsg_queue_pop(uep, ureq, -ECONNRESET); | ||
788 | } | ||
789 | |||
790 | uep->pipe->mod_private = NULL; | ||
791 | uep->pipe = NULL; | ||
792 | |||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * | ||
798 | * usb_ep_ops | ||
799 | * | ||
800 | */ | ||
801 | static int usbhsg_ep_enable(struct usb_ep *ep, | ||
802 | const struct usb_endpoint_descriptor *desc) | ||
803 | { | ||
804 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | ||
805 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
806 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | ||
807 | struct usbhs_pipe *pipe; | ||
808 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
809 | unsigned long flags; | ||
810 | int ret = -EIO; | ||
811 | |||
812 | /******************** spin lock ********************/ | ||
813 | spin_lock_irqsave(lock, flags); | ||
814 | |||
815 | pipe = usbhs_pipe_malloc(priv, desc); | ||
816 | if (pipe) { | ||
817 | uep->pipe = pipe; | ||
818 | pipe->mod_private = uep; | ||
819 | INIT_LIST_HEAD(&uep->list); | ||
820 | |||
821 | if (usb_endpoint_dir_in(desc)) | ||
822 | uep->handler = &usbhsg_handler_send_packet; | ||
823 | else | ||
824 | uep->handler = &usbhsg_handler_recv_packet; | ||
825 | |||
826 | ret = 0; | ||
827 | } | ||
828 | spin_unlock_irqrestore(lock, flags); | ||
829 | /******************** spin unlock ******************/ | ||
830 | |||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | static int usbhsg_ep_disable(struct usb_ep *ep) | ||
835 | { | ||
836 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | ||
837 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
838 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
839 | unsigned long flags; | ||
840 | int ret; | ||
841 | |||
842 | /******************** spin lock ********************/ | ||
843 | spin_lock_irqsave(lock, flags); | ||
844 | ret = usbhsg_pipe_disable(uep); | ||
845 | spin_unlock_irqrestore(lock, flags); | ||
846 | /******************** spin unlock ******************/ | ||
847 | |||
848 | return ret; | ||
849 | } | ||
850 | |||
851 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | ||
852 | gfp_t gfp_flags) | ||
853 | { | ||
854 | struct usbhsg_request *ureq; | ||
855 | |||
856 | ureq = kzalloc(sizeof *ureq, gfp_flags); | ||
857 | if (!ureq) | ||
858 | return NULL; | ||
859 | |||
860 | INIT_LIST_HEAD(&ureq->node); | ||
861 | return &ureq->req; | ||
862 | } | ||
863 | |||
864 | static void usbhsg_ep_free_request(struct usb_ep *ep, | ||
865 | struct usb_request *req) | ||
866 | { | ||
867 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | ||
868 | |||
869 | WARN_ON(!list_empty(&ureq->node)); | ||
870 | kfree(ureq); | ||
871 | } | ||
872 | |||
873 | static int usbhsg_ep_queue(struct usb_ep *ep, struct usb_request *req, | ||
874 | gfp_t gfp_flags) | ||
875 | { | ||
876 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | ||
877 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
878 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | ||
879 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
880 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
881 | unsigned long flags; | ||
882 | int ret = 0; | ||
883 | int is_locked; | ||
884 | |||
885 | /* | ||
886 | * CAUTION [*endpoint queue*] | ||
887 | * | ||
888 | * This function will be called from usb_request :: complete | ||
889 | * or usb driver timing. | ||
890 | * If this function is called from usb_request :: complete, | ||
891 | * it is already under spinlock on this driver. | ||
892 | * but it is called frm usb driver, this function should call spinlock. | ||
893 | * | ||
894 | * This function is using spin_trylock_irqsave to solve this issue. | ||
895 | * if "is_locked" is 1, this mean this function lock it. | ||
896 | * but if it is 0, this mean it is already under spin lock. | ||
897 | * see also | ||
898 | * CAUTION [*queue handler*] | ||
899 | * CAUTION [*request complete*] | ||
900 | */ | ||
901 | |||
902 | /******************** spin lock ********************/ | ||
903 | is_locked = spin_trylock_irqsave(lock, flags); | ||
904 | |||
905 | /* param check */ | ||
906 | if (usbhsg_is_not_connected(gpriv) || | ||
907 | unlikely(!gpriv->driver) || | ||
908 | unlikely(!pipe)) | ||
909 | ret = -ESHUTDOWN; | ||
910 | else | ||
911 | usbhsg_queue_push(uep, ureq); | ||
912 | |||
913 | if (is_locked) | ||
914 | spin_unlock_irqrestore(lock, flags); | ||
915 | /******************** spin unlock ******************/ | ||
916 | |||
917 | usbhsg_queue_prepare(uep); | ||
918 | |||
919 | return ret; | ||
920 | } | ||
921 | |||
922 | static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) | ||
923 | { | ||
924 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | ||
925 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | ||
926 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
927 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
928 | unsigned long flags; | ||
929 | int is_locked; | ||
930 | |||
931 | /* | ||
932 | * see | ||
933 | * CAUTION [*queue handler*] | ||
934 | * CAUTION [*endpoint queue*] | ||
935 | * CAUTION [*request complete*] | ||
936 | */ | ||
937 | |||
938 | /******************** spin lock ********************/ | ||
939 | is_locked = spin_trylock_irqsave(lock, flags); | ||
940 | |||
941 | usbhsg_queue_pop(uep, ureq, -ECONNRESET); | ||
942 | |||
943 | if (is_locked) | ||
944 | spin_unlock_irqrestore(lock, flags); | ||
945 | /******************** spin unlock ******************/ | ||
946 | |||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge) | ||
951 | { | ||
952 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | ||
953 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | ||
954 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
955 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
956 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
957 | unsigned long flags; | ||
958 | int ret = -EAGAIN; | ||
959 | int is_locked; | ||
960 | |||
961 | /* | ||
962 | * see | ||
963 | * CAUTION [*queue handler*] | ||
964 | * CAUTION [*endpoint queue*] | ||
965 | * CAUTION [*request complete*] | ||
966 | */ | ||
967 | |||
968 | /******************** spin lock ********************/ | ||
969 | is_locked = spin_trylock_irqsave(lock, flags); | ||
970 | if (!usbhsg_queue_get(uep)) { | ||
971 | |||
972 | dev_dbg(dev, "set halt %d (pipe %d)\n", | ||
973 | halt, usbhs_pipe_number(pipe)); | ||
974 | |||
975 | if (halt) | ||
976 | usbhs_fifo_stall(pipe); | ||
977 | else | ||
978 | usbhs_fifo_disable(pipe); | ||
979 | |||
980 | if (halt && wedge) | ||
981 | usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE); | ||
982 | else | ||
983 | usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE); | ||
984 | |||
985 | ret = 0; | ||
986 | } | ||
987 | |||
988 | if (is_locked) | ||
989 | spin_unlock_irqrestore(lock, flags); | ||
990 | /******************** spin unlock ******************/ | ||
991 | |||
992 | return ret; | ||
993 | } | ||
994 | |||
995 | static int usbhsg_ep_set_halt(struct usb_ep *ep, int value) | ||
996 | { | ||
997 | return __usbhsg_ep_set_halt_wedge(ep, value, 0); | ||
998 | } | ||
999 | |||
1000 | static int usbhsg_ep_set_wedge(struct usb_ep *ep) | ||
1001 | { | ||
1002 | return __usbhsg_ep_set_halt_wedge(ep, 1, 1); | ||
1003 | } | ||
1004 | |||
1005 | static struct usb_ep_ops usbhsg_ep_ops = { | ||
1006 | .enable = usbhsg_ep_enable, | ||
1007 | .disable = usbhsg_ep_disable, | ||
1008 | |||
1009 | .alloc_request = usbhsg_ep_alloc_request, | ||
1010 | .free_request = usbhsg_ep_free_request, | ||
1011 | |||
1012 | .queue = usbhsg_ep_queue, | ||
1013 | .dequeue = usbhsg_ep_dequeue, | ||
1014 | |||
1015 | .set_halt = usbhsg_ep_set_halt, | ||
1016 | .set_wedge = usbhsg_ep_set_wedge, | ||
1017 | }; | ||
1018 | |||
1019 | /* | ||
1020 | * usb module start/end | ||
1021 | */ | ||
1022 | static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | ||
1023 | { | ||
1024 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
1025 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | ||
1026 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
1027 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1028 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
1029 | unsigned long flags; | ||
1030 | |||
1031 | /******************** spin lock ********************/ | ||
1032 | spin_lock_irqsave(lock, flags); | ||
1033 | |||
1034 | /* | ||
1035 | * enable interrupt and systems if ready | ||
1036 | */ | ||
1037 | usbhsg_status_set(gpriv, status); | ||
1038 | if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && | ||
1039 | usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) | ||
1040 | goto usbhsg_try_start_unlock; | ||
1041 | |||
1042 | dev_dbg(dev, "start gadget\n"); | ||
1043 | |||
1044 | /* | ||
1045 | * pipe initialize and enable DCP | ||
1046 | */ | ||
1047 | usbhs_pipe_init(priv); | ||
1048 | usbhsg_dcp_enable(dcp); | ||
1049 | |||
1050 | /* | ||
1051 | * system config enble | ||
1052 | * - HI speed | ||
1053 | * - function | ||
1054 | * - usb module | ||
1055 | */ | ||
1056 | usbhs_sys_hispeed_ctrl(priv, 1); | ||
1057 | usbhs_sys_function_ctrl(priv, 1); | ||
1058 | usbhs_sys_usb_ctrl(priv, 1); | ||
1059 | |||
1060 | /* | ||
1061 | * enable irq callback | ||
1062 | */ | ||
1063 | mod->irq_dev_state = usbhsg_irq_dev_state; | ||
1064 | mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; | ||
1065 | mod->irq_empty = usbhsg_irq_empty; | ||
1066 | mod->irq_ready = usbhsg_irq_ready; | ||
1067 | mod->irq_bempsts = 0; | ||
1068 | mod->irq_brdysts = 0; | ||
1069 | usbhs_irq_callback_update(priv, mod); | ||
1070 | |||
1071 | usbhsg_try_start_unlock: | ||
1072 | spin_unlock_irqrestore(lock, flags); | ||
1073 | /******************** spin unlock ********************/ | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | ||
1079 | { | ||
1080 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
1081 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
1082 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | ||
1083 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1084 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
1085 | unsigned long flags; | ||
1086 | |||
1087 | /******************** spin lock ********************/ | ||
1088 | spin_lock_irqsave(lock, flags); | ||
1089 | |||
1090 | /* | ||
1091 | * disable interrupt and systems if 1st try | ||
1092 | */ | ||
1093 | usbhsg_status_clr(gpriv, status); | ||
1094 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && | ||
1095 | !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) | ||
1096 | goto usbhsg_try_stop_unlock; | ||
1097 | |||
1098 | /* disable all irq */ | ||
1099 | mod->irq_dev_state = NULL; | ||
1100 | mod->irq_ctrl_stage = NULL; | ||
1101 | mod->irq_empty = NULL; | ||
1102 | mod->irq_ready = NULL; | ||
1103 | mod->irq_bempsts = 0; | ||
1104 | mod->irq_brdysts = 0; | ||
1105 | usbhs_irq_callback_update(priv, mod); | ||
1106 | |||
1107 | usbhsg_dcp_disable(dcp); | ||
1108 | |||
1109 | gpriv->gadget.speed = USB_SPEED_UNKNOWN; | ||
1110 | |||
1111 | /* disable sys */ | ||
1112 | usbhs_sys_hispeed_ctrl(priv, 0); | ||
1113 | usbhs_sys_function_ctrl(priv, 0); | ||
1114 | usbhs_sys_usb_ctrl(priv, 0); | ||
1115 | |||
1116 | spin_unlock_irqrestore(lock, flags); | ||
1117 | /******************** spin unlock ********************/ | ||
1118 | |||
1119 | if (gpriv->driver && | ||
1120 | gpriv->driver->disconnect) | ||
1121 | gpriv->driver->disconnect(&gpriv->gadget); | ||
1122 | |||
1123 | dev_dbg(dev, "stop gadget\n"); | ||
1124 | |||
1125 | return 0; | ||
1126 | |||
1127 | usbhsg_try_stop_unlock: | ||
1128 | spin_unlock_irqrestore(lock, flags); | ||
1129 | |||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | /* | ||
1134 | * | ||
1135 | * linux usb function | ||
1136 | * | ||
1137 | */ | ||
1138 | struct usbhsg_gpriv *the_controller; | ||
1139 | int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | ||
1140 | int (*bind)(struct usb_gadget *)) | ||
1141 | { | ||
1142 | struct usbhsg_gpriv *gpriv = the_controller; | ||
1143 | struct usbhs_priv *priv; | ||
1144 | struct device *dev; | ||
1145 | int ret; | ||
1146 | |||
1147 | if (!bind || | ||
1148 | !driver || | ||
1149 | !driver->setup || | ||
1150 | driver->speed != USB_SPEED_HIGH) | ||
1151 | return -EINVAL; | ||
1152 | if (!gpriv) | ||
1153 | return -ENODEV; | ||
1154 | if (gpriv->driver) | ||
1155 | return -EBUSY; | ||
1156 | |||
1157 | dev = usbhsg_gpriv_to_dev(gpriv); | ||
1158 | priv = usbhsg_gpriv_to_priv(gpriv); | ||
1159 | |||
1160 | /* first hook up the driver ... */ | ||
1161 | gpriv->driver = driver; | ||
1162 | gpriv->gadget.dev.driver = &driver->driver; | ||
1163 | |||
1164 | ret = device_add(&gpriv->gadget.dev); | ||
1165 | if (ret) { | ||
1166 | dev_err(dev, "device_add error %d\n", ret); | ||
1167 | goto add_fail; | ||
1168 | } | ||
1169 | |||
1170 | ret = bind(&gpriv->gadget); | ||
1171 | if (ret) { | ||
1172 | dev_err(dev, "bind to driver %s error %d\n", | ||
1173 | driver->driver.name, ret); | ||
1174 | goto bind_fail; | ||
1175 | } | ||
1176 | |||
1177 | dev_dbg(dev, "bind %s\n", driver->driver.name); | ||
1178 | |||
1179 | return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); | ||
1180 | |||
1181 | bind_fail: | ||
1182 | device_del(&gpriv->gadget.dev); | ||
1183 | add_fail: | ||
1184 | gpriv->driver = NULL; | ||
1185 | gpriv->gadget.dev.driver = NULL; | ||
1186 | |||
1187 | return ret; | ||
1188 | } | ||
1189 | EXPORT_SYMBOL(usb_gadget_probe_driver); | ||
1190 | |||
1191 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
1192 | { | ||
1193 | struct usbhsg_gpriv *gpriv = the_controller; | ||
1194 | struct usbhs_priv *priv; | ||
1195 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
1196 | |||
1197 | if (!gpriv) | ||
1198 | return -ENODEV; | ||
1199 | |||
1200 | if (!driver || | ||
1201 | !driver->unbind || | ||
1202 | driver != gpriv->driver) | ||
1203 | return -EINVAL; | ||
1204 | |||
1205 | dev = usbhsg_gpriv_to_dev(gpriv); | ||
1206 | priv = usbhsg_gpriv_to_priv(gpriv); | ||
1207 | |||
1208 | usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); | ||
1209 | device_del(&gpriv->gadget.dev); | ||
1210 | gpriv->driver = NULL; | ||
1211 | |||
1212 | if (driver->disconnect) | ||
1213 | driver->disconnect(&gpriv->gadget); | ||
1214 | |||
1215 | driver->unbind(&gpriv->gadget); | ||
1216 | dev_dbg(dev, "unbind %s\n", driver->driver.name); | ||
1217 | |||
1218 | return 0; | ||
1219 | } | ||
1220 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
1221 | |||
1222 | /* | ||
1223 | * usb gadget ops | ||
1224 | */ | ||
1225 | static int usbhsg_get_frame(struct usb_gadget *gadget) | ||
1226 | { | ||
1227 | struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); | ||
1228 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | ||
1229 | |||
1230 | return usbhs_frame_get_num(priv); | ||
1231 | } | ||
1232 | |||
1233 | static struct usb_gadget_ops usbhsg_gadget_ops = { | ||
1234 | .get_frame = usbhsg_get_frame, | ||
1235 | }; | ||
1236 | |||
1237 | static int usbhsg_start(struct usbhs_priv *priv) | ||
1238 | { | ||
1239 | return usbhsg_try_start(priv, USBHSG_STATUS_STARTED); | ||
1240 | } | ||
1241 | |||
1242 | static int usbhsg_stop(struct usbhs_priv *priv) | ||
1243 | { | ||
1244 | return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); | ||
1245 | } | ||
1246 | |||
1247 | int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | ||
1248 | { | ||
1249 | struct usbhsg_gpriv *gpriv; | ||
1250 | struct usbhsg_uep *uep; | ||
1251 | struct device *dev = usbhs_priv_to_dev(priv); | ||
1252 | int pipe_size = usbhs_get_dparam(priv, pipe_size); | ||
1253 | int i; | ||
1254 | |||
1255 | gpriv = kzalloc(sizeof(struct usbhsg_gpriv), GFP_KERNEL); | ||
1256 | if (!gpriv) { | ||
1257 | dev_err(dev, "Could not allocate gadget priv\n"); | ||
1258 | return -ENOMEM; | ||
1259 | } | ||
1260 | |||
1261 | uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL); | ||
1262 | if (!uep) { | ||
1263 | dev_err(dev, "Could not allocate ep\n"); | ||
1264 | goto usbhs_mod_gadget_probe_err_gpriv; | ||
1265 | } | ||
1266 | |||
1267 | /* | ||
1268 | * CAUTION | ||
1269 | * | ||
1270 | * There is no guarantee that it is possible to access usb module here. | ||
1271 | * Don't accesses to it. | ||
1272 | * The accesse will be enable after "usbhsg_start" | ||
1273 | */ | ||
1274 | |||
1275 | /* | ||
1276 | * register itself | ||
1277 | */ | ||
1278 | usbhs_mod_register(priv, &gpriv->mod, USBHS_GADGET); | ||
1279 | |||
1280 | /* init gpriv */ | ||
1281 | gpriv->mod.name = "gadget"; | ||
1282 | gpriv->mod.start = usbhsg_start; | ||
1283 | gpriv->mod.stop = usbhsg_stop; | ||
1284 | gpriv->uep = uep; | ||
1285 | gpriv->uep_size = pipe_size; | ||
1286 | usbhsg_status_init(gpriv); | ||
1287 | |||
1288 | /* | ||
1289 | * init gadget | ||
1290 | */ | ||
1291 | device_initialize(&gpriv->gadget.dev); | ||
1292 | dev_set_name(&gpriv->gadget.dev, "gadget"); | ||
1293 | gpriv->gadget.dev.parent = dev; | ||
1294 | gpriv->gadget.name = "renesas_usbhs_udc"; | ||
1295 | gpriv->gadget.ops = &usbhsg_gadget_ops; | ||
1296 | gpriv->gadget.is_dualspeed = 1; | ||
1297 | |||
1298 | INIT_LIST_HEAD(&gpriv->gadget.ep_list); | ||
1299 | |||
1300 | /* | ||
1301 | * init usb_ep | ||
1302 | */ | ||
1303 | usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { | ||
1304 | uep->gpriv = gpriv; | ||
1305 | snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); | ||
1306 | |||
1307 | uep->ep.name = uep->ep_name; | ||
1308 | uep->ep.ops = &usbhsg_ep_ops; | ||
1309 | INIT_LIST_HEAD(&uep->ep.ep_list); | ||
1310 | INIT_LIST_HEAD(&uep->list); | ||
1311 | |||
1312 | /* init DCP */ | ||
1313 | if (usbhsg_is_dcp(uep)) { | ||
1314 | gpriv->gadget.ep0 = &uep->ep; | ||
1315 | uep->ep.maxpacket = 64; | ||
1316 | } | ||
1317 | /* init normal pipe */ | ||
1318 | else { | ||
1319 | uep->ep.maxpacket = 512; | ||
1320 | list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list); | ||
1321 | } | ||
1322 | } | ||
1323 | |||
1324 | the_controller = gpriv; | ||
1325 | |||
1326 | dev_info(dev, "gadget probed\n"); | ||
1327 | |||
1328 | return 0; | ||
1329 | |||
1330 | usbhs_mod_gadget_probe_err_gpriv: | ||
1331 | kfree(gpriv); | ||
1332 | |||
1333 | return -ENOMEM; | ||
1334 | } | ||
1335 | |||
1336 | void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) | ||
1337 | { | ||
1338 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
1339 | |||
1340 | kfree(gpriv); | ||
1341 | } | ||
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c new file mode 100644 index 000000000000..b7a9137f599b --- /dev/null +++ b/drivers/usb/renesas_usbhs/pipe.c | |||
@@ -0,0 +1,880 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
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 St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include "./common.h" | ||
21 | #include "./pipe.h" | ||
22 | |||
23 | /* | ||
24 | * macros | ||
25 | */ | ||
26 | #define usbhsp_priv_to_pipeinfo(pr) (&(pr)->pipe_info) | ||
27 | #define usbhsp_pipe_to_priv(p) ((p)->priv) | ||
28 | |||
29 | #define usbhsp_addr_offset(p) ((usbhs_pipe_number(p) - 1) * 2) | ||
30 | |||
31 | #define usbhsp_is_dcp(p) ((p)->priv->pipe_info.pipe == (p)) | ||
32 | |||
33 | #define usbhsp_flags_set(p, f) ((p)->flags |= USBHS_PIPE_FLAGS_##f) | ||
34 | #define usbhsp_flags_clr(p, f) ((p)->flags &= ~USBHS_PIPE_FLAGS_##f) | ||
35 | #define usbhsp_flags_has(p, f) ((p)->flags & USBHS_PIPE_FLAGS_##f) | ||
36 | #define usbhsp_flags_init(p) do {(p)->flags = 0; } while (0) | ||
37 | |||
38 | #define usbhsp_type(p) ((p)->pipe_type) | ||
39 | #define usbhsp_type_is(p, t) ((p)->pipe_type == t) | ||
40 | |||
41 | /* | ||
42 | * for debug | ||
43 | */ | ||
44 | static char *usbhsp_pipe_name[] = { | ||
45 | [USB_ENDPOINT_XFER_CONTROL] = "DCP", | ||
46 | [USB_ENDPOINT_XFER_BULK] = "BULK", | ||
47 | [USB_ENDPOINT_XFER_INT] = "INT", | ||
48 | [USB_ENDPOINT_XFER_ISOC] = "ISO", | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * usb request functions | ||
53 | */ | ||
54 | void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) | ||
55 | { | ||
56 | u16 val; | ||
57 | |||
58 | val = usbhs_read(priv, USBREQ); | ||
59 | req->bRequest = (val >> 8) & 0xFF; | ||
60 | req->bRequestType = (val >> 0) & 0xFF; | ||
61 | |||
62 | req->wValue = usbhs_read(priv, USBVAL); | ||
63 | req->wIndex = usbhs_read(priv, USBINDX); | ||
64 | req->wLength = usbhs_read(priv, USBLENG); | ||
65 | } | ||
66 | |||
67 | void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) | ||
68 | { | ||
69 | usbhs_write(priv, USBREQ, (req->bRequest << 8) | req->bRequestType); | ||
70 | usbhs_write(priv, USBVAL, req->wValue); | ||
71 | usbhs_write(priv, USBINDX, req->wIndex); | ||
72 | usbhs_write(priv, USBLENG, req->wLength); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * DCPCTR/PIPEnCTR functions | ||
77 | */ | ||
78 | static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | ||
79 | { | ||
80 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
81 | int offset = usbhsp_addr_offset(pipe); | ||
82 | |||
83 | if (usbhsp_is_dcp(pipe)) | ||
84 | usbhs_bset(priv, DCPCTR, mask, val); | ||
85 | else | ||
86 | usbhs_bset(priv, PIPEnCTR + offset, mask, val); | ||
87 | } | ||
88 | |||
89 | static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe) | ||
90 | { | ||
91 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
92 | int offset = usbhsp_addr_offset(pipe); | ||
93 | |||
94 | if (usbhsp_is_dcp(pipe)) | ||
95 | return usbhs_read(priv, DCPCTR); | ||
96 | else | ||
97 | return usbhs_read(priv, PIPEnCTR + offset); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * DCP/PIPE functions | ||
102 | */ | ||
103 | static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe, | ||
104 | u16 dcp_reg, u16 pipe_reg, | ||
105 | u16 mask, u16 val) | ||
106 | { | ||
107 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
108 | |||
109 | if (usbhsp_is_dcp(pipe)) | ||
110 | usbhs_bset(priv, dcp_reg, mask, val); | ||
111 | else | ||
112 | usbhs_bset(priv, pipe_reg, mask, val); | ||
113 | } | ||
114 | |||
115 | static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe, | ||
116 | u16 dcp_reg, u16 pipe_reg) | ||
117 | { | ||
118 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
119 | |||
120 | if (usbhsp_is_dcp(pipe)) | ||
121 | return usbhs_read(priv, dcp_reg); | ||
122 | else | ||
123 | return usbhs_read(priv, pipe_reg); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * DCPCFG/PIPECFG functions | ||
128 | */ | ||
129 | static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | ||
130 | { | ||
131 | __usbhsp_pipe_xxx_set(pipe, DCPCFG, PIPECFG, mask, val); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * PIPEBUF | ||
136 | */ | ||
137 | static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | ||
138 | { | ||
139 | if (usbhsp_is_dcp(pipe)) | ||
140 | return; | ||
141 | |||
142 | __usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * DCPMAXP/PIPEMAXP | ||
147 | */ | ||
148 | static void usbhsp_pipe_maxp_set(struct usbhs_pipe *pipe, u16 mask, u16 val) | ||
149 | { | ||
150 | __usbhsp_pipe_xxx_set(pipe, DCPMAXP, PIPEMAXP, mask, val); | ||
151 | } | ||
152 | |||
153 | static u16 usbhsp_pipe_maxp_get(struct usbhs_pipe *pipe) | ||
154 | { | ||
155 | return __usbhsp_pipe_xxx_get(pipe, DCPMAXP, PIPEMAXP); | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * pipe control functions | ||
160 | */ | ||
161 | static void usbhsp_pipe_select(struct usbhs_pipe *pipe) | ||
162 | { | ||
163 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
164 | |||
165 | /* | ||
166 | * On pipe, this is necessary before | ||
167 | * accesses to below registers. | ||
168 | * | ||
169 | * PIPESEL : usbhsp_pipe_select | ||
170 | * PIPECFG : usbhsp_pipe_cfg_xxx | ||
171 | * PIPEBUF : usbhsp_pipe_buf_xxx | ||
172 | * PIPEMAXP : usbhsp_pipe_maxp_xxx | ||
173 | * PIPEPERI | ||
174 | */ | ||
175 | |||
176 | /* | ||
177 | * if pipe is dcp, no pipe is selected. | ||
178 | * it is no problem, because dcp have its register | ||
179 | */ | ||
180 | usbhs_write(priv, PIPESEL, 0xF & usbhs_pipe_number(pipe)); | ||
181 | } | ||
182 | |||
183 | static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) | ||
184 | { | ||
185 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
186 | struct device *dev = usbhs_priv_to_dev(priv); | ||
187 | int timeout = 1024; | ||
188 | u16 val; | ||
189 | |||
190 | /* | ||
191 | * make sure.... | ||
192 | * | ||
193 | * Modify these bits when CSSTS = 0, PID = NAK, and no pipe number is | ||
194 | * specified by the CURPIPE bits. | ||
195 | * When changing the setting of this bit after changing | ||
196 | * the PID bits for the selected pipe from BUF to NAK, | ||
197 | * check that CSSTS = 0 and PBUSY = 0. | ||
198 | */ | ||
199 | |||
200 | /* | ||
201 | * CURPIPE bit = 0 | ||
202 | * | ||
203 | * see also | ||
204 | * "Operation" | ||
205 | * - "Pipe Control" | ||
206 | * - "Pipe Control Registers Switching Procedure" | ||
207 | */ | ||
208 | usbhs_write(priv, CFIFOSEL, 0); | ||
209 | |||
210 | do { | ||
211 | val = usbhsp_pipectrl_get(pipe); | ||
212 | val &= CSSTS | PID_MASK; | ||
213 | if (!val) | ||
214 | return 0; | ||
215 | |||
216 | udelay(10); | ||
217 | |||
218 | } while (timeout--); | ||
219 | |||
220 | /* | ||
221 | * force NAK | ||
222 | */ | ||
223 | timeout = 1024; | ||
224 | usbhs_fifo_disable(pipe); | ||
225 | do { | ||
226 | val = usbhsp_pipectrl_get(pipe); | ||
227 | val &= PBUSY; | ||
228 | if (!val) | ||
229 | return 0; | ||
230 | |||
231 | } while (timeout--); | ||
232 | |||
233 | dev_err(dev, "pipe barrier failed\n"); | ||
234 | |||
235 | return -EBUSY; | ||
236 | } | ||
237 | |||
238 | static int usbhsp_pipe_is_accessible(struct usbhs_pipe *pipe) | ||
239 | { | ||
240 | u16 val; | ||
241 | |||
242 | val = usbhsp_pipectrl_get(pipe); | ||
243 | if (val & BSTS) | ||
244 | return 0; | ||
245 | |||
246 | return -EBUSY; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * PID ctrl | ||
251 | */ | ||
252 | static void __usbhsp_pid_try_nak_if_stall(struct usbhs_pipe *pipe) | ||
253 | { | ||
254 | u16 pid = usbhsp_pipectrl_get(pipe); | ||
255 | |||
256 | pid &= PID_MASK; | ||
257 | |||
258 | /* | ||
259 | * see | ||
260 | * "Pipe n Control Register" - "PID" | ||
261 | */ | ||
262 | switch (pid) { | ||
263 | case PID_STALL11: | ||
264 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL10); | ||
265 | /* fall-through */ | ||
266 | case PID_STALL10: | ||
267 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_NAK); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | void usbhs_fifo_disable(struct usbhs_pipe *pipe) | ||
272 | { | ||
273 | /* see "Pipe n Control Register" - "PID" */ | ||
274 | __usbhsp_pid_try_nak_if_stall(pipe); | ||
275 | |||
276 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_NAK); | ||
277 | } | ||
278 | |||
279 | void usbhs_fifo_enable(struct usbhs_pipe *pipe) | ||
280 | { | ||
281 | /* see "Pipe n Control Register" - "PID" */ | ||
282 | __usbhsp_pid_try_nak_if_stall(pipe); | ||
283 | |||
284 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF); | ||
285 | } | ||
286 | |||
287 | void usbhs_fifo_stall(struct usbhs_pipe *pipe) | ||
288 | { | ||
289 | u16 pid = usbhsp_pipectrl_get(pipe); | ||
290 | |||
291 | pid &= PID_MASK; | ||
292 | |||
293 | /* | ||
294 | * see | ||
295 | * "Pipe n Control Register" - "PID" | ||
296 | */ | ||
297 | switch (pid) { | ||
298 | case PID_NAK: | ||
299 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL10); | ||
300 | break; | ||
301 | case PID_BUF: | ||
302 | usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL11); | ||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * CFIFO ctrl | ||
309 | */ | ||
310 | void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe) | ||
311 | { | ||
312 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
313 | |||
314 | usbhs_bset(priv, CFIFOCTR, BVAL, BVAL); | ||
315 | } | ||
316 | |||
317 | static void usbhsp_fifo_clear(struct usbhs_pipe *pipe) | ||
318 | { | ||
319 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
320 | |||
321 | usbhs_write(priv, CFIFOCTR, BCLR); | ||
322 | } | ||
323 | |||
324 | static int usbhsp_fifo_barrier(struct usbhs_priv *priv) | ||
325 | { | ||
326 | int timeout = 1024; | ||
327 | |||
328 | do { | ||
329 | /* The FIFO port is accessible */ | ||
330 | if (usbhs_read(priv, CFIFOCTR) & FRDY) | ||
331 | return 0; | ||
332 | |||
333 | udelay(10); | ||
334 | } while (timeout--); | ||
335 | |||
336 | return -EBUSY; | ||
337 | } | ||
338 | |||
339 | static int usbhsp_fifo_rcv_len(struct usbhs_priv *priv) | ||
340 | { | ||
341 | return usbhs_read(priv, CFIFOCTR) & DTLN_MASK; | ||
342 | } | ||
343 | |||
344 | static int usbhsp_fifo_select(struct usbhs_pipe *pipe, int write) | ||
345 | { | ||
346 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
347 | struct device *dev = usbhs_priv_to_dev(priv); | ||
348 | int timeout = 1024; | ||
349 | u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ | ||
350 | u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ | ||
351 | |||
352 | if (usbhsp_is_dcp(pipe)) | ||
353 | base |= (1 == write) << 5; /* ISEL */ | ||
354 | |||
355 | /* "base" will be used below */ | ||
356 | usbhs_write(priv, CFIFOSEL, base | MBW_32); | ||
357 | |||
358 | /* check ISEL and CURPIPE value */ | ||
359 | while (timeout--) { | ||
360 | if (base == (mask & usbhs_read(priv, CFIFOSEL))) | ||
361 | return 0; | ||
362 | udelay(10); | ||
363 | } | ||
364 | |||
365 | dev_err(dev, "fifo select error\n"); | ||
366 | |||
367 | return -EIO; | ||
368 | } | ||
369 | |||
370 | int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe) | ||
371 | { | ||
372 | int ret; | ||
373 | |||
374 | ret = usbhsp_fifo_select(pipe, 1); | ||
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | |||
378 | usbhsp_fifo_clear(pipe); | ||
379 | |||
380 | return ret; | ||
381 | } | ||
382 | |||
383 | int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len) | ||
384 | { | ||
385 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
386 | void __iomem *addr = priv->base + CFIFO; | ||
387 | int maxp = usbhs_pipe_get_maxpacket(pipe); | ||
388 | int total_len; | ||
389 | int i, ret; | ||
390 | |||
391 | ret = usbhsp_pipe_is_accessible(pipe); | ||
392 | if (ret < 0) | ||
393 | return ret; | ||
394 | |||
395 | ret = usbhs_fifo_prepare_write(pipe); | ||
396 | if (ret < 0) | ||
397 | return ret; | ||
398 | |||
399 | ret = usbhsp_fifo_barrier(priv); | ||
400 | if (ret < 0) | ||
401 | return ret; | ||
402 | |||
403 | len = min(len, maxp); | ||
404 | total_len = len; | ||
405 | |||
406 | /* | ||
407 | * FIXME | ||
408 | * | ||
409 | * 32-bit access only | ||
410 | */ | ||
411 | if (len >= 4 && | ||
412 | !((unsigned long)buf & 0x03)) { | ||
413 | iowrite32_rep(addr, buf, len / 4); | ||
414 | len %= 4; | ||
415 | buf += total_len - len; | ||
416 | } | ||
417 | |||
418 | /* the rest operation */ | ||
419 | for (i = 0; i < len; i++) | ||
420 | iowrite8(buf[i], addr + (0x03 - (i & 0x03))); | ||
421 | |||
422 | if (total_len < maxp) | ||
423 | usbhs_fifo_send_terminator(pipe); | ||
424 | |||
425 | return total_len; | ||
426 | } | ||
427 | |||
428 | int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe) | ||
429 | { | ||
430 | int ret; | ||
431 | |||
432 | /* | ||
433 | * select pipe and enable it to prepare packet receive | ||
434 | */ | ||
435 | ret = usbhsp_fifo_select(pipe, 0); | ||
436 | if (ret < 0) | ||
437 | return ret; | ||
438 | |||
439 | usbhs_fifo_enable(pipe); | ||
440 | |||
441 | return ret; | ||
442 | } | ||
443 | |||
444 | int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len) | ||
445 | { | ||
446 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
447 | void __iomem *addr = priv->base + CFIFO; | ||
448 | int rcv_len; | ||
449 | int i, ret; | ||
450 | int total_len; | ||
451 | u32 data = 0; | ||
452 | |||
453 | ret = usbhsp_fifo_select(pipe, 0); | ||
454 | if (ret < 0) | ||
455 | return ret; | ||
456 | |||
457 | ret = usbhsp_fifo_barrier(priv); | ||
458 | if (ret < 0) | ||
459 | return ret; | ||
460 | |||
461 | rcv_len = usbhsp_fifo_rcv_len(priv); | ||
462 | |||
463 | /* | ||
464 | * Buffer clear if Zero-Length packet | ||
465 | * | ||
466 | * see | ||
467 | * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" | ||
468 | */ | ||
469 | if (0 == rcv_len) { | ||
470 | usbhsp_fifo_clear(pipe); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | len = min(rcv_len, len); | ||
475 | total_len = len; | ||
476 | |||
477 | /* | ||
478 | * FIXME | ||
479 | * | ||
480 | * 32-bit access only | ||
481 | */ | ||
482 | if (len >= 4 && | ||
483 | !((unsigned long)buf & 0x03)) { | ||
484 | ioread32_rep(addr, buf, len / 4); | ||
485 | len %= 4; | ||
486 | buf += rcv_len - len; | ||
487 | } | ||
488 | |||
489 | /* the rest operation */ | ||
490 | for (i = 0; i < len; i++) { | ||
491 | if (!(i & 0x03)) | ||
492 | data = ioread32(addr); | ||
493 | |||
494 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | ||
495 | } | ||
496 | |||
497 | return total_len; | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * pipe setup | ||
502 | */ | ||
503 | static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe) | ||
504 | { | ||
505 | /* | ||
506 | * only ISO / BULK pipe can use double buffer | ||
507 | */ | ||
508 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) || | ||
509 | usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC)) | ||
510 | return 1; | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, | ||
516 | const struct usb_endpoint_descriptor *desc, | ||
517 | int is_host) | ||
518 | { | ||
519 | u16 type = 0; | ||
520 | u16 bfre = 0; | ||
521 | u16 dblb = 0; | ||
522 | u16 cntmd = 0; | ||
523 | u16 dir = 0; | ||
524 | u16 epnum = 0; | ||
525 | u16 shtnak = 0; | ||
526 | u16 type_array[] = { | ||
527 | [USB_ENDPOINT_XFER_BULK] = TYPE_BULK, | ||
528 | [USB_ENDPOINT_XFER_INT] = TYPE_INT, | ||
529 | [USB_ENDPOINT_XFER_ISOC] = TYPE_ISO, | ||
530 | }; | ||
531 | int is_double = usbhsp_possible_double_buffer(pipe); | ||
532 | |||
533 | if (usbhsp_is_dcp(pipe)) | ||
534 | return -EINVAL; | ||
535 | |||
536 | /* | ||
537 | * PIPECFG | ||
538 | * | ||
539 | * see | ||
540 | * - "Register Descriptions" - "PIPECFG" register | ||
541 | * - "Features" - "Pipe configuration" | ||
542 | * - "Operation" - "Pipe Control" | ||
543 | */ | ||
544 | |||
545 | /* TYPE */ | ||
546 | type = type_array[usbhsp_type(pipe)]; | ||
547 | |||
548 | /* BFRE */ | ||
549 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC) || | ||
550 | usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK)) | ||
551 | bfre = 0; /* FIXME */ | ||
552 | |||
553 | /* DBLB */ | ||
554 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_ISOC) || | ||
555 | usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK)) | ||
556 | dblb = (is_double) ? DBLB : 0; | ||
557 | |||
558 | /* CNTMD */ | ||
559 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK)) | ||
560 | cntmd = 0; /* FIXME */ | ||
561 | |||
562 | /* DIR */ | ||
563 | if (usb_endpoint_dir_in(desc)) | ||
564 | usbhsp_flags_set(pipe, IS_DIR_IN); | ||
565 | |||
566 | if ((is_host && usb_endpoint_dir_out(desc)) || | ||
567 | (!is_host && usb_endpoint_dir_in(desc))) | ||
568 | dir |= DIR_OUT; | ||
569 | |||
570 | /* SHTNAK */ | ||
571 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) && | ||
572 | !dir) | ||
573 | shtnak = SHTNAK; | ||
574 | |||
575 | /* EPNUM */ | ||
576 | epnum = 0xF & usb_endpoint_num(desc); | ||
577 | |||
578 | return type | | ||
579 | bfre | | ||
580 | dblb | | ||
581 | cntmd | | ||
582 | dir | | ||
583 | shtnak | | ||
584 | epnum; | ||
585 | } | ||
586 | |||
587 | static u16 usbhsp_setup_pipemaxp(struct usbhs_pipe *pipe, | ||
588 | const struct usb_endpoint_descriptor *desc, | ||
589 | int is_host) | ||
590 | { | ||
591 | /* host should set DEVSEL */ | ||
592 | |||
593 | /* reutn MXPS */ | ||
594 | return PIPE_MAXP_MASK & le16_to_cpu(desc->wMaxPacketSize); | ||
595 | } | ||
596 | |||
597 | static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, | ||
598 | const struct usb_endpoint_descriptor *desc, | ||
599 | int is_host) | ||
600 | { | ||
601 | struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); | ||
602 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | ||
603 | struct device *dev = usbhs_priv_to_dev(priv); | ||
604 | int pipe_num = usbhs_pipe_number(pipe); | ||
605 | int is_double = usbhsp_possible_double_buffer(pipe); | ||
606 | u16 buff_size; | ||
607 | u16 bufnmb; | ||
608 | u16 bufnmb_cnt; | ||
609 | |||
610 | /* | ||
611 | * PIPEBUF | ||
612 | * | ||
613 | * see | ||
614 | * - "Register Descriptions" - "PIPEBUF" register | ||
615 | * - "Features" - "Pipe configuration" | ||
616 | * - "Operation" - "FIFO Buffer Memory" | ||
617 | * - "Operation" - "Pipe Control" | ||
618 | * | ||
619 | * ex) if pipe6 - pipe9 are USB_ENDPOINT_XFER_INT (SH7724) | ||
620 | * | ||
621 | * BUFNMB: PIPE | ||
622 | * 0: pipe0 (DCP 256byte) | ||
623 | * 1: - | ||
624 | * 2: - | ||
625 | * 3: - | ||
626 | * 4: pipe6 (INT 64byte) | ||
627 | * 5: pipe7 (INT 64byte) | ||
628 | * 6: pipe8 (INT 64byte) | ||
629 | * 7: pipe9 (INT 64byte) | ||
630 | * 8 - xx: free (for BULK, ISOC) | ||
631 | */ | ||
632 | |||
633 | /* | ||
634 | * FIXME | ||
635 | * | ||
636 | * it doesn't have good buffer allocator | ||
637 | * | ||
638 | * DCP : 256 byte | ||
639 | * BULK: 512 byte | ||
640 | * INT : 64 byte | ||
641 | * ISOC: 512 byte | ||
642 | */ | ||
643 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_CONTROL)) | ||
644 | buff_size = 256; | ||
645 | else if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT)) | ||
646 | buff_size = 64; | ||
647 | else | ||
648 | buff_size = 512; | ||
649 | |||
650 | /* change buff_size to register value */ | ||
651 | bufnmb_cnt = (buff_size / 64) - 1; | ||
652 | |||
653 | /* BUFNMB has been reserved for INT pipe | ||
654 | * see above */ | ||
655 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT)) { | ||
656 | bufnmb = pipe_num - 2; | ||
657 | } else { | ||
658 | bufnmb = info->bufnmb_last; | ||
659 | info->bufnmb_last += bufnmb_cnt + 1; | ||
660 | |||
661 | /* | ||
662 | * double buffer | ||
663 | */ | ||
664 | if (is_double) | ||
665 | info->bufnmb_last += bufnmb_cnt + 1; | ||
666 | } | ||
667 | |||
668 | dev_dbg(dev, "pipe : %d : buff_size 0x%x: bufnmb 0x%x\n", | ||
669 | pipe_num, buff_size, bufnmb); | ||
670 | |||
671 | return (0x1f & bufnmb_cnt) << 10 | | ||
672 | (0xff & bufnmb) << 0; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * pipe control | ||
677 | */ | ||
678 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe) | ||
679 | { | ||
680 | u16 mask = usbhsp_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK; | ||
681 | |||
682 | usbhsp_pipe_select(pipe); | ||
683 | |||
684 | return (int)(usbhsp_pipe_maxp_get(pipe) & mask); | ||
685 | } | ||
686 | |||
687 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe) | ||
688 | { | ||
689 | return usbhsp_flags_has(pipe, IS_DIR_IN); | ||
690 | } | ||
691 | |||
692 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe) | ||
693 | { | ||
694 | usbhsp_pipectrl_set(pipe, SQCLR, SQCLR); | ||
695 | } | ||
696 | |||
697 | static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) | ||
698 | { | ||
699 | struct usbhs_pipe *pos, *pipe; | ||
700 | int i; | ||
701 | |||
702 | /* | ||
703 | * find target pipe | ||
704 | */ | ||
705 | pipe = NULL; | ||
706 | usbhs_for_each_pipe_with_dcp(pos, priv, i) { | ||
707 | if (!usbhsp_type_is(pos, type)) | ||
708 | continue; | ||
709 | if (usbhsp_flags_has(pos, IS_USED)) | ||
710 | continue; | ||
711 | |||
712 | pipe = pos; | ||
713 | break; | ||
714 | } | ||
715 | |||
716 | if (!pipe) | ||
717 | return NULL; | ||
718 | |||
719 | /* | ||
720 | * initialize pipe flags | ||
721 | */ | ||
722 | usbhsp_flags_init(pipe); | ||
723 | usbhsp_flags_set(pipe, IS_USED); | ||
724 | |||
725 | return pipe; | ||
726 | } | ||
727 | |||
728 | void usbhs_pipe_init(struct usbhs_priv *priv) | ||
729 | { | ||
730 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | ||
731 | struct usbhs_pipe *pipe; | ||
732 | int i; | ||
733 | |||
734 | /* | ||
735 | * FIXME | ||
736 | * | ||
737 | * driver needs good allocator. | ||
738 | * | ||
739 | * find first free buffer area (BULK, ISOC) | ||
740 | * (DCP, INT area is fixed) | ||
741 | * | ||
742 | * buffer number 0 - 3 have been reserved for DCP | ||
743 | * see | ||
744 | * usbhsp_to_bufnmb | ||
745 | */ | ||
746 | info->bufnmb_last = 4; | ||
747 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
748 | if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_INT)) | ||
749 | info->bufnmb_last++; | ||
750 | |||
751 | usbhsp_flags_init(pipe); | ||
752 | pipe->mod_private = NULL; | ||
753 | } | ||
754 | } | ||
755 | |||
756 | struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, | ||
757 | const struct usb_endpoint_descriptor *desc) | ||
758 | { | ||
759 | struct device *dev = usbhs_priv_to_dev(priv); | ||
760 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | ||
761 | struct usbhs_pipe *pipe; | ||
762 | int is_host = usbhs_mod_is_host(priv, mod); | ||
763 | int ret; | ||
764 | u16 pipecfg, pipebuf, pipemaxp; | ||
765 | |||
766 | pipe = usbhsp_get_pipe(priv, usb_endpoint_type(desc)); | ||
767 | if (!pipe) | ||
768 | return NULL; | ||
769 | |||
770 | usbhs_fifo_disable(pipe); | ||
771 | |||
772 | /* make sure pipe is not busy */ | ||
773 | ret = usbhsp_pipe_barrier(pipe); | ||
774 | if (ret < 0) { | ||
775 | dev_err(dev, "pipe setup failed %d\n", usbhs_pipe_number(pipe)); | ||
776 | return NULL; | ||
777 | } | ||
778 | |||
779 | pipecfg = usbhsp_setup_pipecfg(pipe, desc, is_host); | ||
780 | pipebuf = usbhsp_setup_pipebuff(pipe, desc, is_host); | ||
781 | pipemaxp = usbhsp_setup_pipemaxp(pipe, desc, is_host); | ||
782 | |||
783 | /* buffer clear | ||
784 | * see PIPECFG :: BFRE */ | ||
785 | usbhsp_pipectrl_set(pipe, ACLRM, ACLRM); | ||
786 | usbhsp_pipectrl_set(pipe, ACLRM, 0); | ||
787 | |||
788 | usbhsp_pipe_select(pipe); | ||
789 | usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg); | ||
790 | usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf); | ||
791 | usbhsp_pipe_maxp_set(pipe, 0xFFFF, pipemaxp); | ||
792 | |||
793 | usbhs_pipe_clear_sequence(pipe); | ||
794 | |||
795 | dev_dbg(dev, "enable pipe %d : %s (%s)\n", | ||
796 | usbhs_pipe_number(pipe), | ||
797 | usbhsp_pipe_name[usb_endpoint_type(desc)], | ||
798 | usbhs_pipe_is_dir_in(pipe) ? "in" : "out"); | ||
799 | |||
800 | return pipe; | ||
801 | } | ||
802 | |||
803 | /* | ||
804 | * dcp control | ||
805 | */ | ||
806 | struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv) | ||
807 | { | ||
808 | struct usbhs_pipe *pipe; | ||
809 | |||
810 | pipe = usbhsp_get_pipe(priv, USB_ENDPOINT_XFER_CONTROL); | ||
811 | if (!pipe) | ||
812 | return NULL; | ||
813 | |||
814 | /* | ||
815 | * dcpcfg : default | ||
816 | * dcpmaxp : default | ||
817 | * pipebuf : nothing to do | ||
818 | */ | ||
819 | |||
820 | usbhsp_pipe_select(pipe); | ||
821 | usbhs_pipe_clear_sequence(pipe); | ||
822 | |||
823 | return pipe; | ||
824 | } | ||
825 | |||
826 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe) | ||
827 | { | ||
828 | WARN_ON(!usbhsp_is_dcp(pipe)); | ||
829 | |||
830 | usbhs_fifo_enable(pipe); | ||
831 | usbhsp_pipectrl_set(pipe, CCPL, CCPL); | ||
832 | } | ||
833 | |||
834 | |||
835 | /* | ||
836 | * pipe module function | ||
837 | */ | ||
838 | int usbhs_pipe_probe(struct usbhs_priv *priv) | ||
839 | { | ||
840 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | ||
841 | struct usbhs_pipe *pipe; | ||
842 | struct device *dev = usbhs_priv_to_dev(priv); | ||
843 | u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); | ||
844 | int pipe_size = usbhs_get_dparam(priv, pipe_size); | ||
845 | int i; | ||
846 | |||
847 | /* This driver expects 1st pipe is DCP */ | ||
848 | if (pipe_type[0] != USB_ENDPOINT_XFER_CONTROL) { | ||
849 | dev_err(dev, "1st PIPE is not DCP\n"); | ||
850 | return -EINVAL; | ||
851 | } | ||
852 | |||
853 | info->pipe = kzalloc(sizeof(struct usbhs_pipe) * pipe_size, GFP_KERNEL); | ||
854 | if (!info->pipe) { | ||
855 | dev_err(dev, "Could not allocate pipe\n"); | ||
856 | return -ENOMEM; | ||
857 | } | ||
858 | |||
859 | info->size = pipe_size; | ||
860 | |||
861 | /* | ||
862 | * init pipe | ||
863 | */ | ||
864 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | ||
865 | pipe->priv = priv; | ||
866 | usbhsp_type(pipe) = pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK; | ||
867 | |||
868 | dev_dbg(dev, "pipe %x\t: %s\n", | ||
869 | i, usbhsp_pipe_name[pipe_type[i]]); | ||
870 | } | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | void usbhs_pipe_remove(struct usbhs_priv *priv) | ||
876 | { | ||
877 | struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); | ||
878 | |||
879 | kfree(info->pipe); | ||
880 | } | ||
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h new file mode 100644 index 000000000000..4a60dcef9676 --- /dev/null +++ b/drivers/usb/renesas_usbhs/pipe.h | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Renesas USB driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
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 St, Fifth Floor, Boston, MA 02110-1301 USA | ||
15 | * | ||
16 | */ | ||
17 | #ifndef RENESAS_USB_PIPE_H | ||
18 | #define RENESAS_USB_PIPE_H | ||
19 | |||
20 | #include "./common.h" | ||
21 | |||
22 | /* | ||
23 | * struct | ||
24 | */ | ||
25 | struct usbhs_pipe { | ||
26 | u32 pipe_type; /* USB_ENDPOINT_XFER_xxx */ | ||
27 | |||
28 | struct usbhs_priv *priv; | ||
29 | |||
30 | u32 flags; | ||
31 | #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) | ||
32 | #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) | ||
33 | |||
34 | void *mod_private; | ||
35 | }; | ||
36 | |||
37 | struct usbhs_pipe_info { | ||
38 | struct usbhs_pipe *pipe; | ||
39 | int size; /* array size of "pipe" */ | ||
40 | int bufnmb_last; /* FIXME : driver needs good allocator */ | ||
41 | }; | ||
42 | |||
43 | /* | ||
44 | * pipe list | ||
45 | */ | ||
46 | #define __usbhs_for_each_pipe(start, pos, info, i) \ | ||
47 | for (i = start, pos = (info)->pipe; \ | ||
48 | i < (info)->size; \ | ||
49 | i++, pos = (info)->pipe + i) | ||
50 | |||
51 | #define usbhs_for_each_pipe(pos, priv, i) \ | ||
52 | __usbhs_for_each_pipe(1, pos, &((priv)->pipe_info), i) | ||
53 | |||
54 | #define usbhs_for_each_pipe_with_dcp(pos, priv, i) \ | ||
55 | __usbhs_for_each_pipe(0, pos, &((priv)->pipe_info), i) | ||
56 | |||
57 | /* | ||
58 | * pipe module probe / remove | ||
59 | */ | ||
60 | int usbhs_pipe_probe(struct usbhs_priv *priv); | ||
61 | void usbhs_pipe_remove(struct usbhs_priv *priv); | ||
62 | |||
63 | /* | ||
64 | * cfifo | ||
65 | */ | ||
66 | int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len); | ||
67 | int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len); | ||
68 | int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe); | ||
69 | int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe); | ||
70 | |||
71 | void usbhs_fifo_enable(struct usbhs_pipe *pipe); | ||
72 | void usbhs_fifo_disable(struct usbhs_pipe *pipe); | ||
73 | void usbhs_fifo_stall(struct usbhs_pipe *pipe); | ||
74 | |||
75 | void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe); | ||
76 | |||
77 | |||
78 | /* | ||
79 | * usb request | ||
80 | */ | ||
81 | void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req); | ||
82 | void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req); | ||
83 | |||
84 | /* | ||
85 | * pipe control | ||
86 | */ | ||
87 | struct usbhs_pipe | ||
88 | *usbhs_pipe_malloc(struct usbhs_priv *priv, | ||
89 | const struct usb_endpoint_descriptor *desc); | ||
90 | |||
91 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); | ||
92 | void usbhs_pipe_init(struct usbhs_priv *priv); | ||
93 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); | ||
94 | void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe); | ||
95 | |||
96 | #define usbhs_pipe_number(p) (((u32)(p) - (u32)(p)->priv->pipe_info.pipe) / \ | ||
97 | sizeof(struct usbhs_pipe)) | ||
98 | |||
99 | /* | ||
100 | * dcp control | ||
101 | */ | ||
102 | struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv); | ||
103 | void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe); | ||
104 | |||
105 | #endif /* RENESAS_USB_PIPE_H */ | ||
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index c2b29761fa98..b71e309116a3 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -527,15 +527,6 @@ config USB_SERIAL_SAFE_PADDED | |||
527 | bool "USB Secure Encapsulated Driver - Padded" | 527 | bool "USB Secure Encapsulated Driver - Padded" |
528 | depends on USB_SERIAL_SAFE | 528 | depends on USB_SERIAL_SAFE |
529 | 529 | ||
530 | config USB_SERIAL_SAMBA | ||
531 | tristate "USB Atmel SAM Boot Assistant (SAM-BA) driver" | ||
532 | help | ||
533 | Say Y here if you want to access the SAM-BA boot application of an | ||
534 | Atmel AT91SAM device. | ||
535 | |||
536 | To compile this driver as a module, choose M here: the | ||
537 | module will be called sam-ba. | ||
538 | |||
539 | config USB_SERIAL_SIEMENS_MPI | 530 | config USB_SERIAL_SIEMENS_MPI |
540 | tristate "USB Siemens MPI driver" | 531 | tristate "USB Siemens MPI driver" |
541 | help | 532 | help |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 9a2117f2b06e..9e536eefb32c 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -48,7 +48,6 @@ obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o | |||
48 | obj-$(CONFIG_USB_SERIAL_QCAUX) += qcaux.o | 48 | obj-$(CONFIG_USB_SERIAL_QCAUX) += qcaux.o |
49 | obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o | 49 | obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o |
50 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o | 50 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o |
51 | obj-$(CONFIG_USB_SERIAL_SAMBA) += sam-ba.o | ||
52 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o | 51 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o |
53 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o | 52 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o |
54 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o | 53 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o |
diff --git a/drivers/usb/serial/sam-ba.c b/drivers/usb/serial/sam-ba.c deleted file mode 100644 index e3bba64afc57..000000000000 --- a/drivers/usb/serial/sam-ba.c +++ /dev/null | |||
@@ -1,206 +0,0 @@ | |||
1 | /* | ||
2 | * Atmel SAM Boot Assistant (SAM-BA) driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Johan Hovold <jhovold@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/tty.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/usb.h> | ||
16 | #include <linux/usb/serial.h> | ||
17 | |||
18 | |||
19 | #define DRIVER_VERSION "v1.0" | ||
20 | #define DRIVER_AUTHOR "Johan Hovold <jhovold@gmail.com>" | ||
21 | #define DRIVER_DESC "Atmel SAM Boot Assistant (SAM-BA) driver" | ||
22 | |||
23 | #define SAMBA_VENDOR_ID 0x3eb | ||
24 | #define SAMBA_PRODUCT_ID 0x6124 | ||
25 | |||
26 | |||
27 | static int debug; | ||
28 | |||
29 | static const struct usb_device_id id_table[] = { | ||
30 | /* | ||
31 | * NOTE: Only match the CDC Data interface. | ||
32 | */ | ||
33 | { USB_DEVICE_AND_INTERFACE_INFO(SAMBA_VENDOR_ID, SAMBA_PRODUCT_ID, | ||
34 | USB_CLASS_CDC_DATA, 0, 0) }, | ||
35 | { } | ||
36 | }; | ||
37 | MODULE_DEVICE_TABLE(usb, id_table); | ||
38 | |||
39 | static struct usb_driver samba_driver = { | ||
40 | .name = "sam-ba", | ||
41 | .probe = usb_serial_probe, | ||
42 | .disconnect = usb_serial_disconnect, | ||
43 | .id_table = id_table, | ||
44 | .no_dynamic_id = 1, | ||
45 | }; | ||
46 | |||
47 | |||
48 | /* | ||
49 | * NOTE: The SAM-BA firmware cannot handle merged write requests so we cannot | ||
50 | * use the generic write implementation (which uses the port write fifo). | ||
51 | */ | ||
52 | static int samba_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
53 | const unsigned char *buf, int count) | ||
54 | { | ||
55 | struct urb *urb; | ||
56 | unsigned long flags; | ||
57 | int result; | ||
58 | int i; | ||
59 | |||
60 | if (!count) | ||
61 | return 0; | ||
62 | |||
63 | count = min_t(int, count, port->bulk_out_size); | ||
64 | |||
65 | spin_lock_irqsave(&port->lock, flags); | ||
66 | if (!port->write_urbs_free) { | ||
67 | spin_unlock_irqrestore(&port->lock, flags); | ||
68 | return 0; | ||
69 | } | ||
70 | i = find_first_bit(&port->write_urbs_free, | ||
71 | ARRAY_SIZE(port->write_urbs)); | ||
72 | __clear_bit(i, &port->write_urbs_free); | ||
73 | port->tx_bytes += count; | ||
74 | spin_unlock_irqrestore(&port->lock, flags); | ||
75 | |||
76 | urb = port->write_urbs[i]; | ||
77 | memcpy(urb->transfer_buffer, buf, count); | ||
78 | urb->transfer_buffer_length = count; | ||
79 | usb_serial_debug_data(debug, &port->dev, __func__, count, | ||
80 | urb->transfer_buffer); | ||
81 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
82 | if (result) { | ||
83 | dev_err(&port->dev, "%s - error submitting urb: %d\n", | ||
84 | __func__, result); | ||
85 | spin_lock_irqsave(&port->lock, flags); | ||
86 | __set_bit(i, &port->write_urbs_free); | ||
87 | port->tx_bytes -= count; | ||
88 | spin_unlock_irqrestore(&port->lock, flags); | ||
89 | |||
90 | return result; | ||
91 | } | ||
92 | |||
93 | return count; | ||
94 | } | ||
95 | |||
96 | static int samba_write_room(struct tty_struct *tty) | ||
97 | { | ||
98 | struct usb_serial_port *port = tty->driver_data; | ||
99 | unsigned long flags; | ||
100 | unsigned long free; | ||
101 | int count; | ||
102 | int room; | ||
103 | |||
104 | spin_lock_irqsave(&port->lock, flags); | ||
105 | free = port->write_urbs_free; | ||
106 | spin_unlock_irqrestore(&port->lock, flags); | ||
107 | |||
108 | count = hweight_long(free); | ||
109 | room = count * port->bulk_out_size; | ||
110 | |||
111 | dbg("%s - returns %d", __func__, room); | ||
112 | |||
113 | return room; | ||
114 | } | ||
115 | |||
116 | static int samba_chars_in_buffer(struct tty_struct *tty) | ||
117 | { | ||
118 | struct usb_serial_port *port = tty->driver_data; | ||
119 | unsigned long flags; | ||
120 | int chars; | ||
121 | |||
122 | spin_lock_irqsave(&port->lock, flags); | ||
123 | chars = port->tx_bytes; | ||
124 | spin_unlock_irqrestore(&port->lock, flags); | ||
125 | |||
126 | dbg("%s - returns %d", __func__, chars); | ||
127 | |||
128 | return chars; | ||
129 | } | ||
130 | |||
131 | static void samba_write_bulk_callback(struct urb *urb) | ||
132 | { | ||
133 | struct usb_serial_port *port = urb->context; | ||
134 | unsigned long flags; | ||
135 | int i; | ||
136 | |||
137 | dbg("%s - port %d", __func__, port->number); | ||
138 | |||
139 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) { | ||
140 | if (port->write_urbs[i] == urb) | ||
141 | break; | ||
142 | } | ||
143 | spin_lock_irqsave(&port->lock, flags); | ||
144 | __set_bit(i, &port->write_urbs_free); | ||
145 | port->tx_bytes -= urb->transfer_buffer_length; | ||
146 | spin_unlock_irqrestore(&port->lock, flags); | ||
147 | |||
148 | if (urb->status) | ||
149 | dbg("%s - non-zero urb status: %d", __func__, urb->status); | ||
150 | |||
151 | usb_serial_port_softint(port); | ||
152 | } | ||
153 | |||
154 | static struct usb_serial_driver samba_device = { | ||
155 | .driver = { | ||
156 | .owner = THIS_MODULE, | ||
157 | .name = "sam-ba", | ||
158 | }, | ||
159 | .usb_driver = &samba_driver, | ||
160 | .id_table = id_table, | ||
161 | .num_ports = 1, | ||
162 | .bulk_in_size = 512, | ||
163 | .bulk_out_size = 2048, | ||
164 | .write = samba_write, | ||
165 | .write_room = samba_write_room, | ||
166 | .chars_in_buffer = samba_chars_in_buffer, | ||
167 | .write_bulk_callback = samba_write_bulk_callback, | ||
168 | .throttle = usb_serial_generic_throttle, | ||
169 | .unthrottle = usb_serial_generic_unthrottle, | ||
170 | }; | ||
171 | |||
172 | static int __init samba_init(void) | ||
173 | { | ||
174 | int retval; | ||
175 | |||
176 | retval = usb_serial_register(&samba_device); | ||
177 | if (retval) | ||
178 | return retval; | ||
179 | |||
180 | retval = usb_register(&samba_driver); | ||
181 | if (retval) { | ||
182 | usb_serial_deregister(&samba_device); | ||
183 | return retval; | ||
184 | } | ||
185 | |||
186 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": " | ||
187 | DRIVER_DESC "\n"); | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static void __exit samba_exit(void) | ||
192 | { | ||
193 | usb_deregister(&samba_driver); | ||
194 | usb_serial_deregister(&samba_device); | ||
195 | } | ||
196 | |||
197 | module_init(samba_init); | ||
198 | module_exit(samba_exit); | ||
199 | |||
200 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
201 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
202 | MODULE_VERSION(DRIVER_VERSION); | ||
203 | MODULE_LICENSE("GPL"); | ||
204 | |||
205 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
206 | MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); | ||