diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-13 12:10:18 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-13 12:10:18 -0800 |
commit | ab4382d27412e7e3e7c936e8d50d8888dfac3df8 (patch) | |
tree | 51d96dea2431140358784b6b426715f37f74fd53 /drivers/tty | |
parent | 728674a7e466628df2aeec6d11a2ae1ef968fb67 (diff) |
tty: move drivers/serial/ to drivers/tty/serial/
The serial drivers are really just tty drivers, so move them to
drivers/tty/ to make things a bit neater overall.
This is part of the tty/serial driver movement proceedure as proposed by
Arnd Bergmann and approved by everyone involved a number of months ago.
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Rogier Wolff <R.E.Wolff@bitwizard.nl>
Cc: Michael H. Warfield <mhw@wittsend.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty')
120 files changed, 97163 insertions, 0 deletions
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index d3685f071b8..396277216e4 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_R3964) += n_r3964.o obj-y += vt/ obj-$(CONFIG_HVC_DRIVER) += hvc/ +obj-y += serial/ diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c new file mode 100644 index 00000000000..d89aa38c5cf --- /dev/null +++ b/drivers/tty/serial/21285.c @@ -0,0 +1,513 @@ +/* + * linux/drivers/serial/21285.c + * + * Driver for the serial port on the 21285 StrongArm-110 core logic chip. + * + * Based on drivers/char/serial.c + */ +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/console.h> +#include <linux/device.h> +#include <linux/tty_flip.h> +#include <linux/serial_core.h> +#include <linux/serial.h> +#include <linux/io.h> + +#include <asm/irq.h> +#include <asm/mach-types.h> +#include <asm/hardware/dec21285.h> +#include <mach/hardware.h> + +#define BAUD_BASE (mem_fclk_21285/64) + +#define SERIAL_21285_NAME "ttyFB" +#define SERIAL_21285_MAJOR 204 +#define SERIAL_21285_MINOR 4 + +#define RXSTAT_DUMMY_READ 0x80000000 +#define RXSTAT_FRAME (1 << 0) +#define RXSTAT_PARITY (1 << 1) +#define RXSTAT_OVERRUN (1 << 2) +#define RXSTAT_ANYERR (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN) + +#define H_UBRLCR_BREAK (1 << 0) +#define H_UBRLCR_PARENB (1 << 1) +#define H_UBRLCR_PAREVN (1 << 2) +#define H_UBRLCR_STOPB (1 << 3) +#define H_UBRLCR_FIFO (1 << 4) + +static const char serial21285_name[] = "Footbridge UART"; + +#define tx_enabled(port) ((port)->unused[0]) +#define rx_enabled(port) ((port)->unused[1]) + +/* + * The documented expression for selecting the divisor is: + * BAUD_BASE / baud - 1 + * However, typically BAUD_BASE is not divisible by baud, so + * we want to select the divisor that gives us the minimum + * error. Therefore, we want: + * int(BAUD_BASE / baud - 0.5) -> + * int(BAUD_BASE / baud - (baud >> 1) / baud) -> + * int((BAUD_BASE - (baud >> 1)) / baud) + */ + +static void serial21285_stop_tx(struct uart_port *port) +{ + if (tx_enabled(port)) { + disable_irq_nosync(IRQ_CONTX); + tx_enabled(port) = 0; + } +} + +static void serial21285_start_tx(struct uart_port *port) +{ + if (!tx_enabled(port)) { + enable_irq(IRQ_CONTX); + tx_enabled(port) = 1; + } +} + +static void serial21285_stop_rx(struct uart_port *port) +{ + if (rx_enabled(port)) { + disable_irq_nosync(IRQ_CONRX); + rx_enabled(port) = 0; + } +} + +static void serial21285_enable_ms(struct uart_port *port) +{ +} + +static irqreturn_t serial21285_rx_chars(int irq, void *dev_id) +{ + struct uart_port *port = dev_id; + struct tty_struct *tty = port->state->port.tty; + unsigned int status, ch, flag, rxs, max_count = 256; + + status = *CSR_UARTFLG; + while (!(status & 0x10) && max_count--) { + ch = *CSR_UARTDR; + flag = TTY_NORMAL; + port->icount.rx++; + + rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ; + if (unlikely(rxs & RXSTAT_ANYERR)) { + if (rxs & RXSTAT_PARITY) + port->icount.parity++; + else if (rxs & RXSTAT_FRAME) + port->icount.frame++; + if (rxs & RXSTAT_OVERRUN) + port->icount.overrun++; + + rxs &= port->read_status_mask; + + if (rxs & RXSTAT_PARITY) + flag = TTY_PARITY; + else if (rxs & RXSTAT_FRAME) + flag = TTY_FRAME; + } + + uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag); + + status = *CSR_UARTFLG; + } + tty_flip_buffer_push(tty); + + return IRQ_HANDLED; + |