diff options
21 files changed, 1711 insertions, 42 deletions
diff --git a/driver-core/debugfs-mark-me-as-the-maintainer.patch b/driver-core/debugfs-mark-me-as-the-maintainer.patch index 27d9f7966711d1..f4fc27d51fb504 100644 --- a/driver-core/debugfs-mark-me-as-the-maintainer.patch +++ b/driver-core/debugfs-mark-me-as-the-maintainer.patch @@ -15,7 +15,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -2033,14 +2033,16 @@ F: drivers/block/drbd/ +@@ -2040,14 +2040,16 @@ F: drivers/block/drbd/ F: lib/lru_cache.c F: Documentation/blockdev/drbd/ @@ -154,6 +154,21 @@ usb/usb-add-uas-driver.patch usb/usb-gadget-file_storage-reuse-definitions-from-a-header-file.patch usb/usb-driver-for-meywa-denki-kayac-yurex.patch usb/usb-yurex-assign-a-real-minor-number-to-the-driver.patch +usb/usb-yurex-fix-memory-leak-and-corrupted-messages.patch +usb/usb-musb-make-dbg-calls-actually-depend-on-config_usb_musb_debug.patch +usb/usb-musb-introduce-da8xx-omap-l1x-glue-layer.patch +usb/usb-musb-support-iso-high-bandwidth-for-gadget-mode.patch +usb/usb-musb-musbhsdma-increase-max_len-to-1mb.patch +usb/usb-musb-host-unmap-the-buffer-for-pio-data-transfers.patch +usb/usb-musb-change-to-direct-addr-in-context-save-restore.patch +usb/usb-musb-gadget-unmapping-the-dma-buffer-when-switching-to-pio-mode.patch +usb/usb-musb-host-support-dma-transfers-greater-than-max-channel-length.patch +usb/usb-musb-suppress-warning-about-unused-flags.patch +usb/usb-musb-gadget-kill-duplicate-code-in-musb_gadget_queue.patch +usb/usb-musb-gadget-kill-unreachable-code-in-musb_g_rx.patch +usb/usb-musb-ignore-spurious-sessreq-interrupts.patch +usb/usb-musb-gadget-fix-zlp-sending-in-musb_g_tx-v1.patch +usb/usb-musb-gadget-only-enable-autoclear-in-double-buffered-case.patch # staging stuff for next is now in the staging-next tree on git.kernel.org diff --git a/tty/serial-mfd-snprintf-returns-largish-values.patch b/tty/serial-mfd-snprintf-returns-largish-values.patch index 9a0835027853a1..db955f6b273191 100644 --- a/tty/serial-mfd-snprintf-returns-largish-values.patch +++ b/tty/serial-mfd-snprintf-returns-largish-values.patch @@ -23,7 +23,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c -@@ -171,6 +171,9 @@ static ssize_t port_show_regs(struct fil +@@ -172,6 +172,9 @@ static ssize_t port_show_regs(struct fil len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV)); @@ -33,7 +33,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); return ret; -@@ -218,6 +221,9 @@ static ssize_t dma_show_regs(struct file +@@ -219,6 +222,9 @@ static ssize_t dma_show_regs(struct file len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR)); diff --git a/tty/serial-mrst_max3110-make-the-irq-option-runtime.patch b/tty/serial-mrst_max3110-make-the-irq-option-runtime.patch index 13df6777ab34db..7a4a0131f38ca6 100644 --- a/tty/serial-mrst_max3110-make-the-irq-option-runtime.patch +++ b/tty/serial-mrst_max3110-make-the-irq-option-runtime.patch @@ -40,7 +40,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> depends on PCI --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c -@@ -446,7 +446,6 @@ static int max3110_main_thread(void *_ma +@@ -447,7 +447,6 @@ static int max3110_main_thread(void *_ma return ret; } @@ -48,7 +48,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static irqreturn_t serial_m3110_irq(int irq, void *dev_id) { struct uart_max3110 *max = dev_id; -@@ -458,7 +457,7 @@ static irqreturn_t serial_m3110_irq(int +@@ -459,7 +458,7 @@ static irqreturn_t serial_m3110_irq(int return IRQ_HANDLED; } @@ -57,7 +57,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* if don't use RX IRQ, then need a thread to polling read */ static int max3110_read_thread(void *_max) { -@@ -481,7 +480,6 @@ static int max3110_read_thread(void *_ma +@@ -482,7 +481,6 @@ static int max3110_read_thread(void *_ma return 0; } @@ -65,7 +65,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static int serial_m3110_startup(struct uart_port *port) { -@@ -504,34 +502,38 @@ static int serial_m3110_startup(struct u +@@ -505,34 +503,38 @@ static int serial_m3110_startup(struct u /* as we use thread to handle tx/rx, need set low latency */ port->state->port.tty->low_latency = 1; @@ -125,7 +125,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> return ret; } -@@ -550,9 +552,8 @@ static void serial_m3110_shutdown(struct +@@ -551,9 +553,8 @@ static void serial_m3110_shutdown(struct max->read_thread = NULL; } diff --git a/tty/serial-mrst_max3110-some-code-cleanup.patch b/tty/serial-mrst_max3110-some-code-cleanup.patch index a9315cc5cee5f0..0d85c63418e1fa 100644 --- a/tty/serial-mrst_max3110-some-code-cleanup.patch +++ b/tty/serial-mrst_max3110-some-code-cleanup.patch @@ -36,8 +36,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, -@@ -31,18 +31,13 @@ - #include <linux/ioport.h> +@@ -32,18 +32,13 @@ + #include <linux/irq.h> #include <linux/init.h> #include <linux/console.h> -#include <linux/sysrq.h> @@ -55,7 +55,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> #include "mrst_max3110.h" -@@ -55,7 +50,7 @@ +@@ -56,7 +51,7 @@ struct uart_max3110 { struct uart_port port; struct spi_device *spi; @@ -64,7 +64,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> wait_queue_head_t wq; struct task_struct *main_thread; -@@ -66,35 +61,30 @@ struct uart_max3110 { +@@ -67,35 +62,30 @@ struct uart_max3110 { u16 cur_conf; u8 clock; u8 parity, word_7bits; @@ -107,7 +107,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> spi_message_init(&message); memset(&x, 0, sizeof x); x.len = len; -@@ -103,7 +93,7 @@ int max3110_write_then_read(struct uart_ +@@ -104,7 +94,7 @@ int max3110_write_then_read(struct uart_ spi_message_add_tail(&x, &message); if (always_fast) @@ -116,7 +116,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> else if (max->baud) x.speed_hz = max->baud; -@@ -112,58 +102,80 @@ int max3110_write_then_read(struct uart_ +@@ -113,58 +103,80 @@ int max3110_write_then_read(struct uart_ return ret; } @@ -224,7 +224,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> return j; } -@@ -177,10 +189,6 @@ static void serial_m3110_con_putchar(str +@@ -178,10 +190,6 @@ static void serial_m3110_con_putchar(str xmit->buf[xmit->head] = (char)ch; xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1); } @@ -235,7 +235,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } /* -@@ -196,6 +204,9 @@ static void serial_m3110_con_write(struc +@@ -197,6 +205,9 @@ static void serial_m3110_con_write(struc return; uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); @@ -245,7 +245,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } static int __init -@@ -209,6 +220,9 @@ serial_m3110_con_setup(struct console *c +@@ -210,6 +221,9 @@ serial_m3110_con_setup(struct console *c pr_info(PR_FMT "setting up console\n"); @@ -255,7 +255,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if (!max) { pr_err(PR_FMT "pmax is NULL, return"); return -ENODEV; -@@ -239,8 +253,6 @@ static struct console serial_m3110_conso +@@ -240,8 +254,6 @@ static struct console serial_m3110_conso .data = &serial_m3110_reg, }; @@ -264,7 +264,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static unsigned int serial_m3110_tx_empty(struct uart_port *port) { return 1; -@@ -258,32 +270,44 @@ static void serial_m3110_stop_rx(struct +@@ -259,32 +271,44 @@ static void serial_m3110_stop_rx(struct } #define WORDS_PER_XFER 128 @@ -319,7 +319,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } if (j) -@@ -293,6 +317,8 @@ static inline void send_circ_buf(struct +@@ -294,6 +318,8 @@ static inline void send_circ_buf(struct left -= len; } } @@ -328,7 +328,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } static void transmit_char(struct uart_max3110 *max) -@@ -312,8 +338,10 @@ static void transmit_char(struct uart_ma +@@ -313,8 +339,10 @@ static void transmit_char(struct uart_ma serial_m3110_stop_tx(port); } @@ -341,7 +341,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static void serial_m3110_start_tx(struct uart_port *port) { struct uart_max3110 *max = -@@ -335,7 +363,7 @@ static void receive_chars(struct uart_ma +@@ -336,7 +364,7 @@ static void receive_chars(struct uart_ma tty = port->state->port.tty; if (!tty) @@ -350,7 +350,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> while (len) { usable = tty_buffer_request_room(tty, len); -@@ -343,32 +371,37 @@ static void receive_chars(struct uart_ma +@@ -344,32 +372,37 @@ static void receive_chars(struct uart_ma tty_insert_flip_string(tty, str, usable); str += usable; port->icount.rx += usable; @@ -398,7 +398,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> receive_chars(max, recv_buf, total); pbuf = recv_buf; total = 0; -@@ -396,7 +429,7 @@ static int max3110_main_thread(void *_ma +@@ -397,7 +430,7 @@ static int max3110_main_thread(void *_ma mutex_lock(&max->thread_mutex); if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags)) @@ -407,7 +407,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* first handle console output */ if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags)) -@@ -433,9 +466,14 @@ static int max3110_read_thread(void *_ma +@@ -434,9 +467,14 @@ static int max3110_read_thread(void *_ma pr_info(PR_FMT "start read thread\n"); do { @@ -425,7 +425,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 20); -@@ -452,15 +490,16 @@ static int serial_m3110_startup(struct u +@@ -453,15 +491,16 @@ static int serial_m3110_startup(struct u u16 config = 0; int ret = 0; @@ -445,7 +445,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* as we use thread to handle tx/rx, need set low latency */ port->state->port.tty->low_latency = 1; -@@ -471,14 +510,30 @@ static int serial_m3110_startup(struct u +@@ -472,14 +511,30 @@ static int serial_m3110_startup(struct u if (ret) return ret; @@ -479,7 +479,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> max->cur_conf = config; return 0; -@@ -515,8 +570,7 @@ static int serial_m3110_request_port(str +@@ -516,8 +571,7 @@ static int serial_m3110_request_port(str static void serial_m3110_config_port(struct uart_port *port, int flags) { @@ -489,7 +489,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } static int -@@ -551,6 +605,9 @@ serial_m3110_set_termios(struct uart_por +@@ -552,6 +606,9 @@ serial_m3110_set_termios(struct uart_por new_conf |= WC_7BIT_WORD; break; default: @@ -499,7 +499,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> case CS8: cval = UART_LCR_WLEN8; new_conf |= WC_8BIT_WORD; -@@ -559,7 +616,7 @@ serial_m3110_set_termios(struct uart_por +@@ -560,7 +617,7 @@ serial_m3110_set_termios(struct uart_por baud = uart_get_baud_rate(port, termios, old, 0, 230400); @@ -508,7 +508,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> switch (baud) { case 300: clk_div = WC_BAUD_DR384; -@@ -595,7 +652,7 @@ serial_m3110_set_termios(struct uart_por +@@ -596,7 +653,7 @@ serial_m3110_set_termios(struct uart_por if (max->clock & MAX3110_HIGH_CLK) break; default: @@ -517,7 +517,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> baud = max->baud; clk_div = max->cur_conf & WC_BAUD_DIV_MASK; tty_termios_encode_baud_rate(termios, baud, baud); -@@ -603,15 +660,21 @@ serial_m3110_set_termios(struct uart_por +@@ -604,15 +661,21 @@ serial_m3110_set_termios(struct uart_por if (max->clock & MAX3110_HIGH_CLK) { clk_div += 1; @@ -541,7 +541,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if (termios->c_cflag & CSTOPB) new_conf |= WC_2_STOPBITS; else -@@ -631,13 +694,14 @@ serial_m3110_set_termios(struct uart_por +@@ -632,13 +695,14 @@ serial_m3110_set_termios(struct uart_por new_conf |= WC_TAG; if (new_conf != max->cur_conf) { @@ -560,7 +560,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static unsigned int serial_m3110_get_mctrl(struct uart_port *port) { return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR; -@@ -671,7 +735,7 @@ struct uart_ops serial_m3110_ops = { +@@ -672,7 +736,7 @@ struct uart_ops serial_m3110_ops = { .break_ctl = serial_m3110_break_ctl, .startup = serial_m3110_startup, .shutdown = serial_m3110_shutdown, @@ -569,7 +569,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> .pm = serial_m3110_pm, .type = serial_m3110_type, .release_port = serial_m3110_release_port, -@@ -687,52 +751,60 @@ static struct uart_driver serial_m3110_r +@@ -688,52 +752,60 @@ static struct uart_driver serial_m3110_r .major = TTY_MAJOR, .minor = 64, .nr = 1, @@ -646,7 +646,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> max->irq = (u16)spi->irq; mutex_init(&max->thread_mutex); -@@ -754,13 +826,15 @@ static int serial_m3110_probe(struct spi +@@ -755,13 +827,15 @@ static int serial_m3110_probe(struct spi ret = -ENODEV; goto err_get_page; } @@ -665,7 +665,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> max->main_thread = kthread_run(max3110_main_thread, max, "max3110_main"); -@@ -769,8 +843,10 @@ static int serial_m3110_probe(struct spi +@@ -770,8 +844,10 @@ static int serial_m3110_probe(struct spi goto err_kthread; } @@ -677,7 +677,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> max->port.membase = (void *)0xff110000; uart_add_one_port(&serial_m3110_reg, &max->port); -@@ -779,19 +855,17 @@ static int serial_m3110_probe(struct spi +@@ -780,19 +856,17 @@ static int serial_m3110_probe(struct spi err_kthread: free_page((unsigned long)buffer); err_get_page: @@ -700,7 +700,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> uart_remove_one_port(&serial_m3110_reg, &max->port); free_page((unsigned long)max->con_xmit.buf); -@@ -810,13 +884,12 @@ static struct spi_driver uart_max3110_dr +@@ -811,13 +885,12 @@ static struct spi_driver uart_max3110_dr .owner = THIS_MODULE, }, .probe = serial_m3110_probe, @@ -716,7 +716,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> { int ret = 0; -@@ -831,7 +904,7 @@ int __init serial_m3110_init(void) +@@ -832,7 +905,7 @@ int __init serial_m3110_init(void) return ret; } @@ -725,7 +725,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> { spi_unregister_driver(&uart_max3110_driver); uart_unregister_driver(&serial_m3110_reg); -@@ -840,5 +913,5 @@ void __exit serial_m3110_exit(void) +@@ -841,5 +914,5 @@ void __exit serial_m3110_exit(void) module_init(serial_m3110_init); module_exit(serial_m3110_exit); diff --git a/usb/usb-add-uas-driver.patch b/usb/usb-add-uas-driver.patch index 978327b2463586..77c6313c870283 100644 --- a/usb/usb-add-uas-driver.patch +++ b/usb/usb-add-uas-driver.patch @@ -25,7 +25,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -5898,6 +5898,14 @@ S: Maintained +@@ -5908,6 +5908,14 @@ S: Maintained F: Documentation/usb/acm.txt F: drivers/usb/class/cdc-acm.* diff --git a/usb/usb-musb-change-to-direct-addr-in-context-save-restore.patch b/usb/usb-musb-change-to-direct-addr-in-context-save-restore.patch new file mode 100644 index 00000000000000..6e26717c59cdc9 --- /dev/null +++ b/usb/usb-musb-change-to-direct-addr-in-context-save-restore.patch @@ -0,0 +1,139 @@ +From balbi@ti.com Tue Oct 5 13:29:35 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Bob Liu <lliubbo@gmail.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: Change to direct addr in context save/restore +Date: Fri, 24 Sep 2010 13:44:07 +0300 +Message-Id: <1285325055-1247-7-git-send-email-balbi@ti.com> + +From: Bob Liu <lliubbo@gmail.com> + +Since not all platforms are using the same offset 0x10 in +musb_save/restore_context() eg Blackfin the offset is 0x40, +Change the indexed address to direct. + +Signed-off-by: Bob Liu <lliubbo@gmail.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_core.c | 46 ++++++++++++++++++++----------------------- + 1 file changed, 22 insertions(+), 24 deletions(-) + +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -2266,6 +2266,7 @@ void musb_save_context(struct musb *musb + { + int i; + void __iomem *musb_base = musb->mregs; ++ void __iomem *epio; + + if (is_host_enabled(musb)) { + musb_context.frame = musb_readw(musb_base, MUSB_FRAME); +@@ -2279,16 +2280,16 @@ void musb_save_context(struct musb *musb + musb_context.index = musb_readb(musb_base, MUSB_INDEX); + musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL); + +- for (i = 0; i < MUSB_C_NUM_EPS; ++i) { +- musb_writeb(musb_base, MUSB_INDEX, i); ++ for (i = 0; i < musb->config->num_eps; ++i) { ++ epio = musb->endpoints[i].regs; + musb_context.index_regs[i].txmaxp = +- musb_readw(musb_base, 0x10 + MUSB_TXMAXP); ++ musb_readw(epio, MUSB_TXMAXP); + musb_context.index_regs[i].txcsr = +- musb_readw(musb_base, 0x10 + MUSB_TXCSR); ++ musb_readw(epio, MUSB_TXCSR); + musb_context.index_regs[i].rxmaxp = +- musb_readw(musb_base, 0x10 + MUSB_RXMAXP); ++ musb_readw(epio, MUSB_RXMAXP); + musb_context.index_regs[i].rxcsr = +- musb_readw(musb_base, 0x10 + MUSB_RXCSR); ++ musb_readw(epio, MUSB_RXCSR); + + if (musb->dyn_fifo) { + musb_context.index_regs[i].txfifoadd = +@@ -2302,13 +2303,13 @@ void musb_save_context(struct musb *musb + } + if (is_host_enabled(musb)) { + musb_context.index_regs[i].txtype = +- musb_readb(musb_base, 0x10 + MUSB_TXTYPE); ++ musb_readb(epio, MUSB_TXTYPE); + musb_context.index_regs[i].txinterval = +- musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL); ++ musb_readb(epio, MUSB_TXINTERVAL); + musb_context.index_regs[i].rxtype = +- musb_readb(musb_base, 0x10 + MUSB_RXTYPE); ++ musb_readb(epio, MUSB_RXTYPE); + musb_context.index_regs[i].rxinterval = +- musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL); ++ musb_readb(epio, MUSB_RXINTERVAL); + + musb_context.index_regs[i].txfunaddr = + musb_read_txfunaddr(musb_base, i); +@@ -2326,8 +2327,6 @@ void musb_save_context(struct musb *musb + } + } + +- musb_writeb(musb_base, MUSB_INDEX, musb_context.index); +- + musb_platform_save_context(musb, &musb_context); + } + +@@ -2336,6 +2335,7 @@ void musb_restore_context(struct musb *m + int i; + void __iomem *musb_base = musb->mregs; + void __iomem *ep_target_regs; ++ void __iomem *epio; + + musb_platform_restore_context(musb, &musb_context); + +@@ -2350,15 +2350,15 @@ void musb_restore_context(struct musb *m + musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe); + musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl); + +- for (i = 0; i < MUSB_C_NUM_EPS; ++i) { +- musb_writeb(musb_base, MUSB_INDEX, i); +- musb_writew(musb_base, 0x10 + MUSB_TXMAXP, ++ for (i = 0; i < musb->config->num_eps; ++i) { ++ epio = musb->endpoints[i].regs; ++ musb_writew(epio, MUSB_TXMAXP, + musb_context.index_regs[i].txmaxp); +- musb_writew(musb_base, 0x10 + MUSB_TXCSR, ++ musb_writew(epio, MUSB_TXCSR, + musb_context.index_regs[i].txcsr); +- musb_writew(musb_base, 0x10 + MUSB_RXMAXP, ++ musb_writew(epio, MUSB_RXMAXP, + musb_context.index_regs[i].rxmaxp); +- musb_writew(musb_base, 0x10 + MUSB_RXCSR, ++ musb_writew(epio, MUSB_RXCSR, + musb_context.index_regs[i].rxcsr); + + if (musb->dyn_fifo) { +@@ -2373,13 +2373,13 @@ void musb_restore_context(struct musb *m + } + + if (is_host_enabled(musb)) { +- musb_writeb(musb_base, 0x10 + MUSB_TXTYPE, ++ musb_writeb(epio, MUSB_TXTYPE, + musb_context.index_regs[i].txtype); +- musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL, ++ musb_writeb(epio, MUSB_TXINTERVAL, + musb_context.index_regs[i].txinterval); +- musb_writeb(musb_base, 0x10 + MUSB_RXTYPE, ++ musb_writeb(epio, MUSB_RXTYPE, + musb_context.index_regs[i].rxtype); +- musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL, ++ musb_writeb(epio, MUSB_RXINTERVAL, + + musb_context.index_regs[i].rxinterval); + musb_write_txfunaddr(musb_base, i, +@@ -2400,8 +2400,6 @@ void musb_restore_context(struct musb *m + musb_context.index_regs[i].rxhubport); + } + } +- +- musb_writeb(musb_base, MUSB_INDEX, musb_context.index); + } + + static int musb_suspend(struct device *dev) diff --git a/usb/usb-musb-gadget-fix-zlp-sending-in-musb_g_tx-v1.patch b/usb/usb-musb-gadget-fix-zlp-sending-in-musb_g_tx-v1.patch new file mode 100644 index 00000000000000..712e90c8a2c824 --- /dev/null +++ b/usb/usb-musb-gadget-fix-zlp-sending-in-musb_g_tx-v1.patch @@ -0,0 +1,109 @@ +From balbi@ti.com Tue Oct 5 13:30:59 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: fix ZLP sending in musb_g_tx(v1) +Date: Fri, 24 Sep 2010 13:44:14 +0300 +Message-Id: <1285325055-1247-14-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +This patch fixes the problem reported by Sergei: + +>how come? we need to send ZLP before giving back the request. +>Well, look at the code ionce again. We need to send ZLP *after* +>request->actual == request->length, but as the check is inserted +>after the ZLP send, ZLP *may* be sent once the first DMA completes, +>not the last. + +The patch also has been discussed on the link below: + + http://marc.info/?t=128454814900001&r=1&w=2 + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Reported-by: Sergei Shtylyov <sshtylyov@mvista.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_gadget.c | 59 ++++++++++++++++++++--------------------- + 1 file changed, 29 insertions(+), 30 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -522,40 +522,39 @@ void musb_g_tx(struct musb *musb, u8 epn + epnum, csr, musb_ep->dma->actual_len, request); + } + +- if (is_dma || request->actual == request->length) { +- /* +- * First, maybe a terminating short packet. Some DMA +- * engines might handle this by themselves. +- */ +- if ((request->zero && request->length +- && request->length % musb_ep->packet_sz == 0) ++ /* ++ * First, maybe a terminating short packet. Some DMA ++ * engines might handle this by themselves. ++ */ ++ if ((request->zero && request->length ++ && (request->length % musb_ep->packet_sz == 0) ++ && (request->actual == request->length)) + #ifdef CONFIG_USB_INVENTRA_DMA +- || (is_dma && (!dma->desired_mode || +- (request->actual & +- (musb_ep->packet_sz - 1)))) ++ || (is_dma && (!dma->desired_mode || ++ (request->actual & ++ (musb_ep->packet_sz - 1)))) + #endif +- ) { +- /* +- * On DMA completion, FIFO may not be +- * available yet... +- */ +- if (csr & MUSB_TXCSR_TXPKTRDY) +- return; ++ ) { ++ /* ++ * On DMA completion, FIFO may not be ++ * available yet... ++ */ ++ if (csr & MUSB_TXCSR_TXPKTRDY) ++ return; + +- DBG(4, "sending zero pkt\n"); +- musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE +- | MUSB_TXCSR_TXPKTRDY); +- request->zero = 0; +- } ++ DBG(4, "sending zero pkt\n"); ++ musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE ++ | MUSB_TXCSR_TXPKTRDY); ++ request->zero = 0; ++ } + +- if (request->actual == request->length) { +- musb_g_giveback(musb_ep, request, 0); +- request = musb_ep->desc ? next_request(musb_ep) : NULL; +- if (!request) { +- DBG(4, "%s idle now\n", +- musb_ep->end_point.name); +- return; +- } ++ if (request->actual == request->length) { ++ musb_g_giveback(musb_ep, request, 0); ++ request = musb_ep->desc ? next_request(musb_ep) : NULL; ++ if (!request) { ++ DBG(4, "%s idle now\n", ++ musb_ep->end_point.name); ++ return; + } + } + diff --git a/usb/usb-musb-gadget-kill-duplicate-code-in-musb_gadget_queue.patch b/usb/usb-musb-gadget-kill-duplicate-code-in-musb_gadget_queue.patch new file mode 100644 index 00000000000000..58719014989f62 --- /dev/null +++ b/usb/usb-musb-gadget-kill-duplicate-code-in-musb_gadget_queue.patch @@ -0,0 +1,34 @@ +From linux-usb-owner@vger.kernel.org Tue Oct 5 13:30:26 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, + Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: kill duplicate code in musb_gadget_queue() +Date: Fri, 24 Sep 2010 13:44:11 +0300 +Message-Id: <1285325055-1247-11-git-send-email-balbi@ti.com> + +From: Sergei Shtylyov <sshtylyov@ru.mvista.com> + +I've noticed that musb_gadget_queue() checks for '!req->buf' condition twice: +in the second case the code is both duplicate and unreachable as the first +check returns early. + +Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_gadget.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1214,8 +1214,6 @@ static int musb_gadget_queue(struct usb_ + + if (is_dma_capable() && musb_ep->dma) + map_dma_buffer(request, musb); +- else if (!req->buf) +- return -ENODATA; + else + request->mapped = 0; + diff --git a/usb/usb-musb-gadget-kill-unreachable-code-in-musb_g_rx.patch b/usb/usb-musb-gadget-kill-unreachable-code-in-musb_g_rx.patch new file mode 100644 index 00000000000000..685cd9b5d7ca55 --- /dev/null +++ b/usb/usb-musb-gadget-kill-unreachable-code-in-musb_g_rx.patch @@ -0,0 +1,52 @@ +From linux-usb-owner@vger.kernel.org Tue Oct 5 13:30:37 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, + Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: kill unreachable code in musb_g_rx() +Date: Fri, 24 Sep 2010 13:44:12 +0300 +Message-Id: <1285325055-1247-12-git-send-email-balbi@ti.com> + +From: Sergei Shtylyov <sshtylyov@ru.mvista.com> + +musb_g_rx() always returns if next_request() call yields NULL, so the DBG() +near the function's end can never be invoked. Remove it along with unneeded +'return'; also remove the duplicate 'request' check... + +Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_gadget.c | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -834,7 +834,7 @@ void musb_g_rx(struct musb *musb, u8 epn + musb_writew(epio, MUSB_RXCSR, csr); + + DBG(3, "%s iso overrun on %p\n", musb_ep->name, request); +- if (request && request->status == -EINPROGRESS) ++ if (request->status == -EINPROGRESS) + request->status = -EOVERFLOW; + } + if (csr & MUSB_RXCSR_INCOMPRX) { +@@ -887,14 +887,8 @@ void musb_g_rx(struct musb *musb, u8 epn + return; + } + +- /* analyze request if the ep is hot */ +- if (request) +- rxstate(musb, to_musb_request(request)); +- else +- DBG(3, "packet waiting for %s%s request\n", +- musb_ep->desc ? "" : "inactive ", +- musb_ep->end_point.name); +- return; ++ /* Analyze request */ ++ rxstate(musb, to_musb_request(request)); + } + + /* ------------------------------------------------------------ */ diff --git a/usb/usb-musb-gadget-only-enable-autoclear-in-double-buffered-case.patch b/usb/usb-musb-gadget-only-enable-autoclear-in-double-buffered-case.patch new file mode 100644 index 00000000000000..4376a184cdc118 --- /dev/null +++ b/usb/usb-musb-gadget-only-enable-autoclear-in-double-buffered-case.patch @@ -0,0 +1,40 @@ +From balbi@ti.com Tue Oct 5 13:31:10 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: only enable AUTOCLEAR in double buffered case +Date: Fri, 24 Sep 2010 13:44:15 +0300 +Message-Id: <1285325055-1247-15-git-send-email-balbi@ti.com> + +commit 633ba7876b96ec339ef685357e2f7c60b5a8ce85 broke +g_file_storage functionality by enabling AUTOCLEAR on +all cases without caring for all gadget drivers. + +This patch will only enable AUTOCLEAR if our endpoint's +FIFO was configured with double buffering support. Note +this is not a complete fix, double buffered case still +doesn't work always, but that hasn't been working for +quite some time. Other than reverting the entire commit +and breaking testusb with double buffered case again, +I decided it was better to fix the single buffered case +and spend more time fixing double buffered case properly. + +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_gadget.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -689,7 +689,8 @@ static void rxstate(struct musb *musb, s + */ + + csr |= MUSB_RXCSR_DMAENAB; +- if (!musb_ep->hb_mult) ++ if (!musb_ep->hb_mult && ++ musb_ep->hw_ep->rx_double_buffered) + csr |= MUSB_RXCSR_AUTOCLEAR; + #ifdef USE_MODE1 + /* csr |= MUSB_RXCSR_DMAMODE; */ diff --git a/usb/usb-musb-gadget-unmapping-the-dma-buffer-when-switching-to-pio-mode.patch b/usb/usb-musb-gadget-unmapping-the-dma-buffer-when-switching-to-pio-mode.patch new file mode 100644 index 00000000000000..2b44fc1afdcb62 --- /dev/null +++ b/usb/usb-musb-gadget-unmapping-the-dma-buffer-when-switching-to-pio-mode.patch @@ -0,0 +1,190 @@ +From balbi@ti.com Tue Oct 5 13:29:53 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Hema HK <hemahk@ti.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: gadget: Unmapping the dma buffer when switching to PIO mode +Date: Fri, 24 Sep 2010 13:44:08 +0300 +Message-Id: <1285325055-1247-8-git-send-email-balbi@ti.com> + +From: Hema HK <hemahk@ti.com> + +Buffer is mapped to dma when dma channel is allocated. buffer needs +to be unmapped when fallback to PIO mode if dma channel_program +fails. + +Signed-off-by: Hema HK <hemahk@ti.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Reviewed-by: Ming Lei <tom.leiming@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_gadget.c | 122 +++++++++++++++++++++++++++-------------- + 1 file changed, 82 insertions(+), 40 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -92,6 +92,60 @@ + + /* ----------------------------------------------------------------------- */ + ++/* Maps the buffer to dma */ ++ ++static inline void map_dma_buffer(struct musb_request *request, ++ struct musb *musb) ++{ ++ if (request->request.dma == DMA_ADDR_INVALID) { ++ request->request.dma = dma_map_single( ++ musb->controller, ++ request->request.buf, ++ request->request.length, ++ request->tx ++ ? DMA_TO_DEVICE ++ : DMA_FROM_DEVICE); ++ request->mapped = 1; ++ } else { ++ dma_sync_single_for_device(musb->controller, ++ request->request.dma, ++ request->request.length, ++ request->tx ++ ? DMA_TO_DEVICE ++ : DMA_FROM_DEVICE); ++ request->mapped = 0; ++ } ++} ++ ++/* Unmap the buffer from dma and maps it back to cpu */ ++static inline void unmap_dma_buffer(struct musb_request *request, ++ struct musb *musb) ++{ ++ if (request->request.dma == DMA_ADDR_INVALID) { ++ DBG(20, "not unmapping a never mapped buffer\n"); ++ return; ++ } ++ ++ if (request->mapped) { ++ dma_unmap_single(musb->controller, ++ request->request.dma, ++ request->request.length, ++ request->tx ++ ? DMA_TO_DEVICE ++ : DMA_FROM_DEVICE); ++ request->request.dma = DMA_ADDR_INVALID; ++ request->mapped = 0; ++ } else { ++ dma_sync_single_for_cpu(musb->controller, ++ request->request.dma, ++ request->request.length, ++ request->tx ++ ? DMA_TO_DEVICE ++ : DMA_FROM_DEVICE); ++ ++ } ++} ++ + /* + * Immediately complete a request. + * +@@ -119,24 +173,8 @@ __acquires(ep->musb->lock) + + ep->busy = 1; + spin_unlock(&musb->lock); +- if (is_dma_capable()) { +- if (req->mapped) { +- dma_unmap_single(musb->controller, +- req->request.dma, +- req->request.length, +- req->tx +- ? DMA_TO_DEVICE +- : DMA_FROM_DEVICE); +- req->request.dma = DMA_ADDR_INVALID; +- req->mapped = 0; +- } else if (req->request.dma != DMA_ADDR_INVALID) +- dma_sync_single_for_cpu(musb->controller, +- req->request.dma, +- req->request.length, +- req->tx +- ? DMA_TO_DEVICE +- : DMA_FROM_DEVICE); +- } ++ if (is_dma_capable() && ep->dma) ++ unmap_dma_buffer(req, musb); + if (request->status == 0) + DBG(5, "%s done request %p, %d/%d\n", + ep->end_point.name, request, +@@ -298,7 +336,7 @@ static void txstate(struct musb *musb, s + csr); + + #ifndef CONFIG_MUSB_PIO_ONLY +- if (is_dma_capable() && musb_ep->dma) { ++ if (is_dma_capable() && !musb_ep->dma && musb->dma_controller) { + struct dma_controller *c = musb->dma_controller; + size_t request_size; + +@@ -395,6 +433,13 @@ static void txstate(struct musb *musb, s + #endif + + if (!use_dma) { ++ /* ++ * Unmap the dma buffer back to cpu if dma channel ++ * programming fails ++ */ ++ if (is_dma_capable() && musb_ep->dma) ++ unmap_dma_buffer(req, musb); ++ + musb_write_fifo(musb_ep->hw_ep, fifo_count, + (u8 *) (request->buf + request->actual)); + request->actual += fifo_count; +@@ -711,6 +756,20 @@ static void rxstate(struct musb *musb, s + return; + } + #endif ++ /* ++ * Unmap the dma buffer back to cpu if dma channel ++ * programming fails. This buffer is mapped if the ++ * channel allocation is successful ++ */ ++ if (is_dma_capable() && musb_ep->dma) { ++ unmap_dma_buffer(req, musb); ++ ++ /* Clear DMAENAB for the ++ * PIO mode transfer ++ */ ++ csr &= ~MUSB_RXCSR_DMAENAB; ++ musb_writew(epio, MUSB_RXCSR, csr); ++ } + + musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *) + (request->buf + request->actual)); +@@ -1153,28 +1212,11 @@ static int musb_gadget_queue(struct usb_ + request->epnum = musb_ep->current_epnum; + request->tx = musb_ep->is_in; + +- if (is_dma_capable() && musb_ep->dma) { +- if (request->request.dma == DMA_ADDR_INVALID) { +- request->request.dma = dma_map_single( +- musb->controller, +- request->request.buf, +- request->request.length, +- request->tx +- ? DMA_TO_DEVICE +- : DMA_FROM_DEVICE); +- request->mapped = 1; +- } else { +- dma_sync_single_for_device(musb->controller, +- request->request.dma, +- request->request.length, +- request->tx +- ? DMA_TO_DEVICE +- : DMA_FROM_DEVICE); +- request->mapped = 0; +- } +- } else if (!req->buf) { ++ if (is_dma_capable() && musb_ep->dma) ++ map_dma_buffer(request, musb); ++ else if (!req->buf) + return -ENODATA; +- } else ++ else + request->mapped = 0; + + spin_lock_irqsave(&musb->lock, lockflags); diff --git a/usb/usb-musb-host-support-dma-transfers-greater-than-max-channel-length.patch b/usb/usb-musb-host-support-dma-transfers-greater-than-max-channel-length.patch new file mode 100644 index 00000000000000..edfd0d195ddd66 --- /dev/null +++ b/usb/usb-musb-host-support-dma-transfers-greater-than-max-channel-length.patch @@ -0,0 +1,57 @@ +From linux-usb-owner@vger.kernel.org Tue Oct 5 13:30:06 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + "T. S., Anil Kumar" <anil@ti.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: host: support DMA transfers greater than max channel length +Date: Fri, 24 Sep 2010 13:44:09 +0300 +Message-Id: <1285325055-1247-9-git-send-email-balbi@ti.com> + +From: T. S., Anil Kumar <anil@ti.com> + +Add support for MUSB Host DMA transfers greater than max +channel length, so that such transfers won't be truncated. + +Signed-off-by: Anil Shetty <anil@ti.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_host.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -1120,6 +1120,7 @@ void musb_host_tx(struct musb *musb, u8 + u32 status = 0; + void __iomem *mbase = musb->mregs; + struct dma_channel *dma; ++ bool transfer_pending = false; + + musb_ep_select(mbase, epnum); + tx_csr = musb_readw(epio, MUSB_TXCSR); +@@ -1280,7 +1281,7 @@ void musb_host_tx(struct musb *musb, u8 + offset = d->offset; + length = d->length; + } +- } else if (dma) { ++ } else if (dma && urb->transfer_buffer_length == qh->offset) { + done = true; + } else { + /* see if we need to send more data, or ZLP */ +@@ -1293,6 +1294,7 @@ void musb_host_tx(struct musb *musb, u8 + if (!done) { + offset = qh->offset; + length = urb->transfer_buffer_length - offset; ++ transfer_pending = true; + } + } + } +@@ -1312,7 +1314,7 @@ void musb_host_tx(struct musb *musb, u8 + urb->actual_length = qh->offset; + musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); + return; +- } else if (usb_pipeisoc(pipe) && dma) { ++ } else if ((usb_pipeisoc(pipe) || transfer_pending) && dma) { + if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb, + offset, length)) { + if (is_cppi_enabled() || tusb_dma_omap()) diff --git a/usb/usb-musb-host-unmap-the-buffer-for-pio-data-transfers.patch b/usb/usb-musb-host-unmap-the-buffer-for-pio-data-transfers.patch new file mode 100644 index 00000000000000..63b0315a556298 --- /dev/null +++ b/usb/usb-musb-host-unmap-the-buffer-for-pio-data-transfers.patch @@ -0,0 +1,86 @@ +From linux-usb-owner@vger.kernel.org Tue Oct 5 13:29:25 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Maulik Mankad <x0082077@ti.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: host: unmap the buffer for PIO data transfers +Date: Fri, 24 Sep 2010 13:44:06 +0300 +Message-Id: <1285325055-1247-6-git-send-email-balbi@ti.com> + +From: Maulik Mankad <x0082077@ti.com> + +The USB stack maps the buffer for DMA if the controller supports DMA. +MUSB controller can perform DMA as well as PIO transfers. +The buffer needs to be unmapped before CPU can perform +PIO data transfers. + +Export unmap_urb_for_dma() so that drivers can perform +the DMA unmapping in a sane way. + +Signed-off-by: Maulik Mankad <x0082077@ti.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/core/hcd.c | 3 ++- + drivers/usb/musb/musb_host.c | 5 +++++ + include/linux/usb/hcd.h | 1 + + 3 files changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -1263,7 +1263,7 @@ static void hcd_free_coherent(struct usb + *dma_handle = 0; + } + +-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) ++void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) + { + enum dma_data_direction dir; + +@@ -1307,6 +1307,7 @@ static void unmap_urb_for_dma(struct usb + URB_DMA_MAP_SG | URB_DMA_MAP_PAGE | + URB_DMA_MAP_SINGLE | URB_MAP_LOCAL); + } ++EXPORT_SYMBOL_GPL(unmap_urb_for_dma); + + static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, + gfp_t mem_flags) +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -41,6 +41,7 @@ + #include <linux/errno.h> + #include <linux/init.h> + #include <linux/list.h> ++#include <linux/dma-mapping.h> + + #include "musb_core.h" + #include "musb_host.h" +@@ -1332,6 +1333,8 @@ void musb_host_tx(struct musb *musb, u8 + */ + if (length > qh->maxpacket) + length = qh->maxpacket; ++ /* Unmap the buffer so that CPU can use it */ ++ unmap_urb_for_dma(musb_to_hcd(musb), urb); + musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); + qh->segsize = length; + +@@ -1752,6 +1755,8 @@ void musb_host_rx(struct musb *musb, u8 + #endif /* Mentor DMA */ + + if (!dma) { ++ /* Unmap the buffer so that CPU can use it */ ++ unmap_urb_for_dma(musb_to_hcd(musb), urb); + done = musb_host_packet_rx(musb, urb, + epnum, iso_err); + DBG(6, "read %spacket\n", done ? "last " : ""); +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -329,6 +329,7 @@ extern int usb_hcd_submit_urb(struct urb + extern int usb_hcd_unlink_urb(struct urb *urb, int status); + extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, + int status); ++extern void unmap_urb_for_dma(struct usb_hcd *, struct urb *); + extern void usb_hcd_flush_endpoint(struct usb_device *udev, + struct usb_host_endpoint *ep); + extern void usb_hcd_disable_endpoint(struct usb_device *udev, diff --git a/usb/usb-musb-ignore-spurious-sessreq-interrupts.patch b/usb/usb-musb-ignore-spurious-sessreq-interrupts.patch new file mode 100644 index 00000000000000..d2e5ef52bdf7d3 --- /dev/null +++ b/usb/usb-musb-ignore-spurious-sessreq-interrupts.patch @@ -0,0 +1,34 @@ +From balbi@ti.com Tue Oct 5 13:30:50 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Heikki Krogerus <ext-heikki.krogerus@nokia.com> +Subject: usb: musb: ignore spurious SESSREQ interrupts +Date: Fri, 24 Sep 2010 13:44:13 +0300 +Message-Id: <1285325055-1247-13-git-send-email-balbi@ti.com> + +From: Heikki Krogerus <ext-heikki.krogerus@nokia.com> + +This will ignore any SESSREQ interrupt if musb is B state. +Charger detection may cause spurious SESSREQ interrupts. + +Signed-off-by: Heikki Krogerus <ext-heikki.krogerus@nokia.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -550,6 +550,11 @@ static irqreturn_t musb_stage0_irq(struc + if (int_usb & MUSB_INTR_SESSREQ) { + void __iomem *mbase = musb->mregs; + ++ if (devctl & MUSB_DEVCTL_BDEVICE) { ++ DBG(3, "SessReq while on B state\n"); ++ return IRQ_HANDLED; ++ } ++ + DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb)); + + /* IRQ arrives from ID pin sense or (later, if VBUS power diff --git a/usb/usb-musb-introduce-da8xx-omap-l1x-glue-layer.patch b/usb/usb-musb-introduce-da8xx-omap-l1x-glue-layer.patch new file mode 100644 index 00000000000000..2d331bb0723f70 --- /dev/null +++ b/usb/usb-musb-introduce-da8xx-omap-l1x-glue-layer.patch @@ -0,0 +1,544 @@ +From linux-usb-owner@vger.kernel.org Tue Oct 5 13:28:43 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, + Yadviga Grigorieva <yadviga@ru.mvista.com>, + Felipe Balbi <balbi@ti.com> +Subject: usb: musb: introduce DA8xx/OMAP-L1x glue layer +Date: Fri, 24 Sep 2010 13:44:03 +0300 +Message-Id: <1285325055-1247-3-git-send-email-balbi@ti.com> + +From: Sergei Shtylyov <sshtylyov@ru.mvista.com> + +Texas Instruments DA8xx/OMAP-L1x glue layer for the +MUSBMHRDC driver. + +Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Yadviga Grigorieva <yadviga@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/Kconfig | 5 + drivers/usb/musb/Makefile | 4 + drivers/usb/musb/da8xx.c | 469 +++++++++++++++++++++++++++++++++++++++++++ + drivers/usb/musb/musb_core.h | 1 + 4 files changed, 478 insertions(+), 1 deletion(-) + +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -45,6 +45,9 @@ config USB_MUSB_SOC + comment "DaVinci 35x and 644x USB support" + depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx + ++comment "DA8xx/OMAP-L1x USB support" ++ depends on USB_MUSB_HDRC && ARCH_DAVINCI_DA8XX ++ + comment "OMAP 243x high speed USB support" + depends on USB_MUSB_HDRC && ARCH_OMAP2430 + +@@ -144,7 +147,7 @@ config USB_MUSB_HDRC_HCD + config MUSB_PIO_ONLY + bool 'Disable DMA (always use PIO)' + depends on USB_MUSB_HDRC +- default y if USB_TUSB6010 ++ default USB_TUSB6010 || ARCH_DAVINCI_DA8XX + help + All data is copied between memory and FIFO by the CPU. + DMA controllers are ignored. +--- a/drivers/usb/musb/Makefile ++++ b/drivers/usb/musb/Makefile +@@ -10,6 +10,10 @@ ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y) + musb_hdrc-objs += davinci.o + endif + ++ifeq ($(CONFIG_ARCH_DAVINCI_DA8XX),y) ++ musb_hdrc-objs += da8xx.o ++endif ++ + ifeq ($(CONFIG_USB_TUSB6010),y) + musb_hdrc-objs += tusb6010.o + endif +--- /dev/null ++++ b/drivers/usb/musb/da8xx.c +@@ -0,0 +1,469 @@ ++/* ++ * Texas Instruments DA8xx/OMAP-L1x "glue layer" ++ * ++ * Copyright (c) 2008-2009 MontaVista Software, Inc. <source@mvista.com> ++ * ++ * Based on the DaVinci "glue layer" code. ++ * Copyright (C) 2005-2006 by Texas Instruments ++ * ++ * This file is part of the Inventra Controller Driver for Linux. ++ * ++ * The Inventra Controller Driver for Linux is free software; you ++ * can redistribute it and/or modify it under the terms of the GNU ++ * General Public License version 2 as published by the Free Software ++ * Foundation. ++ * ++ * The Inventra Controller Driver for Linux is distributed in ++ * the hope that it will be useful, but WITHOUT ANY WARRANTY; ++ * without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public ++ * License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with The Inventra Controller Driver for Linux ; if not, ++ * write to the Free Software Foundation, Inc., 59 Temple Place, ++ * Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/clk.h> ++#include <linux/io.h> ++ ++#include <mach/da8xx.h> ++#include <mach/usb.h> ++ ++#include "musb_core.h" ++ ++/* ++ * DA8XX specific definitions ++ */ ++ ++/* USB 2.0 OTG module registers */ ++#define DA8XX_USB_REVISION_REG 0x00 ++#define DA8XX_USB_CTRL_REG 0x04 ++#define DA8XX_USB_STAT_REG 0x08 ++#define DA8XX_USB_EMULATION_REG 0x0c ++#define DA8XX_USB_MODE_REG 0x10 /* Transparent, CDC, [Generic] RNDIS */ ++#define DA8XX_USB_AUTOREQ_REG 0x14 ++#define DA8XX_USB_SRP_FIX_TIME_REG 0x18 ++#define DA8XX_USB_TEARDOWN_REG 0x1c ++#define DA8XX_USB_INTR_SRC_REG 0x20 ++#define DA8XX_USB_INTR_SRC_SET_REG 0x24 ++#define DA8XX_USB_INTR_SRC_CLEAR_REG 0x28 ++#define DA8XX_USB_INTR_MASK_REG 0x2c ++#define DA8XX_USB_INTR_MASK_SET_REG 0x30 ++#define DA8XX_USB_INTR_MASK_CLEAR_REG 0x34 ++#define DA8XX_USB_INTR_SRC_MASKED_REG 0x38 ++#define DA8XX_USB_END_OF_INTR_REG 0x3c ++#define DA8XX_USB_GENERIC_RNDIS_EP_SIZE_REG(n) (0x50 + (((n) - 1) << 2)) ++ ++/* Control register bits */ ++#define DA8XX_SOFT_RESET_MASK 1 ++ ++#define DA8XX_USB_TX_EP_MASK 0x1f /* EP0 + 4 Tx EPs */ ++#define DA8XX_USB_RX_EP_MASK 0x1e /* 4 Rx EPs */ ++ ++/* USB interrupt register bits */ ++#define DA8XX_INTR_USB_SHIFT 16 ++#define DA8XX_INTR_USB_MASK (0x1ff << DA8XX_INTR_USB_SHIFT) /* 8 Mentor */ ++ /* interrupts and DRVVBUS interrupt */ ++#define DA8XX_INTR_DRVVBUS 0x100 ++#define DA8XX_INTR_RX_SHIFT 8 ++#define DA8XX_INTR_RX_MASK (DA8XX_USB_RX_EP_MASK << DA8XX_INTR_RX_SHIFT) ++#define DA8XX_INTR_TX_SHIFT 0 ++#define DA8XX_INTR_TX_MASK (DA8XX_USB_TX_EP_MASK << DA8XX_INTR_TX_SHIFT) ++ ++#define DA8XX_MENTOR_CORE_OFFSET 0x400 ++ ++#define CFGCHIP2 IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG) ++ ++/* ++ * REVISIT (PM): we should be able to keep the PHY in low power mode most ++ * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0 ++ * and, when in host mode, autosuspending idle root ports... PHY_PLLON ++ * (overriding SUSPENDM?) then likely needs to stay off. ++ */ ++ ++static inline void phy_on(void) ++{ ++ u32 cfgchip2 = __raw_readl(CFGCHIP2); ++ ++ /* ++ * Start the on-chip PHY and its PLL. ++ */ ++ cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN); ++ cfgchip2 |= CFGCHIP2_PHY_PLLON; ++ __raw_writel(cfgchip2, CFGCHIP2); ++ ++ pr_info("Waiting for USB PHY clock good...\n"); ++ while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD)) ++ cpu_relax(); ++} ++ ++static inline void phy_off(void) ++{ ++ u32 cfgchip2 = __raw_readl(CFGCHIP2); ++ ++ /* ++ * Ensure that USB 1.1 reference clock is not being sourced from ++ * USB 2.0 PHY. Otherwise do not power down the PHY. ++ */ ++ if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX) && ++ (cfgchip2 & CFGCHIP2_USB1SUSPENDM)) { ++ pr_warning("USB 1.1 clocked from USB 2.0 PHY -- " ++ "can't power it down\n"); ++ return; ++ } ++ ++ /* ++ * Power down the on-chip PHY. ++ */ ++ cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN; ++ __raw_writel(cfgchip2, CFGCHIP2); ++} ++ ++/* ++ * Because we don't set CTRL.UINT, it's "important" to: ++ * - not read/write INTRUSB/INTRUSBE (except during ++ * initial setup, as a workaround); ++ * - use INTSET/INTCLR instead. ++ */ ++ ++/** ++ * musb_platform_enable - enable interrupts ++ */ ++void musb_platform_enable(struct musb *musb) ++{ ++ void __iomem *reg_base = musb->ctrl_base; ++ u32 mask; ++ ++ /* Workaround: setup IRQs through both register sets. */ ++ mask = ((musb->epmask & DA8XX_USB_TX_EP_MASK) << DA8XX_INTR_TX_SHIFT) | ++ ((musb->epmask & DA8XX_USB_RX_EP_MASK) << DA8XX_INTR_RX_SHIFT) | ++ DA8XX_INTR_USB_MASK; ++ musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask); ++ ++ /* Force the DRVVBUS IRQ so we can start polling for ID change. */ ++ if (is_otg_enabled(musb)) ++ musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG, ++ DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT); ++} ++ ++/** ++ * musb_platform_disable - disable HDRC and flush interrupts ++ */ ++void musb_platform_disable(struct musb *musb) ++{ ++ void __iomem *reg_base = musb->ctrl_base; ++ ++ musb_writel(reg_base, DA8XX_USB_INTR_MASK_CLEAR_REG, ++ DA8XX_INTR_USB_MASK | ++ DA8XX_INTR_TX_MASK | DA8XX_INTR_RX_MASK); ++ musb_writeb(musb->mregs, MUSB_DEVCTL, 0); ++ musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); ++} ++ ++#ifdef CONFIG_USB_MUSB_HDRC_HCD ++#define portstate(stmt) stmt ++#else ++#define portstate(stmt) ++#endif ++ ++static void da8xx_set_vbus(struct musb *musb, int is_on) ++{ ++ WARN_ON(is_on && is_peripheral_active(musb)); ++} ++ ++#define POLL_SECONDS 2 ++ ++static struct timer_list otg_workaround; ++ ++static void otg_timer(unsigned long _musb) ++{ ++ struct musb *musb = (void *)_musb; ++ void __iomem *mregs = musb->mregs; ++ u8 devctl; ++ unsigned long flags; ++ ++ /* ++ * We poll because DaVinci's won't expose several OTG-critical ++ * status change events (from the transceiver) otherwise. ++ */ ++ devctl = musb_readb(mregs, MUSB_DEVCTL); ++ DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb)); ++ ++ spin_lock_irqsave(&musb->lock, flags); ++ switch (musb->xceiv->state) { ++ case OTG_STATE_A_WAIT_BCON: ++ devctl &= ~MUSB_DEVCTL_SESSION; ++ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); ++ ++ devctl = musb_readb(musb->mregs, MUSB_DEVCTL); ++ if (devctl & MUSB_DEVCTL_BDEVICE) { ++ musb->xceiv->state = OTG_STATE_B_IDLE; ++ MUSB_DEV_MODE(musb); ++ } else { ++ musb->xceiv->state = OTG_STATE_A_IDLE; ++ MUSB_HST_MODE(musb); ++ } ++ break; ++ case OTG_STATE_A_WAIT_VFALL: ++ /* ++ * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3 ++ * RTL seems to mis-handle session "start" otherwise (or in ++ * our case "recover"), in routine "VBUS was valid by the time ++ * VBUSERR got reported during enumeration" cases. ++ */ ++ if (devctl & MUSB_DEVCTL_VBUS) { ++ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); ++ break; ++ } ++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; ++ musb_writel(musb->ctrl_base, DA8XX_USB_INTR_SRC_SET_REG, ++ MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT); ++ break; ++ case OTG_STATE_B_IDLE: ++ if (!is_peripheral_enabled(musb)) ++ break; ++ ++ /* ++ * There's no ID-changed IRQ, so we have no good way to tell ++ * when to switch to the A-Default state machine (by setting ++ * the DEVCTL.Session bit). ++ * ++ * Workaround: whenever we're in B_IDLE, try setting the ++ * session flag every few seconds. If it works, ID was ++ * grounded and we're now in the A-Default state machine. ++ * ++ * NOTE: setting the session flag is _supposed_ to trigger ++ * SRP but clearly it doesn't. ++ */ ++ musb_writeb(mregs, MUSB_DEVCTL, devctl | MUSB_DEVCTL_SESSION); ++ devctl = musb_readb(mregs, MUSB_DEVCTL); ++ if (devctl & MUSB_DEVCTL_BDEVICE) ++ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); ++ else ++ musb->xceiv->state = OTG_STATE_A_IDLE; ++ break; ++ default: ++ break; ++ } ++ spin_unlock_irqrestore(&musb->lock, flags); ++} ++ ++void musb_platform_try_idle(struct musb *musb, unsigned long timeout) ++{ ++ static unsigned long last_timer; ++ ++ if (!is_otg_enabled(musb)) ++ return; ++ ++ if (timeout == 0) ++ timeout = jiffies + msecs_to_jiffies(3); ++ ++ /* Never idle if active, or when VBUS timeout is not set as host */ ++ if (musb->is_active || (musb->a_wait_bcon == 0 && ++ musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { ++ DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); ++ del_timer(&otg_workaround); ++ last_timer = jiffies; ++ return; ++ } ++ ++ if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) { ++ DBG(4, "Longer idle timer already pending, ignoring...\n"); ++ return; ++ } ++ last_timer = timeout; ++ ++ DBG(4, "%s inactive, starting idle timer for %u ms\n", ++ otg_state_string(musb), jiffies_to_msecs(timeout - jiffies)); ++ mod_timer(&otg_workaround, timeout); ++} ++ ++static irqreturn_t da8xx_interrupt(int irq, void *hci) ++{ ++ struct musb *musb = hci; ++ void __iomem *reg_base = musb->ctrl_base; ++ unsigned long flags; ++ irqreturn_t ret = IRQ_NONE; ++ u32 status; ++ ++ spin_lock_irqsave(&musb->lock, flags); ++ ++ /* ++ * NOTE: DA8XX shadows the Mentor IRQs. Don't manage them through ++ * the Mentor registers (except for setup), use the TI ones and EOI. ++ */ ++ ++ /* Acknowledge and handle non-CPPI interrupts */ ++ status = musb_readl(reg_base, DA8XX_USB_INTR_SRC_MASKED_REG); ++ if (!status) ++ goto eoi; ++ ++ musb_writel(reg_base, DA8XX_USB_INTR_SRC_CLEAR_REG, status); ++ DBG(4, "USB IRQ %08x\n", status); ++ ++ musb->int_rx = (status & DA8XX_INTR_RX_MASK) >> DA8XX_INTR_RX_SHIFT; ++ musb->int_tx = (status & DA8XX_INTR_TX_MASK) >> DA8XX_INTR_TX_SHIFT; ++ musb->int_usb = (status & DA8XX_INTR_USB_MASK) >> DA8XX_INTR_USB_SHIFT; ++ ++ /* ++ * DRVVBUS IRQs are the only proxy we have (a very poor one!) for ++ * DA8xx's missing ID change IRQ. We need an ID change IRQ to ++ * switch appropriately between halves of the OTG state machine. ++ * Managing DEVCTL.Session per Mentor docs requires that we know its ++ * value but DEVCTL.BDevice is invalid without DEVCTL.Session set. ++ * Also, DRVVBUS pulses for SRP (but not at 5 V)... ++ */ ++ if (status & (DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT)) { ++ int drvvbus = musb_readl(reg_base, DA8XX_USB_STAT_REG); ++ void __iomem *mregs = musb->mregs; ++ u8 devctl = musb_readb(mregs, MUSB_DEVCTL); ++ int err; ++ ++ err = is_host_enabled(musb) && (musb->int_usb & ++ MUSB_INTR_VBUSERROR); ++ if (err) { ++ /* ++ * The Mentor core doesn't debounce VBUS as needed ++ * to cope with device connect current spikes. This ++ * means it's not uncommon for bus-powered devices ++ * to get VBUS errors during enumeration. ++ * ++ * This is a workaround, but newer RTL from Mentor ++ * seems to allow a better one: "re"-starting sessions ++ * without waiting for VBUS to stop registering in ++ * devctl. ++ */ ++ musb->int_usb &= ~MUSB_INTR_VBUSERROR; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; ++ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); ++ WARNING("VBUS error workaround (delay coming)\n"); ++ } else if (is_host_enabled(musb) && drvvbus) { ++ MUSB_HST_MODE(musb); ++ musb->xceiv->default_a = 1; ++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; ++ portstate(musb->port1_status |= USB_PORT_STAT_POWER); ++ del_timer(&otg_workaround); ++ } else { ++ musb->is_active = 0; ++ MUSB_DEV_MODE(musb); ++ musb->xceiv->default_a = 0; ++ musb->xceiv->state = OTG_STATE_B_IDLE; ++ portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); ++ } ++ ++ DBG(2, "VBUS %s (%s)%s, devctl %02x\n", ++ drvvbus ? "on" : "off", ++ otg_state_string(musb), ++ err ? " ERROR" : "", ++ devctl); ++ ret = IRQ_HANDLED; ++ } ++ ++ if (musb->int_tx || musb->int_rx || musb->int_usb) ++ ret |= musb_interrupt(musb); ++ ++ eoi: ++ /* EOI needs to be written for the IRQ to be re-asserted. */ ++ if (ret == IRQ_HANDLED || status) ++ musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); ++ ++ /* Poll for ID change */ ++ if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) ++ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); ++ ++ spin_unlock_irqrestore(&musb->lock, flags); ++ ++ return ret; ++} ++ ++int musb_platform_set_mode(struct musb *musb, u8 musb_mode) ++{ ++ u32 cfgchip2 = __raw_readl(CFGCHIP2); ++ ++ cfgchip2 &= ~CFGCHIP2_OTGMODE; ++ switch (musb_mode) { ++#ifdef CONFIG_USB_MUSB_HDRC_HCD ++ case MUSB_HOST: /* Force VBUS valid, ID = 0 */ ++ cfgchip2 |= CFGCHIP2_FORCE_HOST; ++ break; ++#endif ++#ifdef CONFIG_USB_GADGET_MUSB_HDRC ++ case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ ++ cfgchip2 |= CFGCHIP2_FORCE_DEVICE; ++ break; ++#endif ++#ifdef CONFIG_USB_MUSB_OTG ++ case MUSB_OTG: /* Don't override the VBUS/ID comparators */ ++ cfgchip2 |= CFGCHIP2_NO_OVERRIDE; ++ break; ++#endif ++ default: ++ DBG(2, "Trying to set unsupported mode %u\n", musb_mode); ++ } ++ ++ __raw_writel(cfgchip2, CFGCHIP2); ++ return 0; ++} ++ ++int __init musb_platform_init(struct musb *musb, void *board_data) ++{ ++ void __iomem *reg_base = musb->ctrl_base; ++ u32 rev; ++ ++ musb->mregs += DA8XX_MENTOR_CORE_OFFSET; ++ ++ clk_enable(musb->clock); ++ ++ /* Returns zero if e.g. not clocked */ ++ rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); ++ if (!rev) ++ goto fail; ++ ++ usb_nop_xceiv_register(); ++ musb->xceiv = otg_get_transceiver(); ++ if (!musb->xceiv) ++ goto fail; ++ ++ if (is_host_enabled(musb)) ++ setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); ++ ++ musb->board_set_vbus = da8xx_set_vbus; ++ ++ /* Reset the controller */ ++ musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); ++ ++ /* Start the on-chip PHY and its PLL. */ ++ phy_on(); ++ ++ msleep(5); ++ ++ /* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */ ++ pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n", ++ rev, __raw_readl(CFGCHIP2), ++ musb_readb(reg_base, DA8XX_USB_CTRL_REG)); ++ ++ musb->isr = da8xx_interrupt; ++ return 0; ++fail: ++ clk_disable(musb->clock); ++ return -ENODEV; ++} ++ ++int musb_platform_exit(struct musb *musb) ++{ ++ if (is_host_enabled(musb)) ++ del_timer_sync(&otg_workaround); ++ ++ phy_off(); ++ ++ otg_put_transceiver(musb->xceiv); ++ usb_nop_xceiv_unregister(); ++ ++ clk_disable(musb->clock); ++ ++ return 0; ++} +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -599,6 +599,7 @@ extern void musb_hnp_stop(struct musb *m + extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode); + + #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \ ++ defined(CONFIG_ARCH_DAVINCI_DA8XX) || \ + defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) + extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout); diff --git a/usb/usb-musb-make-dbg-calls-actually-depend-on-config_usb_musb_debug.patch b/usb/usb-musb-make-dbg-calls-actually-depend-on-config_usb_musb_debug.patch new file mode 100644 index 00000000000000..e9a02f1087711e --- /dev/null +++ b/usb/usb-musb-make-dbg-calls-actually-depend-on-config_usb_musb_debug.patch @@ -0,0 +1,56 @@ +From balbi@ti.com Tue Oct 5 13:28:24 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, Felipe Balbi <balbi@ti.com> +Subject: USB: musb: make DBG() calls actually depend on CONFIG_USB_MUSB_DEBUG +Date: Fri, 24 Sep 2010 13:44:02 +0300 +Message-Id: <1285325055-1247-2-git-send-email-balbi@ti.com> + +From: Sergei Shtylyov <sshtylyov@ru.mvista.com> + +Enabling CONFIG_USB_MUSB_DEBUG option causes -DDEBUG to be added to gcc's +command line, however the DBG() macro doesn't depend on DEBUG, so that the +debugging messages get printed regardless of the option, and I don't think +that this was intended. Get rid of otherwise unused xprintk() macro and make +DBG() macro directly call pr_debug() which only results in the actual code +generated if DEBUG is defined. + +This change makes musb_hdrc.o ~30% less in size with CONFIG_USB_MUSB_DEBUG +disabled (in host mode). + +Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/musb/musb_debug.h | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/usb/musb/musb_debug.h ++++ b/drivers/usb/musb/musb_debug.h +@@ -42,11 +42,10 @@ + #define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args) + #define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args) + +-#define xprintk(level, facility, format, args...) do { \ +- if (_dbg_level(level)) { \ +- printk(facility "%s %d: " format , \ +- __func__, __LINE__ , ## args); \ +- } } while (0) ++#define DBG(level, format, args...) do { \ ++ if (_dbg_level(level)) \ ++ pr_debug("%s %d: " format, __func__, __LINE__, ## args); \ ++ } while (0) + + extern unsigned musb_debug; + +@@ -55,8 +54,6 @@ static inline int _dbg_level(unsigned l) + return musb_debug >= l; + } + +-#define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args) +- + extern const char *otg_state_string(struct musb *); + + #ifdef CONFIG_DEBUG_FS diff --git a/usb/usb-musb-musbhsdma-increase-max_len-to-1mb.patch b/usb/usb-musb-musbhsdma-increase-max_len-to-1mb.patch new file mode 100644 index 00000000000000..8f7361b9af86a8 --- /dev/null +++ b/usb/usb-musb-musbhsdma-increase-max_len-to-1mb.patch @@ -0,0 +1,32 @@ +From linux-usb-owner@vger.kernel.org Tue Oct 5 13:29:16 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Anil Shetty <anil@ti.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: musbhsdma: increase max_len to 1MB +Date: Fri, 24 Sep 2010 13:44:05 +0300 +Message-Id: <1285325055-1247-5-git-send-email-balbi@ti.com> + +From: Anil Shetty <anil@ti.com> + +MUSB's DMA controller max channel length was set to 64k. +Transfer length greater than this max value is being truncated. + +Signed-off-by: Anil Shetty <anil@ti.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musbhsdma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/musb/musbhsdma.c ++++ b/drivers/usb/musb/musbhsdma.c +@@ -91,7 +91,7 @@ static struct dma_channel *dma_channel_a + channel = &(musb_channel->channel); + channel->private_data = musb_channel; + channel->status = MUSB_DMA_STATUS_FREE; +- channel->max_len = 0x10000; ++ channel->max_len = 0x100000; + /* Tx => mode 1; Rx => mode 0 */ + channel->desired_mode = transmit; + channel->actual_len = 0; diff --git a/usb/usb-musb-support-iso-high-bandwidth-for-gadget-mode.patch b/usb/usb-musb-support-iso-high-bandwidth-for-gadget-mode.patch new file mode 100644 index 00000000000000..e615d7525a0533 --- /dev/null +++ b/usb/usb-musb-support-iso-high-bandwidth-for-gadget-mode.patch @@ -0,0 +1,146 @@ +From balbi@ti.com Tue Oct 5 13:28:57 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Ming Lei <tom.leiming@gmail.com>, + David Brownell <dbrownell@users.sourceforge.net>, + Anand Gadiyar <gadiyar@ti.com>, Mike Frysinger <vapier@gentoo.org>, + Sergei Shtylyov <sshtylyov@ru.mvista.com>, Felipe Balbi <balbi@ti.com> +Subject: usb: musb: support ISO high bandwidth for gadget mode +Date: Fri, 24 Sep 2010 13:44:04 +0300 +Message-Id: <1285325055-1247-4-git-send-email-balbi@ti.com> + +From: Ming Lei <tom.leiming@gmail.com> + +This patch has been tested OK on beagle B5 board and +use usbtest #15 and #16 as testcase. + +Signed-off-by: Ming Lei <tom.leiming@gmail.com> +Reviewed-by: Sergei Shtylyov <sshtylyov@mvista.com> +Cc: David Brownell <dbrownell@users.sourceforge.net> +Cc: Anand Gadiyar <gadiyar@ti.com> +Cc: Mike Frysinger <vapier@gentoo.org> +Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/musb_gadget.c | 49 ++++++++++++++++++++++++++++++----------- + drivers/usb/musb/musb_gadget.h | 2 + + 2 files changed, 39 insertions(+), 12 deletions(-) + +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -337,13 +337,15 @@ static void txstate(struct musb *musb, s + csr |= (MUSB_TXCSR_DMAENAB | + MUSB_TXCSR_MODE); + /* against programming guide */ +- } else +- csr |= (MUSB_TXCSR_AUTOSET +- | MUSB_TXCSR_DMAENAB ++ } else { ++ csr |= (MUSB_TXCSR_DMAENAB + | MUSB_TXCSR_DMAMODE + | MUSB_TXCSR_MODE); +- ++ if (!musb_ep->hb_mult) ++ csr |= MUSB_TXCSR_AUTOSET; ++ } + csr &= ~MUSB_TXCSR_P_UNDERRUN; ++ + musb_writew(epio, MUSB_TXCSR, csr); + } + } +@@ -643,7 +645,8 @@ static void rxstate(struct musb *musb, s + */ + + csr |= MUSB_RXCSR_DMAENAB; +- csr |= MUSB_RXCSR_AUTOCLEAR; ++ if (!musb_ep->hb_mult) ++ csr |= MUSB_RXCSR_AUTOCLEAR; + #ifdef USE_MODE1 + /* csr |= MUSB_RXCSR_DMAMODE; */ + +@@ -875,9 +878,25 @@ static int musb_gadget_enable(struct usb + + /* REVISIT this rules out high bandwidth periodic transfers */ + tmp = le16_to_cpu(desc->wMaxPacketSize); +- if (tmp & ~0x07ff) +- goto fail; +- musb_ep->packet_sz = tmp; ++ if (tmp & ~0x07ff) { ++ int ok; ++ ++ if (usb_endpoint_dir_in(desc)) ++ ok = musb->hb_iso_tx; ++ else ++ ok = musb->hb_iso_rx; ++ ++ if (!ok) { ++ DBG(4, "%s: not support ISO high bandwidth\n", __func__); ++ goto fail; ++ } ++ musb_ep->hb_mult = (tmp >> 11) & 3; ++ } else { ++ musb_ep->hb_mult = 0; ++ } ++ ++ musb_ep->packet_sz = tmp & 0x7ff; ++ tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1); + + /* enable the interrupts for the endpoint, set the endpoint + * packet size (or fail), set the mode, clear the fifo +@@ -890,8 +909,11 @@ static int musb_gadget_enable(struct usb + musb_ep->is_in = 1; + if (!musb_ep->is_in) + goto fail; +- if (tmp > hw_ep->max_packet_sz_tx) ++ ++ if (tmp > hw_ep->max_packet_sz_tx) { ++ DBG(4, "%s: packet size beyond hw fifo size\n", __func__); + goto fail; ++ } + + int_txe |= (1 << epnum); + musb_writew(mbase, MUSB_INTRTXE, int_txe); +@@ -906,7 +928,7 @@ static int musb_gadget_enable(struct usb + if (musb->hwvers < MUSB_HWVERS_2000) + musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); + else +- musb_writew(regs, MUSB_TXMAXP, tmp); ++ musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); + + csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; + if (musb_readw(regs, MUSB_TXCSR) +@@ -927,8 +949,11 @@ static int musb_gadget_enable(struct usb + musb_ep->is_in = 0; + if (musb_ep->is_in) + goto fail; +- if (tmp > hw_ep->max_packet_sz_rx) ++ ++ if (tmp > hw_ep->max_packet_sz_rx) { ++ DBG(4, "%s: packet size beyond hw fifo size\n", __func__); + goto fail; ++ } + + int_rxe |= (1 << epnum); + musb_writew(mbase, MUSB_INTRRXE, int_rxe); +@@ -942,7 +967,7 @@ static int musb_gadget_enable(struct usb + if (musb->hwvers < MUSB_HWVERS_2000) + musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx); + else +- musb_writew(regs, MUSB_RXMAXP, tmp); ++ musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); + + /* force shared fifo to OUT-only mode */ + if (hw_ep->is_shared_fifo) { +--- a/drivers/usb/musb/musb_gadget.h ++++ b/drivers/usb/musb/musb_gadget.h +@@ -79,6 +79,8 @@ struct musb_ep { + + /* true if lock must be dropped but req_list may not be advanced */ + u8 busy; ++ ++ u8 hb_mult; + }; + + static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) diff --git a/usb/usb-musb-suppress-warning-about-unused-flags.patch b/usb/usb-musb-suppress-warning-about-unused-flags.patch new file mode 100644 index 00000000000000..b2cc71efe4d3a2 --- /dev/null +++ b/usb/usb-musb-suppress-warning-about-unused-flags.patch @@ -0,0 +1,35 @@ +From linux-usb-owner@vger.kernel.org Tue Oct 5 13:30:15 2010 +From: Felipe Balbi <balbi@ti.com> +To: Greg KH <greg@kroah.com> +Cc: Linux USB Mailing List <linux-usb@vger.kernel.org>, + Jon Povey <jon.povey@racelogic.co.uk>, + Felipe Balbi <balbi@ti.com> +Subject: USB: musb: suppress warning about unused flags +Date: Fri, 24 Sep 2010 13:44:10 +0300 +Message-Id: <1285325055-1247-10-git-send-email-balbi@ti.com> + +From: Jon Povey <jon.povey@racelogic.co.uk> + +Wrap flags with uninitialized_var() to suppress this: + +drivers/usb/musb/cppi_dma.c:1158: warning: 'flags' may be used uninitialized +in this function + +Signed-off-by: Jon Povey <jon.povey@racelogic.co.uk> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/usb/musb/cppi_dma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/musb/cppi_dma.c ++++ b/drivers/usb/musb/cppi_dma.c +@@ -1156,7 +1156,7 @@ irqreturn_t cppi_interrupt(int irq, void + struct musb_hw_ep *hw_ep = NULL; + u32 rx, tx; + int i, index; +- unsigned long flags; ++ unsigned long uninitialized_var(flags); + + cppi = container_of(musb->dma_controller, struct cppi, controller); + if (cppi->irq) diff --git a/usb/usb-yurex-fix-memory-leak-and-corrupted-messages.patch b/usb/usb-yurex-fix-memory-leak-and-corrupted-messages.patch new file mode 100644 index 00000000000000..289c600642e15b --- /dev/null +++ b/usb/usb-yurex-fix-memory-leak-and-corrupted-messages.patch @@ -0,0 +1,100 @@ +From tomoki.sekiyama@gmail.com Tue Oct 5 14:18:42 2010 +From: Tomoki Sekiyama <tomoki.sekiyama@gmail.com> +To: gregkh@suse.de +Cc: linux-usb@vger.kernel.org, + Tomoki Sekiyama <tomoki.sekiyama@gmail.com> +Subject: USB: yurex: fix memory leak and corrupted messages +Date: Sun, 3 Oct 2010 06:59:06 +0900 +Message-Id: <1286056746-25648-1-git-send-email-tomoki.sekiyama@gmail.com> + +This fixes the memory leak on disconnecting the device. +In addition, it fixes some messages corrupted by incorrect encoding. + +Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/misc/yurex.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -37,7 +37,7 @@ + #define CMD_PADDING 0xff + + #define YUREX_BUF_SIZE 8 +-#define YUREX_WRITE_TIMEOUT (HZ) ++#define YUREX_WRITE_TIMEOUT (HZ*2) + + /* table of devices that work with this driver */ + static struct usb_device_id yurex_table[] = { +@@ -83,7 +83,7 @@ static void yurex_control_callback(struc + int status = urb->status; + + if (status) { +- err("%s - control failed: %d�n", __func__, status); ++ err("%s - control failed: %d\n", __func__, status); + wake_up_interruptible(&dev->waitq); + return; + } +@@ -97,6 +97,16 @@ static void yurex_delete(struct kref *kr + dbg("yurex_delete"); + + usb_put_dev(dev->udev); ++ if (dev->cntl_urb) { ++ usb_kill_urb(dev->cntl_urb); ++ if (dev->cntl_req) ++ usb_free_coherent(dev->udev, YUREX_BUF_SIZE, ++ dev->cntl_req, dev->cntl_urb->setup_dma); ++ if (dev->cntl_buffer) ++ usb_free_coherent(dev->udev, YUREX_BUF_SIZE, ++ dev->cntl_buffer, dev->cntl_urb->transfer_dma); ++ usb_free_urb(dev->cntl_urb); ++ } + if (dev->urb) { + usb_kill_urb(dev->urb); + if (dev->int_buffer) +@@ -253,7 +263,7 @@ static int yurex_probe(struct usb_interf + usb_sndctrlpipe(dev->udev, 0), + (void *)dev->cntl_req, dev->cntl_buffer, + YUREX_BUF_SIZE, yurex_control_callback, dev); +- dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + + /* allocate interrupt URB */ +@@ -276,6 +286,7 @@ static int yurex_probe(struct usb_interf + usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr), + dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, + dev, 1); ++ dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + if (usb_submit_urb(dev->urb, GFP_KERNEL)) { + retval = -EIO; + err("Could not submitting URB"); +@@ -296,7 +307,7 @@ static int yurex_probe(struct usb_interf + dev->bbu = -1; + + dev_info(&interface->dev, +- "USB Yurex device now attached to Yurex-%d�n", ++ "USB YUREX device now attached to Yurex #%d\n", + interface->minor); + + return 0; +@@ -331,7 +342,7 @@ static void yurex_disconnect(struct usb_ + /* decrement our usage count */ + kref_put(&dev->kref, yurex_delete); + +- dev_info(&interface->dev, "USB Yurex #%d now disconnected", minor); ++ dev_info(&interface->dev, "USB YUREX #%d now disconnected\n", minor); + } + + static struct usb_driver yurex_driver = { +@@ -417,7 +428,7 @@ static ssize_t yurex_read(struct file *f + } + + spin_lock_irqsave(&dev->lock, flags); +- bytes_read = snprintf(in_buffer, 20, "%lld�n", dev->bbu); ++ bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); + spin_unlock_irqrestore(&dev->lock, flags); + + if (*ppos < bytes_read) { |
