diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-21 12:04:45 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-24 20:05:19 +0100 |
commit | 82e6923e1862428b755ec306b3dbccf926849314 (patch) | |
tree | e0be095c30c7cbfeff2a2096cf53e9c2f92fed13 /drivers | |
parent | Linux 2.6.38-rc2 (diff) | |
download | linux-82e6923e1862428b755ec306b3dbccf926849314.tar.xz linux-82e6923e1862428b755ec306b3dbccf926849314.zip |
ARM: lh7a40x: remove unmaintained platform support
lh7a40x has only been receiving updates for updates to generic code.
The last involvement from the maintainer according to the git logs was
in 2006. As such, it is a maintainence burden with no benefit.
This gets rid of two defconfigs.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/smc91x.h | 62 | ||||
-rw-r--r-- | drivers/tty/serial/Kconfig | 23 | ||||
-rw-r--r-- | drivers/tty/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/tty/serial/serial_lh7a40x.c | 682 | ||||
-rw-r--r-- | drivers/usb/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/Kconfig | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/gadget_chips.h | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/lh7a40x_udc.c | 2152 | ||||
-rw-r--r-- | drivers/usb/gadget/lh7a40x_udc.h | 259 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ohci-lh7a404.c | 252 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 10 | ||||
-rw-r--r-- | drivers/video/Kconfig | 63 |
14 files changed, 0 insertions, 3531 deletions
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index ee747919a766..68d48ab6eacf 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -206,68 +206,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define RPC_LSA_DEFAULT RPC_LED_TX_RX #define RPC_LSB_DEFAULT RPC_LED_100_10 -#elif defined(CONFIG_MACH_LPD79520) || \ - defined(CONFIG_MACH_LPD7A400) || \ - defined(CONFIG_MACH_LPD7A404) - -/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the - * way that the CPU handles chip selects and the way that the SMC chip - * expects the chip select to operate. Refer to - * Documentation/arm/Sharp-LH/IOBarrier for details. The read from - * IOBARRIER is a byte, in order that we read the least-common - * denominator. It would be wasteful to read 32 bits from an 8-bit - * accessible region. - * - * There is no explicit protection against interrupts intervening - * between the writew and the IOBARRIER. In SMC ISR there is a - * preamble that performs an IOBARRIER in the extremely unlikely event - * that the driver interrupts itself between a writew to the chip an - * the IOBARRIER that follows *and* the cache is large enough that the - * first off-chip access while handing the interrupt is to the SMC - * chip. Other devices in the same address space as the SMC chip must - * be aware of the potential for trouble and perform a similar - * IOBARRIER on entry to their ISR. - */ - -#include <mach/constants.h> /* IOBARRIER_VIRT */ - -#define SMC_CAN_USE_8BIT 0 -#define SMC_CAN_USE_16BIT 1 -#define SMC_CAN_USE_32BIT 0 -#define SMC_NOWAIT 0 -#define LPD7X_IOBARRIER readb (IOBARRIER_VIRT) - -#define SMC_inw(a,r)\ - ({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; }) -#define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; }) - -#define SMC_insw LPD7_SMC_insw -static inline void LPD7_SMC_insw (unsigned char* a, int r, - unsigned char* p, int l) -{ - unsigned short* ps = (unsigned short*) p; - while (l-- > 0) { - *ps++ = readw (a + r); - LPD7X_IOBARRIER; - } -} - -#define SMC_outsw LPD7_SMC_outsw -static inline void LPD7_SMC_outsw (unsigned char* a, int r, - unsigned char* p, int l) -{ - unsigned short* ps = (unsigned short*) p; - while (l-- > 0) { - writew (*ps++, a + r); - LPD7X_IOBARRIER; - } -} - -#define SMC_INTERRUPT_PREAMBLE LPD7X_IOBARRIER - -#define RPC_LSA_DEFAULT RPC_LED_TX_RX -#define RPC_LSB_DEFAULT RPC_LED_100_10 - #elif defined(CONFIG_ARCH_VERSATILE) #define SMC_CAN_USE_8BIT 1 diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index b1682d7f1d8a..1174d4d90407 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1110,29 +1110,6 @@ config SERIAL_PMACZILOG_CONSOLE on your (Power)Mac as the console, you can do so by answering Y to this option. -config SERIAL_LH7A40X - tristate "Sharp LH7A40X embedded UART support" - depends on ARM && ARCH_LH7A40X - select SERIAL_CORE - help - This enables support for the three on-board UARTs of the - Sharp LH7A40X series CPUs. Choose Y or M. - -config SERIAL_LH7A40X_CONSOLE - bool "Support for console on Sharp LH7A40X serial port" - depends on SERIAL_LH7A40X=y - select SERIAL_CORE_CONSOLE - help - Say Y here if you wish to use one of the serial ports as the - system console--the system console is the device which - receives all kernel messages and warnings and which allows - logins in single user mode. - - Even if you say Y here, the currently visible framebuffer console - (/dev/tty0) will still be used as the default system console, but - you can alter that using a kernel command line, for example - "console=ttyAM1". - config SERIAL_CPM tristate "CPM SCC/SMC serial port support" depends on CPM2 || 8xx diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 8ea92e9c73b0..8e325408b1a6 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -54,7 +54,6 @@ obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o obj-$(CONFIG_SERIAL_MCF) += mcf.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o -obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o obj-$(CONFIG_SERIAL_DZ) += dz.o obj-$(CONFIG_SERIAL_ZS) += zs.o obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o diff --git a/drivers/tty/serial/serial_lh7a40x.c b/drivers/tty/serial/serial_lh7a40x.c deleted file mode 100644 index ea744707c4d6..000000000000 --- a/drivers/tty/serial/serial_lh7a40x.c +++ /dev/null @@ -1,682 +0,0 @@ -/* drivers/serial/serial_lh7a40x.c - * - * Copyright (C) 2004 Coastal Environmental Systems - * - * This program 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. - * - */ - -/* Driver for Sharp LH7A40X embedded serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd. - * - * --- - * - * This driver supports the embedded UARTs of the Sharp LH7A40X series - * CPUs. While similar to the 16550 and other UART chips, there is - * nothing close to register compatibility. Moreover, some of the - * modem control lines are not available, either in the chip or they - * are lacking in the board-level implementation. - * - * - Use of SIRDIS - * For simplicity, we disable the IR functions of any UART whenever - * we enable it. - * - */ - - -#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial_core.h> -#include <linux/serial.h> -#include <linux/io.h> - -#include <asm/irq.h> -#include <mach/hardware.h> - -#define DEV_MAJOR 204 -#define DEV_MINOR 16 -#define DEV_NR 3 - -#define ISR_LOOP_LIMIT 256 - -#define UR(p,o) _UR ((p)->membase, o) -#define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o)))) -#define BIT_CLR(p,o,m) UR(p,o) = UR(p,o) & (~(unsigned int)m) -#define BIT_SET(p,o,m) UR(p,o) = UR(p,o) | ( (unsigned int)m) - -#define UART_REG_SIZE 32 - -#define UART_R_DATA (0x00) -#define UART_R_FCON (0x04) -#define UART_R_BRCON (0x08) -#define UART_R_CON (0x0c) -#define UART_R_STATUS (0x10) -#define UART_R_RAWISR (0x14) -#define UART_R_INTEN (0x18) -#define UART_R_ISR (0x1c) - -#define UARTEN (0x01) /* UART enable */ -#define SIRDIS (0x02) /* Serial IR disable (UART1 only) */ - -#define RxEmpty (0x10) -#define TxEmpty (0x80) -#define TxFull (0x20) -#define nRxRdy RxEmpty -#define nTxRdy TxFull -#define TxBusy (0x08) - -#define RxBreak (0x0800) -#define RxOverrunError (0x0400) -#define RxParityError (0x0200) -#define RxFramingError (0x0100) -#define RxError (RxBreak | RxOverrunError | RxParityError | RxFramingError) - -#define DCD (0x04) -#define DSR (0x02) -#define CTS (0x01) - -#define RxInt (0x01) -#define TxInt (0x02) -#define ModemInt (0x04) -#define RxTimeoutInt (0x08) - -#define MSEOI (0x10) - -#define WLEN_8 (0x60) -#define WLEN_7 (0x40) -#define WLEN_6 (0x20) -#define WLEN_5 (0x00) -#define WLEN (0x60) /* Mask for all word-length bits */ -#define STP2 (0x08) -#define PEN (0x02) /* Parity Enable */ -#define EPS (0x04) /* Even Parity Set */ -#define FEN (0x10) /* FIFO Enable */ -#define BRK (0x01) /* Send Break */ - - -struct uart_port_lh7a40x { - struct uart_port port; - unsigned int statusPrev; /* Most recently read modem status */ -}; - -static void lh7a40xuart_stop_tx (struct uart_port* port) -{ - BIT_CLR (port, UART_R_INTEN, TxInt); -} - -static void lh7a40xuart_start_tx (struct uart_port* port) -{ - BIT_SET (port, UART_R_INTEN, TxInt); - - /* *** FIXME: do I need to check for startup of the - transmitter? The old driver did, but AMBA - doesn't . */ -} - -static void lh7a40xuart_stop_rx (struct uart_port* port) -{ - BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt); -} - -static void lh7a40xuart_enable_ms (struct uart_port* port) -{ - BIT_SET (port, UART_R_INTEN, ModemInt); -} - -static void lh7a40xuart_rx_chars (struct uart_port* port) -{ - struct tty_struct* tty = port->state->port.tty; - int cbRxMax = 256; /* (Gross) limit on receive */ - unsigned int data; /* Received data and status */ - unsigned int flag; - - while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) { - data = UR (port, UART_R_DATA); - flag = TTY_NORMAL; - ++port->icount.rx; - - if (unlikely(data & RxError)) { - if (data & RxBreak) { - data &= ~(RxFramingError | RxParityError); - ++port->icount.brk; - if (uart_handle_break (port)) - continue; - } - else if (data & RxParityError) - ++port->icount.parity; - else if (data & RxFramingError) - ++port->icount.frame; - if (data & RxOverrunError) - ++port->icount.overrun; - - /* Mask by termios, leave Rx'd byte */ - data &= port->read_status_mask | 0xff; - - if (data & RxBreak) - flag = TTY_BREAK; - else if (data & RxParityError) - flag = TTY_PARITY; - else if (data & RxFramingError) - flag = TTY_FRAME; - } - - if (uart_handle_sysrq_char (port, (unsigned char) data)) - continue; - - uart_insert_char(port, data, RxOverrunError, data, flag); - } - tty_flip_buffer_push (tty); - return; -} - -static void lh7a40xuart_tx_chars (struct uart_port* port) -{ - struct circ_buf* xmit = &port->state->xmit; - int cbTxMax = port->fifosize; - - if (port->x_char) { - UR (port, UART_R_DATA) = port->x_char; - ++port->icount.tx; - port->x_char = 0; - return; - } - if (uart_circ_empty (xmit) || uart_tx_stopped (port)) { - lh7a40xuart_stop_tx (port); - return; - } - - /* Unlike the AMBA UART, the lh7a40x UART does not guarantee - that at least half of the FIFO is empty. Instead, we check - status for every character. Using the AMBA method causes - the transmitter to drop characters. */ - - do { - UR (port, UART_R_DATA) = xmit->buf[xmit->tail]; - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - ++port->icount.tx; - if (uart_circ_empty(xmit)) - break; - } while (!(UR (port, UART_R_STATUS) & nTxRdy) - && cbTxMax--); - - if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) - uart_write_wakeup (port); - - if (uart_circ_empty (xmit)) - lh7a40xuart_stop_tx (port); -} - -static void lh7a40xuart_modem_status (struct uart_port* port) -{ - unsigned int status = UR (port, UART_R_STATUS); - unsigned int delta - = status ^ ((struct uart_port_lh7a40x*) port)->statusPrev; - - BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */ - - if (!delta) /* Only happens if we missed 2 transitions */ - return; - - ((struct uart_port_lh7a40x*) port)->statusPrev = status; - - if (delta & DCD) - uart_handle_dcd_change (port, status & DCD); - - if (delta & DSR) - ++port->icount.dsr; - - if (delta & CTS) - uart_handle_cts_change (port, status & CTS); - - wake_up_interruptible (&port->state->port.delta_msr_wait); -} - -static irqreturn_t lh7a40xuart_int (int irq, void* dev_id) -{ - struct uart_port* port = dev_id; - unsigned int cLoopLimit = ISR_LOOP_LIMIT; - unsigned int isr = UR (port, UART_R_ISR); - - - do { - if (isr & (RxInt | RxTimeoutInt)) - lh7a40xuart_rx_chars(port); - if (isr & ModemInt) - lh7a40xuart_modem_status (port); - if (isr & TxInt) - lh7a40xuart_tx_chars (port); - - if (--cLoopLimit == 0) - break; - - isr = UR (port, UART_R_ISR); - } while (isr & (RxInt | TxInt | RxTimeoutInt)); - - return IRQ_HANDLED; -} - -static unsigned int lh7a40xuart_tx_empty (struct uart_port* port) -{ - return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0; -} - -static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port) -{ - unsigned int result = 0; - unsigned int status = UR (port, UART_R_STATUS); - - if (status & DCD) - result |= TIOCM_CAR; - if (status & DSR) - result |= TIOCM_DSR; - if (status & CTS) - result |= TIOCM_CTS; - - return result; -} - -static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl) -{ - /* None of the ports supports DTR. UART1 supports RTS through GPIO. */ - /* Note, kernel appears to be setting DTR and RTS on console. */ - - /* *** FIXME: this deserves more work. There's some work in - tracing all of the IO pins. */ -#if 0 - if( port->mapbase == UART1_PHYS) { - gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); - - if (mctrl & TIOCM_RTS) - gpio->pbdr &= ~GPIOB_UART1_RTS; - else - gpio->pbdr |= GPIOB_UART1_RTS; - } -#endif -} - -static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state) -{ - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - if (break_state == -1) - BIT_SET (port, UART_R_FCON, BRK); /* Assert break */ - else - BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */ - spin_unlock_irqrestore(&port->lock, flags); -} - -static int lh7a40xuart_startup (struct uart_port* port) -{ - int retval; - - retval = request_irq (port->irq, lh7a40xuart_int, 0, - "serial_lh7a40x", port); - if (retval) - return retval; - - /* Initial modem control-line settings */ - ((struct uart_port_lh7a40x*) port)->statusPrev - = UR (port, UART_R_STATUS); - - /* There is presently no configuration option to enable IR. - Thus, we always disable it. */ - - BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); - BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt); - - return 0; -} - -static void lh7a40xuart_shutdown (struct uart_port* port) -{ - free_irq (port->irq, port); - BIT_CLR (port, UART_R_FCON, BRK | FEN); - BIT_CLR (port, UART_R_CON, UARTEN); -} - -static void lh7a40xuart_set_termios (struct uart_port* port, - struct ktermios* termios, - struct ktermios* old) -{ - unsigned int con; - unsigned int inten; - unsigned int fcon; - unsigned long flags; - unsigned int baud; - unsigned int quot; - - baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16); - quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */ - - switch (termios->c_cflag & CSIZE) { - case CS5: - fcon = WLEN_5; - break; - case CS6: - fcon = WLEN_6; - break; - case CS7: - fcon = WLEN_7; - break; - case CS8: - default: - fcon = WLEN_8; - break; - } - if (termios->c_cflag & CSTOPB) - fcon |= STP2; - if (termios->c_cflag & PARENB) { - fcon |= PEN; - if (!(termios->c_cflag & PARODD)) - fcon |= EPS; - } - if (port->fifosize > 1) - fcon |= FEN; - - spin_lock_irqsave (&port->lock, flags); - - uart_update_timeout (port, termios->c_cflag, baud); - - port->read_status_mask = RxOverrunError; - if (termios->c_iflag & INPCK) - port->read_status_mask |= RxFramingError | RxParityError; - if (termios->c_iflag & (BRKINT | PARMRK)) - port->read_status_mask |= RxBreak; - - /* Figure mask for status we ignore */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= RxFramingError | RxParityError; - if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= RxBreak; - /* Ignore overrun when ignorning parity */ - /* *** FIXME: is this in the right place? */ - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= RxOverrunError; - } - - /* Ignore all receive errors when receive disabled */ - if ((termios->c_cflag & CREAD) == 0) - port->ignore_status_mask |= RxError; - - con = UR (port, UART_R_CON); - inten = (UR (port, UART_R_INTEN) & ~ModemInt); - - if (UART_ENABLE_MS (port, termios->c_cflag)) - inten |= ModemInt; - - BIT_CLR (port, UART_R_CON, UARTEN); /* Disable UART */ - UR (port, UART_R_INTEN) = 0; /* Disable interrupts */ - UR (port, UART_R_BRCON) = quot - 1; /* Set baud rate divisor */ - UR (port, UART_R_FCON) = fcon; /* Set FIFO and frame ctrl */ - UR (port, UART_R_INTEN) = inten; /* Enable interrupts */ - UR (port, UART_R_CON) = con; /* Restore UART mode */ - - spin_unlock_irqrestore(&port->lock, flags); -} - -static const char* lh7a40xuart_type (struct uart_port* port) -{ - return port->type == PORT_LH7A40X ? "LH7A40X" : NULL; -} - -static void lh7a40xuart_release_port (struct uart_port* port) -{ - release_mem_region (port->mapbase, UART_REG_SIZE); -} - -static int lh7a40xuart_request_port (struct uart_port* port) -{ - return request_mem_region (port->mapbase, UART_REG_SIZE, - "serial_lh7a40x") != NULL - ? 0 : -EBUSY; -} - -static void lh7a40xuart_config_port (struct uart_port* port, int flags) -{ - if (flags & UART_CONFIG_TYPE) { - port->type = PORT_LH7A40X; - lh7a40xuart_request_port (port); - } -} - -static int lh7a40xuart_verify_port (struct uart_port* port, - struct serial_struct* ser) -{ - int ret = 0; - - if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X) - ret = -EINVAL; - if (ser->irq < 0 || ser->irq >= nr_irqs) - ret = -EINVAL; - if (ser->baud_base < 9600) /* *** FIXME: is this true? */ - ret = -EINVAL; - return ret; -} - -static struct uart_ops lh7a40x_uart_ops = { - .tx_empty = lh7a40xuart_tx_empty, - .set_mctrl = lh7a40xuart_set_mctrl, - .get_mctrl = lh7a40xuart_get_mctrl, - .stop_tx = lh7a40xuart_stop_tx, - .start_tx = lh7a40xuart_start_tx, - .stop_rx = lh7a40xuart_stop_rx, - .enable_ms = lh7a40xuart_enable_ms, - .break_ctl = lh7a40xuart_break_ctl, - .startup = lh7a40xuart_startup, - .shutdown = lh7a40xuart_shutdown, - .set_termios = lh7a40xuart_set_termios, - .type = lh7a40xuart_type, - .release_port = lh7a40xuart_release_port, - .request_port = lh7a40xuart_request_port, - .config_port = lh7a40xuart_config_port, - .verify_port = lh7a40xuart_verify_port, -}; - -static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { - { - .port = { - .membase = (void*) io_p2v (UART1_PHYS), - .mapbase = UART1_PHYS, - .iotype = UPIO_MEM, - .irq = IRQ_UART1INTR, - .uartclk = 14745600/2, - .fifosize = 16, - .ops = &lh7a40x_uart_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - }, - }, - { - .port = { - .membase = (void*) io_p2v (UART2_PHYS), - .mapbase = UART2_PHYS, - .iotype = UPIO_MEM, - .irq = IRQ_UART2INTR, - .uartclk = 14745600/2, - .fifosize = 16, - .ops = &lh7a40x_uart_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - }, - }, - { - .port = { - .membase = (void*) io_p2v (UART3_PHYS), - .mapbase = UART3_PHYS, - .iotype = UPIO_MEM, - .irq = IRQ_UART3INTR, - .uartclk = 14745600/2, - .fifosize = 16, - .ops = &lh7a40x_uart_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 2, - }, - }, -}; - -#ifndef CONFIG_SERIAL_LH7A40X_CONSOLE -# define LH7A40X_CONSOLE NULL -#else -# define LH7A40X_CONSOLE &lh7a40x_console - -static void lh7a40xuart_console_putchar(struct uart_port *port, int ch) -{ - while (UR(port, UART_R_STATUS) & nTxRdy) - ; - UR(port, UART_R_DATA) = ch; -} - -static void lh7a40xuart_console_write (struct console* co, - const char* s, - unsigned int count) -{ - struct uart_port* port = &lh7a40x_ports[co->index].port; - unsigned int con = UR (port, UART_R_CON); - unsigned int inten = UR (port, UART_R_INTEN); - - - UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ - BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ - - uart_console_write(port, s, count, lh7a40xuart_console_putchar); - - /* Wait until all characters are sent */ - while (UR (port, UART_R_STATUS) & TxBusy) - ; - - /* Restore control and interrupt mask */ - UR (port, UART_R_CON) = con; - UR (port, UART_R_INTEN) = inten; -} - -static void __init lh7a40xuart_console_get_options (struct uart_port* port, - int* baud, - int* parity, - int* bits) -{ - if (UR (port, UART_R_CON) & UARTEN) { - unsigned int fcon = UR (port, UART_R_FCON); - unsigned int quot = UR (port, UART_R_BRCON) + 1; - - switch (fcon & (PEN | EPS)) { - default: *parity = 'n'; break; - case PEN: *parity = 'o'; break; - case PEN | EPS: *parity = 'e'; break; - } - - switch (fcon & WLEN) { - default: - case WLEN_8: *bits = 8; break; - case WLEN_7: *bits = 7; break; - case WLEN_6: *bits = 6; break; - case WLEN_5: *bits = 5; break; - } - - *baud = port->uartclk/(16*quot); - } -} - -static int __init lh7a40xuart_console_setup (struct console* co, char* options) -{ - struct uart_port* port; - int baud = 38400; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - if (co->index >= DEV_NR) /* Bounds check on device number */ - co->index = 0; - port = &lh7a40x_ports[co->index].port; - - if (options) - uart_parse_options (options, &baud, &parity, &bits, &flow); - else - lh7a40xuart_console_get_options (port, &baud, &parity, &bits); - - return uart_set_options (port, co, baud, parity, bits, flow); -} - -static struct uart_driver lh7a40x_reg; -static struct console lh7a40x_console = { - .name = "ttyAM", - .write = lh7a40xuart_console_write, - .device = uart_console_device, - .setup = lh7a40xuart_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &lh7a40x_reg, -}; - -static int __init lh7a40xuart_console_init(void) -{ - register_console (&lh7a40x_console); - return 0; -} - -console_initcall (lh7a40xuart_console_init); - -#endif - -static struct uart_driver lh7a40x_reg = { - .owner = THIS_MODULE, - .driver_name = "ttyAM", - .dev_name = "ttyAM", - .major = DEV_MAJOR, - .minor = DEV_MINOR, - .nr = DEV_NR, - .cons = LH7A40X_CONSOLE, -}; - -static int __init lh7a40xuart_init(void) -{ - int ret; - - printk (KERN_INFO "serial: LH7A40X serial driver\n"); - - ret = uart_register_driver (&lh7a40x_reg); - - if (ret == 0) { - int i; - - for (i = 0; i < DEV_NR; i++) { - /* UART3, when used, requires GPIO pin reallocation */ - if (lh7a40x_ports[i].port.mapbase == UART3_PHYS) - GPIO_PINMUX |= 1<<3; - uart_add_one_port (&lh7a40x_reg, - &lh7a40x_ports[i].port); - } - } - return ret; -} - -static void __exit lh7a40xuart_exit(void) -{ - int i; - - for (i = 0; i < DEV_NR; i++) - uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port); - - uart_unregister_driver (&lh7a40x_reg); -} - -module_init (lh7a40xuart_init); -module_exit (lh7a40xuart_exit); - -MODULE_AUTHOR ("Marc Singer"); -MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver"); -MODULE_LICENSE ("GPL"); diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index fceea5e4e02f..41b6e51188e4 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -31,7 +31,6 @@ config USB_ARCH_HAS_OHCI # ARM: default y if SA1111 default y if ARCH_OMAP - default y if ARCH_LH7A404 default y if ARCH_S3C2410 default y if PXA27x default y if PXA3xx diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1dc9739277b4..08a48ae23745 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -176,18 +176,6 @@ config USB_FSL_USB2 default USB_GADGET select USB_GADGET_SELECTED -config USB_GADGET_LH7A40X - boolean "LH7A40X" - depends on ARCH_LH7A40X - help - This driver provides USB Device Controller driver for LH7A40x - -config USB_LH7A40X - tristate - depends on USB_GADGET_LH7A40X - default USB_GADGET - select USB_GADGET_SELECTED - config USB_GADGET_OMAP boolean "OMAP USB Device Controller" depends on ARCH_OMAP diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 55f5e8ae5924..a2f7f9a4f4a8 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o obj-$(CONFIG_USB_IMX) += imx_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o obj-$(CONFIG_USB_OMAP) += omap_udc.o -obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o obj-$(CONFIG_USB_AT91) += at91_udc.o obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 5c2720d64ffa..e896f6359dfe 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -45,12 +45,6 @@ #define gadget_is_goku(g) 0 #endif -#ifdef CONFIG_USB_GADGET_LH7A40X -#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name) -#else -#define gadget_is_lh7a40x(g) 0 -#endif - #ifdef CONFIG_USB_GADGET_OMAP #define gadget_is_omap(g) !strcmp("omap_udc", (g)->name) #else @@ -181,8 +175,6 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x06; else if (gadget_is_omap(gadget)) return 0x08; - else if (gadget_is_lh7a40x(gadget)) - return 0x09; else if (gadget_is_pxa27x(gadget)) return 0x11; else if (gadget_is_s3c2410(gadget)) diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c deleted file mode 100644 index 6b58bd8ce623..000000000000 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ /dev/null @@ -1,2152 +0,0 @@ -/* - * linux/drivers/usb/gadget/lh7a40x_udc.c - * Sharp LH7A40x on-chip full speed USB device controllers - * - * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID - * Copyright (C) 2004 Bo Henriksen, Nordic ID - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/platform_device.h> -#include <linux/slab.h> - -#include "lh7a40x_udc.h" - -//#define DEBUG printk -//#define DEBUG_EP0 printk -//#define DEBUG_SETUP printk - -#ifndef DEBUG_EP0 -# define DEBUG_EP0(fmt,args...) -#endif -#ifndef DEBUG_SETUP -# define DEBUG_SETUP(fmt,args...) -#endif -#ifndef DEBUG -# define NO_STATES -# define DEBUG(fmt,args...) -#endif - -#define DRIVER_DESC "LH7A40x USB Device Controller" -#define DRIVER_VERSION __DATE__ - -#ifndef _BIT /* FIXME - what happended to _BIT in 2.6.7bk18? */ -#define _BIT(x) (1<<(x)) -#endif - -struct lh7a40x_udc *the_controller; - -static const char driver_name[] = "lh7a40x_udc"; -static const char driver_desc[] = DRIVER_DESC; -static const char ep0name[] = "ep0-control"; - -/* - Local definintions. -*/ - -#ifndef NO_STATES -static char *state_names[] = { - "WAIT_FOR_SETUP", - "DATA_STATE_XMIT", - "DATA_STATE_NEED_ZLP", - "WAIT_FOR_OUT_STATUS", - "DATA_STATE_RECV" -}; -#endif - -/* - Local declarations. -*/ -static int lh7a40x_ep_enable(struct usb_ep *ep, - const struct usb_endpoint_descriptor *); -static int lh7a40x_ep_disable(struct usb_ep *ep); -static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t); -static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *); -static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t); -static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *); -static int lh7a40x_set_halt(struct usb_ep *ep, int); -static int lh7a40x_fifo_status(struct usb_ep *ep); -static void lh7a40x_fifo_flush(struct usb_ep *ep); -static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep); -static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr); - -static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, - int status); -static void pio_irq_enable(int bEndpointAddress); -static void pio_irq_disable(int bEndpointAddress); -static void stop_activity(struct lh7a40x_udc *dev, - struct usb_gadget_driver *driver); -static void flush(struct lh7a40x_ep *ep); -static void udc_enable(struct lh7a40x_udc *dev); -static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address); - -static struct usb_ep_ops lh7a40x_ep_ops = { - .enable = lh7a40x_ep_enable, - .disable = lh7a40x_ep_disable, - - .alloc_request = lh7a40x_alloc_request, - .free_request = lh7a40x_free_request, - - .queue = lh7a40x_queue, - .dequeue = lh7a40x_dequeue, - - .set_halt = lh7a40x_set_halt, - .fifo_status = lh7a40x_fifo_status, - .fifo_flush = lh7a40x_fifo_flush, -}; - -/* Inline code */ - -static __inline__ int write_packet(struct lh7a40x_ep *ep, - struct lh7a40x_request *req, int max) -{ - u8 *buf; - int length, count; - volatile u32 *fifo = (volatile u32 *)ep->fifo; - - buf = req->req.buf + req->req.actual; - prefetch(buf); - - length = req->req.length - req->req.actual; - length = min(length, max); - req->req.actual += length; - - DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo); - - count = length; - while (count--) { - *fifo = *buf++; - } - - return length; -} - -static __inline__ void usb_set_index(u32 ep) -{ - *(volatile u32 *)io_p2v(USB_INDEX) = ep; -} - -static __inline__ u32 usb_read(u32 port) -{ - return *(volatile u32 *)io_p2v(port); -} - -static __inline__ void usb_write(u32 val, u32 port) -{ - *(volatile u32 *)io_p2v(port) = val; -} - -static __inline__ void usb_set(u32 val, u32 port) -{ - volatile u32 *ioport = (volatile u32 *)io_p2v(port); - u32 after = (*ioport) | val; - *ioport = after; -} - -static __inline__ void usb_clear(u32 val, u32 port) -{ - volatile u32 *ioport = (volatile u32 *)io_p2v(port); - u32 after = (*ioport) & ~val; - *ioport = after; -} - -/*-------------------------------------------------------------------------*/ - -#define GPIO_PORTC_DR (0x80000E08) -#define GPIO_PORTC_DDR (0x80000E18) -#define GPIO_PORTC_PDR (0x80000E70) - -/* get port C pin data register */ -#define get_portc_pdr(bit) ((usb_read(GPIO_PORTC_PDR) & _BIT(bit)) != 0) -/* get port C data direction register */ -#define get_portc_ddr(bit) ((usb_read(GPIO_PORTC_DDR) & _BIT(bit)) != 0) -/* set port C data register */ -#define set_portc_dr(bit, val) (val ? usb_set(_BIT(bit), GPIO_PORTC_DR) : usb_clear(_BIT(bit), GPIO_PORTC_DR)) -/* set port C data direction register */ -#define set_portc_ddr(bit, val) (val ? usb_set(_BIT(bit), GPIO_PORTC_DDR) : usb_clear(_BIT(bit), GPIO_PORTC_DDR)) - -/* - * LPD7A404 GPIO's: - * Port C bit 1 = USB Port 1 Power Enable - * Port C bit 2 = USB Port 1 Data Carrier Detect - */ -#define is_usb_connected() get_portc_pdr(2) - -#ifdef CONFIG_USB_GADGET_DEBUG_FILES - -static const char proc_node_name[] = "driver/udc"; - -static int -udc_proc_read(char *page, char **start, off_t off, int count, - int *eof, void *_dev) -{ - char *buf = page; - struct lh7a40x_udc *dev = _dev; - char *next = buf; - unsigned size = count; - unsigned long flags; - int t; - - if (off != 0) - return 0; - - local_irq_save(flags); - - /* basic device status */ - t = scnprintf(next, size, - DRIVER_DESC "\n" - "%s version: %s\n" - "Gadget driver: %s\n" - "Host: %s\n\n", - driver_name, DRIVER_VERSION, - dev->driver ? dev->driver->driver.name : "(none)", - is_usb_connected()? "full speed" : "disconnected"); - size -= t; - next += t; - - t = scnprintf(next, size, - "GPIO:\n" - " Port C bit 1: %d, dir %d\n" - " Port C bit 2: %d, dir %d\n\n", - get_portc_pdr(1), get_portc_ddr(1), - get_portc_pdr(2), get_portc_ddr(2) - ); - size -= t; - next += t; - - t = scnprintf(next, size, - "DCP pullup: %d\n\n", - (usb_read(USB_PM) & PM_USB_DCP) != 0); - size -= t; - next += t; - - local_irq_restore(flags); - *eof = 1; - return count - size; -} - -#define create_proc_files() create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev) -#define remove_proc_files() remove_proc_entry(proc_node_name, NULL) - -#else /* !CONFIG_USB_GADGET_DEBUG_FILES */ - -#define create_proc_files() do {} while (0) -#define remove_proc_files() do {} while (0) - -#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ - -/* - * udc_disable - disable USB device controller - */ -static void udc_disable(struct lh7a40x_udc *dev) -{ - DEBUG("%s, %p\n", __func__, dev); - - udc_set_address(dev, 0); - - /* Disable interrupts */ - usb_write(0, USB_IN_INT_EN); - usb_write(0, USB_OUT_INT_EN); - usb_write(0, USB_INT_EN); - - /* Disable the USB */ - usb_write(0, USB_PM); - -#ifdef CONFIG_ARCH_LH7A404 - /* Disable USB power */ - set_portc_dr(1, 0); -#endif - - /* if hardware supports it, disconnect from usb */ - /* make_usb_disappear(); */ - - dev->ep0state = WAIT_FOR_SETUP; - dev->gadget.speed = USB_SPEED_UNKNOWN; - dev->usb_address = 0; -} - -/* - * udc_reinit - initialize software state - */ -static void udc_reinit(struct lh7a40x_udc *dev) -{ - u32 i; - - DEBUG("%s, %p\n", __func__, dev); - - /* device/ep0 records init */ - INIT_LIST_HEAD(&dev->gadget.ep_list); - INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); - dev->ep0state = WAIT_FOR_SETUP; - - /* basic endpoint records init */ - for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { - struct lh7a40x_ep *ep = &dev->ep[i]; - - if (i != 0) - list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); - - ep->desc = 0; - ep->stopped = 0; - INIT_LIST_HEAD(&ep->queue); - ep->pio_irqs = 0; - } - - /* the rest was statically initialized, and is read-only */ -} - -#define BYTES2MAXP(x) (x / 8) -#define MAXP2BYTES(x) (x * 8) - -/* until it's enabled, this UDC should be completely invisible - * to any USB host. - */ -static void udc_enable(struct lh7a40x_udc *dev) -{ - int ep; - - DEBUG("%s, %p\n", __func__, dev); - - dev->gadget.speed = USB_SPEED_UNKNOWN; - -#ifdef CONFIG_ARCH_LH7A404 - /* Set Port C bit 1 & 2 as output */ - set_portc_ddr(1, 1); - set_portc_ddr(2, 1); - - /* Enable USB power */ - set_portc_dr(1, 0); -#endif - - /* - * C.f Chapter 18.1.3.1 Initializing the USB - */ - - /* Disable the USB */ - usb_clear(PM_USB_ENABLE, USB_PM); - - /* Reset APB & I/O sides of the USB */ - usb_set(USB_RESET_APB | USB_RESET_IO, USB_RESET); - mdelay(5); - usb_clear(USB_RESET_APB | USB_RESET_IO, USB_RESET); - - /* Set MAXP values for each */ - for (ep = 0; ep < UDC_MAX_ENDPOINTS; ep++) { - struct lh7a40x_ep *ep_reg = &dev->ep[ep]; - u32 csr; - - usb_set_index(ep); - - switch (ep_reg->ep_type) { - case ep_bulk_in: - case ep_interrupt: - usb_clear(USB_IN_CSR2_USB_DMA_EN | USB_IN_CSR2_AUTO_SET, - ep_reg->csr2); - /* Fall through */ - case ep_control: - usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)), - USB_IN_MAXP); - break; - case ep_bulk_out: - usb_clear(USB_OUT_CSR2_USB_DMA_EN | - USB_OUT_CSR2_AUTO_CLR, ep_reg->csr2); - usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)), - USB_OUT_MAXP); - break; - } - - /* Read & Write CSR1, just in case */ - csr = usb_read(ep_reg->csr1); - usb_write(csr, ep_reg->csr1); - - flush(ep_reg); - } - - /* Disable interrupts */ - usb_write(0, USB_IN_INT_EN); - usb_write(0, USB_OUT_INT_EN); - usb_write(0, USB_INT_EN); - - /* Enable interrupts */ - usb_set(USB_IN_INT_EP0, USB_IN_INT_EN); - usb_set(USB_INT_RESET_INT | USB_INT_RESUME_INT, USB_INT_EN); - /* Dont enable rest of the interrupts */ - /* usb_set(USB_IN_INT_EP3 | USB_IN_INT_EP1 | USB_IN_INT_EP0, USB_IN_INT_EN); - usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN); */ - - /* Enable SUSPEND */ - usb_set(PM_ENABLE_SUSPEND, USB_PM); - - /* Enable the USB */ - usb_set(PM_USB_ENABLE, USB_PM); - -#ifdef CONFIG_ARCH_LH7A404 - /* NOTE: DOES NOT WORK! */ - /* Let host detect UDC: - * Software must write a 0 to the PMR:DCP_CTRL bit to turn this - * transistor on and pull the USBDP pin HIGH. - */ - /* usb_clear(PM_USB_DCP, USB_PM); - usb_set(PM_USB_DCP, USB_PM); */ -#endif -} - -/* - Register entry point for the peripheral controller driver. -*/ -int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) -{ - struct lh7a40x_udc *dev = the_controller; - int retval; - - DEBUG("%s: %s\n", __func__, driver->driver.name); - - if (!driver - || driver->speed != USB_SPEED_FULL - || !bind - || !driver->disconnect - || !driver->setup) - return -EINVAL; - if (!dev) - return -ENODEV; - if (dev->driver) - return -EBUSY; - - /* first hook up the driver ... */ - dev->driver = driver; - dev->gadget.dev.driver = &driver->driver; - - device_add(&dev->gadget.dev); - retval = bind(&dev->gadget); - if (retval) { - printk(KERN_WARNING "%s: bind to driver %s --> error %d\n", - dev->gadget.name, driver->driver.name, retval); - device_del(&dev->gadget.dev); - - dev->driver = 0; - dev->gadget.dev.driver = 0; - return retval; - } - - /* ... then enable host detection and ep0; and we're ready - * for set_configuration as well as eventual disconnect. - * NOTE: this shouldn't power up until later. - */ - printk(KERN_WARNING "%s: registered gadget driver '%s'\n", - dev->gadget.name, driver->driver.name); - - udc_enable(dev); - - return 0; -} -EXPORT_SYMBOL(usb_gadget_probe_driver); - -/* - Unregister entry point for the peripheral controller driver. -*/ -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -{ - struct lh7a40x_udc *dev = the_controller; - unsigned long flags; - - if (!dev) - return -ENODEV; - if (!driver || driver != dev->driver || !driver->unbind) - return -EINVAL; - - spin_lock_irqsave(&dev->lock, flags); - dev->driver = 0; - stop_activity(dev, driver); - spin_unlock_irqrestore(&dev->lock, flags); - - driver->unbind(&dev->gadget); - dev->gadget.dev.driver = NULL; - device_del(&dev->gadget.dev); - - udc_disable(dev); - - DEBUG("unregistered gadget driver '%s'\n", driver->driver.name); - return 0; -} - -EXPORT_SYMBOL(usb_gadget_unregister_driver); - -/*-------------------------------------------------------------------------*/ - -/** Write request to FIFO (max write == maxp size) - * Return: 0 = still running, 1 = completed, negative = errno - * NOTE: INDEX register must be set for EP - */ -static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req) -{ - u32 max; - u32 csr; - - max = le16_to_cpu(ep->desc->wMaxPacketSize); - - csr = usb_read(ep->csr1); - DEBUG("CSR: %x %d\n", csr, csr & USB_IN_CSR1_FIFO_NOT_EMPTY); - - if (!(csr & USB_IN_CSR1_FIFO_NOT_EMPTY)) { - unsigned count; - int is_last, is_short; - - count = write_packet(ep, req, max); - usb_set(USB_IN_CSR1_IN_PKT_RDY, ep->csr1); - - /* last packet is usually short (or a zlp) */ - if (unlikely(count != max)) - is_last = is_short = 1; - else { - if (likely(req->req.length != req->req.actual) - || req->req.zero) - is_last = 0; - else - is_last = 1; - /* interrupt/iso maxpacket may not fill the fifo */ - is_short = unlikely(max < ep_maxpacket(ep)); - } - - DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __func__, - ep->ep.name, count, - is_last ? "/L" : "", is_short ? "/S" : "", - req->req.length - req->req.actual, req); - - /* requests complete when all IN data is in the FIFO */ - if (is_last) { - done(ep, req, 0); - if (list_empty(&ep->queue)) { - pio_irq_disable(ep_index(ep)); - } - return 1; - } - } else { - DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep)); - } - - return 0; -} - -/** Read to request from FIFO (max read == bytes in fifo) - * Return: 0 = still running, 1 = completed, negative = errno - * NOTE: INDEX register must be set for EP - */ -static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req) -{ - u32 csr; - u8 *buf; - unsigned bufferspace, count, is_short; - volatile u32 *fifo = (volatile u32 *)ep->fifo; - - /* make sure there's a packet in the FIFO. */ - csr = usb_read(ep->csr1); - if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) { - DEBUG("%s: Packet NOT ready!\n", __func__); - return -EINVAL; - } - - buf = req->req.buf + req->req.actual; - prefetchw(buf); - bufferspace = req->req.length - req->req.actual; - - /* read all bytes from this packet */ - count = usb_read(USB_OUT_FIFO_WC1); - req->req.actual += min(count, bufferspace); - - is_short = (count < ep->ep.maxpacket); - DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n", - ep->ep.name, csr, count, - is_short ? "/S" : "", req, req->req.actual, req->req.length); - - while (likely(count-- != 0)) { - u8 byte = (u8) (*fifo & 0xff); - - if (unlikely(bufferspace == 0)) { - /* this happens when the driver's buffer - * is smaller than what the host sent. - * discard the extra data. - */ - if (req->req.status != -EOVERFLOW) - printk(KERN_WARNING "%s overflow %d\n", - ep->ep.name, count); - req->req.status = -EOVERFLOW; - } else { - *buf++ = byte; - bufferspace--; - } - } - - usb_clear(USB_OUT_CSR1_OUT_PKT_RDY, ep->csr1); - - /* completion */ - if (is_short || req->req.actual == req->req.length) { - done(ep, req, 0); - usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); - - if (list_empty(&ep->queue)) - pio_irq_disable(ep_index(ep)); - return 1; - } - - /* finished that packet. the next one may be waiting... */ - return 0; -} - -/* - * done - retire a request; caller blocked irqs - * INDEX register is preserved to keep same - */ -static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status) -{ - unsigned int stopped = ep->stopped; - u32 index; - - DEBUG("%s, %p\n", __func__, ep); - list_del_init(&req->queue); - - if (likely(req->req.status == -EINPROGRESS)) - req->req.status = status; - else - status = req->req.status; - - if (status && status != -ESHUTDOWN) - DEBUG("complete %s req %p stat %d len %u/%u\n", - ep->ep.name, &req->req, status, - req->req.actual, req->req.length); - - /* don't modify queue heads during completion callback */ - ep->stopped = 1; - /* Read current index (completion may modify it) */ - index = usb_read(USB_INDEX); - - spin_unlock(&ep->dev->lock); - req->req.complete(&ep->ep, &req->req); - spin_lock(&ep->dev->lock); - - /* Restore index */ - usb_set_index(index); - ep->stopped = stopped; -} - -/** Enable EP interrupt */ -static void pio_irq_enable(int ep) -{ - DEBUG("%s: %d\n", __func__, ep); - - switch (ep) { - case 1: - usb_set(USB_IN_INT_EP1, USB_IN_INT_EN); - break; - case 2: - usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN); - break; - case 3: - usb_set(USB_IN_INT_EP3, USB_IN_INT_EN); - break; - default: - DEBUG("Unknown endpoint: %d\n", ep); - break; - } -} - -/** Disable EP interrupt */ -static void pio_irq_disable(int ep) -{ - DEBUG("%s: %d\n", __func__, ep); - - switch (ep) { - case 1: - usb_clear(USB_IN_INT_EP1, USB_IN_INT_EN); - break; - case 2: - usb_clear(USB_OUT_INT_EP2, USB_OUT_INT_EN); - break; - case 3: - usb_clear(USB_IN_INT_EP3, USB_IN_INT_EN); - break; - default: - DEBUG("Unknown endpoint: %d\n", ep); - break; - } -} - -/* - * nuke - dequeue ALL requests - */ -void nuke(struct lh7a40x_ep *ep, int status) -{ - struct lh7a40x_request *req; - - DEBUG("%s, %p\n", __func__, ep); - - /* Flush FIFO */ - flush(ep); - - /* called with irqs blocked */ - while (!list_empty(&ep->queue)) { - req = list_entry(ep->queue.next, struct lh7a40x_request, queue); - done(ep, req, status); - } - - /* Disable IRQ if EP is enabled (has descriptor) */ - if (ep->desc) - pio_irq_disable(ep_index(ep)); -} - -/* -void nuke_all(struct lh7a40x_udc *dev) -{ - int n; - for(n=0; n<UDC_MAX_ENDPOINTS; n++) { - struct lh7a40x_ep *ep = &dev->ep[n]; - usb_set_index(n); - nuke(ep, 0); - } -}*/ - -/* -static void flush_all(struct lh7a40x_udc *dev) -{ - int n; - for (n = 0; n < UDC_MAX_ENDPOINTS; n++) - { - struct lh7a40x_ep *ep = &dev->ep[n]; - flush(ep); - } -} -*/ - -/** Flush EP - * NOTE: INDEX register must be set before this call - */ -static void flush(struct lh7a40x_ep *ep) -{ - DEBUG("%s, %p\n", __func__, ep); - - switch (ep->ep_type) { - case ep_control: - /* check, by implication c.f. 15.1.2.11 */ - break; - - case ep_bulk_in: - case ep_interrupt: - /* if(csr & USB_IN_CSR1_IN_PKT_RDY) */ - usb_set(USB_IN_CSR1_FIFO_FLUSH, ep->csr1); - break; - - case ep_bulk_out: - /* if(csr & USB_OUT_CSR1_OUT_PKT_RDY) */ - usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); - break; - } -} - -/** - * lh7a40x_in_epn - handle IN interrupt - */ -static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) -{ - u32 csr; - struct lh7a40x_ep *ep = &dev->ep[ep_idx]; - struct lh7a40x_request *req; - - usb_set_index(ep_idx); - - csr = usb_read(ep->csr1); - DEBUG("%s: %d, csr %x\n", __func__, ep_idx, csr); - - if (csr & USB_IN_CSR1_SENT_STALL) { - DEBUG("USB_IN_CSR1_SENT_STALL\n"); - usb_set(USB_IN_CSR1_SENT_STALL /*|USB_IN_CSR1_SEND_STALL */ , - ep->csr1); - return; - } - - if (!ep->desc) { - DEBUG("%s: NO EP DESC\n", __func__); - return; - } - - if (list_empty(&ep->queue)) - req = 0; - else - req = list_entry(ep->queue.next, struct lh7a40x_request, queue); - - DEBUG("req: %p\n", req); - - if (!req) - return; - - write_fifo(ep, req); -} - -/* ********************************************************************************************* */ -/* Bulk OUT (recv) - */ - -static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) -{ - struct lh7a40x_ep *ep = &dev->ep[ep_idx]; - struct lh7a40x_request *req; - - DEBUG("%s: %d\n", __func__, ep_idx); - - usb_set_index(ep_idx); - - if (ep->desc) { - u32 csr; - csr = usb_read(ep->csr1); - - while ((csr = - usb_read(ep-> - csr1)) & (USB_OUT_CSR1_OUT_PKT_RDY | - USB_OUT_CSR1_SENT_STALL)) { - DEBUG("%s: %x\n", __func__, csr); - - if (csr & USB_OUT_CSR1_SENT_STALL) { - DEBUG("%s: stall sent, flush fifo\n", - __func__); - /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */ - flush(ep); - } else if (csr & USB_OUT_CSR1_OUT_PKT_RDY) { - if (list_empty(&ep->queue)) - req = 0; - else - req = - list_entry(ep->queue.next, - struct lh7a40x_request, - queue); - - if (!req) { - printk(KERN_WARNING - "%s: NULL REQ %d\n", - __func__, ep_idx); - flush(ep); - break; - } else { - read_fifo(ep, req); - } - } - - } - - } else { - /* Throw packet away.. */ - printk(KERN_WARNING "%s: No descriptor?!?\n", __func__); - flush(ep); - } -} - -static void stop_activity(struct lh7a40x_udc *dev, - struct usb_gadget_driver *driver) -{ - int i; - - /* don't disconnect drivers more than once */ - if (dev->gadget.speed == USB_SPEED_UNKNOWN) - driver = 0; - dev->gadget.speed = USB_SPEED_UNKNOWN; - - /* prevent new request submissions, kill any outstanding requests */ - for (i = 0; i < UDC_MAX_ENDPOINTS; i++) { - struct lh7a40x_ep *ep = &dev->ep[i]; - ep->stopped = 1; - - usb_set_index(i); - nuke(ep, -ESHUTDOWN); - } - - /* report disconnect; the driver is already quiesced */ - if (driver) { - spin_unlock(&dev->lock); - driver->disconnect(&dev->gadget); - spin_lock(&dev->lock); - } - - /* re-init driver-visible data structures */ - udc_reinit(dev); -} - -/** Handle USB RESET interrupt - */ -static void lh7a40x_reset_intr(struct lh7a40x_udc *dev) -{ -#if 0 /* def CONFIG_ARCH_LH7A404 */ - /* Does not work always... */ - - DEBUG("%s: %d\n", __func__, dev->usb_address); - - if (!dev->usb_address) { - /*usb_set(USB_RESET_IO, USB_RESET); - mdelay(5); - usb_clear(USB_RESET_IO, USB_RESET); */ - return; - } - /* Put the USB controller into reset. */ - usb_set(USB_RESET_IO, USB_RESET); - - /* Set Device ID to 0 */ - udc_set_address(dev, 0); - - /* Let PLL2 settle down */ - mdelay(5); - - /* Release the USB controller from reset */ - usb_clear(USB_RESET_IO, USB_RESET); - - /* Re-enable UDC */ - udc_enable(dev); - -#endif - dev->gadget.speed = USB_SPEED_FULL; -} - -/* - * lh7a40x usb client interrupt handler. - */ -static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev) -{ - struct lh7a40x_udc *dev = _dev; - - DEBUG("\n\n"); - - spin_lock(&dev->lock); - - for (;;) { - u32 intr_in = usb_read(USB_IN_INT); - u32 intr_out = usb_read(USB_OUT_INT); - u32 intr_int = usb_read(USB_INT); - - /* Test also against enable bits.. (lh7a40x errata).. Sigh.. */ - u32 in_en = usb_read(USB_IN_INT_EN); - u32 out_en = usb_read(USB_OUT_INT_EN); - - if (!intr_out && !intr_in && !intr_int) - break; - - DEBUG("%s (on state %s)\n", __func__, - state_names[dev->ep0state]); - DEBUG("intr_out = %x\n", intr_out); - DEBUG("intr_in = %x\n", intr_in); - DEBUG("intr_int = %x\n", intr_int); - - if (intr_in) { - usb_write(intr_in, USB_IN_INT); - - if ((intr_in & USB_IN_INT_EP1) - && (in_en & USB_IN_INT_EP1)) { - DEBUG("USB_IN_INT_EP1\n"); - lh7a40x_in_epn(dev, 1, intr_in); - } - if ((intr_in & USB_IN_INT_EP3) - && (in_en & USB_IN_INT_EP3)) { - DEBUG("USB_IN_INT_EP3\n"); - lh7a40x_in_epn(dev, 3, intr_in); - } - if (intr_in & USB_IN_INT_EP0) { - DEBUG("USB_IN_INT_EP0 (control)\n"); - lh7a40x_handle_ep0(dev, intr_in); - } - } - - if (intr_out) { - usb_write(intr_out, USB_OUT_INT); - - if ((intr_out & USB_OUT_INT_EP2) - && (out_en & USB_OUT_INT_EP2)) { - DEBUG("USB_OUT_INT_EP2\n"); - lh7a40x_out_epn(dev, 2, intr_out); - } - } - - if (intr_int) { - usb_write(intr_int, USB_INT); - - if (intr_int & USB_INT_RESET_INT) { - lh7a40x_reset_intr(dev); - } - - if (intr_int & USB_INT_RESUME_INT) { - DEBUG("USB resume\n"); - - if (dev->gadget.speed != USB_SPEED_UNKNOWN - && dev->driver - && dev->driver->resume - && is_usb_connected()) { - dev->driver->resume(&dev->gadget); - } - } - - if (intr_int & USB_INT_SUSPEND_INT) { - DEBUG("USB suspend%s\n", - is_usb_connected()? "" : "+disconnect"); - if (!is_usb_connected()) { - stop_activity(dev, dev->driver); - } else if (dev->gadget.speed != - USB_SPEED_UNKNOWN && dev->driver - && dev->driver->suspend) { - dev->driver->suspend(&dev->gadget); - } - } - - } - } - - spin_unlock(&dev->lock); - - return IRQ_HANDLED; -} - -static int lh7a40x_ep_enable(struct usb_ep *_ep, - const struct usb_endpoint_descriptor *desc) -{ - struct lh7a40x_ep *ep; - struct lh7a40x_udc *dev; - unsigned long flags; - - DEBUG("%s, %p\n", __func__, _ep); - - ep = container_of(_ep, struct lh7a40x_ep, ep); - if (!_ep || !desc || ep->desc || _ep->name == ep0name - || desc->bDescriptorType != USB_DT_ENDPOINT - || ep->bEndpointAddress != desc->bEndpointAddress - || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) { - DEBUG("%s, bad ep or descriptor\n", __func__); - return -EINVAL; - } - - /* xfer types must match, except that interrupt ~= bulk */ - if (ep->bmAttributes != desc->bmAttributes - && ep->bmAttributes != USB_ENDPOINT_XFER_BULK - && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { - DEBUG("%s, %s type mismatch\n", __func__, _ep->name); - return -EINVAL; - } - - /* hardware _could_ do smaller, but driver doesn't */ - if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep)) - || !desc->wMaxPacketSize) { - DEBUG("%s, bad %s maxpacket\n", __func__, _ep->name); - return -ERANGE; - } - - dev = ep->dev; - if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { - DEBUG("%s, bogus device state\n", __func__); - return -ESHUTDOWN; - } - - spin_lock_irqsave(&ep->dev->lock, flags); - - ep->stopped = 0; - ep->desc = desc; - ep->pio_irqs = 0; - ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); - - spin_unlock_irqrestore(&ep->dev->lock, flags); - - /* Reset halt state (does flush) */ - lh7a40x_set_halt(_ep, 0); - - DEBUG("%s: enabled %s\n", __func__, _ep->name); - return 0; -} - -/** Disable EP - * NOTE: Sets INDEX register - */ -static int lh7a40x_ep_disable(struct usb_ep *_ep) -{ - struct lh7a40x_ep *ep; - unsigned long flags; - - DEBUG("%s, %p\n", __func__, _ep); - - ep = container_of(_ep, struct lh7a40x_ep, ep); - if (!_ep || !ep->desc) { - DEBUG("%s, %s not enabled\n", __func__, - _ep ? ep->ep.name : NULL); - return -EINVAL; - } - - spin_lock_irqsave(&ep->dev->lock, flags); - - usb_set_index(ep_index(ep)); - - /* Nuke all pending requests (does flush) */ - nuke(ep, -ESHUTDOWN); - - /* Disable ep IRQ */ - pio_irq_disable(ep_index(ep)); - - ep->desc = 0; - ep->stopped = 1; - - spin_unlock_irqrestore(&ep->dev->lock, flags); - - DEBUG("%s: disabled %s\n", __func__, _ep->name); - return 0; -} - -static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, - gfp_t gfp_flags) -{ - struct lh7a40x_request *req; - - DEBUG("%s, %p\n", __func__, ep); - - req = kzalloc(sizeof(*req), gfp_flags); - if (!req) - return 0; - - INIT_LIST_HEAD(&req->queue); - - return &req->req; -} - -static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req) -{ - struct lh7a40x_request *req; - - DEBUG("%s, %p\n", __func__, ep); - - req = container_of(_req, struct lh7a40x_request, req); - WARN_ON(!list_empty(&req->queue)); - kfree(req); -} - -/** Queue one request - * Kickstart transfer if needed - * NOTE: Sets INDEX register - */ -static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req, - gfp_t gfp_flags) -{ - struct lh7a40x_request *req; - struct lh7a40x_ep *ep; - struct lh7a40x_udc *dev; - unsigned long flags; - - DEBUG("\n\n\n%s, %p\n", __func__, _ep); - - req = container_of(_req, struct lh7a40x_request, req); - if (unlikely - (!_req || !_req->complete || !_req->buf - || !list_empty(&req->queue))) { - DEBUG("%s, bad params\n", __func__); - return -EINVAL; - } - - ep = container_of(_ep, struct lh7a40x_ep, ep); - if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { - DEBUG("%s, bad ep\n", __func__); - return -EINVAL; - } - - dev = ep->dev; - if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { - DEBUG("%s, bogus device state %p\n", __func__, dev->driver); - return -ESHUTDOWN; - } - - DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length, - _req->buf); - - spin_lock_irqsave(&dev->lock, flags); - - _req->status = -EINPROGRESS; - _req->actual = 0; - - /* kickstart this i/o queue? */ - DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue), - ep->stopped); - if (list_empty(&ep->queue) && likely(!ep->stopped)) { - u32 csr; - - if (unlikely(ep_index(ep) == 0)) { - /* EP0 */ - list_add_tail(&req->queue, &ep->queue); - lh7a40x_ep0_kick(dev, ep); - req = 0; - } else if (ep_is_in(ep)) { - /* EP1 & EP3 */ - usb_set_index(ep_index(ep)); - csr = usb_read(ep->csr1); - pio_irq_enable(ep_index(ep)); - if ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY) == 0) { - if (write_fifo(ep, req) == 1) - req = 0; - } - } else { - /* EP2 */ - usb_set_index(ep_index(ep)); - csr = usb_read(ep->csr1); - pio_irq_enable(ep_index(ep)); - if (!(csr & USB_OUT_CSR1_FIFO_FULL)) { - if (read_fifo(ep, req) == 1) - req = 0; - } - } - } - - /* pio or dma irq handler advances the queue. */ - if (likely(req != 0)) - list_add_tail(&req->queue, &ep->queue); - - spin_unlock_irqrestore(&dev->lock, flags); - - return 0; -} - -/* dequeue JUST ONE request */ -static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req) -{ - struct lh7a40x_ep *ep; - struct lh7a40x_request *req; - unsigned long flags; - - DEBUG("%s, %p\n", __func__, _ep); - - ep = container_of(_ep, struct lh7a40x_ep, ep); - if (!_ep || ep->ep.name == ep0name) - return -EINVAL; - - spin_lock_irqsave(&ep->dev->lock, flags); - - /* make sure it's actually queued on this endpoint */ - list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) - break; - } - if (&req->req != _req) { - spin_unlock_irqrestore(&ep->dev->lock, flags); - return -EINVAL; - } - - done(ep, req, -ECONNRESET); - - spin_unlock_irqrestore(&ep->dev->lock, flags); - return 0; -} - -/** Halt specific EP - * Return 0 if success - * NOTE: Sets INDEX register to EP ! - */ -static int lh7a40x_set_halt(struct usb_ep *_ep, int value) -{ - struct lh7a40x_ep *ep; - unsigned long flags; - - ep = container_of(_ep, struct lh7a40x_ep, ep); - if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { - DEBUG("%s, bad ep\n", __func__); - return -EINVAL; - } - - usb_set_index(ep_index(ep)); - - DEBUG("%s, ep %d, val %d\n", __func__, ep_index(ep), value); - - spin_lock_irqsave(&ep->dev->lock, flags); - - if (ep_index(ep) == 0) { - /* EP0 */ - usb_set(EP0_SEND_STALL, ep->csr1); - } else if (ep_is_in(ep)) { - u32 csr = usb_read(ep->csr1); - if (value && ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY) - || !list_empty(&ep->queue))) { - /* - * Attempts to halt IN endpoints will fail (returning -EAGAIN) - * if any transfer requests are still queued, or if the controller - * FIFO still holds bytes that the host hasn't collected. - */ - spin_unlock_irqrestore(&ep->dev->lock, flags); - DEBUG - ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n", - (csr & USB_IN_CSR1_FIFO_NOT_EMPTY), - !list_empty(&ep->queue)); - return -EAGAIN; - } - flush(ep); - if (value) - usb_set(USB_IN_CSR1_SEND_STALL, ep->csr1); - else { - usb_clear(USB_IN_CSR1_SEND_STALL, ep->csr1); - usb_set(USB_IN_CSR1_CLR_DATA_TOGGLE, ep->csr1); - } - - } else { - - flush(ep); - if (value) - usb_set(USB_OUT_CSR1_SEND_STALL, ep->csr1); - else { - usb_clear(USB_OUT_CSR1_SEND_STALL, ep->csr1); - usb_set(USB_OUT_CSR1_CLR_DATA_REG, ep->csr1); - } - } - - if (value) { - ep->stopped = 1; - } else { - ep->stopped = 0; - } - - spin_unlock_irqrestore(&ep->dev->lock, flags); - - DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS"); - - return 0; -} - -/** Return bytes in EP FIFO - * NOTE: Sets INDEX register to EP - */ -static int lh7a40x_fifo_status(struct usb_ep *_ep) -{ - u32 csr; - int count = 0; - struct lh7a40x_ep *ep; - - ep = container_of(_ep, struct lh7a40x_ep, ep); - if (!_ep) { - DEBUG("%s, bad ep\n", __func__); - return -ENODEV; - } - - DEBUG("%s, %d\n", __func__, ep_index(ep)); - - /* LPD can't report unclaimed bytes from IN fifos */ - if (ep_is_in(ep)) - return -EOPNOTSUPP; - - usb_set_index(ep_index(ep)); - - csr = usb_read(ep->csr1); - if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN || - csr & USB_OUT_CSR1_OUT_PKT_RDY) { - count = usb_read(USB_OUT_FIFO_WC1); - } - - return count; -} - -/** Flush EP FIFO - * NOTE: Sets INDEX register to EP - */ -static void lh7a40x_fifo_flush(struct usb_ep *_ep) -{ - struct lh7a40x_ep *ep; - - ep = container_of(_ep, struct lh7a40x_ep, ep); - if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) { - DEBUG("%s, bad ep\n", __func__); - return; - } - - usb_set_index(ep_index(ep)); - flush(ep); -} - -/****************************************************************/ -/* End Point 0 related functions */ -/****************************************************************/ - -/* return: 0 = still running, 1 = completed, negative = errno */ -static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req) -{ - u32 max; - unsigned count; - int is_last; - - max = ep_maxpacket(ep); - - DEBUG_EP0("%s\n", __func__); - - count = write_packet(ep, req, max); - - /* last packet is usually short (or a zlp) */ - if (unlikely(count != max)) - is_last = 1; - else { - if (likely(req->req.length != req->req.actual) || req->req.zero) - is_last = 0; - else - is_last = 1; - } - - DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __func__, - ep->ep.name, count, - is_last ? "/L" : "", req->req.length - req->req.actual, req); - - /* requests complete when all IN data is in the FIFO */ - if (is_last) { - done(ep, req, 0); - return 1; - } - - return 0; -} - -static __inline__ int lh7a40x_fifo_read(struct lh7a40x_ep *ep, - unsigned char *cp, int max) -{ - int bytes; - int count = usb_read(USB_OUT_FIFO_WC1); - volatile u32 *fifo = (volatile u32 *)ep->fifo; - - if (count > max) - count = max; - bytes = count; - while (count--) - *cp++ = *fifo & 0xFF; - return bytes; -} - -static __inline__ void lh7a40x_fifo_write(struct lh7a40x_ep *ep, - unsigned char *cp, int count) -{ - volatile u32 *fifo = (volatile u32 *)ep->fifo; - DEBUG_EP0("fifo_write: %d %d\n", ep_index(ep), count); - while (count--) - *fifo = *cp++; -} - -static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req) -{ - u32 csr; - u8 *buf; - unsigned bufferspace, count, is_short; - volatile u32 *fifo = (volatile u32 *)ep->fifo; - - DEBUG_EP0("%s\n", __func__); - - csr = usb_read(USB_EP0_CSR); - if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) - return 0; - - buf = req->req.buf + req->req.actual; - prefetchw(buf); - bufferspace = req->req.length - req->req.actual; - - /* read all bytes from this packet */ - if (likely(csr & EP0_OUT_PKT_RDY)) { - count = usb_read(USB_OUT_FIFO_WC1); - req->req.actual += min(count, bufferspace); - } else /* zlp */ - count = 0; - - is_short = (count < ep->ep.maxpacket); - DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n", - ep->ep.name, csr, count, - is_short ? "/S" : "", req, req->req.actual, req->req.length); - - while (likely(count-- != 0)) { - u8 byte = (u8) (*fifo & 0xff); - - if (unlikely(bufferspace == 0)) { - /* this happens when the driver's buffer - * is smaller than what the host sent. - * discard the extra data. - */ - if (req->req.status != -EOVERFLOW) - DEBUG_EP0("%s overflow %d\n", ep->ep.name, - count); - req->req.status = -EOVERFLOW; - } else { - *buf++ = byte; - bufferspace--; - } - } - - /* completion */ - if (is_short || req->req.actual == req->req.length) { - done(ep, req, 0); - return 1; - } - - /* finished that packet. the next one may be waiting... */ - return 0; -} - -/** - * udc_set_address - set the USB address for this device - * @address: - * - * Called from control endpoint function after it decodes a set address setup packet. - */ -static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address) -{ - DEBUG_EP0("%s: %d\n", __func__, address); - /* c.f. 15.1.2.2 Table 15-4 address will be used after DATA_END is set */ - dev->usb_address = address; - usb_set((address & USB_FA_FUNCTION_ADDR), USB_FA); - usb_set(USB_FA_ADDR_UPDATE | (address & USB_FA_FUNCTION_ADDR), USB_FA); - /* usb_read(USB_FA); */ -} - -/* - * DATA_STATE_RECV (OUT_PKT_RDY) - * - if error - * set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits - * - else - * set EP0_CLR_OUT bit - if last set EP0_DATA_END bit - */ -static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr) -{ - struct lh7a40x_request *req; - struct lh7a40x_ep *ep = &dev->ep[0]; - int ret; - - DEBUG_EP0("%s: %x\n", __func__, csr); - - if (list_empty(&ep->queue)) - req = 0; - else - req = list_entry(ep->queue.next, struct lh7a40x_request, queue); - - if (req) { - - if (req->req.length == 0) { - DEBUG_EP0("ZERO LENGTH OUT!\n"); - usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR); - dev->ep0state = WAIT_FOR_SETUP; - return; - } - ret = read_fifo_ep0(ep, req); - if (ret) { - /* Done! */ - DEBUG_EP0("%s: finished, waiting for status\n", - __func__); - - usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR); - dev->ep0state = WAIT_FOR_SETUP; - } else { - /* Not done yet.. */ - DEBUG_EP0("%s: not finished\n", __func__); - usb_set(EP0_CLR_OUT, USB_EP0_CSR); - } - } else { - DEBUG_EP0("NO REQ??!\n"); - } -} - -/* - * DATA_STATE_XMIT - */ -static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr) -{ - struct lh7a40x_request *req; - struct lh7a40x_ep *ep = &dev->ep[0]; - int ret, need_zlp = 0; - - DEBUG_EP0("%s: %x\n", __func__, csr); - - if (list_empty(&ep->queue)) - req = 0; - else - req = list_entry(ep->queue.next, struct lh7a40x_request, queue); - - if (!req) { - DEBUG_EP0("%s: NULL REQ\n", __func__); - return 0; - } - - if (req->req.length == 0) { - - usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR); - dev->ep0state = WAIT_FOR_SETUP; - return 1; - } - - if (req->req.length - req->req.actual == EP0_PACKETSIZE) { - /* Next write will end with the packet size, */ - /* so we need Zero-length-packet */ - need_zlp = 1; - } - - ret = write_fifo_ep0(ep, req); - - if (ret == 1 && !need_zlp) { - /* Last packet */ - DEBUG_EP0("%s: finished, waiting for status\n", __func__); - - usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR); - dev->ep0state = WAIT_FOR_SETUP; - } else { - DEBUG_EP0("%s: not finished\n", __func__); - usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR); - } - - if (need_zlp) { - DEBUG_EP0("%s: Need ZLP!\n", __func__); - usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR); - dev->ep0state = DATA_STATE_NEED_ZLP; - } - - return 1; -} - -static int lh7a40x_handle_get_status(struct lh7a40x_udc *dev, - struct usb_ctrlrequest *ctrl) -{ - struct lh7a40x_ep *ep0 = &dev->ep[0]; - struct lh7a40x_ep *qep; - int reqtype = (ctrl->bRequestType & USB_RECIP_MASK); - u16 val = 0; - - if (reqtype == USB_RECIP_INTERFACE) { - /* This is not supported. - * And according to the USB spec, this one does nothing.. - * Just return 0 - */ - DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n"); - } else if (reqtype == USB_RECIP_DEVICE) { - DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n"); - val |= (1 << 0); /* Self powered */ - /*val |= (1<<1); *//* Remote wakeup */ - } else if (reqtype == USB_RECIP_ENDPOINT) { - int ep_num = (ctrl->wIndex & ~USB_DIR_IN); - - DEBUG_SETUP - ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n", - ep_num, ctrl->wLength); - - if (ctrl->wLength > 2 || ep_num > 3) - return -EOPNOTSUPP; - - qep = &dev->ep[ep_num]; - if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0) - && ep_index(qep) != 0) { - return -EOPNOTSUPP; - } - - usb_set_index(ep_index(qep)); - - /* Return status on next IN token */ - switch (qep->ep_type) { - case ep_control: - val = - (usb_read(qep->csr1) & EP0_SEND_STALL) == - EP0_SEND_STALL; - break; - case ep_bulk_in: - case ep_interrupt: - val = - (usb_read(qep->csr1) & USB_IN_CSR1_SEND_STALL) == - USB_IN_CSR1_SEND_STALL; - break; - case ep_bulk_out: - val = - (usb_read(qep->csr1) & USB_OUT_CSR1_SEND_STALL) == - USB_OUT_CSR1_SEND_STALL; - break; - } - - /* Back to EP0 index */ - usb_set_index(0); - - DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num, - ctrl->wIndex, val); - } else { - DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype); - return -EOPNOTSUPP; - } - - /* Clear "out packet ready" */ - usb_set((EP0_CLR_OUT), USB_EP0_CSR); - /* Put status to FIFO */ - lh7a40x_fifo_write(ep0, (u8 *) & val, sizeof(val)); - /* Issue "In packet ready" */ - usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR); - - return 0; -} - -/* - * WAIT_FOR_SETUP (OUT_PKT_RDY) - * - read data packet from EP0 FIFO - * - decode command - * - if error - * set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits - * - else - * set EP0_CLR_OUT | EP0_DATA_END bits - */ -static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr) -{ - struct lh7a40x_ep *ep = &dev->ep[0]; - struct usb_ctrlrequest ctrl; - int i, bytes, is_in; - - DEBUG_SETUP("%s: %x\n", __func__, csr); - - /* Nuke all previous transfers */ - nuke(ep, -EPROTO); - - /* read control req from fifo (8 bytes) */ - bytes = lh7a40x_fifo_read(ep, (unsigned char *)&ctrl, 8); - - DEBUG_SETUP("Read CTRL REQ %d bytes\n", bytes); - DEBUG_SETUP("CTRL.bRequestType = %d (is_in %d)\n", ctrl.bRequestType, - ctrl.bRequestType == USB_DIR_IN); - DEBUG_SETUP("CTRL.bRequest = %d\n", ctrl.bRequest); - DEBUG_SETUP("CTRL.wLength = %d\n", ctrl.wLength); - DEBUG_SETUP("CTRL.wValue = %d (%d)\n", ctrl.wValue, ctrl.wValue >> 8); - DEBUG_SETUP("CTRL.wIndex = %d\n", ctrl.wIndex); - - /* Set direction of EP0 */ - if (likely(ctrl.bRequestType & USB_DIR_IN)) { - ep->bEndpointAddress |= USB_DIR_IN; - is_in = 1; - } else { - ep->bEndpointAddress &= ~USB_DIR_IN; - is_in = 0; - } - - dev->req_pending = 1; - - /* Handle some SETUP packets ourselves */ - switch (ctrl.bRequest) { - case USB_REQ_SET_ADDRESS: - if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) - break; - - DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue); - udc_set_address(dev, ctrl.wValue); - usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR); - return; - - case USB_REQ_GET_STATUS:{ - if (lh7a40x_handle_get_status(dev, &ctrl) == 0) - return; - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - if (ctrl.bRequestType == USB_RECIP_ENDPOINT) { - struct lh7a40x_ep *qep; - int ep_num = (ctrl.wIndex & 0x0f); - - /* Support only HALT feature */ - if (ctrl.wValue != 0 || ctrl.wLength != 0 - || ep_num > 3 || ep_num < 1) - break; - - qep = &dev->ep[ep_num]; - spin_unlock(&dev->lock); - if (ctrl.bRequest == USB_REQ_SET_FEATURE) { - DEBUG_SETUP("SET_FEATURE (%d)\n", - ep_num); - lh7a40x_set_halt(&qep->ep, 1); - } else { - DEBUG_SETUP("CLR_FEATURE (%d)\n", - ep_num); - lh7a40x_set_halt(&qep->ep, 0); - } - spin_lock(&dev->lock); - usb_set_index(0); - - /* Reply with a ZLP on next IN token */ - usb_set((EP0_CLR_OUT | EP0_DATA_END), - USB_EP0_CSR); - return; - } - break; - } - - default: - break; - } - - if (likely(dev->driver)) { - /* device-2-host (IN) or no data setup command, process immediately */ - spin_unlock(&dev->lock); - i = dev->driver->setup(&dev->gadget, &ctrl); - spin_lock(&dev->lock); - - if (i < 0) { - /* setup processing failed, force stall */ - DEBUG_SETUP - (" --> ERROR: gadget setup FAILED (stalling), setup returned %d\n", - i); - usb_set_index(0); - usb_set((EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL), - USB_EP0_CSR); - - /* ep->stopped = 1; */ - dev->ep0state = WAIT_FOR_SETUP; - } - } -} - -/* - * DATA_STATE_NEED_ZLP - */ -static void lh7a40x_ep0_in_zlp(struct lh7a40x_udc *dev, u32 csr) -{ - DEBUG_EP0("%s: %x\n", __func__, csr); - - /* c.f. Table 15-14 */ - usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR); - dev->ep0state = WAIT_FOR_SETUP; -} - -/* - * handle ep0 interrupt - */ -static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr) -{ - struct lh7a40x_ep *ep = &dev->ep[0]; - u32 csr; - - /* Set index 0 */ - usb_set_index(0); - csr = usb_read(USB_EP0_CSR); - - DEBUG_EP0("%s: csr = %x\n", __func__, csr); - - /* - * For overview of what we should be doing see c.f. Chapter 18.1.2.4 - * We will follow that outline here modified by our own global state - * indication which provides hints as to what we think should be - * happening.. - */ - - /* - * if SENT_STALL is set - * - clear the SENT_STALL bit - */ - if (csr & EP0_SENT_STALL) { - DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __func__, csr); - usb_clear((EP0_SENT_STALL | EP0_SEND_STALL), USB_EP0_CSR); - nuke(ep, -ECONNABORTED); - dev->ep0state = WAIT_FOR_SETUP; - return; - } - - /* - * if a transfer is in progress && IN_PKT_RDY and OUT_PKT_RDY are clear - * - fill EP0 FIFO - * - if last packet - * - set IN_PKT_RDY | DATA_END - * - else - * set IN_PKT_RDY - */ - if (!(csr & (EP0_IN_PKT_RDY | EP0_OUT_PKT_RDY))) { - DEBUG_EP0("%s: IN_PKT_RDY and OUT_PKT_RDY are clear\n", - __func__); - - switch (dev->ep0state) { - case DATA_STATE_XMIT: - DEBUG_EP0("continue with DATA_STATE_XMIT\n"); - lh7a40x_ep0_in(dev, csr); - return; - case DATA_STATE_NEED_ZLP: - DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n"); - lh7a40x_ep0_in_zlp(dev, csr); - return; - default: - /* Stall? */ - DEBUG_EP0("Odd state!! state = %s\n", - state_names[dev->ep0state]); - dev->ep0state = WAIT_FOR_SETUP; - /* nuke(ep, 0); */ - /* usb_set(EP0_SEND_STALL, ep->csr1); */ - break; - } - } - - /* - * if SETUP_END is set - * - abort the last transfer - * - set SERVICED_SETUP_END_BIT - */ - if (csr & EP0_SETUP_END) { - DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __func__, csr); - - usb_set(EP0_CLR_SETUP_END, USB_EP0_CSR); - - nuke(ep, 0); - dev->ep0state = WAIT_FOR_SETUP; - } - - /* - * if EP0_OUT_PKT_RDY is set - * - read data packet from EP0 FIFO - * - decode command - * - if error - * set SERVICED_OUT_PKT_RDY | DATA_END bits | SEND_STALL - * - else - * set SERVICED_OUT_PKT_RDY | DATA_END bits - */ - if (csr & EP0_OUT_PKT_RDY) { - - DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __func__, - csr); - - switch (dev->ep0state) { - case WAIT_FOR_SETUP: - DEBUG_EP0("WAIT_FOR_SETUP\n"); - lh7a40x_ep0_setup(dev, csr); - break; - - case DATA_STATE_RECV: - DEBUG_EP0("DATA_STATE_RECV\n"); - lh7a40x_ep0_out(dev, csr); - break; - - default: - /* send stall? */ - DEBUG_EP0("strange state!! 2. send stall? state = %d\n", - dev->ep0state); - break; - } - } -} - -static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep) -{ - u32 csr; - - usb_set_index(0); - csr = usb_read(USB_EP0_CSR); - - DEBUG_EP0("%s: %x\n", __func__, csr); - - /* Clear "out packet ready" */ - usb_set(EP0_CLR_OUT, USB_EP0_CSR); - - if (ep_is_in(ep)) { - dev->ep0state = DATA_STATE_XMIT; - lh7a40x_ep0_in(dev, csr); - } else { - dev->ep0state = DATA_STATE_RECV; - lh7a40x_ep0_out(dev, csr); - } -} - -/* --------------------------------------------------------------------------- - * device-scoped parts of the api to the usb controller hardware - * --------------------------------------------------------------------------- - */ - -static int lh7a40x_udc_get_frame(struct usb_gadget *_gadget) -{ - u32 frame1 = usb_read(USB_FRM_NUM1); /* Least significant 8 bits */ - u32 frame2 = usb_read(USB_FRM_NUM2); /* Most significant 3 bits */ - DEBUG("%s, %p\n", __func__, _gadget); - return ((frame2 & 0x07) << 8) | (frame1 & 0xff); -} - -static int lh7a40x_udc_wakeup(struct usb_gadget *_gadget) -{ - /* host may not have enabled remote wakeup */ - /*if ((UDCCS0 & UDCCS0_DRWF) == 0) - return -EHOSTUNREACH; - udc_set_mask_UDCCR(UDCCR_RSM); */ - return -ENOTSUPP; -} - -static const struct usb_gadget_ops lh7a40x_udc_ops = { - .get_frame = lh7a40x_udc_get_frame, - .wakeup = lh7a40x_udc_wakeup, - /* current versions must always be self-powered */ -}; - -static void nop_release(struct device *dev) -{ - DEBUG("%s %s\n", __func__, dev_name(dev)); -} - -static struct lh7a40x_udc memory = { - .usb_address = 0, - - .gadget = { - .ops = &lh7a40x_udc_ops, - .ep0 = &memory.ep[0].ep, - .name = driver_name, - .dev = { - .init_name = "gadget", - .release = nop_release, - }, - }, - - /* control endpoint */ - .ep[0] = { - .ep = { - .name = ep0name, - .ops = &lh7a40x_ep_ops, - .maxpacket = EP0_PACKETSIZE, - }, - .dev = &memory, - - .bEndpointAddress = 0, - .bmAttributes = 0, - - .ep_type = ep_control, - .fifo = io_p2v(USB_EP0_FIFO), - .csr1 = USB_EP0_CSR, - .csr2 = USB_EP0_CSR, - }, - - /* first group of endpoints */ - .ep[1] = { - .ep = { - .name = "ep1in-bulk", - .ops = &lh7a40x_ep_ops, - .maxpacket = 64, - }, - .dev = &memory, - - .bEndpointAddress = USB_DIR_IN | 1, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - - .ep_type = ep_bulk_in, - .fifo = io_p2v(USB_EP1_FIFO), - .csr1 = USB_IN_CSR1, - .csr2 = USB_IN_CSR2, - }, - - .ep[2] = { - .ep = { - .name = "ep2out-bulk", - .ops = &lh7a40x_ep_ops, - .maxpacket = 64, - }, - .dev = &memory, - - .bEndpointAddress = 2, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - - .ep_type = ep_bulk_out, - .fifo = io_p2v(USB_EP2_FIFO), - .csr1 = USB_OUT_CSR1, - .csr2 = USB_OUT_CSR2, - }, - - .ep[3] = { - .ep = { - .name = "ep3in-int", - .ops = &lh7a40x_ep_ops, - .maxpacket = 64, - }, - .dev = &memory, - - .bEndpointAddress = USB_DIR_IN | 3, - .bmAttributes = USB_ENDPOINT_XFER_INT, - - .ep_type = ep_interrupt, - .fifo = io_p2v(USB_EP3_FIFO), - .csr1 = USB_IN_CSR1, - .csr2 = USB_IN_CSR2, - }, -}; - -/* - * probe - binds to the platform device - */ -static int lh7a40x_udc_probe(struct platform_device *pdev) -{ - struct lh7a40x_udc *dev = &memory; - int retval; - - DEBUG("%s: %p\n", __func__, pdev); - - spin_lock_init(&dev->lock); - dev->dev = &pdev->dev; - - device_initialize(&dev->gadget.dev); - dev->gadget.dev.parent = &pdev->dev; - - the_controller = dev; - platform_set_drvdata(pdev, dev); - - udc_disable(dev); - udc_reinit(dev); - - /* irq setup after old hardware state is cleaned up */ - retval = - request_irq(IRQ_USBINTR, lh7a40x_udc_irq, IRQF_DISABLED, driver_name, - dev); - if (retval != 0) { - DEBUG(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name, - IRQ_USBINTR, retval); - return -EBUSY; - } - - create_proc_files(); - - return retval; -} - -static int lh7a40x_udc_remove(struct platform_device *pdev) -{ - struct lh7a40x_udc *dev = platform_get_drvdata(pdev); - - DEBUG("%s: %p\n", __func__, pdev); - - if (dev->driver) - return -EBUSY; - - udc_disable(dev); - remove_proc_files(); - - free_irq(IRQ_USBINTR, dev); - - platform_set_drvdata(pdev, 0); - - the_controller = 0; - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static struct platform_driver udc_driver = { - .probe = lh7a40x_udc_probe, - .remove = lh7a40x_udc_remove, - /* FIXME power management support */ - /* .suspend = ... disable UDC */ - /* .resume = ... re-enable UDC */ - .driver = { - .name = (char *)driver_name, - .owner = THIS_MODULE, - }, -}; - -static int __init udc_init(void) -{ - DEBUG("%s: %s version %s\n", __func__, driver_name, DRIVER_VERSION); - return platform_driver_register(&udc_driver); -} - -static void __exit udc_exit(void) -{ - platform_driver_unregister(&udc_driver); -} - -module_init(udc_init); -module_exit(udc_exit); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Mikko Lahteenmaki, Bo Henriksen"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:lh7a40x_udc"); diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h deleted file mode 100644 index ca861203a301..000000000000 --- a/drivers/usb/gadget/lh7a40x_udc.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * linux/drivers/usb/gadget/lh7a40x_udc.h - * Sharp LH7A40x on-chip full speed USB device controllers - * - * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID - * Copyright (C) 2004 Bo Henriksen, Nordic ID - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __LH7A40X_H_ -#define __LH7A40X_H_ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/timer.h> -#include <linux/list.h> -#include <linux/interrupt.h> -#include <linux/proc_fs.h> -#include <linux/mm.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> - -#include <asm/byteorder.h> -#include <asm/dma.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/system.h> -#include <asm/unaligned.h> -#include <mach/hardware.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> - -/* - * Memory map - */ - -#define USB_FA 0x80000200 // function address register -#define USB_PM 0x80000204 // power management register - -#define USB_IN_INT 0x80000208 // IN interrupt register bank (EP0-EP3) -#define USB_OUT_INT 0x80000210 // OUT interrupt register bank (EP2) -#define USB_INT 0x80000218 // interrupt register bank - -#define USB_IN_INT_EN 0x8000021C // IN interrupt enable register bank -#define USB_OUT_INT_EN 0x80000224 // OUT interrupt enable register bank -#define USB_INT_EN 0x8000022C // USB interrupt enable register bank - -#define USB_FRM_NUM1 0x80000230 // Frame number1 register -#define USB_FRM_NUM2 0x80000234 // Frame number2 register -#define USB_INDEX 0x80000238 // index register - -#define USB_IN_MAXP 0x80000240 // IN MAXP register -#define USB_IN_CSR1 0x80000244 // IN CSR1 register/EP0 CSR register -#define USB_EP0_CSR 0x80000244 // IN CSR1 register/EP0 CSR register -#define USB_IN_CSR2 0x80000248 // IN CSR2 register -#define USB_OUT_MAXP 0x8000024C // OUT MAXP register - -#define USB_OUT_CSR1 0x80000250 // OUT CSR1 register -#define USB_OUT_CSR2 0x80000254 // OUT CSR2 register -#define USB_OUT_FIFO_WC1 0x80000258 // OUT FIFO write count1 register -#define USB_OUT_FIFO_WC2 0x8000025C // OUT FIFO write count2 register - -#define USB_RESET 0x8000044C // USB reset register - -#define USB_EP0_FIFO 0x80000280 -#define USB_EP1_FIFO 0x80000284 -#define USB_EP2_FIFO 0x80000288 -#define USB_EP3_FIFO 0x8000028c - -/* - * USB reset register - */ -#define USB_RESET_APB (1<<1) //resets USB APB control side WRITE -#define USB_RESET_IO (1<<0) //resets USB IO side WRITE - -/* - * USB function address register - */ -#define USB_FA_ADDR_UPDATE (1<<7) -#define USB_FA_FUNCTION_ADDR (0x7F) - -/* - * Power Management register - */ -#define PM_USB_DCP (1<<5) -#define PM_USB_ENABLE (1<<4) -#define PM_USB_RESET (1<<3) -#define PM_UC_RESUME (1<<2) -#define PM_SUSPEND_MODE (1<<1) -#define PM_ENABLE_SUSPEND (1<<0) - -/* - * IN interrupt register - */ -#define USB_IN_INT_EP3 (1<<3) -#define USB_IN_INT_EP1 (1<<1) -#define USB_IN_INT_EP0 (1<<0) - -/* - * OUT interrupt register - */ -#define USB_OUT_INT_EP2 (1<<2) - -/* - * USB interrupt register - */ -#define USB_INT_RESET_INT (1<<2) -#define USB_INT_RESUME_INT (1<<1) -#define USB_INT_SUSPEND_INT (1<<0) - -/* - * USB interrupt enable register - */ -#define USB_INT_EN_USB_RESET_INTER (1<<2) -#define USB_INT_EN_RESUME_INTER (1<<1) -#define USB_INT_EN_SUSPEND_INTER (1<<0) - -/* - * INCSR1 register - */ -#define USB_IN_CSR1_CLR_DATA_TOGGLE (1<<6) -#define USB_IN_CSR1_SENT_STALL (1<<5) -#define USB_IN_CSR1_SEND_STALL (1<<4) -#define USB_IN_CSR1_FIFO_FLUSH (1<<3) -#define USB_IN_CSR1_FIFO_NOT_EMPTY (1<<1) -#define USB_IN_CSR1_IN_PKT_RDY (1<<0) - -/* - * INCSR2 register - */ -#define USB_IN_CSR2_AUTO_SET (1<<7) -#define USB_IN_CSR2_USB_DMA_EN (1<<4) - -/* - * OUT CSR1 register - */ -#define USB_OUT_CSR1_CLR_DATA_REG (1<<7) -#define USB_OUT_CSR1_SENT_STALL (1<<6) -#define USB_OUT_CSR1_SEND_STALL (1<<5) -#define USB_OUT_CSR1_FIFO_FLUSH (1<<4) -#define USB_OUT_CSR1_FIFO_FULL (1<<1) -#define USB_OUT_CSR1_OUT_PKT_RDY (1<<0) - -/* - * OUT CSR2 register - */ -#define USB_OUT_CSR2_AUTO_CLR (1<<7) -#define USB_OUT_CSR2_USB_DMA_EN (1<<4) - -/* - * EP0 CSR - */ -#define EP0_CLR_SETUP_END (1<<7) /* Clear "Setup Ends" Bit (w) */ -#define EP0_CLR_OUT (1<<6) /* Clear "Out packet ready" Bit (w) */ -#define EP0_SEND_STALL (1<<5) /* Send STALL Handshake (rw) */ -#define EP0_SETUP_END (1<<4) /* Setup Ends (r) */ - -#define EP0_DATA_END (1<<3) /* Data end (rw) */ -#define EP0_SENT_STALL (1<<2) /* Sent Stall Handshake (r) */ -#define EP0_IN_PKT_RDY (1<<1) /* In packet ready (rw) */ -#define EP0_OUT_PKT_RDY (1<<0) /* Out packet ready (r) */ - -/* general CSR */ -#define OUT_PKT_RDY (1<<0) -#define IN_PKT_RDY (1<<0) - -/* - * IN/OUT MAXP register - */ -#define USB_OUT_MAXP_MAXP (0xF) -#define USB_IN_MAXP_MAXP (0xF) - -// Max packet size -//#define EP0_PACKETSIZE 0x10 -#define EP0_PACKETSIZE 0x8 -#define EP0_MAXPACKETSIZE 0x10 - -#define UDC_MAX_ENDPOINTS 4 - -#define WAIT_FOR_SETUP 0 -#define DATA_STATE_XMIT 1 -#define DATA_STATE_NEED_ZLP 2 -#define WAIT_FOR_OUT_STATUS 3 -#define DATA_STATE_RECV 4 - -/* ********************************************************************************************* */ -/* IO - */ - -typedef enum ep_type { - ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt -} ep_type_t; - -struct lh7a40x_ep { - struct usb_ep ep; - struct lh7a40x_udc *dev; - - const struct usb_endpoint_descriptor *desc; - struct list_head queue; - unsigned long pio_irqs; - - u8 stopped; - u8 bEndpointAddress; - u8 bmAttributes; - - ep_type_t ep_type; - u32 fifo; - u32 csr1; - u32 csr2; -}; - -struct lh7a40x_request { - struct usb_request req; - struct list_head queue; -}; - -struct lh7a40x_udc { - struct usb_gadget gadget; - struct usb_gadget_driver *driver; - struct device *dev; - spinlock_t lock; - - int ep0state; - struct lh7a40x_ep ep[UDC_MAX_ENDPOINTS]; - - unsigned char usb_address; - - unsigned req_pending:1, req_std:1, req_config:1; -}; - -extern struct lh7a40x_udc *the_controller; - -#define ep_is_in(EP) (((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN) -#define ep_index(EP) ((EP)->bEndpointAddress&0xF) -#define ep_maxpacket(EP) ((EP)->ep.maxpacket) - -#endif diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 759a12ff8048..b426c1e8a679 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1023,11 +1023,6 @@ MODULE_LICENSE ("GPL"); #define OMAP3_PLATFORM_DRIVER ohci_hcd_omap3_driver #endif -#ifdef CONFIG_ARCH_LH7A404 -#include "ohci-lh7a404.c" -#define PLATFORM_DRIVER ohci_hcd_lh7a404_driver -#endif - #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #include "ohci-pxa27x.c" #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c deleted file mode 100644 index 18d39f0463ee..000000000000 --- a/drivers/usb/host/ohci-lh7a404.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> - * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> - * (C) Copyright 2002 Hewlett-Packard Company - * - * Bus Glue for Sharp LH7A404 - * - * Written by Christopher Hoover <ch@hpl.hp.com> - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ohci-sa1111.c - * by Durgesh Pattamatta <pattamattad@sharpsec.com> - * - * This file is licenced under the GPL. - */ - -#include <linux/platform_device.h> -#include <linux/signal.h> - -#include <mach/hardware.h> - - -extern int usb_disabled(void); - -/*-------------------------------------------------------------------------*/ - -static void lh7a404_start_hc(struct platform_device *dev) -{ - printk(KERN_DEBUG "%s: starting LH7A404 OHCI USB Controller\n", - __FILE__); - - /* - * Now, carefully enable the USB clock, and take - * the USB host controller out of reset. - */ - CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */ - udelay(1000); - USBH_CMDSTATUS = OHCI_HCR; - - printk(KERN_DEBUG "%s: Clock to USB host has been enabled \n", __FILE__); -} - -static void lh7a404_stop_hc(struct platform_device *dev) -{ - printk(KERN_DEBUG "%s: stopping LH7A404 OHCI USB Controller\n", - __FILE__); - - CSC_PWRCNT &= ~CSC_PWRCNT_USBH_EN; /* Disable clock */ -} - - -/*-------------------------------------------------------------------------*/ - -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - - -/** - * usb_hcd_lh7a404_probe - initialize LH7A404-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - * - */ -int usb_hcd_lh7a404_probe (const struct hc_driver *driver, - struct platform_device *dev) -{ - int retval; - struct usb_hcd *hcd; - - if (dev->resource[1].flags != IORESOURCE_IRQ) { - pr_debug("resource[1] is not IORESOURCE_IRQ"); - return -ENOMEM; - } - - hcd = usb_create_hcd(driver, &dev->dev, "lh7a404"); - if (!hcd) - return -ENOMEM; - hcd->rsrc_start = dev->resource[0].start; - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("ioremap failed"); - retval = -ENOMEM; - goto err2; - } - - lh7a404_start_hc(dev); - ohci_hcd_init(hcd_to_ohci(hcd)); - - retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); - if (retval == 0) - return retval; - - lh7a404_stop_hc(dev); - iounmap(hcd->regs); - err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - err1: - usb_put_hcd(hcd); - return retval; -} - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_hcd_lh7a404_remove - shutdown processing for LH7A404-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_lh7a404_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - */ -void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev) -{ - usb_remove_hcd(hcd); - lh7a404_stop_hc(dev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -} - -/*-------------------------------------------------------------------------*/ - -static int __devinit -ohci_lh7a404_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - ohci_dbg (ohci, "ohci_lh7a404_start, ohci:%p", ohci); - if ((ret = ohci_init(ohci)) < 0) - return ret; - - if ((ret = ohci_run (ohci)) < 0) { - err ("can't start %s", hcd->self.bus_name); - ohci_stop (hcd); - return ret; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ohci_lh7a404_hc_driver = { - .description = hcd_name, - .product_desc = "LH7A404 OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_lh7a404_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -/*-------------------------------------------------------------------------*/ - -static int ohci_hcd_lh7a404_drv_probe(struct platform_device *pdev) -{ - int ret; - - pr_debug ("In ohci_hcd_lh7a404_drv_probe"); - - if (usb_disabled()) - return -ENODEV; - - ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, pdev); - return ret; -} - -static int ohci_hcd_lh7a404_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_hcd_lh7a404_remove(hcd, pdev); - return 0; -} - /*TBD*/ -/*static int ohci_hcd_lh7a404_drv_suspend(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - return 0; -} -static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - - return 0; -} -*/ - -static struct platform_driver ohci_hcd_lh7a404_driver = { - .probe = ohci_hcd_lh7a404_drv_probe, - .remove = ohci_hcd_lh7a404_drv_remove, - .shutdown = usb_hcd_platform_shutdown, - /*.suspend = ohci_hcd_lh7a404_drv_suspend, */ - /*.resume = ohci_hcd_lh7a404_drv_resume, */ - .driver = { - .name = "lh7a404-ohci", - .owner = THIS_MODULE, - }, -}; - -MODULE_ALIAS("platform:lh7a404-ohci"); diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 51facb985c84..04812b42fe6f 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -575,18 +575,8 @@ static inline void _ohci_writel (const struct ohci_hcd *ohci, #endif } -#ifdef CONFIG_ARCH_LH7A404 -/* Marc Singer: at the time this code was written, the LH7A404 - * had a problem reading the USB host registers. This - * implementation of the ohci_readl function performs the read - * twice as a work-around. - */ -#define ohci_readl(o,r) (_ohci_readl(o,r),_ohci_readl(o,r)) -#define ohci_writel(o,v,r) _ohci_writel(o,v,r) -#else #define ohci_readl(o,r) _ohci_readl(o,r) #define ohci_writel(o,v,r) _ohci_writel(o,v,r) -#endif /*-------------------------------------------------------------------------*/ diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6bafb51bb437..b57bc273b184 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -322,69 +322,6 @@ config FB_ARMCLCD here and read <file:Documentation/kbuild/modules.txt>. The module will be called amba-clcd. -choice - - depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X) - prompt "LCD Panel" - default FB_ARMCLCD_SHARP_LQ035Q7DB02 - -config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT - bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC" - help - This is an implementation of the Sharp LQ035Q7DB02, a 3.5" - color QVGA, HRTFT panel. The LogicPD device includes - an integrated HRTFT controller IC. - The native resolution is 240x320. - -config FB_ARMCLCD_SHARP_LQ057Q3DC02 - bool "LogicPD LCD 5.7\" QVGA" - help - This is an implementation of the Sharp LQ057Q3DC02, a 5.7" - color QVGA, TFT panel. The LogicPD device includes an - The native resolution is 320x240. - -config FB_ARMCLCD_SHARP_LQ64D343 - bool "LogicPD LCD 6.4\" VGA" - help - This is an implementation of the Sharp LQ64D343, a 6.4" - color VGA, TFT panel. The LogicPD device includes an - The native resolution is 640x480. - -config FB_ARMCLCD_SHARP_LQ10D368 - bool "LogicPD LCD 10.4\" VGA" - help - This is an implementation of the Sharp LQ10D368, a 10.4" - color VGA, TFT panel. The LogicPD device includes an - The native resolution is 640x480. - - -config FB_ARMCLCD_SHARP_LQ121S1DG41 - bool "LogicPD LCD 12.1\" SVGA" - help - This is an implementation of the Sharp LQ121S1DG41, a 12.1" - color SVGA, TFT panel. The LogicPD device includes an - The native resolution is 800x600. - - This panel requires a clock rate may be an integer fraction - of the base LCDCLK frequency. The driver will select the - highest frequency available that is lower than the maximum - allowed. The panel may flicker if the clock rate is - slower than the recommended minimum. - -config FB_ARMCLCD_AUO_A070VW01_WIDE - bool "AU Optronics A070VW01 LCD 7.0\" WIDE" - help - This is an implementation of the AU Optronics, a 7.0" - WIDE Color. The native resolution is 234x480. - -config FB_ARMCLCD_HITACHI - bool "Hitachi Wide Screen 800x480" - help - This is an implementation of the Hitachi 800x480. - -endchoice - - config FB_ACORN bool "Acorn VIDC support" depends on (FB = y) && ARM && ARCH_ACORN |