From 3afbd89c9639c344300dcdd7d4e5e18dda559fd4 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 25 Jan 2012 09:05:04 +0100 Subject: serial/efm32: add new driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 13 + drivers/tty/serial/Makefile | 1 + drivers/tty/serial/efm32-uart.c | 830 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 844 insertions(+) create mode 100644 drivers/tty/serial/efm32-uart.c (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index aca2386c5ef1..6e24a8f5fd2a 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1628,4 +1628,17 @@ config SERIAL_AR933X_NR_UARTS Set this to the number of serial ports you want the driver to support. +config SERIAL_EFM32_UART + tristate "EFM32 UART/USART port." + depends on ARCH_EFM32 + select SERIAL_CORE + help + This driver support the USART and UART ports on + Energy Micro's efm32 SoCs. + +config SERIAL_EFM32_UART_CONSOLE + bool "EFM32 UART/USART console support" + depends on SERIAL_EFM32_UART=y + select SERIAL_CORE_CONSOLE + endmenu diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index f5b01f2ce525..1997ad4a39a6 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -92,3 +92,4 @@ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o +obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c new file mode 100644 index 000000000000..615e46470491 --- /dev/null +++ b/drivers/tty/serial/efm32-uart.c @@ -0,0 +1,830 @@ +#if defined(CONFIG_SERIAL_EFM32_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRIVER_NAME "efm32-uart" +#define DEV_NAME "ttyefm" + +#define UARTn_CTRL 0x00 +#define UARTn_CTRL_SYNC 0x0001 +#define UARTn_CTRL_TXBIL 0x1000 + +#define UARTn_FRAME 0x04 +#define UARTn_FRAME_DATABITS__MASK 0x000f +#define UARTn_FRAME_DATABITS(n) ((n) - 3) +#define UARTn_FRAME_PARITY_NONE 0x0000 +#define UARTn_FRAME_PARITY_EVEN 0x0200 +#define UARTn_FRAME_PARITY_ODD 0x0300 +#define UARTn_FRAME_STOPBITS_HALF 0x0000 +#define UARTn_FRAME_STOPBITS_ONE 0x1000 +#define UARTn_FRAME_STOPBITS_TWO 0x3000 + +#define UARTn_CMD 0x0c +#define UARTn_CMD_RXEN 0x0001 +#define UARTn_CMD_RXDIS 0x0002 +#define UARTn_CMD_TXEN 0x0004 +#define UARTn_CMD_TXDIS 0x0008 + +#define UARTn_STATUS 0x10 +#define UARTn_STATUS_TXENS 0x0002 +#define UARTn_STATUS_TXC 0x0020 +#define UARTn_STATUS_TXBL 0x0040 +#define UARTn_STATUS_RXDATAV 0x0080 + +#define UARTn_CLKDIV 0x14 + +#define UARTn_RXDATAX 0x18 +#define UARTn_RXDATAX_RXDATA__MASK 0x01ff +#define UARTn_RXDATAX_PERR 0x4000 +#define UARTn_RXDATAX_FERR 0x8000 +/* + * This is a software only flag used for ignore_status_mask and + * read_status_mask! It's used for breaks that the hardware doesn't report + * explicitly. + */ +#define SW_UARTn_RXDATAX_BERR 0x2000 + +#define UARTn_TXDATA 0x34 + +#define UARTn_IF 0x40 +#define UARTn_IF_TXC 0x0001 +#define UARTn_IF_TXBL 0x0002 +#define UARTn_IF_RXDATAV 0x0004 +#define UARTn_IF_RXOF 0x0010 + +#define UARTn_IFS 0x44 +#define UARTn_IFC 0x48 +#define UARTn_IEN 0x4c + +#define UARTn_ROUTE 0x54 +#define UARTn_ROUTE_LOCATION__MASK 0x0700 +#define UARTn_ROUTE_LOCATION(n) (((n) << 8) & UARTn_ROUTE_LOCATION__MASK) +#define UARTn_ROUTE_RXPEN 0x0001 +#define UARTn_ROUTE_TXPEN 0x0002 + +struct efm32_uart_port { + struct uart_port port; + unsigned int txirq; + struct clk *clk; +}; +#define to_efm_port(_port) container_of(_port, struct efm32_uart_port, port) +#define efm_debug(efm_port, format, arg...) \ + dev_dbg(efm_port->port.dev, format, ##arg) + +static void efm32_uart_write32(struct efm32_uart_port *efm_port, + u32 value, unsigned offset) +{ + writel_relaxed(value, efm_port->port.membase + offset); +} + +static u32 efm32_uart_read32(struct efm32_uart_port *efm_port, + unsigned offset) +{ + return readl_relaxed(efm_port->port.membase + offset); +} + +static unsigned int efm32_uart_tx_empty(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); + + if (status & UARTn_STATUS_TXC) + return TIOCSER_TEMT; + else + return 0; +} + +static void efm32_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* sorry, neither handshaking lines nor loop functionallity */ +} + +static unsigned int efm32_uart_get_mctrl(struct uart_port *port) +{ + /* sorry, no handshaking lines available */ + return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR; +} + +static void efm32_uart_stop_tx(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 ien = efm32_uart_read32(efm_port, UARTn_IEN); + + efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); + ien &= ~(UARTn_IF_TXC | UARTn_IF_TXBL); + efm32_uart_write32(efm_port, ien, UARTn_IEN); +} + +static void efm32_uart_tx_chars(struct efm32_uart_port *efm_port) +{ + struct uart_port *port = &efm_port->port; + struct circ_buf *xmit = &port->state->xmit; + + while (efm32_uart_read32(efm_port, UARTn_STATUS) & + UARTn_STATUS_TXBL) { + if (port->x_char) { + port->icount.tx++; + efm32_uart_write32(efm_port, port->x_char, + UARTn_TXDATA); + port->x_char = 0; + continue; + } + if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { + port->icount.tx++; + efm32_uart_write32(efm_port, xmit->buf[xmit->tail], + UARTn_TXDATA); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } else + break; + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (!port->x_char && uart_circ_empty(xmit) && + efm32_uart_read32(efm_port, UARTn_STATUS) & + UARTn_STATUS_TXC) + efm32_uart_stop_tx(port); +} + +static void efm32_uart_start_tx(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 ien; + + efm32_uart_write32(efm_port, + UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IFC); + ien = efm32_uart_read32(efm_port, UARTn_IEN); + efm32_uart_write32(efm_port, + ien | UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IEN); + efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); + + efm32_uart_tx_chars(efm_port); +} + +static void efm32_uart_stop_rx(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + + efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD); +} + +static void efm32_uart_enable_ms(struct uart_port *port) +{ + /* no handshake lines, no modem status interrupts */ +} + +static void efm32_uart_break_ctl(struct uart_port *port, int ctl) +{ + /* not possible without fiddling with gpios */ +} + +static void efm32_uart_rx_chars(struct efm32_uart_port *efm_port, + struct tty_struct *tty) +{ + struct uart_port *port = &efm_port->port; + + while (efm32_uart_read32(efm_port, UARTn_STATUS) & + UARTn_STATUS_RXDATAV) { + u32 rxdata = efm32_uart_read32(efm_port, UARTn_RXDATAX); + int flag = 0; + + /* + * This is a reserved bit and I only saw it read as 0. But to be + * sure not to be confused too much by new devices adhere to the + * warning in the reference manual that reserverd bits might + * read as 1 in the future. + */ + rxdata &= ~SW_UARTn_RXDATAX_BERR; + + port->icount.rx++; + + if ((rxdata & UARTn_RXDATAX_FERR) && + !(rxdata & UARTn_RXDATAX_RXDATA__MASK)) { + rxdata |= SW_UARTn_RXDATAX_BERR; + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } else if (rxdata & UARTn_RXDATAX_PERR) + port->icount.parity++; + else if (rxdata & UARTn_RXDATAX_FERR) + port->icount.frame++; + + rxdata &= port->read_status_mask; + + if (rxdata & SW_UARTn_RXDATAX_BERR) + flag = TTY_BREAK; + else if (rxdata & UARTn_RXDATAX_PERR) + flag = TTY_PARITY; + else if (rxdata & UARTn_RXDATAX_FERR) + flag = TTY_FRAME; + else if (uart_handle_sysrq_char(port, + rxdata & UARTn_RXDATAX_RXDATA__MASK)) + continue; + + if (tty && (rxdata & port->ignore_status_mask) == 0) + tty_insert_flip_char(tty, + rxdata & UARTn_RXDATAX_RXDATA__MASK, flag); + } +} + +static irqreturn_t efm32_uart_rxirq(int irq, void *data) +{ + struct efm32_uart_port *efm_port = data; + u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); + int handled = IRQ_NONE; + struct uart_port *port = &efm_port->port; + struct tty_struct *tty; + + spin_lock(&port->lock); + + tty = tty_kref_get(port->state->port.tty); + + if (irqflag & UARTn_IF_RXDATAV) { + efm32_uart_write32(efm_port, UARTn_IF_RXDATAV, UARTn_IFC); + efm32_uart_rx_chars(efm_port, tty); + + handled = IRQ_HANDLED; + } + + if (irqflag & UARTn_IF_RXOF) { + efm32_uart_write32(efm_port, UARTn_IF_RXOF, UARTn_IFC); + port->icount.overrun++; + if (tty) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + handled = IRQ_HANDLED; + } + + if (tty) { + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } + + spin_unlock(&port->lock); + + return handled; +} + +static irqreturn_t efm32_uart_txirq(int irq, void *data) +{ + struct efm32_uart_port *efm_port = data; + u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); + + /* TXBL doesn't need to be cleared */ + if (irqflag & UARTn_IF_TXC) + efm32_uart_write32(efm_port, UARTn_IF_TXC, UARTn_IFC); + + if (irqflag & (UARTn_IF_TXC | UARTn_IF_TXBL)) { + efm32_uart_tx_chars(efm_port); + return IRQ_HANDLED; + } else + return IRQ_NONE; +} + +static int efm32_uart_startup(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + u32 location = 0; + struct efm32_uart_pdata *pdata = dev_get_platdata(port->dev); + int ret; + + if (pdata) + location = UARTn_ROUTE_LOCATION(pdata->location); + + ret = clk_enable(efm_port->clk); + if (ret) { + efm_debug(efm_port, "failed to enable clk\n"); + goto err_clk_enable; + } + port->uartclk = clk_get_rate(efm_port->clk); + + /* Enable pins at configured location */ + efm32_uart_write32(efm_port, location | UARTn_ROUTE_RXPEN | UARTn_ROUTE_TXPEN, + UARTn_ROUTE); + + ret = request_irq(port->irq, efm32_uart_rxirq, 0, + DRIVER_NAME, efm_port); + if (ret) { + efm_debug(efm_port, "failed to register rxirq\n"); + goto err_request_irq_rx; + } + + /* disable all irqs */ + efm32_uart_write32(efm_port, 0, UARTn_IEN); + + ret = request_irq(efm_port->txirq, efm32_uart_txirq, 0, + DRIVER_NAME, efm_port); + if (ret) { + efm_debug(efm_port, "failed to register txirq\n"); + free_irq(port->irq, efm_port); +err_request_irq_rx: + + clk_disable(efm_port->clk); + } else { + efm32_uart_write32(efm_port, + UARTn_IF_RXDATAV | UARTn_IF_RXOF, UARTn_IEN); + efm32_uart_write32(efm_port, UARTn_CMD_RXEN, UARTn_CMD); + } + +err_clk_enable: + return ret; +} + +static void efm32_uart_shutdown(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + + efm32_uart_write32(efm_port, 0, UARTn_IEN); + free_irq(port->irq, efm_port); + + clk_disable(efm_port->clk); +} + +static void efm32_uart_set_termios(struct uart_port *port, + struct ktermios *new, struct ktermios *old) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + unsigned long flags; + unsigned baud; + u32 clkdiv; + u32 frame = 0; + + /* no modem control lines */ + new->c_cflag &= ~(CRTSCTS | CMSPAR); + + baud = uart_get_baud_rate(port, new, old, + DIV_ROUND_CLOSEST(port->uartclk, 16 * 8192), + DIV_ROUND_CLOSEST(port->uartclk, 16)); + + switch (new->c_cflag & CSIZE) { + case CS5: + frame |= UARTn_FRAME_DATABITS(5); + break; + case CS6: + frame |= UARTn_FRAME_DATABITS(6); + break; + case CS7: + frame |= UARTn_FRAME_DATABITS(7); + break; + case CS8: + frame |= UARTn_FRAME_DATABITS(8); + break; + } + + if (new->c_cflag & CSTOPB) + /* the receiver only verifies the first stop bit */ + frame |= UARTn_FRAME_STOPBITS_TWO; + else + frame |= UARTn_FRAME_STOPBITS_ONE; + + if (new->c_cflag & PARENB) { + if (new->c_cflag & PARODD) + frame |= UARTn_FRAME_PARITY_ODD; + else + frame |= UARTn_FRAME_PARITY_EVEN; + } else + frame |= UARTn_FRAME_PARITY_NONE; + + /* + * the 6 lowest bits of CLKDIV are dc, bit 6 has value 0.25. + * port->uartclk <= 14e6, so 4 * port->uartclk doesn't overflow. + */ + clkdiv = (DIV_ROUND_CLOSEST(4 * port->uartclk, 16 * baud) - 4) << 6; + + spin_lock_irqsave(&port->lock, flags); + + efm32_uart_write32(efm_port, + UARTn_CMD_TXDIS | UARTn_CMD_RXDIS, UARTn_CMD); + + port->read_status_mask = UARTn_RXDATAX_RXDATA__MASK; + if (new->c_iflag & INPCK) + port->read_status_mask |= + UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; + if (new->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= SW_UARTn_RXDATAX_BERR; + + port->ignore_status_mask = 0; + if (new->c_iflag & IGNPAR) + port->ignore_status_mask |= + UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; + if (new->c_iflag & IGNBRK) + port->ignore_status_mask |= SW_UARTn_RXDATAX_BERR; + + uart_update_timeout(port, new->c_cflag, baud); + + efm32_uart_write32(efm_port, UARTn_CTRL_TXBIL, UARTn_CTRL); + efm32_uart_write32(efm_port, frame, UARTn_FRAME); + efm32_uart_write32(efm_port, clkdiv, UARTn_CLKDIV); + + efm32_uart_write32(efm_port, UARTn_CMD_TXEN | UARTn_CMD_RXEN, + UARTn_CMD); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *efm32_uart_type(struct uart_port *port) +{ + return port->type == PORT_EFMUART ? "efm32-uart" : NULL; +} + +static void efm32_uart_release_port(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + + clk_unprepare(efm_port->clk); + clk_put(efm_port->clk); + iounmap(port->membase); +} + +static int efm32_uart_request_port(struct uart_port *port) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + int ret; + + port->membase = ioremap(port->mapbase, 60); + if (!efm_port->port.membase) { + ret = -ENOMEM; + efm_debug(efm_port, "failed to remap\n"); + goto err_ioremap; + } + + efm_port->clk = clk_get(port->dev, NULL); + if (IS_ERR(efm_port->clk)) { + ret = PTR_ERR(efm_port->clk); + efm_debug(efm_port, "failed to get clock\n"); + goto err_clk_get; + } + + ret = clk_prepare(efm_port->clk); + if (ret) { + clk_put(efm_port->clk); +err_clk_get: + + iounmap(port->membase); +err_ioremap: + return ret; + } + return 0; +} + +static void efm32_uart_config_port(struct uart_port *port, int type) +{ + if (type & UART_CONFIG_TYPE && + !efm32_uart_request_port(port)) + port->type = PORT_EFMUART; +} + +static int efm32_uart_verify_port(struct uart_port *port, + struct serial_struct *serinfo) +{ + int ret = 0; + + if (serinfo->type != PORT_UNKNOWN && serinfo->type != PORT_EFMUART) + ret = -EINVAL; + + return ret; +} + +static struct uart_ops efm32_uart_pops = { + .tx_empty = efm32_uart_tx_empty, + .set_mctrl = efm32_uart_set_mctrl, + .get_mctrl = efm32_uart_get_mctrl, + .stop_tx = efm32_uart_stop_tx, + .start_tx = efm32_uart_start_tx, + .stop_rx = efm32_uart_stop_rx, + .enable_ms = efm32_uart_enable_ms, + .break_ctl = efm32_uart_break_ctl, + .startup = efm32_uart_startup, + .shutdown = efm32_uart_shutdown, + .set_termios = efm32_uart_set_termios, + .type = efm32_uart_type, + .release_port = efm32_uart_release_port, + .request_port = efm32_uart_request_port, + .config_port = efm32_uart_config_port, + .verify_port = efm32_uart_verify_port, +}; + +static struct efm32_uart_port *efm32_uart_ports[5]; + +#ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE +static void efm32_uart_console_putchar(struct uart_port *port, int ch) +{ + struct efm32_uart_port *efm_port = to_efm_port(port); + unsigned int timeout = 0x400; + u32 status; + + while (1) { + status = efm32_uart_read32(efm_port, UARTn_STATUS); + + if (status & UARTn_STATUS_TXBL) + break; + if (!timeout--) + return; + } + efm32_uart_write32(efm_port, ch, UARTn_TXDATA); +} + +static void efm32_uart_console_write(struct console *co, const char *s, + unsigned int count) +{ + struct efm32_uart_port *efm_port = efm32_uart_ports[co->index]; + u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); + unsigned int timeout = 0x400; + + if (!(status & UARTn_STATUS_TXENS)) + efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); + + uart_console_write(&efm_port->port, s, count, + efm32_uart_console_putchar); + + /* Wait for the transmitter to become empty */ + while (1) { + u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); + if (status & UARTn_STATUS_TXC) + break; + if (!timeout--) + break; + } + + if (!(status & UARTn_STATUS_TXENS)) + efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); +} + +static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, + int *baud, int *parity, int *bits) +{ + u32 ctrl = efm32_uart_read32(efm_port, UARTn_CTRL); + u32 route, clkdiv, frame; + + if (ctrl & UARTn_CTRL_SYNC) + /* not operating in async mode */ + return; + + route = efm32_uart_read32(efm_port, UARTn_ROUTE); + if (!(route & UARTn_ROUTE_TXPEN)) + /* tx pin not routed */ + return; + + clkdiv = efm32_uart_read32(efm_port, UARTn_CLKDIV); + + *baud = DIV_ROUND_CLOSEST(4 * efm_port->port.uartclk, + 16 * (4 + (clkdiv >> 6))); + + frame = efm32_uart_read32(efm_port, UARTn_FRAME); + if (frame & UARTn_FRAME_PARITY_ODD) + *parity = 'o'; + else if (frame & UARTn_FRAME_PARITY_EVEN) + *parity = 'e'; + else + *parity = 'n'; + + *bits = (frame & UARTn_FRAME_DATABITS__MASK) - + UARTn_FRAME_DATABITS(4) + 4; + + efm_debug(efm_port, "get_opts: options=%d%c%d\n", + *baud, *parity, *bits); +} + +static int efm32_uart_console_setup(struct console *co, char *options) +{ + struct efm32_uart_port *efm_port; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + int ret; + + if (co->index < 0 || co->index >= ARRAY_SIZE(efm32_uart_ports)) { + unsigned i; + for (i = 0; i < ARRAY_SIZE(efm32_uart_ports); ++i) { + if (efm32_uart_ports[i]) { + pr_warn("efm32-console: fall back to console index %u (from %hhi)\n", + i, co->index); + co->index = i; + break; + } + } + } + + efm_port = efm32_uart_ports[co->index]; + if (!efm_port) { + pr_warn("efm32-console: No port at %d\n", co->index); + return -ENODEV; + } + + ret = clk_prepare(efm_port->clk); + if (ret) { + dev_warn(efm_port->port.dev, + "console: clk_prepare failed: %d\n", ret); + return ret; + } + + efm_port->port.uartclk = clk_get_rate(efm_port->clk); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + efm32_uart_console_get_options(efm_port, + &baud, &parity, &bits); + + return uart_set_options(&efm_port->port, co, baud, parity, bits, flow); +} + +static struct uart_driver efm32_uart_reg; + +static struct console efm32_uart_console = { + .name = DEV_NAME, + .write = efm32_uart_console_write, + .device = uart_console_device, + .setup = efm32_uart_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &efm32_uart_reg, +}; + +#else +#define efm32_uart_console (*(struct console *)NULL) +#endif /* ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE / else */ + +static struct uart_driver efm32_uart_reg = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = DEV_NAME, + .nr = ARRAY_SIZE(efm32_uart_ports), + .cons = &efm32_uart_console, +}; + +static int efm32_uart_probe_dt(struct platform_device *pdev, + struct efm32_uart_port *efm_port) +{ + struct device_node *np = pdev->dev.of_node; + int ret; + + if (!np) + return 1; + + ret = of_alias_get_id(np, "serial"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get alias id: %d\n", ret); + return ret; + } else { + efm_port->port.line = ret; + return 0; + } + +} + +static int __devinit efm32_uart_probe(struct platform_device *pdev) +{ + struct efm32_uart_port *efm_port; + struct resource *res; + int ret; + + efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL); + if (!efm_port) { + dev_dbg(&pdev->dev, "failed to allocate private data\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + dev_dbg(&pdev->dev, "failed to determine base address\n"); + goto err_get_base; + } + + if (resource_size(res) < 60) { + ret = -EINVAL; + dev_dbg(&pdev->dev, "memory resource too small\n"); + goto err_too_small; + } + + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_dbg(&pdev->dev, "failed to get rx irq\n"); + goto err_get_rxirq; + } + + efm_port->port.irq = ret; + + ret = platform_get_irq(pdev, 1); + if (ret <= 0) + ret = efm_port->port.irq + 1; + + efm_port->txirq = ret; + + efm_port->port.dev = &pdev->dev; + efm_port->port.mapbase = res->start; + efm_port->port.type = PORT_EFMUART; + efm_port->port.iotype = UPIO_MEM32; + efm_port->port.fifosize = 2; + efm_port->port.ops = &efm32_uart_pops; + efm_port->port.flags = UPF_BOOT_AUTOCONF; + + ret = efm32_uart_probe_dt(pdev, efm_port); + if (ret > 0) + /* not created by device tree */ + efm_port->port.line = pdev->id; + + if (efm_port->port.line >= 0 && + efm_port->port.line < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[efm_port->port.line] = efm_port; + + ret = uart_add_one_port(&efm32_uart_reg, &efm_port->port); + if (ret) { + dev_dbg(&pdev->dev, "failed to add port: %d\n", ret); + + if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[pdev->id] = NULL; +err_get_rxirq: +err_too_small: +err_get_base: + kfree(efm_port); + } else { + platform_set_drvdata(pdev, efm_port); + dev_dbg(&pdev->dev, "\\o/\n"); + } + + return ret; +} + +static int __devexit efm32_uart_remove(struct platform_device *pdev) +{ + struct efm32_uart_port *efm_port = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + uart_remove_one_port(&efm32_uart_reg, &efm_port->port); + + if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[pdev->id] = NULL; + + kfree(efm_port); + + return 0; +} + +static struct of_device_id efm32_uart_dt_ids[] = { + { + .compatible = "efm32,uart", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids); + +static struct platform_driver efm32_uart_driver = { + .probe = efm32_uart_probe, + .remove = __devexit_p(efm32_uart_remove), + + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = efm32_uart_dt_ids, + }, +}; + +static int __init efm32_uart_init(void) +{ + int ret; + + ret = uart_register_driver(&efm32_uart_reg); + if (ret) + return ret; + + ret = platform_driver_register(&efm32_uart_driver); + if (ret) + uart_unregister_driver(&efm32_uart_reg); + + pr_info("EFM32 UART/USART driver\n"); + + return ret; +} +module_init(efm32_uart_init); + +static void __exit efm32_uart_exit(void) +{ + platform_driver_unregister(&efm32_uart_driver); + uart_unregister_driver(&efm32_uart_reg); +} + +MODULE_AUTHOR("Uwe Kleine-Koenig "); +MODULE_DESCRIPTION("EFM32 UART/USART driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit v1.2.3 From d4e33fac2408d37f7b52e80ca2a89f9fb482914f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 26 Jan 2012 17:44:09 +0000 Subject: serial: Kill off NO_IRQ We transform the offenders into a test of irq <= 0 which will be ok while the ARM people get their platform sorted. Once that is done (or in a while if they don't do it anyway) then we will change them all to !irq checks. For arch specific drivers that are already using NO_IRQ = 0 we just test against zero so we don't need to re-review them later. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_beat.c | 2 +- drivers/tty/hvc/hvc_rtas.c | 2 +- drivers/tty/hvc/hvc_udbg.c | 2 +- drivers/tty/hvc/hvc_xen.c | 2 +- drivers/tty/hvc/hvcs.c | 4 ++-- drivers/tty/hvc/hvsi.c | 2 +- drivers/tty/serial/21285.c | 4 ++-- drivers/tty/serial/8250.c | 21 +++++++-------------- drivers/tty/serial/m32r_sio.c | 11 ++--------- drivers/tty/serial/mpc52xx_uart.c | 4 ++-- drivers/tty/serial/mux.c | 2 +- drivers/tty/serial/pmac_zilog.c | 2 +- drivers/tty/serial/sunzilog.c | 10 +++++----- drivers/tty/serial/ucc_uart.c | 2 +- drivers/tty/serial/vr41xx_siu.c | 4 ++-- 15 files changed, 30 insertions(+), 44 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/hvc/hvc_beat.c b/drivers/tty/hvc/hvc_beat.c index 5fe4631e2a61..1560d235449e 100644 --- a/drivers/tty/hvc/hvc_beat.c +++ b/drivers/tty/hvc/hvc_beat.c @@ -113,7 +113,7 @@ static int __init hvc_beat_init(void) if (!firmware_has_feature(FW_FEATURE_BEAT)) return -ENODEV; - hp = hvc_alloc(0, NO_IRQ, &hvc_beat_get_put_ops, 16); + hp = hvc_alloc(0, 0, &hvc_beat_get_put_ops, 16); if (IS_ERR(hp)) return PTR_ERR(hp); hvc_beat_dev = hp; diff --git a/drivers/tty/hvc/hvc_rtas.c b/drivers/tty/hvc/hvc_rtas.c index 61c4a61558d9..0069bb86ba49 100644 --- a/drivers/tty/hvc/hvc_rtas.c +++ b/drivers/tty/hvc/hvc_rtas.c @@ -94,7 +94,7 @@ static int __init hvc_rtas_init(void) /* Allocate an hvc_struct for the console device we instantiated * earlier. Save off hp so that we can return it on exit */ - hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops, 16); + hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16); if (IS_ERR(hp)) return PTR_ERR(hp); diff --git a/drivers/tty/hvc/hvc_udbg.c b/drivers/tty/hvc/hvc_udbg.c index b0957e61a7be..4c9b13e7748c 100644 --- a/drivers/tty/hvc/hvc_udbg.c +++ b/drivers/tty/hvc/hvc_udbg.c @@ -69,7 +69,7 @@ static int __init hvc_udbg_init(void) BUG_ON(hvc_udbg_dev); - hp = hvc_alloc(0, NO_IRQ, &hvc_udbg_ops, 16); + hp = hvc_alloc(0, 0, &hvc_udbg_ops, 16); if (IS_ERR(hp)) return PTR_ERR(hp); diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 52fdf60bdbe2..a1b0a75c3eae 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -176,7 +176,7 @@ static int __init xen_hvc_init(void) xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn); } if (xencons_irq < 0) - xencons_irq = 0; /* NO_IRQ */ + xencons_irq = 0; else irq_set_noprobe(xencons_irq); diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index b9040bec36bd..df7e7a0a5e6c 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1203,7 +1203,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) { struct hvcs_struct *hvcsd; unsigned long flags; - int irq = NO_IRQ; + int irq; /* * Is someone trying to close the file associated with this device after @@ -1264,7 +1264,7 @@ static void hvcs_hangup(struct tty_struct * tty) struct hvcs_struct *hvcsd = tty->driver_data; unsigned long flags; int temp_open_count; - int irq = NO_IRQ; + int irq; spin_lock_irqsave(&hvcsd->lock, flags); /* Preserve this so that we know how many kref refs to put */ diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index cdfa3e02d627..1b5f28bd7930 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -1237,7 +1237,7 @@ static int __init hvsi_console_init(void) hp->state = HVSI_CLOSED; hp->vtermno = *vtermno; hp->virq = irq_create_mapping(NULL, irq[0]); - if (hp->virq == NO_IRQ) { + if (hp->virq == 0) { printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n", __func__, irq[0]); continue; diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c index 1b37626e8f13..f899996b4363 100644 --- a/drivers/tty/serial/21285.c +++ b/drivers/tty/serial/21285.c @@ -331,7 +331,7 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285) ret = -EINVAL; - if (ser->irq != NO_IRQ) + if (ser->irq <= 0) ret = -EINVAL; if (ser->baud_base != port->uartclk / 16) ret = -EINVAL; @@ -360,7 +360,7 @@ static struct uart_ops serial21285_ops = { static struct uart_port serial21285_port = { .mapbase = 0x42000160, .iotype = UPIO_MEM, - .irq = NO_IRQ, + .irq = 0, .fifosize = 16, .ops = &serial21285_ops, .flags = UPF_BOOT_AUTOCONF, diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 9f50c4e3c2be..b0eb96139324 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -86,13 +86,6 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */ #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -/* - * We default to IRQ0 for the "no irq" hack. Some - * machine types want others as well - they're free - * to redefine this in their header file. - */ -#define is_real_interrupt(irq) ((irq) != 0) - #ifdef CONFIG_SERIAL_8250_DETECT_IRQ #define CONFIG_SERIAL_DETECT_IRQ 1 #endif @@ -1750,7 +1743,7 @@ static void serial8250_backup_timeout(unsigned long data) * Must disable interrupts or else we risk racing with the interrupt * based handler. */ - if (is_real_interrupt(up->port.irq)) { + if (up->port.irq) { ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); } @@ -1775,7 +1768,7 @@ static void serial8250_backup_timeout(unsigned long data) if (!(iir & UART_IIR_NO_INT)) serial8250_tx_chars(up); - if (is_real_interrupt(up->port.irq)) + if (up->port.irq) serial_out(up, UART_IER, ier); spin_unlock_irqrestore(&up->port.lock, flags); @@ -2028,7 +2021,7 @@ static int serial8250_startup(struct uart_port *port) serial_outp(up, UART_LCR, 0); } - if (is_real_interrupt(up->port.irq)) { + if (up->port.irq) { unsigned char iir1; /* * Test for UARTs that do not reassert THRE when the @@ -2083,7 +2076,7 @@ static int serial8250_startup(struct uart_port *port) * hardware interrupt, we use a timer-based system. The original * driver used to do this with IRQ0. */ - if (!is_real_interrupt(up->port.irq)) { + if (!up->port.irq) { up->timer.data = (unsigned long)up; mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); } else { @@ -2099,13 +2092,13 @@ static int serial8250_startup(struct uart_port *port) spin_lock_irqsave(&up->port.lock, flags); if (up->port.flags & UPF_FOURPORT) { - if (!is_real_interrupt(up->port.irq)) + if (!up->port.irq) up->port.mctrl |= TIOCM_OUT1; } else /* * Most PC uarts need OUT2 raised to enable interrupts. */ - if (is_real_interrupt(up->port.irq)) + if (up->port.irq) up->port.mctrl |= TIOCM_OUT2; serial8250_set_mctrl(&up->port, up->port.mctrl); @@ -2223,7 +2216,7 @@ static void serial8250_shutdown(struct uart_port *port) del_timer_sync(&up->timer); up->timer.function = serial8250_timeout; - if (is_real_interrupt(up->port.irq)) + if (up->port.irq) serial_unlink_irq_chain(up); } diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 94a6792bf97b..e465dda63edf 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -70,13 +70,6 @@ #define PASS_LIMIT 256 -/* - * We default to IRQ0 for the "no irq" hack. Some - * machine types want others as well - they're free - * to redefine this in their header file. - */ -#define is_real_interrupt(irq) ((irq) != 0) - #define BASE_BAUD 115200 /* Standard COM flags */ @@ -640,7 +633,7 @@ static int m32r_sio_startup(struct uart_port *port) * hardware interrupt, we use a timer-based system. The original * driver used to do this with IRQ0. */ - if (!is_real_interrupt(up->port.irq)) { + if (!up->port.irq) { unsigned int timeout = up->port.timeout; timeout = timeout > 6 ? (timeout / 2 - 2) : 1; @@ -687,7 +680,7 @@ static void m32r_sio_shutdown(struct uart_port *port) sio_init(); - if (!is_real_interrupt(up->port.irq)) + if (!up->port.irq) del_timer_sync(&up->timer); else serial_unlink_irq_chain(up); diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 1093a88a1fe3..e9a770d77a6e 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -507,7 +507,7 @@ static int __init mpc512x_psc_fifoc_init(void) psc_fifoc_irq = irq_of_parse_and_map(np, 0); of_node_put(np); - if (psc_fifoc_irq == NO_IRQ) { + if (psc_fifoc_irq == 0) { pr_err("%s: Can't get FIFOC irq\n", __func__); iounmap(psc_fifoc); return -ENODEV; @@ -1354,7 +1354,7 @@ static int __devinit mpc52xx_uart_of_probe(struct platform_device *op) } psc_ops->get_irq(port, op->dev.of_node); - if (port->irq == NO_IRQ) { + if (port->irq == 0) { dev_dbg(&op->dev, "Could not get irq\n"); return -EINVAL; } diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 06f6aefd5ba6..c61d950e07c1 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -499,7 +499,7 @@ static int __init mux_probe(struct parisc_device *dev) port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); port->iotype = UPIO_MEM; port->type = PORT_MUX; - port->irq = NO_IRQ; + port->irq = 0; port->uartclk = 0; port->fifosize = MUX_FIFO_SIZE; port->ops = &mux_pops; diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index e9c2dfe471a2..08ebe901bb59 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1506,7 +1506,7 @@ no_dma: * fixed up interrupt info, but we use the device-tree directly * here due to early probing so we need the fixup too. */ - if (uap->port.irq == NO_IRQ && + if (uap->port.irq == 0 && np->parent && np->parent->parent && of_device_is_compatible(np->parent->parent, "gatwick")) { /* IRQs on gatwick are offset by 64 */ diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 8e916e76b7b5..5a47d1b196d8 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -1397,7 +1397,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) #endif } -static int zilog_irq = -1; +static int zilog_irq; static int __devinit zs_probe(struct platform_device *op) { @@ -1425,7 +1425,7 @@ static int __devinit zs_probe(struct platform_device *op) rp = sunzilog_chip_regs[inst]; - if (zilog_irq == -1) + if (!zilog_irq) zilog_irq = op->archdata.irqs[0]; up = &sunzilog_port_table[inst * 2]; @@ -1580,7 +1580,7 @@ static int __init sunzilog_init(void) if (err) goto out_unregister_uart; - if (zilog_irq != -1) { + if (!zilog_irq) { struct uart_sunzilog_port *up = sunzilog_irq_chain; err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, "zs", sunzilog_irq_chain); @@ -1621,7 +1621,7 @@ static void __exit sunzilog_exit(void) { platform_driver_unregister(&zs_driver); - if (zilog_irq != -1) { + if (!zilog_irq) { struct uart_sunzilog_port *up = sunzilog_irq_chain; /* Disable Interrupts */ @@ -1637,7 +1637,7 @@ static void __exit sunzilog_exit(void) } free_irq(zilog_irq, sunzilog_irq_chain); - zilog_irq = -1; + zilog_irq = 0; } if (sunzilog_reg.nr) { diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 2ebe606a2db1..f99b0c965f85 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -1360,7 +1360,7 @@ static int ucc_uart_probe(struct platform_device *ofdev) } qe_port->port.irq = irq_of_parse_and_map(np, 0); - if (qe_port->port.irq == NO_IRQ) { + if (qe_port->port.irq == 0) { dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n", qe_port->ucc_num + 1); ret = -EINVAL; diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index 83148e79ca13..cf0d9485ec08 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c @@ -61,7 +61,7 @@ static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { [0 ... SIU_PORTS_MAX-1] = { .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock), - .irq = -1, + .irq = 0, }, }; @@ -171,7 +171,7 @@ static inline unsigned int siu_check_type(struct uart_port *port) { if (port->line == 0) return PORT_VR41XX_SIU; - if (port->line == 1 && port->irq != -1) + if (port->line == 1 && port->irq) return PORT_VR41XX_DSIU; return PORT_UNKNOWN; -- cgit v1.2.3 From 5816269e4ee3db2bc2ad44afc89f4abe81c7aa26 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 25 Jan 2012 19:50:36 -0700 Subject: tty: serial: OMAP: use a 1-byte RX FIFO threshold in PIO mode In the (default) PIO mode, use a one-byte RX FIFO threshold. The OMAP UART IP blocks do not appear to be capable of waking the system under an RX timeout condition. Since the previous RX FIFO threshold was 16 bytes, this meant that omap-serial.c did not become aware of any received data until all those bytes arrived or until another UART interrupt occurred. This made the serial console and presumably other serial applications (GPS, serial Bluetooth) unusable or extremely slow. A 1-byte RX FIFO threshold also allows the MPU to enter a low-power consumption state while waiting for the FIFO to fill. This can be verified using the serial console by comparing the behavior when "0123456789abcde" is pasted in from another window, with the behavior when "0123456789abcdef" is pasted in. Since the former string is less than sixteen bytes long, the string is not echoed for some time, while the latter string is echoed immediately. DMA operation is unaffected by this patch. Thanks to Russell King - ARM Linux for some additional information on the standard behavior of the RX timeout event, which was used to improve this commit description. Signed-off-by: Paul Walmsley Cc: Tomi Valkeinen Cc: Govindraj Raja Cc: Alan Cox Cc: Russell King Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d192dcbb82f5..c9c9ba2a5bb6 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -46,6 +46,13 @@ #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/ +/* SCR register bitmasks */ +#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7) + +/* FCR register bitmasks */ +#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT 6 +#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6) + static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; /* Forward declaration of functions */ @@ -811,14 +818,21 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ - serial_out(up, UART_FCR, up->fcr); - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + + up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK; if (up->use_dma) { serial_out(up, UART_TI752_TLR, 0); - up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8); + up->scr |= UART_FCR_TRIGGER_4; + } else { + /* Set receive FIFO threshold to 1 byte */ + up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; + up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT); } + serial_out(up, UART_FCR, up->fcr); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_OMAP_SCR, up->scr); serial_out(up, UART_EFR, up->efr); -- cgit v1.2.3 From edbe5dbefe5b514d094558ab59c8dc7578e117dd Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 25 Jan 2012 19:50:52 -0700 Subject: tty: serial: OMAP: block idle while the UART is transferring data in PIO mode Prevent OMAP UARTs from going idle while they are still transferring data in PIO mode. This works around an oversight in the OMAP UART hardware present in OMAP34xx and earlier: an idle UART won't send a wakeup when the TX FIFO threshold is reached. This causes long delays during data transmission when the MPU powerdomain enters a low-power mode. The MPU interrupt controller is not able to respond to interrupts when it's in a low-power state, so the TX buffer is not refilled until another wakeup event occurs. This fix changes the erratum i291 DMA idle workaround. Rather than toggling between force-idle and no-idle, it will toggle between smart-idle and no-idle. The important part of the workaround is the no-idle part, so this shouldn't result in any change in behavior. This fix should work on all OMAP UARTs. Future patches intended for the 3.4 merge window will make this workaround conditional on a "feature" flag, and will use the OMAP36xx+ TX event wakeup support. Thanks to Kevin Hilman for mentioning the erratum i291 workaround, which led to the development of this approach. Signed-off-by: Paul Walmsley Cc: Alan Cox Cc: Tomi Valkeinen Acked-by: Govindraj.R Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/serial.c | 8 ++++---- drivers/tty/serial/omap-serial.c | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 247d89478f24..f590afc1f673 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -107,18 +107,18 @@ static void omap_uart_set_noidle(struct platform_device *pdev) omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO); } -static void omap_uart_set_forceidle(struct platform_device *pdev) +static void omap_uart_set_smartidle(struct platform_device *pdev) { struct omap_device *od = to_omap_device(pdev); - omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE); + omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART); } #else static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) {} static void omap_uart_set_noidle(struct platform_device *pdev) {} -static void omap_uart_set_forceidle(struct platform_device *pdev) {} +static void omap_uart_set_smartidle(struct platform_device *pdev) {} #endif /* CONFIG_PM */ #ifdef CONFIG_OMAP_MUX @@ -349,7 +349,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; omap_up.flags = UPF_BOOT_AUTOCONF; omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count; - omap_up.set_forceidle = omap_uart_set_forceidle; + omap_up.set_forceidle = omap_uart_set_smartidle; omap_up.set_noidle = omap_uart_set_noidle; omap_up.enable_wakeup = omap_uart_enable_wakeup; omap_up.dma_rx_buf_size = info->dma_rx_buf_size; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index c9c9ba2a5bb6..11fa15623e13 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -136,6 +136,7 @@ static void serial_omap_enable_ms(struct uart_port *port) static void serial_omap_stop_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; + struct omap_uart_port_info *pdata = up->pdev->dev.platform_data; if (up->use_dma && up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) { @@ -158,6 +159,9 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); } + if (!up->use_dma && pdata->set_forceidle) + pdata->set_forceidle(up->pdev); + pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); } @@ -286,6 +290,7 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up) static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; + struct omap_uart_port_info *pdata = up->pdev->dev.platform_data; struct circ_buf *xmit; unsigned int start; int ret = 0; @@ -293,6 +298,8 @@ static void serial_omap_start_tx(struct uart_port *port) if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); serial_omap_enable_ier_thri(up); + if (pdata->set_noidle) + pdata->set_noidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); return; -- cgit v1.2.3 From 6bbcbf22085e0b144899d6067e243dd26c0e7533 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 25 Jan 2012 19:50:56 -0700 Subject: tty: serial: omap-serial: wakeup latency constraint is in microseconds, not milliseconds The receive FIFO wakeup latency estimate in the omap-serial driver is three orders of magnitude too small. This effectively prevents the MPU from going to a low-power state when CONFIG_CPU_IDLE=y. This is a major power management regression and masks some other FIFO-related bugs in the driver. Fix by correcting the most egregious problem in the RX wakeup latency estimate. There are several other flaws in the estimator; these will be fixed by a separate patch series intended for 3.4. The difference in low-power states with this patch can be observed via debugfs in pm_debug/count. This estimate does not have any effect when CONFIG_CPU_IDLE=n. Signed-off-by: Paul Walmsley Cc: Tomi Valkeinen Cc: Alan Cox Acked-by: Govindraj.R Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 11fa15623e13..72fa783729d2 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -740,8 +740,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, quot = serial_omap_get_divisor(port, baud); /* calculate wakeup latency constraint */ - up->calc_latency = (1000000 * up->port.fifosize) / - (1000 * baud / 8); + up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8); up->latency = up->calc_latency; schedule_work(&up->qos_work); -- cgit v1.2.3 From d011411ddb294e90511211a9edfc79da1c0465dc Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Mon, 6 Feb 2012 17:24:43 +0800 Subject: serial: pch_uart: add debugfs hook for register dump This driver will be use as interfaces for multiple kinds of devices like Bluetooth/GPS etc, this debug hook will make driver debugging much easier. Signed-off-by: Feng Tang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 84 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 17ae65762d1a..6d9ca2933361 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -144,6 +145,8 @@ enum { #define PCH_UART_DLL 0x00 #define PCH_UART_DLM 0x01 +#define PCH_UART_BRCSR 0x0E + #define PCH_UART_IID_RLS (PCH_UART_IIR_REI) #define PCH_UART_IID_RDR (PCH_UART_IIR_RRI) #define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI) @@ -243,6 +246,8 @@ struct eg20t_port { int tx_dma_use; void *rx_buf_virt; dma_addr_t rx_buf_dma; + + struct dentry *debugfs; }; /** @@ -292,6 +297,73 @@ static const int trigger_level_64[4] = { 1, 16, 32, 56 }; static const int trigger_level_16[4] = { 1, 4, 8, 14 }; static const int trigger_level_1[4] = { 1, 1, 1, 1 }; +#ifdef CONFIG_DEBUG_FS + +#define PCH_REGS_BUFSIZE 1024 +static int pch_show_regs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t port_show_regs(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct eg20t_port *priv = file->private_data; + char *buf; + u32 len = 0; + ssize_t ret; + unsigned char lcr; + + buf = kzalloc(PCH_REGS_BUFSIZE, GFP_KERNEL); + if (!buf) + return 0; + + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "PCH EG20T port[%d] regs:\n", priv->port.line); + + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "=================================\n"); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "IER: \t0x%02x\n", ioread8(priv->membase + UART_IER)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "BRCSR: \t0x%02x\n", + ioread8(priv->membase + PCH_UART_BRCSR)); + + lcr = ioread8(priv->membase + UART_LCR); + iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL)); + len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, + "DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM)); + iowrite8(lcr, priv->membase + UART_LCR); + + if (len > PCH_REGS_BUFSIZE) + len = PCH_REGS_BUFSIZE; + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + return ret; +} + +static const struct file_operations port_regs_ops = { + .owner = THIS_MODULE, + .open = pch_show_regs_open, + .read = port_show_regs, + .llseek = default_llseek, +}; +#endif /* CONFIG_DEBUG_FS */ + static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize, int base_baud) { @@ -1554,6 +1626,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, int port_type; struct pch_uart_driver_data *board; const char *board_name; + char name[32]; /* for debugfs file name */ board = &drv_dat[id->driver_data]; port_type = board->port_type; @@ -1623,6 +1696,12 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, if (ret < 0) goto init_port_hal_free; +#ifdef CONFIG_DEBUG_FS + snprintf(name, sizeof(name), "uart%d_regs", board->line_no); + priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO, + NULL, priv, &port_regs_ops); +#endif + return priv; init_port_hal_free: @@ -1639,6 +1718,11 @@ init_port_alloc_err: static void pch_uart_exit_port(struct eg20t_port *priv) { + +#ifdef CONFIG_DEBUG_FS + if (priv->debugfs) + debugfs_remove(priv->debugfs); +#endif uart_remove_one_port(&pch_uart_driver, &priv->port); pci_set_drvdata(priv->pdev, NULL); free_page((unsigned long)priv->rxbuf.buf); -- cgit v1.2.3 From 30c6c6b5bf82d4f4a23235a0aa0657681d1c21f2 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Mon, 6 Feb 2012 17:24:44 +0800 Subject: serial: pch_uart: trivial cleanup by removing the get_msr() The short get_msr() has some unnecessary code and only used once, so merge it with its caller to make code cleaner. No functional change at all. Signed-off-by: Feng Tang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 6d9ca2933361..811edcbe7304 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -373,14 +373,6 @@ static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize, priv->fcr = 0; } -static unsigned int get_msr(struct eg20t_port *priv, void __iomem *base) -{ - unsigned int msr = ioread8(base + UART_MSR); - priv->dmsr |= msr & PCH_UART_MSR_DELTA; - - return msr; -} - static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv, unsigned int flag) { @@ -514,8 +506,9 @@ static int pch_uart_hal_set_fifo(struct eg20t_port *priv, static u8 pch_uart_hal_get_modem(struct eg20t_port *priv) { - priv->dmsr = 0; - return get_msr(priv, priv->membase); + unsigned int msr = ioread8(priv->membase + UART_MSR); + priv->dmsr = msr & PCH_UART_MSR_DELTA; + return (u8)msr; } static void pch_uart_hal_write(struct eg20t_port *priv, @@ -596,7 +589,7 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf, static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) { - int ret; + int ret = 0; struct uart_port *port = &priv->port; if (port->x_char) { @@ -605,8 +598,6 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) buf[0] = port->x_char; port->x_char = 0; ret = 1; - } else { - ret = 0; } return ret; @@ -1104,14 +1095,12 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) static unsigned int pch_uart_tx_empty(struct uart_port *port) { struct eg20t_port *priv; - int ret; + priv = container_of(port, struct eg20t_port, port); if (priv->tx_empty) - ret = TIOCSER_TEMT; + return TIOCSER_TEMT; else - ret = 0; - - return ret; + return 0; } /* Returns the current state of modem control inputs. */ @@ -1345,9 +1334,8 @@ static void pch_uart_set_termios(struct uart_port *port, else parity = PCH_UART_HAL_PARITY_EVEN; - } else { + } else parity = PCH_UART_HAL_PARITY_NONE; - } /* Only UART0 has auto hardware flow function */ if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256)) @@ -1519,7 +1507,6 @@ static void pch_console_write(struct console *co, const char *s, unsigned int count) { struct eg20t_port *priv; - unsigned long flags; u8 ier; int locked = 1; -- cgit v1.2.3 From 6f56d0f43656deb98c6366a133a75b5a7cf73a26 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Mon, 6 Feb 2012 17:24:45 +0800 Subject: serial: pch_uart: trivail cleanup by removing the pch_uart_hal_request() pch_uart_hal_request() has parameters which it never uses, also it is very short, so merge it with its caller to make code cleaner. No functional changes at all. Signed-off-by: Feng Tang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 811edcbe7304..aa4d07b4a9d5 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -364,15 +364,6 @@ static const struct file_operations port_regs_ops = { }; #endif /* CONFIG_DEBUG_FS */ -static void pch_uart_hal_request(struct pci_dev *pdev, int fifosize, - int base_baud) -{ - struct eg20t_port *priv = pci_get_drvdata(pdev); - - priv->trigger_level = 1; - priv->fcr = 0; -} - static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv, unsigned int flag) { @@ -1674,7 +1665,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, spin_lock_init(&priv->port.lock); pci_set_drvdata(pdev, priv); - pch_uart_hal_request(pdev, fifosize, base_baud); + priv->trigger_level = 1; + priv->fcr = 0; #ifdef CONFIG_SERIAL_PCH_UART_CONSOLE pch_uart_ports[board->line_no] = priv; @@ -1717,9 +1709,7 @@ static void pch_uart_exit_port(struct eg20t_port *priv) static void pch_uart_pci_remove(struct pci_dev *pdev) { - struct eg20t_port *priv; - - priv = (struct eg20t_port *)pci_get_drvdata(pdev); + struct eg20t_port *priv = pci_get_drvdata(pdev); pci_disable_msi(pdev); -- cgit v1.2.3 From 3f5dc70721af68b76ad544b0c61fea365d67c041 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 8 Feb 2012 14:35:46 +0100 Subject: tty: serial: altera_uart: remove early_altera_uart_setup The function has no users inside the tree and the nios2 (out-of-mainline) port doesn't use it either (anymore). Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/altera_uart.c | 23 ----------------------- include/linux/altera_uart.h | 4 ---- 2 files changed, 27 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 1d04c5037f25..217833e94b5b 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -403,29 +403,6 @@ static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; #if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) -int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) -{ - struct uart_port *port; - int i; - - for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) { - port = &altera_uart_ports[i].port; - - port->line = i; - port->type = PORT_ALTERA_UART; - port->mapbase = platp[i].mapbase; - port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); - port->iotype = SERIAL_IO_MEM; - port->irq = platp[i].irq; - port->uartclk = platp[i].uartclk; - port->flags = UPF_BOOT_AUTOCONF; - port->ops = &altera_uart_ops; - port->private_data = platp; - } - - return 0; -} - static void altera_uart_console_putc(struct uart_port *port, const char c) { while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & diff --git a/include/linux/altera_uart.h b/include/linux/altera_uart.h index a10a90791976..c022c82db7ca 100644 --- a/include/linux/altera_uart.h +++ b/include/linux/altera_uart.h @@ -5,8 +5,6 @@ #ifndef __ALTUART_H #define __ALTUART_H -#include - struct altera_uart_platform_uart { unsigned long mapbase; /* Physical address base */ unsigned int irq; /* Interrupt vector */ @@ -14,6 +12,4 @@ struct altera_uart_platform_uart { unsigned int bus_shift; /* Bus shift (address stride) */ }; -int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp); - #endif /* __ALTUART_H */ -- cgit v1.2.3 From 418a936e84e8f346da322c2e839992aa9df108d4 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 8 Feb 2012 14:36:09 +0100 Subject: tty: serial: altera_uart: Add CONSOLE_POLL support This allows altera_uart to be used for KGDB debugging over serial line. Signed-off-by: Tobias Klauser Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Makefile | 2 +- drivers/tty/serial/altera_uart.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 1997ad4a39a6..50d279000e79 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -75,12 +75,12 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o +obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o -obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 217833e94b5b..e7903751e058 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -377,6 +377,26 @@ static int altera_uart_verify_port(struct uart_port *port, return 0; } +#ifdef CONFIG_CONSOLE_POLL +static int altera_uart_poll_get_char(struct uart_port *port) +{ + while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & + ALTERA_UART_STATUS_RRDY_MSK)) + cpu_relax(); + + return altera_uart_readl(port, ALTERA_UART_RXDATA_REG); +} + +static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c) +{ + while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) & + ALTERA_UART_STATUS_TRDY_MSK)) + cpu_relax(); + + altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG); +} +#endif + /* * Define the basic serial functions we support. */ @@ -397,6 +417,10 @@ static struct uart_ops altera_uart_ops = { .release_port = altera_uart_release_port, .config_port = altera_uart_config_port, .verify_port = altera_uart_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = altera_uart_poll_get_char, + .poll_put_char = altera_uart_poll_put_char, +#endif }; static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS]; -- cgit v1.2.3 From 6816383a09b5be8d35f14f4c25dedb64498e4959 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 9 Feb 2012 18:48:19 -0500 Subject: tty: sparc: rename drivers/tty/serial/suncore.h -> include/linux/sunserialcore.h There are multiple users of this file from different source paths now, and rather than have ../ paths in include statements, just move the file to the linux header dir. Suggested-by: David S. Miller Signed-off-by: Paul Gortmaker Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- drivers/tty/serial/8250/8250.c | 7 +++---- drivers/tty/serial/suncore.c | 2 +- drivers/tty/serial/suncore.h | 33 --------------------------------- drivers/tty/serial/sunhv.c | 3 +-- drivers/tty/serial/sunsab.c | 2 +- drivers/tty/serial/sunsu.c | 3 +-- drivers/tty/serial/sunzilog.c | 2 +- include/linux/sunserialcore.h | 33 +++++++++++++++++++++++++++++++++ 9 files changed, 42 insertions(+), 45 deletions(-) delete mode 100644 drivers/tty/serial/suncore.h create mode 100644 include/linux/sunserialcore.h (limited to 'drivers/tty/serial') diff --git a/MAINTAINERS b/MAINTAINERS index 9a648eb8e213..27c052cc8835 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6187,8 +6187,8 @@ L: sparclinux@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git S: Maintained +F: include/linux/sunserialcore.h F: drivers/tty/serial/suncore.c -F: drivers/tty/serial/suncore.h F: drivers/tty/serial/sunhv.c F: drivers/tty/serial/sunsab.c F: drivers/tty/serial/sunsab.h diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index b423d0f962a2..917ab8452746 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -38,16 +38,15 @@ #include #include #include +#ifdef CONFIG_SPARC +#include +#endif #include #include #include "8250.h" -#ifdef CONFIG_SPARC -#include "../suncore.h" -#endif - /* * Configuration: * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option diff --git a/drivers/tty/serial/suncore.c b/drivers/tty/serial/suncore.c index 6381a0282ee7..6e4ac8db2d79 100644 --- a/drivers/tty/serial/suncore.c +++ b/drivers/tty/serial/suncore.c @@ -17,11 +17,11 @@ #include #include #include +#include #include #include -#include "suncore.h" static int sunserial_current_minor = 64; diff --git a/drivers/tty/serial/suncore.h b/drivers/tty/serial/suncore.h deleted file mode 100644 index db2057936c31..000000000000 --- a/drivers/tty/serial/suncore.h +++ /dev/null @@ -1,33 +0,0 @@ -/* suncore.h - * - * Generic SUN serial/kbd/ms layer. Based entirely - * upon drivers/sbus/char/sunserial.h which is: - * - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * - * Port to new UART layer is: - * - * Copyright (C) 2002 David S. Miller (davem@redhat.com) - */ - -#ifndef _SERIAL_SUN_H -#define _SERIAL_SUN_H - -/* Serial keyboard defines for L1-A processing... */ -#define SUNKBD_RESET 0xff -#define SUNKBD_L1 0x01 -#define SUNKBD_UP 0x80 -#define SUNKBD_A 0x4d - -extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *); -extern int suncore_mouse_baud_detection(unsigned char, int); - -extern int sunserial_register_minors(struct uart_driver *, int); -extern void sunserial_unregister_minors(struct uart_driver *, int); - -extern int sunserial_console_match(struct console *, struct device_node *, - struct uart_driver *, int, bool); -extern void sunserial_console_termios(struct console *, - struct device_node *); - -#endif /* !(_SERIAL_SUN_H) */ diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index c0b7246d7339..3ba5d285c2d0 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -29,8 +29,7 @@ #endif #include - -#include "suncore.h" +#include #define CON_BREAK ((long)-1) #define CON_HUP ((long)-2) diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index b5fa2a57b9da..62dacd0ba526 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -43,8 +43,8 @@ #endif #include +#include -#include "suncore.h" #include "sunsab.h" struct uart_sunsab_port { diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index ad0f8f5f6ea1..d3ca6da129fe 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -47,8 +47,7 @@ #endif #include - -#include "suncore.h" +#include /* We are on a NS PC87303 clocked with 24.0 MHz, which results * in a UART clock of 1.8462 MHz. diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 5a47d1b196d8..da4415842a43 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -43,8 +43,8 @@ #endif #include +#include -#include "suncore.h" #include "sunzilog.h" /* On 32-bit sparcs we need to delay after register accesses diff --git a/include/linux/sunserialcore.h b/include/linux/sunserialcore.h new file mode 100644 index 000000000000..68e7430bb0fe --- /dev/null +++ b/include/linux/sunserialcore.h @@ -0,0 +1,33 @@ +/* sunserialcore.h + * + * Generic SUN serial/kbd/ms layer. Based entirely + * upon drivers/sbus/char/sunserial.h which is: + * + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + * + * Port to new UART layer is: + * + * Copyright (C) 2002 David S. Miller (davem@redhat.com) + */ + +#ifndef _SERIAL_SUN_H +#define _SERIAL_SUN_H + +/* Serial keyboard defines for L1-A processing... */ +#define SUNKBD_RESET 0xff +#define SUNKBD_L1 0x01 +#define SUNKBD_UP 0x80 +#define SUNKBD_A 0x4d + +extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *); +extern int suncore_mouse_baud_detection(unsigned char, int); + +extern int sunserial_register_minors(struct uart_driver *, int); +extern void sunserial_unregister_minors(struct uart_driver *, int); + +extern int sunserial_console_match(struct console *, struct device_node *, + struct uart_driver *, int, bool); +extern void sunserial_console_termios(struct console *, + struct device_node *); + +#endif /* !(_SERIAL_SUN_H) */ -- cgit v1.2.3 From b7974deddc57307ddc9193d81e76ff818862d4e9 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Wed, 15 Feb 2012 18:55:41 +0100 Subject: tty/serial/mux.c: linux/tty.h included twice drivers/tty/serial/mux.c included 'linux/tty.h' twice, remove the duplicate. Signed-off-by: Danny Kukawka Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mux.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index c61d950e07c1..7ea8a263fd9e 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include -- cgit v1.2.3 From 90af6d208263d0f3541eee0525f093c248d88a42 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sat, 18 Feb 2012 19:49:47 +0900 Subject: serial: Fix typo in sn_console.c Correct spelling "receieve" to "receive" in drivers/tty/serial/sn_console.c Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sn_console.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sn_console.c b/drivers/tty/serial/sn_console.c index 238c7df73ef5..4e1b5515f881 100644 --- a/drivers/tty/serial/sn_console.c +++ b/drivers/tty/serial/sn_console.c @@ -461,12 +461,12 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags) struct tty_struct *tty; if (!port) { - printk(KERN_ERR "sn_receive_chars - port NULL so can't receieve\n"); + printk(KERN_ERR "sn_receive_chars - port NULL so can't receive\n"); return; } if (!port->sc_ops) { - printk(KERN_ERR "sn_receive_chars - port->sc_ops NULL so can't receieve\n"); + printk(KERN_ERR "sn_receive_chars - port->sc_ops NULL so can't receive\n"); return; } -- cgit v1.2.3 From b26469a8b139fba11d9336c1c117fafccfa9c7d5 Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Thu, 23 Feb 2012 08:23:52 +0100 Subject: serial: samsung: fix s3c2442 platform data Without that fix machines having a s3c2442 CPU have something like that in dmesg: samsung-uart s3c2440-uart.0: could not find driver data samsung-uart s3c2440-uart.1: could not find driver data samsung-uart s3c2440-uart.2: could not find driver data And serial is never initialized. The previous log was obtained trough early printk on the gta02 machine. Signed-off-by: Denis 'GNUtoo' Carikli Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index c55e5fb16fa3..de249d265bec 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1507,7 +1507,7 @@ static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { #endif #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \ - defined(CONFIG_CPU_S3C2443) + defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2442) static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { .info = &(struct s3c24xx_uart_info) { .name = "Samsung S3C2440 UART", -- cgit v1.2.3 From 6dc01aa65306fe46b7ba38db51fad4ed81c23d00 Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Mon, 20 Feb 2012 10:24:40 +0900 Subject: amba-pl011​/dma: Add check for the residue in DMA callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In DMA-operated uart, I found that rx data can be taken by the UART interrupts during the DMA irq handler. pl011_int is occurred just before it goes inside spin_lock_irq. When it returns to the callback, DMA buffer already has been flushed. Then, pl011_dma_rx_chars gets invalid data. So I add check for the residue as the patch bellow. Signed-off-by: Chanho Min Acked-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 6800f5f26241..cc3ea066c43a 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -827,7 +827,12 @@ static void pl011_dma_rx_callback(void *data) { struct uart_amba_port *uap = data; struct pl011_dmarx_data *dmarx = &uap->dmarx; + struct dma_chan *rxchan = dmarx->chan; bool lastbuf = dmarx->use_buf_b; + struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ? + &dmarx->sgbuf_b : &dmarx->sgbuf_a; + size_t pending; + struct dma_tx_state state; int ret; /* @@ -838,11 +843,21 @@ static void pl011_dma_rx_callback(void *data) * we immediately trigger the next DMA job. */ spin_lock_irq(&uap->port.lock); + /* + * Rx data can be taken by the UART interrupts during + * the DMA irq handler. So we check the residue here. + */ + rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state); + pending = sgbuf->sg.length - state.residue; + BUG_ON(pending > PL011_DMA_BUFFER_SIZE); + /* Then we terminate the transfer - we now know our residue */ + dmaengine_terminate_all(rxchan); + uap->dmarx.running = false; dmarx->use_buf_b = !lastbuf; ret = pl011_dma_rx_trigger_dma(uap); - pl011_dma_rx_chars(uap, PL011_DMA_BUFFER_SIZE, lastbuf, false); + pl011_dma_rx_chars(uap, pending, lastbuf, false); spin_unlock_irq(&uap->port.lock); /* * Do this check after we picked the DMA chars so we don't -- cgit v1.2.3 From a5f43138da9beddc46b00ec31d167143a7176683 Mon Sep 17 00:00:00 2001 From: "Cousson, Benoit" Date: Tue, 28 Feb 2012 18:22:12 +0100 Subject: tty: serial: OMAP: Fix oops due to NULL pdata in DT boot The following commit: be4b0281956c5cae4f63f31f11d07625a6988766 (tty: serial: OMAP: block idle while the UART is transferring data in PIO mode), is introducing an oops if OMAP is booted using device tree blob because the pdata will not be initialized. Check if pdata is set before de-referencing it. Signed-off-by: Benoit Cousson Reviewed-by: Paul Walmsley Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index f80904145fd4..0121486ac4fa 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -159,7 +159,7 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); } - if (!up->use_dma && pdata->set_forceidle) + if (!up->use_dma && pdata && pdata->set_forceidle) pdata->set_forceidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); @@ -298,7 +298,7 @@ static void serial_omap_start_tx(struct uart_port *port) if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); serial_omap_enable_ier_thri(up); - if (pdata->set_noidle) + if (pdata && pdata->set_noidle) pdata->set_noidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); @@ -1613,7 +1613,7 @@ static int serial_omap_runtime_resume(struct device *dev) struct uart_omap_port *up = dev_get_drvdata(dev); struct omap_uart_port_info *pdata = dev->platform_data; - if (up) { + if (up && pdata) { if (pdata->get_context_loss_count) { u32 loss_cnt = pdata->get_context_loss_count(dev); -- cgit v1.2.3 From 2f16669d322e05171c9e1cfd94f402f7399bd2a3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:51:52 +0100 Subject: TTY: remove re-assignments to tty_driver members All num, magic and owner are set by alloc_tty_driver. No need to re-set them on each allocation site. pti driver sets something different to what it passes to alloc_tty_driver. It is not a bug, since we don't use the lines parameter in any way. Anyway this is fixed, and now we do the right thing. Signed-off-by: Jiri Slaby Acked-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 1 - arch/m68k/emu/nfcon.c | 1 - arch/xtensa/platforms/iss/console.c | 1 - drivers/char/pcmcia/synclink_cs.c | 1 - drivers/char/ttyprintk.c | 2 -- drivers/isdn/capi/capi.c | 1 - drivers/isdn/gigaset/interface.c | 7 +------ drivers/misc/pti.c | 5 +---- drivers/mmc/card/sdio_uart.c | 1 - drivers/net/usb/hso.c | 2 -- drivers/s390/char/con3215.c | 1 - drivers/s390/char/sclp_tty.c | 1 - drivers/s390/char/sclp_vt220.c | 1 - drivers/s390/char/tty3270.c | 1 - drivers/tty/amiserial.c | 1 - drivers/tty/bfin_jtag_comm.c | 1 - drivers/tty/cyclades.c | 1 - drivers/tty/ehv_bytechan.c | 1 - drivers/tty/hvc/hvc_console.c | 1 - drivers/tty/hvc/hvcs.c | 2 -- drivers/tty/hvc/hvsi.c | 1 - drivers/tty/ipwireless/tty.c | 1 - drivers/tty/isicom.c | 1 - drivers/tty/moxa.c | 1 - drivers/tty/mxser.c | 3 --- drivers/tty/n_gsm.c | 1 - drivers/tty/nozomi.c | 1 - drivers/tty/pty.c | 4 ---- drivers/tty/rocket.c | 1 - drivers/tty/serial/ifx6x60.c | 3 --- drivers/tty/serial/msm_smd_tty.c | 1 - drivers/tty/serial/serial_core.c | 1 - drivers/tty/synclink.c | 1 - drivers/tty/synclink_gt.c | 1 - drivers/tty/synclinkmp.c | 1 - drivers/tty/vt/vt.c | 2 +- drivers/usb/class/cdc-acm.c | 1 - drivers/usb/gadget/u_serial.c | 1 - drivers/usb/serial/usb-serial.c | 1 - net/bluetooth/rfcomm/tty.c | 1 - net/irda/ircomm/ircomm_tty.c | 1 - 41 files changed, 3 insertions(+), 59 deletions(-) (limited to 'drivers/tty/serial') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index bff0824cf8a4..f513dc02bb87 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -928,7 +928,6 @@ simrs_init (void) /* Initialize the tty_driver structure */ - hp_simserial_driver->owner = THIS_MODULE; hp_simserial_driver->driver_name = "simserial"; hp_simserial_driver->name = "ttyS"; hp_simserial_driver->major = TTY_MAJOR; diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c index ab20dc0ff63b..8db25e806947 100644 --- a/arch/m68k/emu/nfcon.c +++ b/arch/m68k/emu/nfcon.c @@ -127,7 +127,6 @@ static int __init nfcon_init(void) if (!nfcon_tty_driver) return -ENOMEM; - nfcon_tty_driver->owner = THIS_MODULE; nfcon_tty_driver->driver_name = "nfcon"; nfcon_tty_driver->name = "nfcon"; nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 2c723e8b30da..247e9d40a52e 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -216,7 +216,6 @@ int __init rs_init(void) /* Initialize the tty_driver structure */ - serial_driver->owner = THIS_MODULE; serial_driver->driver_name = "iss_serial"; serial_driver->name = "ttyS"; serial_driver->major = TTY_MAJOR; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 07f6a5abe372..c3bcb1221e6b 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2836,7 +2836,6 @@ static int __init synclink_cs_init(void) /* Initialize the tty_driver structure */ - serial_driver->owner = THIS_MODULE; serial_driver->driver_name = "synclink_cs"; serial_driver->name = "ttySLP"; serial_driver->major = ttymajor; diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index eedd5474850c..46b77ede84c0 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -184,12 +184,10 @@ static int __init ttyprintk_init(void) if (!ttyprintk_driver) return ret; - ttyprintk_driver->owner = THIS_MODULE; ttyprintk_driver->driver_name = "ttyprintk"; ttyprintk_driver->name = "ttyprintk"; ttyprintk_driver->major = TTYAUX_MAJOR; ttyprintk_driver->minor_start = 3; - ttyprintk_driver->num = 1; ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE; ttyprintk_driver->init_termios = tty_std_termios; ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET; diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 94948be5d366..baf08eba495c 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1287,7 +1287,6 @@ static int __init capinc_tty_init(void) kfree(capiminors); return -ENOMEM; } - drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->name = "capi"; drv->major = 0; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index ee0a549a933a..648260b07f1a 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -669,17 +669,15 @@ EXPORT_SYMBOL_GPL(gigaset_if_receive); void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, const char *devname) { - unsigned minors = drv->minors; int ret; struct tty_driver *tty; drv->have_tty = 0; - drv->tty = tty = alloc_tty_driver(minors); + drv->tty = tty = alloc_tty_driver(drv->minors); if (tty == NULL) goto enomem; - tty->magic = TTY_DRIVER_MAGIC, tty->type = TTY_DRIVER_TYPE_SERIAL, tty->subtype = SERIAL_TYPE_NORMAL, tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; @@ -687,9 +685,6 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, tty->driver_name = procname; tty->name = devname; tty->minor_start = drv->minor; - tty->num = drv->minors; - - tty->owner = THIS_MODULE; tty->init_termios = tty_std_termios; tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index 9a35db3d27fc..383133b201a1 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c @@ -907,20 +907,17 @@ static int __init pti_init(void) /* First register module as tty device */ - pti_tty_driver = alloc_tty_driver(1); + pti_tty_driver = alloc_tty_driver(PTITTY_MINOR_NUM); if (pti_tty_driver == NULL) { pr_err("%s(%d): Memory allocation failed for ptiTTY driver\n", __func__, __LINE__); return -ENOMEM; } - pti_tty_driver->owner = THIS_MODULE; - pti_tty_driver->magic = TTY_DRIVER_MAGIC; pti_tty_driver->driver_name = DRIVERNAME; pti_tty_driver->name = TTYNAME; pti_tty_driver->major = 0; pti_tty_driver->minor_start = PTITTY_MINOR_START; - pti_tty_driver->num = PTITTY_MINOR_NUM; pti_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; pti_tty_driver->subtype = SYSTEM_TYPE_SYSCONS; pti_tty_driver->flags = TTY_DRIVER_REAL_RAW | diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index bd4a67cdac3f..5a2cbfac66d2 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -1175,7 +1175,6 @@ static int __init sdio_uart_init(void) if (!tty_drv) return -ENOMEM; - tty_drv->owner = THIS_MODULE; tty_drv->driver_name = "sdio_uart"; tty_drv->name = "ttySDIO"; tty_drv->major = 0; /* dynamically allocated */ diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 304fe78ff60e..a73090f4c688 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -3313,7 +3313,6 @@ static int __init hso_init(void) /* fill in all needed values */ tty_drv->magic = TTY_DRIVER_MAGIC; - tty_drv->owner = THIS_MODULE; tty_drv->driver_name = driver_name; tty_drv->name = tty_filename; @@ -3322,7 +3321,6 @@ static int __init hso_init(void) tty_drv->major = tty_major; tty_drv->minor_start = 0; - tty_drv->num = HSO_SERIAL_TTY_MINORS; tty_drv->type = TTY_DRIVER_TYPE_SERIAL; tty_drv->subtype = SERIAL_TYPE_NORMAL; tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 934458ad55e5..fe916bfd60f2 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -1137,7 +1137,6 @@ static int __init tty3215_init(void) * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc */ - driver->owner = THIS_MODULE; driver->driver_name = "tty3215"; driver->name = "ttyS"; driver->major = TTY_MAJOR; diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index a879c139926a..40a9d69c898e 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -551,7 +551,6 @@ sclp_tty_init(void) return rc; } - driver->owner = THIS_MODULE; driver->driver_name = "sclp_line"; driver->name = "sclp_line"; driver->major = TTY_MAJOR; diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 5d706e6c946f..b635472ae660 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -685,7 +685,6 @@ static int __init sclp_vt220_tty_init(void) if (rc) goto out_driver; - driver->owner = THIS_MODULE; driver->driver_name = SCLP_VT220_DRIVER_NAME; driver->name = SCLP_VT220_DEVICE_NAME; driver->major = SCLP_VT220_MAJOR; diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 2db1482b406e..b43445a55cb6 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1784,7 +1784,6 @@ static int __init tty3270_init(void) * Entries in tty3270_driver that are NOT initialized: * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc */ - driver->owner = THIS_MODULE; driver->driver_name = "ttyTUB"; driver->name = "ttyTUB"; driver->major = IBM_TTY3270_MAJOR; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index b84c83456dcc..b42f00d987ae 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1974,7 +1974,6 @@ static int __init amiga_serial_probe(struct platform_device *pdev) /* Initialize the tty_driver structure */ - serial_driver->owner = THIS_MODULE; serial_driver->driver_name = "amiserial"; serial_driver->name = "ttyS"; serial_driver->major = TTY_MAJOR; diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c index 3a997760ec32..946f799861f5 100644 --- a/drivers/tty/bfin_jtag_comm.c +++ b/drivers/tty/bfin_jtag_comm.c @@ -257,7 +257,6 @@ static int __init bfin_jc_init(void) if (!bfin_jc_driver) goto err_driver; - bfin_jc_driver->owner = THIS_MODULE; bfin_jc_driver->driver_name = DRV_NAME; bfin_jc_driver->name = DEV_NAME; bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL; diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index 5575fee7a55e..bc7b5a5650ba 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -4090,7 +4090,6 @@ static int __init cy_init(void) /* Initialize the tty_driver structure */ - cy_serial_driver->owner = THIS_MODULE; cy_serial_driver->driver_name = "cyclades"; cy_serial_driver->name = "ttyC"; cy_serial_driver->major = CYCLADES_MAJOR; diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 1595dba0072c..4813684cb634 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -825,7 +825,6 @@ static int __init ehv_bc_init(void) goto error; } - ehv_bc_driver->owner = THIS_MODULE; ehv_bc_driver->driver_name = "ehv-bc"; ehv_bc_driver->name = ehv_bc_console.name; ehv_bc_driver->type = TTY_DRIVER_TYPE_CONSOLE; diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index b6b2d18fa38d..8880adf5fc6f 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -917,7 +917,6 @@ static int hvc_init(void) goto out; } - drv->owner = THIS_MODULE; drv->driver_name = "hvc"; drv->name = "hvc"; drv->major = HVC_MAJOR; diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index df7e7a0a5e6c..da0aa476804d 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1499,8 +1499,6 @@ static int __devinit hvcs_initialize(void) goto index_fail; } - hvcs_tty_driver->owner = THIS_MODULE; - hvcs_tty_driver->driver_name = hvcs_driver_name; hvcs_tty_driver->name = hvcs_device_node; diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 1b5f28bd7930..60bc45164189 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -1088,7 +1088,6 @@ static int __init hvsi_init(void) if (!hvsi_driver) return -ENOMEM; - hvsi_driver->owner = THIS_MODULE; hvsi_driver->driver_name = "hvsi"; hvsi_driver->name = "hvsi"; hvsi_driver->major = HVSI_MAJOR; diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c index ef92869502a7..6990b3b649d3 100644 --- a/drivers/tty/ipwireless/tty.c +++ b/drivers/tty/ipwireless/tty.c @@ -614,7 +614,6 @@ int ipwireless_tty_init(void) if (!ipw_tty_driver) return -ENOMEM; - ipw_tty_driver->owner = THIS_MODULE; ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME; ipw_tty_driver->name = "ttyIPWp"; ipw_tty_driver->major = 0; diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index e5c295ab5dec..b3a28b5f02ad 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -1678,7 +1678,6 @@ static int __init isicom_init(void) goto error; } - isicom_normal->owner = THIS_MODULE; isicom_normal->name = "ttyM"; isicom_normal->major = ISICOM_NMAJOR; isicom_normal->minor_start = 0; diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index d15a071b1a54..4a26323a926f 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1036,7 +1036,6 @@ static int __init moxa_init(void) if (!moxaDriver) return -ENOMEM; - moxaDriver->owner = THIS_MODULE; moxaDriver->name = "ttyMX"; moxaDriver->major = ttymajor; moxaDriver->minor_start = 0; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 8998d527232a..260d03123524 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -2658,12 +2658,9 @@ static int __init mxser_module_init(void) MXSER_VERSION); /* Initialize the tty_driver structure */ - mxvar_sdriver->owner = THIS_MODULE; - mxvar_sdriver->magic = TTY_DRIVER_MAGIC; mxvar_sdriver->name = "ttyMI"; mxvar_sdriver->major = ttymajor; mxvar_sdriver->minor_start = 0; - mxvar_sdriver->num = MXSER_PORTS + 1; mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; mxvar_sdriver->init_termios = tty_std_termios; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index fc7bbba585ce..c43b683b6eb8 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -3120,7 +3120,6 @@ static int __init gsm_init(void) pr_err("gsm_init: tty allocation failed.\n"); return -EINVAL; } - gsm_tty_driver->owner = THIS_MODULE; gsm_tty_driver->driver_name = "gsmtty"; gsm_tty_driver->name = "gsmtty"; gsm_tty_driver->major = 0; /* Dynamic */ diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index 580da78b2d86..e7592f9037da 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -1916,7 +1916,6 @@ static __init int nozomi_init(void) if (!ntty_driver) return -ENOMEM; - ntty_driver->owner = THIS_MODULE; ntty_driver->driver_name = NOZOMI_NAME_TTY; ntty_driver->name = "noz"; ntty_driver->major = 0; diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index d505837b3478..f96ecaec24f8 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -393,7 +393,6 @@ static void __init legacy_pty_init(void) if (!pty_slave_driver) panic("Couldn't allocate pty slave driver"); - pty_driver->owner = THIS_MODULE; pty_driver->driver_name = "pty_master"; pty_driver->name = "pty"; pty_driver->major = PTY_MASTER_MAJOR; @@ -411,7 +410,6 @@ static void __init legacy_pty_init(void) pty_driver->other = pty_slave_driver; tty_set_operations(pty_driver, &master_pty_ops_bsd); - pty_slave_driver->owner = THIS_MODULE; pty_slave_driver->driver_name = "pty_slave"; pty_slave_driver->name = "ttyp"; pty_slave_driver->major = PTY_SLAVE_MAJOR; @@ -671,7 +669,6 @@ static void __init unix98_pty_init(void) if (!pts_driver) panic("Couldn't allocate Unix98 pts driver"); - ptm_driver->owner = THIS_MODULE; ptm_driver->driver_name = "pty_master"; ptm_driver->name = "ptm"; ptm_driver->major = UNIX98_PTY_MASTER_MAJOR; @@ -690,7 +687,6 @@ static void __init unix98_pty_init(void) ptm_driver->other = pts_driver; tty_set_operations(ptm_driver, &ptm_unix98_ops); - pts_driver->owner = THIS_MODULE; pts_driver->driver_name = "pty_slave"; pts_driver->name = "pts"; pts_driver->major = UNIX98_PTY_SLAVE_MAJOR; diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index de88aa5566e5..b088e1ea4331 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -2277,7 +2277,6 @@ static int __init rp_init(void) * driver with the tty layer. */ - rocket_driver->owner = THIS_MODULE; rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV; rocket_driver->name = "ttyR"; rocket_driver->driver_name = "Comtrol RocketPort"; diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 7e925e20cbaa..144cd3987d4c 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1375,12 +1375,9 @@ static int __init ifx_spi_init(void) return -ENOMEM; } - tty_drv->magic = TTY_DRIVER_MAGIC; - tty_drv->owner = THIS_MODULE; tty_drv->driver_name = DRVNAME; tty_drv->name = TTYNAME; tty_drv->minor_start = IFX_SPI_TTY_ID; - tty_drv->num = 1; tty_drv->type = TTY_DRIVER_TYPE_SERIAL; tty_drv->subtype = SERIAL_TYPE_NORMAL; tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c index 4f41dcdcb771..b25e6ee71443 100644 --- a/drivers/tty/serial/msm_smd_tty.c +++ b/drivers/tty/serial/msm_smd_tty.c @@ -203,7 +203,6 @@ static int __init smd_tty_init(void) if (smd_tty_driver == 0) return -ENOMEM; - smd_tty_driver->owner = THIS_MODULE; smd_tty_driver->driver_name = "smd_tty_driver"; smd_tty_driver->name = "smd"; smd_tty_driver->major = 0; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 13056180adf5..9c4c05b2825b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2230,7 +2230,6 @@ int uart_register_driver(struct uart_driver *drv) drv->tty_driver = normal; - normal->owner = drv->owner; normal->driver_name = drv->driver_name; normal->name = drv->dev_name; normal->major = drv->major; diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index ff8017f87914..2b2988c779c7 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -4333,7 +4333,6 @@ static int mgsl_init_tty(void) if (!serial_driver) return -ENOMEM; - serial_driver->owner = THIS_MODULE; serial_driver->driver_name = "synclink"; serial_driver->name = "ttySL"; serial_driver->major = ttymajor; diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 18b48cd3b41d..a8b66be37e6e 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -3795,7 +3795,6 @@ static int __init slgt_init(void) /* Initialize the tty_driver structure */ - serial_driver->owner = THIS_MODULE; serial_driver->driver_name = tty_driver_name; serial_driver->name = tty_dev_prefix; serial_driver->major = ttymajor; diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index a7efe538df00..ddabb61c85ba 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -3977,7 +3977,6 @@ static int __init synclinkmp_init(void) /* Initialize the tty_driver structure */ - serial_driver->owner = THIS_MODULE; serial_driver->driver_name = "synclinkmp"; serial_driver->name = "ttySLM"; serial_driver->major = ttymajor; diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index e5abceacc2d0..84c4a7d5603e 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2994,7 +2994,7 @@ int __init vty_init(const struct file_operations *console_fops) console_driver = alloc_tty_driver(MAX_NR_CONSOLES); if (!console_driver) panic("Couldn't allocate console driver\n"); - console_driver->owner = THIS_MODULE; + console_driver->name = "tty"; console_driver->name_base = 1; console_driver->major = TTY_MAJOR; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 11a1130319d1..6bb8472155c6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1670,7 +1670,6 @@ static int __init acm_init(void) acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS); if (!acm_tty_driver) return -ENOMEM; - acm_tty_driver->owner = THIS_MODULE, acm_tty_driver->driver_name = "acm", acm_tty_driver->name = "ttyACM", acm_tty_driver->major = ACM_TTY_MAJOR, diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 6597a6813e43..490b01dd5d60 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -1087,7 +1087,6 @@ int __init gserial_setup(struct usb_gadget *g, unsigned count) if (!gs_tty_driver) return -ENOMEM; - gs_tty_driver->owner = THIS_MODULE; gs_tty_driver->driver_name = "g_serial"; gs_tty_driver->name = PREFIX; /* uses dynamically assigned dev_t values */ diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 1e30cc92719c..d4e724d9b1f4 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1235,7 +1235,6 @@ static int __init usb_serial_init(void) goto exit_bus; } - usb_serial_tty_driver->owner = THIS_MODULE; usb_serial_tty_driver->driver_name = "usbserial"; usb_serial_tty_driver->name = "ttyUSB"; usb_serial_tty_driver->major = SERIAL_TTY_MAJOR; diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index a2d4f5122a6a..7adb03ca51c2 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -1157,7 +1157,6 @@ int __init rfcomm_init_ttys(void) if (!rfcomm_tty_driver) return -ENOMEM; - rfcomm_tty_driver->owner = THIS_MODULE; rfcomm_tty_driver->driver_name = "rfcomm"; rfcomm_tty_driver->name = "rfcomm"; rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR; diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 253695d43fd9..828f88603d6c 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -122,7 +122,6 @@ static int __init ircomm_tty_init(void) return -ENOMEM; } - driver->owner = THIS_MODULE; driver->driver_name = "ircomm"; driver->name = "ircomm"; driver->major = IRCOMM_TTY_MAJOR; -- cgit v1.2.3 From 410235fd4d20b8feaf8930a0575d23acc088aa87 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:01 +0100 Subject: TTY: remove unneeded tty->index checks Checking if tty->index is in bounds is not needed. The tty has the index set in the initial open. This is done in get_tty_driver. And it can be only in interval <0,driver->num). So remove the tests which check exactly this interval. Some are left untouched as they check against the current backing device count. (Leaving apart that the check is racy in most of the cases.) Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/ia64/hp/sim/simserial.c | 9 +++------ arch/xtensa/platforms/iss/console.c | 8 ++------ drivers/char/pcmcia/synclink_cs.c | 2 +- drivers/isdn/capi/capi.c | 3 +-- drivers/isdn/gigaset/common.c | 2 -- drivers/isdn/i4l/isdn_tty.c | 7 ++----- drivers/s390/char/con3215.c | 8 ++------ drivers/tty/amiserial.c | 10 +++------- drivers/tty/cyclades.c | 6 +----- drivers/tty/hvc/hvcs.c | 24 ++++++++++-------------- drivers/tty/hvc/hvsi.c | 5 +---- drivers/tty/isicom.c | 2 -- drivers/tty/mxser.c | 2 -- drivers/tty/rocket.c | 6 +++--- drivers/tty/serial/68328serial.c | 9 ++------- drivers/tty/serial/crisv10.c | 15 +++------------ drivers/tty/synclink.c | 2 +- drivers/tty/synclink_gt.c | 2 +- drivers/tty/synclinkmp.c | 2 +- drivers/usb/gadget/u_serial.c | 3 --- net/irda/ircomm/ircomm_tty.c | 6 +----- 21 files changed, 38 insertions(+), 95 deletions(-) (limited to 'drivers/tty/serial') diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index f513dc02bb87..2a2fe0c56119 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -769,13 +769,10 @@ errout: static int rs_open(struct tty_struct *tty, struct file * filp) { struct async_struct *info; - int retval, line; + int retval; unsigned long page; - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) - return -ENODEV; - retval = get_async_struct(line, &info); + retval = get_async_struct(tty->index, &info); if (retval) return retval; tty->driver_data = info; @@ -920,7 +917,7 @@ simrs_init (void) if (!ia64_platform_is("hpsim")) return -ENODEV; - hp_simserial_driver = alloc_tty_driver(1); + hp_simserial_driver = alloc_tty_driver(NR_PORTS); if (!hp_simserial_driver) return -ENOMEM; diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 247e9d40a52e..19a802a13096 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -68,11 +68,6 @@ static void rs_poll(unsigned long); static int rs_open(struct tty_struct *tty, struct file * filp) { - int line = tty->index; - - if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES)) - return -ENODEV; - spin_lock(&timer_lock); if (tty->count == 1) { @@ -101,6 +96,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) { spin_lock(&timer_lock); if (tty->count == 1) + /* this will cause a deadlock if the timer ticks right now */ del_timer_sync(&serial_timer); spin_unlock(&timer_lock); } @@ -210,7 +206,7 @@ static const struct tty_operations serial_ops = { int __init rs_init(void) { - serial_driver = alloc_tty_driver(1); + serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES); printk ("%s %s\n", serial_name, serial_version); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index c3bcb1221e6b..f6453df4921c 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -2484,7 +2484,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) /* verify range of specified line number */ line = tty->index; - if ((line < 0) || (line >= mgslpc_device_count)) { + if (line >= mgslpc_device_count) { printk("%s(%d):mgslpc_open with invalid line #%d.\n", __FILE__,__LINE__,line); return -ENODEV; diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index baf08eba495c..3a7905b06e53 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1013,8 +1013,7 @@ static const struct file_operations capi_fops = static int capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty) { - int idx = tty->index; - struct capiminor *mp = capiminor_get(idx); + struct capiminor *mp = capiminor_get(tty->index); int ret = tty_standard_install(driver, tty); if (ret == 0) diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index db621db67f61..ac0186e54bf4 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -1051,8 +1051,6 @@ static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) { - if (tty->index < 0 || tty->index >= tty->driver->num) - return NULL; return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2c26b64ebbea..ac4840124bc0 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1590,12 +1590,9 @@ static int isdn_tty_open(struct tty_struct *tty, struct file *filp) { modem_info *info; - int retval, line; + int retval; - line = tty->index; - if (line < 0 || line >= ISDN_MAX_CHANNELS) - return -ENODEV; - info = &dev->mdm.info[line]; + info = &dev->mdm.info[tty->index]; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) return -ENODEV; if (!try_module_get(info->owner)) { diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index fe916bfd60f2..ed23fec7abbe 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -926,13 +926,9 @@ console_initcall(con3215_init); static int tty3215_open(struct tty_struct *tty, struct file * filp) { struct raw3215_info *raw; - int retval, line; + int retval; - line = tty->index; - if ((line < 0) || (line >= NR_3215)) - return -ENODEV; - - raw = raw3215[line]; + raw = raw3215[tty->index]; if (raw == NULL) return -ENODEV; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index b42f00d987ae..753286257554 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -1768,13 +1768,9 @@ static int get_async_struct(int line, struct async_struct **ret_info) static int rs_open(struct tty_struct *tty, struct file * filp) { struct async_struct *info; - int retval, line; + int retval; - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) { - return -ENODEV; - } - retval = get_async_struct(line, &info); + retval = get_async_struct(tty->index, &info); if (retval) { return retval; } @@ -1964,7 +1960,7 @@ static int __init amiga_serial_probe(struct platform_device *pdev) struct serial_state * state; int error; - serial_driver = alloc_tty_driver(1); + serial_driver = alloc_tty_driver(NR_PORTS); if (!serial_driver) return -ENOMEM; diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index bc7b5a5650ba..e61cabdd69df 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1515,13 +1515,9 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) static int cy_open(struct tty_struct *tty, struct file *filp) { struct cyclades_port *info; - unsigned int i, line; + unsigned int i, line = tty->index; int retval; - line = tty->index; - if (tty->index < 0 || NR_PORTS <= line) - return -ENODEV; - for (i = 0; i < NR_CARDS; i++) if (line < cy_card[i].first_line + cy_card[i].nports && line >= cy_card[i].first_line) diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index da0aa476804d..d23759183b47 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c @@ -1090,27 +1090,23 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, */ static struct hvcs_struct *hvcs_get_by_index(int index) { - struct hvcs_struct *hvcsd = NULL; + struct hvcs_struct *hvcsd; unsigned long flags; spin_lock(&hvcs_structs_lock); - /* We can immediately discard OOB requests */ - if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) { - list_for_each_entry(hvcsd, &hvcs_structs, next) { - spin_lock_irqsave(&hvcsd->lock, flags); - if (hvcsd->index == index) { - kref_get(&hvcsd->kref); - spin_unlock_irqrestore(&hvcsd->lock, flags); - spin_unlock(&hvcs_structs_lock); - return hvcsd; - } + list_for_each_entry(hvcsd, &hvcs_structs, next) { + spin_lock_irqsave(&hvcsd->lock, flags); + if (hvcsd->index == index) { + kref_get(&hvcsd->kref); spin_unlock_irqrestore(&hvcsd->lock, flags); + spin_unlock(&hvcs_structs_lock); + return hvcsd; } - hvcsd = NULL; + spin_unlock_irqrestore(&hvcsd->lock, flags); } - spin_unlock(&hvcs_structs_lock); - return hvcsd; + + return NULL; } /* diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index 60bc45164189..a7488b748647 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c @@ -737,14 +737,11 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) { struct hvsi_struct *hp; unsigned long flags; - int line = tty->index; int ret; pr_debug("%s\n", __func__); - if (line < 0 || line >= hvsi_count) - return -ENODEV; - hp = &hvsi_ports[line]; + hp = &hvsi_ports[tty->index]; tty->driver_data = hp; diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index b3a28b5f02ad..03c14979accf 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -849,8 +849,6 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) unsigned int board; int line = tty->index; - if (line < 0 || line > PORT_COUNT-1) - return NULL; board = BOARD(line); card = &isi_card[board]; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 260d03123524..17ff377e4129 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1010,8 +1010,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) line = tty->index; if (line == MXSER_PORTS) return 0; - if (line < 0 || line > MXSER_PORTS) - return -ENODEV; info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; if (!info->ioaddr) return -ENODEV; diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index b088e1ea4331..777d5f9cf6cc 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -892,12 +892,12 @@ static int rp_open(struct tty_struct *tty, struct file *filp) { struct r_port *info; struct tty_port *port; - int line = 0, retval; + int retval; CHANNEL_t *cp; unsigned long page; - line = tty->index; - if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL)) + info = rp_table[tty->index]; + if (info == NULL) return -ENXIO; port = &info->port; diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index a88ef9782a4f..7398390e7e65 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -1190,14 +1190,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, int rs_open(struct tty_struct *tty, struct file * filp) { struct m68k_serial *info; - int retval, line; - - line = tty->index; - - if (line >= NR_PORTS || line < 0) /* we have exactly one */ - return -ENODEV; + int retval; - info = &m68k_soft[line]; + info = &m68k_soft[tty->index]; if (serial_paranoia_check(info, tty->name, "rs_open")) return -ENODEV; diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 1dfba7b779c8..23d791696879 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -4105,20 +4105,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) { struct e100_serial *info; - int retval, line; + int retval; unsigned long page; int allocated_resources = 0; - /* find which port we want to open */ - line = tty->index; - - if (line < 0 || line >= NR_PORTS) - return -ENODEV; - - /* find the corresponding e100_serial struct in the table */ - info = rs_table + line; - - /* don't allow the opening of ports that are not enabled in the HW config */ + info = rs_table + tty->index; if (!info->enabled) return -ENODEV; @@ -4131,7 +4122,7 @@ rs_open(struct tty_struct *tty, struct file * filp) tty->driver_data = info; info->port.tty = tty; - info->port.tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + tty->low_latency = !!(info->flags & ASYNC_LOW_LATENCY); if (!tmp_buf) { page = get_zeroed_page(GFP_KERNEL); diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 2b2988c779c7..8e518da85fd5 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -3381,7 +3381,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) /* verify range of specified line number */ line = tty->index; - if ((line < 0) || (line >= mgsl_device_count)) { + if (line >= mgsl_device_count) { printk("%s(%d):mgsl_open with invalid line #%d.\n", __FILE__,__LINE__,line); return -ENODEV; diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index a8b66be37e6e..6bee4907c6a5 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -654,7 +654,7 @@ static int open(struct tty_struct *tty, struct file *filp) unsigned long flags; line = tty->index; - if ((line < 0) || (line >= slgt_device_count)) { + if (line >= slgt_device_count) { DBGERR(("%s: open with invalid line #%d.\n", driver_name, line)); return -ENODEV; } diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index ddabb61c85ba..4fb6c4b31b79 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -721,7 +721,7 @@ static int open(struct tty_struct *tty, struct file *filp) unsigned long flags; line = tty->index; - if ((line < 0) || (line >= synclinkmp_device_count)) { + if (line >= synclinkmp_device_count) { printk("%s(%d): open with invalid line #%d.\n", __FILE__,__LINE__,line); return -ENODEV; diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 490b01dd5d60..6c23938d2711 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -725,9 +725,6 @@ static int gs_open(struct tty_struct *tty, struct file *file) struct gs_port *port; int status; - if (port_num < 0 || port_num >= n_ports) - return -ENXIO; - do { mutex_lock(&ports[port_num].lock); port = ports[port_num].port; diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 828f88603d6c..6b9d5a0e42f9 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -365,16 +365,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) { struct ircomm_tty_cb *self; - unsigned int line; + unsigned int line = tty->index; unsigned long flags; int ret; IRDA_DEBUG(2, "%s()\n", __func__ ); - line = tty->index; - if (line >= IRCOMM_TTY_PORTS) - return -ENODEV; - /* Check if instance already exists */ self = hashbin_lock_find(ircomm_tty, line, NULL); if (!self) { -- cgit v1.2.3 From 4da2405606d47ca767e0c6ba556f127cfa2181d0 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:08 +0100 Subject: TTY: serial, use atomic_inc_return in ioc4_serial We want to know the value of the atomic variable in intr_connect after the increment. But atomic_inc doesn't, per definition, return the value. It is just a pure coincidence that ia64 defines atomic_inc as atomic_inc_return. So fix this mistake by using atomic_inc_return properly. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ioc4_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c index 6b36c1554d7e..dfec69a310ab 100644 --- a/drivers/tty/serial/ioc4_serial.c +++ b/drivers/tty/serial/ioc4_serial.c @@ -975,7 +975,7 @@ intr_connect(struct ioc4_soft *soft, int type, BUG_ON(!((type == IOC4_SIO_INTR_TYPE) || (type == IOC4_OTHER_INTR_TYPE))); - i = atomic_inc(&soft-> is_intr_type[type].is_num_intrs) - 1; + i = atomic_inc_return(&soft-> is_intr_type[type].is_num_intrs) - 1; BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0))); /* Save off the lower level interrupt handler */ -- cgit v1.2.3 From 8bc87dc999d57d7d2ab92ab203ff7e94e860d8fa Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:09 +0100 Subject: TTY: serial, include pci.h in m32r_sio It uses pointers to pci_dev, but compiler complains it doesn't know it: In file included from .../m32r_sio.c:53: .../m32r_sio.h:21: warning: "struct pci_dev" declared inside parameter list .../m32r_sio.h:21: warning: its scope is only this definition or declaration, which is probably not what you want .../m32r_sio.h:22: warning: "struct pci_dev" declared inside parameter list Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/m32r_sio.h index e9b7e11793b1..8129824496c6 100644 --- a/drivers/tty/serial/m32r_sio.h +++ b/drivers/tty/serial/m32r_sio.h @@ -15,6 +15,7 @@ * (at your option) any later version. */ +#include struct m32r_sio_probe { struct module *owner; -- cgit v1.2.3 From 11ba8899f96066600a7adeee28baed7a4a8cb7eb Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 5 Mar 2012 14:52:10 +0100 Subject: TTY: remove serialP.h inclusion from some files All of them do not use the ugly interface defined in that header. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/platforms/iss/console.c | 1 - drivers/tty/serial/ioc4_serial.c | 1 - drivers/tty/serial/m32r_sio.c | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index d1a7861b81f7..f9726f6afdf1 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c index dfec69a310ab..e16894fb2ca3 100644 --- a/drivers/tty/serial/ioc4_serial.c +++ b/drivers/tty/serial/ioc4_serial.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index e465dda63edf..a0703624d5e5 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From e0955acecf311f1079d2cc0d8c36b843b5db4ff6 Mon Sep 17 00:00:00 2001 From: Frank Benkert Date: Mon, 5 Mar 2012 16:14:29 +0100 Subject: mpc5200b/uart: select more tolerant uart prescaler on low baudrates In addition to the /32 prescaler, the MPC5200B supports a second baudrate prescaler /4 to reach higher baudrates. The current calculation (introduced with commit 0d1f22e4) in the kernel preferes this low prescaler as often as possible, but with some imprecise counterparts the communication on low baudrates fails. According a support-mail from freescale the low prescaler (/4) allows just 1% tolerance in bittiming in contrast to 4% of the high prescaler (/32). The prescaler not only affects the baudrate-calculation, but also the sampling of the bits on the wire. With this patch, we use the slightly less precise, but higher tolerant prescaler calculation on low baudrates up to (and including) 115200 baud and the more precise calculation above. Tested on a custom MPC5200B board with "fsl,mpc5200b-psc-uart". Calculation Examples with prescaler (PS) 4 and 32 and divisor (DIV) on various baudrates. Real stands for the real baudrate generated and Diff for the differences between: 50 Baud PS 32 DIV 0xa122 Real 50 Diff 0.00% 75 Baud PS 32 DIV 0x6b6c Real 75 Diff 0.00% 110 Baud PS 32 DIV 0x493e Real 110 Diff 0.00% 134 Baud PS 32 DIV 0x3c20 Real 133 Diff 0.75% 150 Baud PS 32 DIV 0x35b6 Real 150 Diff 0.00% 200 Baud PS 32 DIV 0x2849 Real 199 Diff 0.50% 300 Baud PS 4 DIV 0xd6d8 Real 300 Diff 0.00% PS 32 DIV 0x1adb Real 300 Diff 0.00% 600 Baud PS 4 DIV 0x6b6c Real 600 Diff 0.00% PS 32 DIV 0x0d6e Real 599 Diff 0.17% 1200 Baud PS 4 DIV 0x35b6 Real 1200 Diff 0.00% PS 32 DIV 0x06b7 Real 1199 Diff 0.08% 1800 Baud PS 4 DIV 0x23cf Real 1799 Diff 0.06% PS 32 DIV 0x047a Real 1799 Diff 0.06% 2400 Baud PS 4 DIV 0x1adb Real 2400 Diff 0.00% PS 32 DIV 0x035b Real 2401 Diff - 0.04% 4800 Baud PS 4 DIV 0x0d6e Real 4799 Diff 0.02% PS 32 DIV 0x01ae Real 4796 Diff 0.08% 9600 Baud PS 4 DIV 0x06b7 Real 9598 Diff 0.02% PS 32 DIV 0x00d7 Real 9593 Diff 0.07% 19200 Baud PS 4 DIV 0x035b Real 19208 Diff - 0.04% PS 32 DIV 0x006b Real 19275 Diff - 0.39% 38400 Baud PS 4 DIV 0x01ae Real 38372 Diff 0.07% PS 32 DIV 0x0036 Real 38194 Diff 0.54% 57600 Baud PS 4 DIV 0x011e Real 57692 Diff - 0.16% PS 32 DIV 0x0024 Real 57291 Diff 0.54% 76800 Baud PS 4 DIV 0x00d7 Real 76744 Diff 0.07% PS 32 DIV 0x001b Real 76388 Diff 0.54% 115200 Baud PS 4 DIV 0x008f Real 115384 Diff - 0.16% PS 32 DIV 0x0012 Real 114583 Diff 0.54% 153600 Baud PS 4 DIV 0x006b Real 154205 Diff - 0.39% PS 32 DIV 0x000d Real 158653 Diff - 3.29% 230400 Baud PS 4 DIV 0x0048 Real 229166 Diff 0.54% PS 32 DIV 0x0009 Real 229166 Diff 0.54% 307200 Baud PS 4 DIV 0x0036 Real 305555 Diff 0.54% PS 32 DIV 0x0007 Real 294642 Diff 4.09% 460800 Baud PS 4 DIV 0x0024 Real 458333 Diff 0.54% PS 32 DIV 0x0005 Real 412500 Diff 10.48% 500000 Baud PS 4 DIV 0x0021 Real 500000 Diff 0.00% PS 32 DIV 0x0004 Real 515625 Diff - 3.13% 576000 Baud PS 4 DIV 0x001d Real 568965 Diff 1.22% PS 32 DIV 0x0004 Real 515625 Diff 10.48% 614400 Baud PS 4 DIV 0x001b Real 611111 Diff 0.54% PS 32 DIV 0x0003 Real 687500 Diff -11.90% 921600 Baud PS 4 DIV 0x0012 Real 916666 Diff 0.54% PS 32 DIV 0x0002 Real 1031250 Diff -11.90% 1000000 Baud PS 4 DIV 0x0011 Real 970588 Diff 2.94% PS 32 DIV 0x0002 Real 1031250 Diff - 3.13% 1152000 Baud PS 4 DIV 0x000e Real 1178571 Diff - 2.31% PS 32 DIV 0x0002 Real 1031250 Diff 10.48% 1500000 Baud PS 4 DIV 0x000b Real 1500000 Diff 0.00% PS 32 DIV 0x0001 Real 2062500 Diff -37.50% 2000000 Baud PS 4 DIV 0x0008 Real 2062500 Diff - 3.13% PS 32 DIV 0x0001 Real 2062500 Diff - 3.13% 2500000 Baud PS 4 DIV 0x0007 Real 2357142 Diff 5.71% PS 32 DIV 0x0001 Real 2062500 Diff 17.50% 3000000 Baud PS 4 DIV 0x0006 Real 2750000 Diff 8.33% PS 32 DIV 0x0001 Real 2062500 Diff 31.25% 3500000 Baud PS 4 DIV 0x0005 Real 3300000 Diff 5.71% PS 32 DIV 0x0001 Real 2062500 Diff 41.07% 4000000 Baud PS 4 DIV 0x0004 Real 4125000 Diff - 3.13% PS 32 DIV 0x0001 Real 2062500 Diff 48.44% Signed-off-by: Frank Benkert Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpc52xx_uart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index e9a770d77a6e..bedac0d4c9ce 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -262,8 +262,9 @@ static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port, port->uartclk / 4); divisor = (port->uartclk + 2 * baud) / (4 * baud); - /* select the proper prescaler and set the divisor */ - if (divisor > 0xffff) { + /* select the proper prescaler and set the divisor + * prefer high prescaler for more tolerance on low baudrates */ + if (divisor > 0xffff || baud <= 115200) { divisor = (divisor + 4) / 8; prescaler = 0xdd00; /* /32 */ } else -- cgit v1.2.3 From a8a3ec9df2158d217494c9dd8db8a099ef4fb921 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 9 Mar 2012 09:51:48 -0800 Subject: pch_uart: Use uartclk instead of base_baud The term "base baud" refers to the fastest baud rate the device can communicate at. This is clock/16. pch_uart is using base_baud as the clock itself. Rename the variables to be semantically correct. Signed-off-by: Darren Hart CC: Tomoya MORINAGA CC: Feng Tang CC: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index aa4d07b4a9d5..5178213835c6 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -206,7 +206,7 @@ enum { #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -#define DEFAULT_BAUD_RATE 1843200 /* 1.8432MHz */ +#define DEFAULT_UARTCLK 1843200 /* 1.8432MHz */ struct pch_uart_buffer { unsigned char *buf; @@ -221,7 +221,7 @@ struct eg20t_port { unsigned int iobase; struct pci_dev *pdev; int fifo_size; - int base_baud; + int uartclk; int start_tx; int start_rx; int tx_empty; @@ -387,7 +387,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud, unsigned int dll, dlm, lcr; int div; - div = DIV_ROUND_CLOSEST(priv->base_baud / 16, baud); + div = DIV_ROUND_CLOSEST(priv->uartclk / 16, baud); if (div < 0 || USHRT_MAX <= div) { dev_err(priv->port.dev, "Invalid Baud(div=0x%x)\n", div); return -EINVAL; @@ -1205,9 +1205,9 @@ static int pch_uart_startup(struct uart_port *port) priv->tx_empty = 1; if (port->uartclk) - priv->base_baud = port->uartclk; + priv->uartclk = port->uartclk; else - port->uartclk = priv->base_baud; + port->uartclk = priv->uartclk; pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT); ret = pch_uart_hal_set_line(priv, default_baud, @@ -1557,7 +1557,7 @@ static int __init pch_console_setup(struct console *co, char *options) return -ENODEV; /* setup uartclock */ - port->uartclk = DEFAULT_BAUD_RATE; + port->uartclk = DEFAULT_UARTCLK; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -1600,7 +1600,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, unsigned int iobase; unsigned int mapbase; unsigned char *rxbuf; - int fifosize, base_baud; + int fifosize, uartclk; int port_type; struct pch_uart_driver_data *board; const char *board_name; @@ -1617,12 +1617,12 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, if (!rxbuf) goto init_port_free_txbuf; - base_baud = DEFAULT_BAUD_RATE; + uartclk = DEFAULT_UARTCLK; /* quirk for CM-iTC board */ board_name = dmi_get_system_info(DMI_BOARD_NAME); if (board_name && strstr(board_name, "CM-iTC")) - base_baud = 192000000; /* 192.0MHz */ + uartclk = 192000000; /* 192.0MHz */ switch (port_type) { case PORT_UNKNOWN: @@ -1648,7 +1648,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, priv->rxbuf.size = PAGE_SIZE; priv->fifo_size = fifosize; - priv->base_baud = base_baud; + priv->uartclk = uartclk; priv->port_type = PORT_MAX_8250 + port_type + 1; priv->port.dev = &pdev->dev; priv->port.iobase = iobase; -- cgit v1.2.3 From 077175f08e365629312ce32918e0c8047151763d Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 9 Mar 2012 09:51:49 -0800 Subject: pch_uart: Add Fish River Island II uart clock quirks Add support for the Fish River Island II (FRI2) UART clock following the CM-iTC quirk handling mechanism. Depending on the firmware installed on the device, the FRI2 uses a 48MHz or a 64MHz UART clock. This is detected with DMI strings. Add similar UART clock quirk handling to the pch_console_setup() function to enable kernel messages on boards with non-standard UART clocks. Per Alan's suggestion, abstract out UART clock selection into pch_uart_get_uartclk() to avoid code duplication. Signed-off-by: Darren Hart CC: Tomoya MORINAGA CC: Feng Tang CC: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 5178213835c6..88a1be058a44 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -206,7 +206,10 @@ enum { #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) -#define DEFAULT_UARTCLK 1843200 /* 1.8432MHz */ +#define DEFAULT_UARTCLK 1843200 /* 1.8432 MHz */ +#define CMITC_UARTCLK 192000000 /* 192.0000 MHz */ +#define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */ +#define FRI2_48_UARTCLK 48000000 /* 48.0000 MHz */ struct pch_uart_buffer { unsigned char *buf; @@ -364,6 +367,26 @@ static const struct file_operations port_regs_ops = { }; #endif /* CONFIG_DEBUG_FS */ +/* Return UART clock, checking for board specific clocks. */ +static int pch_uart_get_uartclk(void) +{ + const char *cmp; + + cmp = dmi_get_system_info(DMI_BOARD_NAME); + if (cmp && strstr(cmp, "CM-iTC")) + return CMITC_UARTCLK; + + cmp = dmi_get_system_info(DMI_BIOS_VERSION); + if (cmp && strnstr(cmp, "FRI2", 4)) + return FRI2_64_UARTCLK; + + cmp = dmi_get_system_info(DMI_PRODUCT_NAME); + if (cmp && strstr(cmp, "Fish River Island II")) + return FRI2_48_UARTCLK; + + return DEFAULT_UARTCLK; +} + static void pch_uart_hal_enable_interrupt(struct eg20t_port *priv, unsigned int flag) { @@ -1556,8 +1579,7 @@ static int __init pch_console_setup(struct console *co, char *options) if (!port || (!port->iobase && !port->membase)) return -ENODEV; - /* setup uartclock */ - port->uartclk = DEFAULT_UARTCLK; + port->uartclk = pch_uart_get_uartclk(); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -1600,10 +1622,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, unsigned int iobase; unsigned int mapbase; unsigned char *rxbuf; - int fifosize, uartclk; + int fifosize; int port_type; struct pch_uart_driver_data *board; - const char *board_name; char name[32]; /* for debugfs file name */ board = &drv_dat[id->driver_data]; @@ -1617,13 +1638,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, if (!rxbuf) goto init_port_free_txbuf; - uartclk = DEFAULT_UARTCLK; - - /* quirk for CM-iTC board */ - board_name = dmi_get_system_info(DMI_BOARD_NAME); - if (board_name && strstr(board_name, "CM-iTC")) - uartclk = 192000000; /* 192.0MHz */ - switch (port_type) { case PORT_UNKNOWN: fifosize = 256; /* EG20T/ML7213: UART0 */ @@ -1648,7 +1662,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, priv->rxbuf.size = PAGE_SIZE; priv->fifo_size = fifosize; - priv->uartclk = uartclk; + priv->uartclk = pch_uart_get_uartclk(); priv->port_type = PORT_MAX_8250 + port_type + 1; priv->port.dev = &pdev->dev; priv->port.iobase = iobase; -- cgit v1.2.3 From 2a44feb20bbe3db3b86bc5d976c8647cfda48588 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 9 Mar 2012 09:51:50 -0800 Subject: pch_uart: Add user_uartclk parameter For cases where boards with non-default clocks are not yet added to the kernel or when the clock varies across hardware revisions, it is useful to be able to specify the UART clock on the kernel command line. Add the user_uartclk parameter and prefer it, if set, to the default and board specific UART clock settings. Specify user_uartclock on the command-line with "pch_uart.user_uartclk=48000000". Signed-off-by: Darren Hart CC: Tomoya MORINAGA CC: Feng Tang CC: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 88a1be058a44..46f6fbf41d91 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -295,6 +295,7 @@ static struct pch_uart_driver_data drv_dat[] = { static struct eg20t_port *pch_uart_ports[PCH_UART_NR]; #endif static unsigned int default_baud = 9600; +static unsigned int user_uartclk = 0; static const int trigger_level_256[4] = { 1, 64, 128, 224 }; static const int trigger_level_64[4] = { 1, 16, 32, 56 }; static const int trigger_level_16[4] = { 1, 4, 8, 14 }; @@ -372,6 +373,9 @@ static int pch_uart_get_uartclk(void) { const char *cmp; + if (user_uartclk) + return user_uartclk; + cmp = dmi_get_system_info(DMI_BOARD_NAME); if (cmp && strstr(cmp, "CM-iTC")) return CMITC_UARTCLK; @@ -1860,3 +1864,4 @@ module_exit(pch_uart_module_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver"); module_param(default_baud, uint, S_IRUGO); +module_param(user_uartclk, uint, S_IRUGO); -- cgit v1.2.3 From 7ce9251d606780a53efc7dcdaa4518d93867c27f Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 9 Mar 2012 09:51:51 -0800 Subject: pch_uart: Use existing default_baud in setup_console Rather than hardcode 9600, use the existing default_baud parameter (which also defaults to 9600). Signed-off-by: Darren Hart CC: Tomoya MORINAGA CC: Feng Tang CC: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 46f6fbf41d91..cca742b01800 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1566,7 +1566,7 @@ pch_console_write(struct console *co, const char *s, unsigned int count) static int __init pch_console_setup(struct console *co, char *options) { struct uart_port *port; - int baud = 9600; + int baud = default_baud; int bits = 8; int parity = 'n'; int flow = 'n'; -- cgit v1.2.3 From a46f5533ecfc7bbdd646d84fdab8656031a715c6 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 9 Mar 2012 09:51:52 -0800 Subject: pch_uart: Add module parameter descriptions Document default_baud and user_uartclk module parameters. Signed-off-by: Darren Hart CC: Tomoya MORINAGA CC: Feng Tang CC: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index cca742b01800..332f2eb8abbc 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1864,4 +1864,8 @@ module_exit(pch_uart_module_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver"); module_param(default_baud, uint, S_IRUGO); +MODULE_PARM_DESC(default_baud, + "Default BAUD for initial driver state and console (default 9600)"); module_param(user_uartclk, uint, S_IRUGO); +MODULE_PARM_DESC(user_uartclk, + "Override UART default or board specific UART clock"); -- cgit v1.2.3 From 0acf519f3f22450ae8f90cdb0f77b046fc731624 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 8 Mar 2012 19:12:08 -0500 Subject: serial: delete last unused traces of pausing I/O in 8250 This is the last traces of pausing I/O that we had back some twenty years ago. Probably was only required for 8MHz ISA cards running "on the edge" at 12MHz. Anyway it hasn't been in use for years, so lets just bury it for good. Signed-off-by: Paul Gortmaker Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 308 ++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 158 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 917ab8452746..9674eac5535c 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -486,26 +486,18 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) (up->port.serial_in(&(up)->port, (offset))) #define serial_out(up, offset, value) \ (up->port.serial_out(&(up)->port, (offset), (value))) -/* - * We used to support using pause I/O for certain machines. We - * haven't supported this for a while, but just in case it's badly - * needed for certain old 386 machines, I've left these #define's - * in.... - */ -#define serial_inp(up, offset) serial_in(up, offset) -#define serial_outp(up, offset, value) serial_out(up, offset, value) /* Uart divisor latch read */ static inline int _serial_dl_read(struct uart_8250_port *up) { - return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8; + return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; } /* Uart divisor latch write */ static inline void _serial_dl_write(struct uart_8250_port *up, int value) { - serial_outp(up, UART_DLL, value & 0xff); - serial_outp(up, UART_DLM, value >> 8 & 0xff); + serial_out(up, UART_DLL, value & 0xff); + serial_out(up, UART_DLM, value >> 8 & 0xff); } #if defined(CONFIG_MIPS_ALCHEMY) @@ -575,10 +567,10 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) static void serial8250_clear_fifos(struct uart_8250_port *p) { if (p->capabilities & UART_CAP_FIFO) { - serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO | + serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(p, UART_FCR, 0); + serial_out(p, UART_FCR, 0); } } @@ -591,15 +583,15 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) { if (p->capabilities & UART_CAP_SLEEP) { if (p->capabilities & UART_CAP_EFR) { - serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(p, UART_EFR, UART_EFR_ECB); - serial_outp(p, UART_LCR, 0); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, UART_EFR_ECB); + serial_out(p, UART_LCR, 0); } - serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); + serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0); if (p->capabilities & UART_CAP_EFR) { - serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(p, UART_EFR, 0); - serial_outp(p, UART_LCR, 0); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(p, UART_EFR, 0); + serial_out(p, UART_LCR, 0); } } } @@ -614,12 +606,12 @@ static int __enable_rsa(struct uart_8250_port *up) unsigned char mode; int result; - mode = serial_inp(up, UART_RSA_MSR); + mode = serial_in(up, UART_RSA_MSR); result = mode & UART_RSA_MSR_FIFO; if (!result) { - serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); - mode = serial_inp(up, UART_RSA_MSR); + serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); result = mode & UART_RSA_MSR_FIFO; } @@ -638,7 +630,7 @@ static void enable_rsa(struct uart_8250_port *up) spin_unlock_irq(&up->port.lock); } if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) - serial_outp(up, UART_RSA_FRR, 0); + serial_out(up, UART_RSA_FRR, 0); } } @@ -657,12 +649,12 @@ static void disable_rsa(struct uart_8250_port *up) up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { spin_lock_irq(&up->port.lock); - mode = serial_inp(up, UART_RSA_MSR); + mode = serial_in(up, UART_RSA_MSR); result = !(mode & UART_RSA_MSR_FIFO); if (!result) { - serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); - mode = serial_inp(up, UART_RSA_MSR); + serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); + mode = serial_in(up, UART_RSA_MSR); result = !(mode & UART_RSA_MSR_FIFO); } @@ -683,28 +675,28 @@ static int size_fifo(struct uart_8250_port *up) unsigned short old_dl; int count; - old_lcr = serial_inp(up, UART_LCR); - serial_outp(up, UART_LCR, 0); - old_fcr = serial_inp(up, UART_FCR); - old_mcr = serial_inp(up, UART_MCR); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | + old_lcr = serial_in(up, UART_LCR); + serial_out(up, UART_LCR, 0); + old_fcr = serial_in(up, UART_FCR); + old_mcr = serial_in(up, UART_MCR); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(up, UART_MCR, UART_MCR_LOOP); - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_out(up, UART_MCR, UART_MCR_LOOP); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); old_dl = serial_dl_read(up); serial_dl_write(up, 0x0001); - serial_outp(up, UART_LCR, 0x03); + serial_out(up, UART_LCR, 0x03); for (count = 0; count < 256; count++) - serial_outp(up, UART_TX, count); + serial_out(up, UART_TX, count); mdelay(20);/* FIXME - schedule_timeout */ - for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) && + for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) && (count < 256); count++) - serial_inp(up, UART_RX); - serial_outp(up, UART_FCR, old_fcr); - serial_outp(up, UART_MCR, old_mcr); - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_in(up, UART_RX); + serial_out(up, UART_FCR, old_fcr); + serial_out(up, UART_MCR, old_mcr); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_dl_write(up, old_dl); - serial_outp(up, UART_LCR, old_lcr); + serial_out(up, UART_LCR, old_lcr); return count; } @@ -719,20 +711,20 @@ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) unsigned char old_dll, old_dlm, old_lcr; unsigned int id; - old_lcr = serial_inp(p, UART_LCR); - serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A); + old_lcr = serial_in(p, UART_LCR); + serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); - old_dll = serial_inp(p, UART_DLL); - old_dlm = serial_inp(p, UART_DLM); + old_dll = serial_in(p, UART_DLL); + old_dlm = serial_in(p, UART_DLM); - serial_outp(p, UART_DLL, 0); - serial_outp(p, UART_DLM, 0); + serial_out(p, UART_DLL, 0); + serial_out(p, UART_DLM, 0); - id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8; + id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8; - serial_outp(p, UART_DLL, old_dll); - serial_outp(p, UART_DLM, old_dlm); - serial_outp(p, UART_LCR, old_lcr); + serial_out(p, UART_DLL, old_dll); + serial_out(p, UART_DLM, old_dlm); + serial_out(p, UART_LCR, old_lcr); return id; } @@ -842,11 +834,11 @@ static void autoconfig_8250(struct uart_8250_port *up) up->port.type = PORT_8250; scratch = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, 0xa5); + serial_out(up, UART_SCR, 0xa5); status1 = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, 0x5a); + serial_out(up, UART_SCR, 0x5a); status2 = serial_in(up, UART_SCR); - serial_outp(up, UART_SCR, scratch); + serial_out(up, UART_SCR, scratch); if (status1 == 0xa5 && status2 == 0x5a) up->port.type = PORT_16450; @@ -877,7 +869,7 @@ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) } else { status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ - serial_outp(up, 0x04, status); + serial_out(up, 0x04, status); } return 1; } @@ -900,9 +892,9 @@ static void autoconfig_16550a(struct uart_8250_port *up) * Check for presence of the EFR when DLAB is set. * Only ST16C650V1 UARTs pass this test. */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); if (serial_in(up, UART_EFR) == 0) { - serial_outp(up, UART_EFR, 0xA8); + serial_out(up, UART_EFR, 0xA8); if (serial_in(up, UART_EFR) != 0) { DEBUG_AUTOCONF("EFRv1 "); up->port.type = PORT_16650; @@ -910,7 +902,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) } else { DEBUG_AUTOCONF("Motorola 8xxx DUART "); } - serial_outp(up, UART_EFR, 0); + serial_out(up, UART_EFR, 0); return; } @@ -918,7 +910,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) * Maybe it requires 0xbf to be written to the LCR. * (other ST16C650V2 UARTs, TI16C752A, etc) */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) { DEBUG_AUTOCONF("EFRv2 "); autoconfig_has_efr(up); @@ -932,23 +924,23 @@ static void autoconfig_16550a(struct uart_8250_port *up) * switch back to bank 2, read it from EXCR1 again and check * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2 */ - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0); status1 = serial_in(up, UART_MCR); - serial_outp(up, UART_LCR, 0xE0); + serial_out(up, UART_LCR, 0xE0); status2 = serial_in(up, 0x02); /* EXCR1 */ if (!((status2 ^ status1) & UART_MCR_LOOP)) { - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP); - serial_outp(up, UART_LCR, 0xE0); + serial_out(up, UART_LCR, 0); + serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP); + serial_out(up, UART_LCR, 0xE0); status2 = serial_in(up, 0x02); /* EXCR1 */ - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_MCR, status1); + serial_out(up, UART_LCR, 0); + serial_out(up, UART_MCR, status1); if ((status2 ^ status1) & UART_MCR_LOOP) { unsigned short quot; - serial_outp(up, UART_LCR, 0xE0); + serial_out(up, UART_LCR, 0xE0); quot = serial_dl_read(up); quot <<= 3; @@ -956,7 +948,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) if (ns16550a_goto_highspeed(up)) serial_dl_write(up, quot); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0); up->port.uartclk = 921600*16; up->port.type = PORT_NS16550A; @@ -971,15 +963,15 @@ static void autoconfig_16550a(struct uart_8250_port *up) * Try setting it with and without DLAB set. Cheap clones * set bit 5 without DLAB set. */ - serial_outp(up, UART_LCR, 0); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + serial_out(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); status1 = serial_in(up, UART_IIR) >> 5; - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); status2 = serial_in(up, UART_IIR) >> 5; - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_LCR, 0); DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2); @@ -998,13 +990,13 @@ static void autoconfig_16550a(struct uart_8250_port *up) * already a 1 and maybe locked there before we even start start. */ iersave = serial_in(up, UART_IER); - serial_outp(up, UART_IER, iersave & ~UART_IER_UUE); + serial_out(up, UART_IER, iersave & ~UART_IER_UUE); if (!(serial_in(up, UART_IER) & UART_IER_UUE)) { /* * OK it's in a known zero state, try writing and reading * without disturbing the current state of the other bits. */ - serial_outp(up, UART_IER, iersave | UART_IER_UUE); + serial_out(up, UART_IER, iersave | UART_IER_UUE); if (serial_in(up, UART_IER) & UART_IER_UUE) { /* * It's an Xscale. @@ -1022,7 +1014,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) */ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); } - serial_outp(up, UART_IER, iersave); + serial_out(up, UART_IER, iersave); /* * Exar uarts have EFR in a weird location @@ -1084,8 +1076,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * Note: this is safe as long as MCR bit 4 is clear * and the device is in "PC" mode. */ - scratch = serial_inp(up, UART_IER); - serial_outp(up, UART_IER, 0); + scratch = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0); #ifdef __i386__ outb(0xff, 0x080); #endif @@ -1093,13 +1085,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * Mask out IER[7:4] bits for test as some UARTs (e.g. TL * 16C754B) allow only to modify them if an EFR bit is set. */ - scratch2 = serial_inp(up, UART_IER) & 0x0f; - serial_outp(up, UART_IER, 0x0F); + scratch2 = serial_in(up, UART_IER) & 0x0f; + serial_out(up, UART_IER, 0x0F); #ifdef __i386__ outb(0, 0x080); #endif - scratch3 = serial_inp(up, UART_IER) & 0x0f; - serial_outp(up, UART_IER, scratch); + scratch3 = serial_in(up, UART_IER) & 0x0f; + serial_out(up, UART_IER, scratch); if (scratch2 != 0 || scratch3 != 0x0F) { /* * We failed; there's nothing here @@ -1123,9 +1115,9 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * that conflicts with COM 1-4 --- we hope! */ if (!(up->port.flags & UPF_SKIP_TEST)) { - serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); - status1 = serial_inp(up, UART_MSR) & 0xF0; - serial_outp(up, UART_MCR, save_mcr); + serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A); + status1 = serial_in(up, UART_MSR) & 0xF0; + serial_out(up, UART_MCR, save_mcr); if (status1 != 0x90) { DEBUG_AUTOCONF("LOOP test failed (%02x) ", status1); @@ -1142,11 +1134,11 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * We also initialise the EFR (if any) to zero for later. The * EFR occupies the same register location as the FCR and IIR. */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(up, UART_EFR, 0); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_EFR, 0); + serial_out(up, UART_LCR, 0); - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(up, UART_IIR) >> 6; DEBUG_AUTOCONF("iir=%d ", scratch); @@ -1183,7 +1175,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) } #endif - serial_outp(up, UART_LCR, save_lcr); + serial_out(up, UART_LCR, save_lcr); if (up->capabilities != uart_config[up->port.type].flags) { printk(KERN_WARNING @@ -1204,15 +1196,15 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) */ #ifdef CONFIG_SERIAL_8250_RSA if (up->port.type == PORT_RSA) - serial_outp(up, UART_RSA_FRR, 0); + serial_out(up, UART_RSA_FRR, 0); #endif - serial_outp(up, UART_MCR, save_mcr); + serial_out(up, UART_MCR, save_mcr); serial8250_clear_fifos(up); serial_in(up, UART_RX); if (up->capabilities & UART_CAP_UUE) - serial_outp(up, UART_IER, UART_IER_UUE); + serial_out(up, UART_IER, UART_IER_UUE); else - serial_outp(up, UART_IER, 0); + serial_out(up, UART_IER, 0); out: spin_unlock_irqrestore(&up->port.lock, flags); @@ -1236,31 +1228,31 @@ static void autoconfig_irq(struct uart_8250_port *up) /* forget possible initially masked and pending IRQ */ probe_irq_off(probe_irq_on()); - save_mcr = serial_inp(up, UART_MCR); - save_ier = serial_inp(up, UART_IER); - serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); + save_mcr = serial_in(up, UART_MCR); + save_ier = serial_in(up, UART_IER); + serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); irqs = probe_irq_on(); - serial_outp(up, UART_MCR, 0); + serial_out(up, UART_MCR, 0); udelay(10); if (up->port.flags & UPF_FOURPORT) { - serial_outp(up, UART_MCR, + serial_out(up, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); } else { - serial_outp(up, UART_MCR, + serial_out(up, UART_MCR, UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); } - serial_outp(up, UART_IER, 0x0f); /* enable all intrs */ - (void)serial_inp(up, UART_LSR); - (void)serial_inp(up, UART_RX); - (void)serial_inp(up, UART_IIR); - (void)serial_inp(up, UART_MSR); - serial_outp(up, UART_TX, 0xFF); + serial_out(up, UART_IER, 0x0f); /* enable all intrs */ + (void)serial_in(up, UART_LSR); + (void)serial_in(up, UART_RX); + (void)serial_in(up, UART_IIR); + (void)serial_in(up, UART_MSR); + serial_out(up, UART_TX, 0xFF); udelay(20); irq = probe_irq_off(irqs); - serial_outp(up, UART_MCR, save_mcr); - serial_outp(up, UART_IER, save_ier); + serial_out(up, UART_MCR, save_mcr); + serial_out(up, UART_IER, save_ier); if (up->port.flags & UPF_FOURPORT) outb_p(save_ICP, ICP); @@ -1380,7 +1372,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) do { if (likely(lsr & UART_LSR_DR)) - ch = serial_inp(up, UART_RX); + ch = serial_in(up, UART_RX); else /* * Intel 82571 has a Serial Over Lan device that will @@ -1445,7 +1437,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); ignore_char: - lsr = serial_inp(up, UART_LSR); + lsr = serial_in(up, UART_LSR); } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); spin_unlock(&up->port.lock); tty_flip_buffer_push(tty); @@ -1460,7 +1452,7 @@ void serial8250_tx_chars(struct uart_8250_port *up) int count; if (up->port.x_char) { - serial_outp(up, UART_TX, up->port.x_char); + serial_out(up, UART_TX, up->port.x_char); up->port.icount.tx++; up->port.x_char = 0; return; @@ -1532,7 +1524,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) spin_lock_irqsave(&up->port.lock, flags); - status = serial_inp(up, UART_LSR); + status = serial_in(up, UART_LSR); DEBUG_INTR("status = %x...", status); @@ -1894,12 +1886,12 @@ static int serial8250_get_poll_char(struct uart_port *port) { struct uart_8250_port *up = container_of(port, struct uart_8250_port, port); - unsigned char lsr = serial_inp(up, UART_LSR); + unsigned char lsr = serial_in(up, UART_LSR); if (!(lsr & UART_LSR_DR)) return NO_POLL_CHAR; - return serial_inp(up, UART_RX); + return serial_in(up, UART_RX); } @@ -1959,14 +1951,14 @@ static int serial8250_startup(struct uart_port *port) if (up->port.type == PORT_16C950) { /* Wake up and initialize UART */ up->acr = 0; - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(up, UART_EFR, UART_EFR_ECB); - serial_outp(up, UART_IER, 0); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_EFR, UART_EFR_ECB); + serial_out(up, UART_IER, 0); + serial_out(up, UART_LCR, 0); serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_outp(up, UART_EFR, UART_EFR_ECB); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_EFR, UART_EFR_ECB); + serial_out(up, UART_LCR, 0); } #ifdef CONFIG_SERIAL_8250_RSA @@ -1986,10 +1978,10 @@ static int serial8250_startup(struct uart_port *port) /* * Clear the interrupt registers. */ - (void) serial_inp(up, UART_LSR); - (void) serial_inp(up, UART_RX); - (void) serial_inp(up, UART_IIR); - (void) serial_inp(up, UART_MSR); + (void) serial_in(up, UART_LSR); + (void) serial_in(up, UART_RX); + (void) serial_in(up, UART_IIR); + (void) serial_in(up, UART_MSR); /* * At this point, there's no way the LSR could still be 0xff; @@ -1997,7 +1989,7 @@ static int serial8250_startup(struct uart_port *port) * here. */ if (!(up->port.flags & UPF_BUGGY_UART) && - (serial_inp(up, UART_LSR) == 0xff)) { + (serial_in(up, UART_LSR) == 0xff)) { printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", serial_index(&up->port)); return -ENODEV; @@ -2009,15 +2001,15 @@ static int serial8250_startup(struct uart_port *port) if (up->port.type == PORT_16850) { unsigned char fctr; - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); - serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX); - serial_outp(up, UART_TRG, UART_TRG_96); - serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX); - serial_outp(up, UART_TRG, UART_TRG_96); + fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); + serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX); + serial_out(up, UART_TRG, UART_TRG_96); + serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX); + serial_out(up, UART_TRG, UART_TRG_96); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0); } if (up->port.irq) { @@ -2087,7 +2079,7 @@ static int serial8250_startup(struct uart_port *port) /* * Now, initialize the UART */ - serial_outp(up, UART_LCR, UART_LCR_WLEN8); + serial_out(up, UART_LCR, UART_LCR_WLEN8); spin_lock_irqsave(&up->port.lock, flags); if (up->port.flags & UPF_FOURPORT) { @@ -2120,10 +2112,10 @@ static int serial8250_startup(struct uart_port *port) * Do a quick test to see if we receive an * interrupt when we enable the TX irq. */ - serial_outp(up, UART_IER, UART_IER_THRI); + serial_out(up, UART_IER, UART_IER_THRI); lsr = serial_in(up, UART_LSR); iir = serial_in(up, UART_IIR); - serial_outp(up, UART_IER, 0); + serial_out(up, UART_IER, 0); if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { if (!(up->bugs & UART_BUG_TXEN)) { @@ -2143,10 +2135,10 @@ dont_test_tx_en: * saved flags to avoid getting false values from polling * routines or the previous session. */ - serial_inp(up, UART_LSR); - serial_inp(up, UART_RX); - serial_inp(up, UART_IIR); - serial_inp(up, UART_MSR); + serial_in(up, UART_LSR); + serial_in(up, UART_RX); + serial_in(up, UART_IIR); + serial_in(up, UART_MSR); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; @@ -2156,7 +2148,7 @@ dont_test_tx_en: * anyway, so we don't enable them here. */ up->ier = UART_IER_RLSI | UART_IER_RDI; - serial_outp(up, UART_IER, up->ier); + serial_out(up, UART_IER, up->ier); if (up->port.flags & UPF_FOURPORT) { unsigned int icp; @@ -2181,7 +2173,7 @@ static void serial8250_shutdown(struct uart_port *port) * Disable interrupts from this port */ up->ier = 0; - serial_outp(up, UART_IER, 0); + serial_out(up, UART_IER, 0); spin_lock_irqsave(&up->port.lock, flags); if (up->port.flags & UPF_FOURPORT) { @@ -2197,7 +2189,7 @@ static void serial8250_shutdown(struct uart_port *port) /* * Disable break condition and FIFOs */ - serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); + serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); serial8250_clear_fifos(up); #ifdef CONFIG_SERIAL_8250_RSA @@ -2374,11 +2366,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & CRTSCTS) efr |= UART_EFR_CTS; - serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); if (up->port.flags & UPF_EXAR_EFR) - serial_outp(up, UART_XR_EFR, efr); + serial_out(up, UART_XR_EFR, efr); else - serial_outp(up, UART_EFR, efr); + serial_out(up, UART_EFR, efr); } #ifdef CONFIG_ARCH_OMAP @@ -2394,9 +2386,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (up->capabilities & UART_NATSEMI) { /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */ - serial_outp(up, UART_LCR, 0xe0); + serial_out(up, UART_LCR, 0xe0); } else { - serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ } serial_dl_write(up, quot); @@ -2406,16 +2398,16 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * is written without DLAB set, this mode will be disabled. */ if (up->port.type == PORT_16750) - serial_outp(up, UART_FCR, fcr); + serial_out(up, UART_FCR, fcr); - serial_outp(up, UART_LCR, cval); /* reset DLAB */ + serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ if (up->port.type != PORT_16750) { if (fcr & UART_FCR_ENABLE_FIFO) { /* emulated UARTs (Lucent Venus 167x) need two steps */ - serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); } - serial_outp(up, UART_FCR, fcr); /* set fcr */ + serial_out(up, UART_FCR, fcr); /* set fcr */ } serial8250_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags); @@ -2997,11 +2989,11 @@ void serial8250_resume_port(int line) if (up->capabilities & UART_NATSEMI) { /* Ensure it's still in high speed mode */ - serial_outp(up, UART_LCR, 0xE0); + serial_out(up, UART_LCR, 0xE0); ns16550a_goto_highspeed(up); - serial_outp(up, UART_LCR, 0); + serial_out(up, UART_LCR, 0); up->port.uartclk = 921600*16; } uart_resume_port(&serial8250_reg, &up->port); -- cgit v1.2.3 From 3f0ab32753b49ae7afc5b69e3f23152d92aa1f85 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 8 Mar 2012 19:12:09 -0500 Subject: serial: make 8250's serial_in shareable to other drivers. Currently 8250.c has serial_in and serial_out as shortcuts to doing the port I/O. They are implemented as macros a ways down in the file. This isn't by accident, but is implicitly required, so cpp doesn't mangle other instances of the common string "serial_in", as it exists as a field in the port struct itself. The above mangling avoidance violates the principle of least surprise, and it also prevents the shortcuts from being relocated up to the top of file, or into 8250.h -- either being a better location than the current one. Move them to 8250.h so other 8250-like drivers can also use the shortcuts, and in the process, make the conflicting names go away by using static inlines instead of macros. The object file size remains unchanged with this modification. Signed-off-by: Paul Gortmaker Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 5 ----- drivers/tty/serial/8250/8250.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 9674eac5535c..4009e2438e40 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -482,11 +482,6 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) } } -#define serial_in(up, offset) \ - (up->port.serial_in(&(up)->port, (offset))) -#define serial_out(up, offset, value) \ - (up->port.serial_out(&(up)->port, (offset), (value))) - /* Uart divisor latch read */ static inline int _serial_dl_read(struct uart_8250_port *up) { diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index ae027be57e25..2868a1da254d 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -86,6 +86,16 @@ struct serial8250_config { #define SERIAL8250_SHARE_IRQS 0 #endif +static inline int serial_in(struct uart_8250_port *up, int offset) +{ + return up->port.serial_in(&up->port, offset); +} + +static inline void serial_out(struct uart_8250_port *up, int offset, int value) +{ + up->port.serial_out(&up->port, offset, value); +} + #if defined(__alpha__) && !defined(CONFIG_PCI) /* * Digital did something really horribly wrong with the OUT1 and OUT2 -- cgit v1.2.3 From 0d263a264c4b8376ccf33248f6fac873310e5e05 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 8 Mar 2012 19:12:10 -0500 Subject: serial: delete useless void casts in 8250.c These might have worked some magic with an ancient gcc back in 1992, but "objdump --disassemble" on gcc 4.6 on x86-64 shows identical output before and after this commit. Send the casts and their hysterical rasins to the bitbucket. Signed-off-by: Paul Gortmaker Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 4009e2438e40..6a71716111ae 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -1218,7 +1218,7 @@ static void autoconfig_irq(struct uart_8250_port *up) ICP = (up->port.iobase & 0xfe0) | 0x1f; save_ICP = inb_p(ICP); outb_p(0x80, ICP); - (void) inb_p(ICP); + inb_p(ICP); } /* forget possible initially masked and pending IRQ */ @@ -1238,10 +1238,10 @@ static void autoconfig_irq(struct uart_8250_port *up) UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); } serial_out(up, UART_IER, 0x0f); /* enable all intrs */ - (void)serial_in(up, UART_LSR); - (void)serial_in(up, UART_RX); - (void)serial_in(up, UART_IIR); - (void)serial_in(up, UART_MSR); + serial_in(up, UART_LSR); + serial_in(up, UART_RX); + serial_in(up, UART_IIR); + serial_in(up, UART_MSR); serial_out(up, UART_TX, 0xFF); udelay(20); irq = probe_irq_off(irqs); @@ -1973,10 +1973,10 @@ static int serial8250_startup(struct uart_port *port) /* * Clear the interrupt registers. */ - (void) serial_in(up, UART_LSR); - (void) serial_in(up, UART_RX); - (void) serial_in(up, UART_IIR); - (void) serial_in(up, UART_MSR); + serial_in(up, UART_LSR); + serial_in(up, UART_RX); + serial_in(up, UART_IIR); + serial_in(up, UART_MSR); /* * At this point, there's no way the LSR could still be 0xff; @@ -2152,7 +2152,7 @@ dont_test_tx_en: */ icp = (up->port.iobase & 0xfe0) | 0x01f; outb_p(0x80, icp); - (void) inb_p(icp); + inb_p(icp); } return 0; @@ -2198,7 +2198,7 @@ static void serial8250_shutdown(struct uart_port *port) * Read data port to reset things, and then unlink from * the IRQ chain. */ - (void) serial_in(up, UART_RX); + serial_in(up, UART_RX); del_timer_sync(&up->timer); up->timer.function = serial8250_timeout; -- cgit v1.2.3 From dfe42443ea1d30c98db59b7b1f914bc147d31336 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 8 Mar 2012 19:12:11 -0500 Subject: serial: reduce number of indirections in 8250 code The serial_8250_port struct contains within a serial_port struct and many times one or the other, or both are in scope within functions via a passed in arg, or via container_of. However there are a lot of cases where we have access directly to the port pointer, but yet go through the parent 8250_port structure instead to get it. These should just use the port struct directly. Similarly there are cases where it makes sense (from a code cleanliness point of view) to declare a local for the port struct, so we aren't going through the parent 8250_port struct repeatedly to get to it. We get a small reduction in text size, but it appears that gcc was smart enough to internally be doing most of this already, so the readability improvement is the larger gain. Signed-off-by: Paul Gortmaker Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 322 +++++++++++++++++++++-------------------- 1 file changed, 167 insertions(+), 155 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 6a71716111ae..a0d114d8baef 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -1040,24 +1040,25 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) { unsigned char status1, scratch, scratch2, scratch3; unsigned char save_lcr, save_mcr; + struct uart_port *port = &up->port; unsigned long flags; - if (!up->port.iobase && !up->port.mapbase && !up->port.membase) + if (!port->iobase && !port->mapbase && !port->membase) return; DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ", - serial_index(&up->port), up->port.iobase, up->port.membase); + serial_index(port), port->iobase, port->membase); /* * We really do need global IRQs disabled here - we're going to * be frobbing the chips IRQ enable register to see if it exists. */ - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); up->capabilities = 0; up->bugs = 0; - if (!(up->port.flags & UPF_BUGGY_UART)) { + if (!(port->flags & UPF_BUGGY_UART)) { /* * Do a simple existence test first; if we fail this, * there's no point trying anything else. @@ -1109,7 +1110,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) * manufacturer would be stupid enough to design a board * that conflicts with COM 1-4 --- we hope! */ - if (!(up->port.flags & UPF_SKIP_TEST)) { + if (!(port->flags & UPF_SKIP_TEST)) { serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A); status1 = serial_in(up, UART_MSR) & 0xF0; serial_out(up, UART_MCR, save_mcr); @@ -1143,10 +1144,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) autoconfig_8250(up); break; case 1: - up->port.type = PORT_UNKNOWN; + port->type = PORT_UNKNOWN; break; case 2: - up->port.type = PORT_16550; + port->type = PORT_16550; break; case 3: autoconfig_16550a(up); @@ -1157,13 +1158,12 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) /* * Only probe for RSA ports if we got the region. */ - if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) { + if (port->type == PORT_16550A && probeflags & PROBE_RSA) { int i; for (i = 0 ; i < probe_rsa_count; ++i) { - if (probe_rsa[i] == up->port.iobase && - __enable_rsa(up)) { - up->port.type = PORT_RSA; + if (probe_rsa[i] == port->iobase && __enable_rsa(up)) { + port->type = PORT_RSA; break; } } @@ -1172,25 +1172,25 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_out(up, UART_LCR, save_lcr); - if (up->capabilities != uart_config[up->port.type].flags) { + if (up->capabilities != uart_config[port->type].flags) { printk(KERN_WARNING "ttyS%d: detected caps %08x should be %08x\n", - serial_index(&up->port), up->capabilities, - uart_config[up->port.type].flags); + serial_index(port), up->capabilities, + uart_config[port->type].flags); } - up->port.fifosize = uart_config[up->port.type].fifo_size; - up->capabilities = uart_config[up->port.type].flags; - up->tx_loadsz = uart_config[up->port.type].tx_loadsz; + port->fifosize = uart_config[up->port.type].fifo_size; + up->capabilities = uart_config[port->type].flags; + up->tx_loadsz = uart_config[port->type].tx_loadsz; - if (up->port.type == PORT_UNKNOWN) + if (port->type == PORT_UNKNOWN) goto out; /* * Reset the UART. */ #ifdef CONFIG_SERIAL_8250_RSA - if (up->port.type == PORT_RSA) + if (port->type == PORT_RSA) serial_out(up, UART_RSA_FRR, 0); #endif serial_out(up, UART_MCR, save_mcr); @@ -1202,20 +1202,21 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_out(up, UART_IER, 0); out: - spin_unlock_irqrestore(&up->port.lock, flags); - DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); + spin_unlock_irqrestore(&port->lock, flags); + DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name); } static void autoconfig_irq(struct uart_8250_port *up) { + struct uart_port *port = &up->port; unsigned char save_mcr, save_ier; unsigned char save_ICP = 0; unsigned int ICP = 0; unsigned long irqs; int irq; - if (up->port.flags & UPF_FOURPORT) { - ICP = (up->port.iobase & 0xfe0) | 0x1f; + if (port->flags & UPF_FOURPORT) { + ICP = (port->iobase & 0xfe0) | 0x1f; save_ICP = inb_p(ICP); outb_p(0x80, ICP); inb_p(ICP); @@ -1230,7 +1231,7 @@ static void autoconfig_irq(struct uart_8250_port *up) irqs = probe_irq_on(); serial_out(up, UART_MCR, 0); udelay(10); - if (up->port.flags & UPF_FOURPORT) { + if (port->flags & UPF_FOURPORT) { serial_out(up, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); } else { @@ -1249,10 +1250,10 @@ static void autoconfig_irq(struct uart_8250_port *up) serial_out(up, UART_MCR, save_mcr); serial_out(up, UART_IER, save_ier); - if (up->port.flags & UPF_FOURPORT) + if (port->flags & UPF_FOURPORT) outb_p(save_ICP, ICP); - up->port.irq = (irq > 0) ? irq : 0; + port->irq = (irq > 0) ? irq : 0; } static inline void __stop_tx(struct uart_8250_port *p) @@ -1273,7 +1274,7 @@ static void serial8250_stop_tx(struct uart_port *port) /* * We really want to stop the transmitter from sending. */ - if (up->port.type == PORT_16C950) { + if (port->type == PORT_16C950) { up->acr |= UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); } @@ -1292,7 +1293,7 @@ static void serial8250_start_tx(struct uart_port *port) unsigned char lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - if ((up->port.type == PORT_RM9000) ? + if ((port->type == PORT_RM9000) ? (lsr & UART_LSR_THRE) : (lsr & UART_LSR_TEMT)) serial8250_tx_chars(up); @@ -1302,7 +1303,7 @@ static void serial8250_start_tx(struct uart_port *port) /* * Re-enable the transmitter if we disabled it. */ - if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { + if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) { up->acr &= ~UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); } @@ -1360,7 +1361,8 @@ static void clear_rx_fifo(struct uart_8250_port *up) unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { - struct tty_struct *tty = up->port.state->port.tty; + struct uart_port *port = &up->port; + struct tty_struct *tty = port->state->port.tty; unsigned char ch; int max_count = 256; char flag; @@ -1379,7 +1381,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) ch = 0; flag = TTY_NORMAL; - up->port.icount.rx++; + port->icount.rx++; lsr |= up->lsr_saved_flags; up->lsr_saved_flags = 0; @@ -1390,12 +1392,12 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) */ if (lsr & UART_LSR_BI) { lsr &= ~(UART_LSR_FE | UART_LSR_PE); - up->port.icount.brk++; + port->icount.brk++; /* * If tegra port then clear the rx fifo to * accept another break/character. */ - if (up->port.type == PORT_TEGRA) + if (port->type == PORT_TEGRA) clear_rx_fifo(up); /* @@ -1404,19 +1406,19 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) * may get masked by ignore_status_mask * or read_status_mask. */ - if (uart_handle_break(&up->port)) + if (uart_handle_break(port)) goto ignore_char; } else if (lsr & UART_LSR_PE) - up->port.icount.parity++; + port->icount.parity++; else if (lsr & UART_LSR_FE) - up->port.icount.frame++; + port->icount.frame++; if (lsr & UART_LSR_OE) - up->port.icount.overrun++; + port->icount.overrun++; /* * Mask off conditions which should be ignored. */ - lsr &= up->port.read_status_mask; + lsr &= port->read_status_mask; if (lsr & UART_LSR_BI) { DEBUG_INTR("handling break...."); @@ -1426,34 +1428,35 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) else if (lsr & UART_LSR_FE) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch)) + if (uart_handle_sysrq_char(port, ch)) goto ignore_char; - uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag); + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); ignore_char: lsr = serial_in(up, UART_LSR); } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); - spin_unlock(&up->port.lock); + spin_unlock(&port->lock); tty_flip_buffer_push(tty); - spin_lock(&up->port.lock); + spin_lock(&port->lock); return lsr; } EXPORT_SYMBOL_GPL(serial8250_rx_chars); void serial8250_tx_chars(struct uart_8250_port *up) { - struct circ_buf *xmit = &up->port.state->xmit; + struct uart_port *port = &up->port; + struct circ_buf *xmit = &port->state->xmit; int count; - if (up->port.x_char) { - serial_out(up, UART_TX, up->port.x_char); - up->port.icount.tx++; - up->port.x_char = 0; + if (port->x_char) { + serial_out(up, UART_TX, port->x_char); + port->icount.tx++; + port->x_char = 0; return; } - if (uart_tx_stopped(&up->port)) { - serial8250_stop_tx(&up->port); + if (uart_tx_stopped(port)) { + serial8250_stop_tx(port); return; } if (uart_circ_empty(xmit)) { @@ -1465,13 +1468,13 @@ void serial8250_tx_chars(struct uart_8250_port *up) do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - up->port.icount.tx++; + port->icount.tx++; if (uart_circ_empty(xmit)) break; } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); + uart_write_wakeup(port); DEBUG_INTR("THRE..."); @@ -1482,22 +1485,23 @@ EXPORT_SYMBOL_GPL(serial8250_tx_chars); unsigned int serial8250_modem_status(struct uart_8250_port *up) { + struct uart_port *port = &up->port; unsigned int status = serial_in(up, UART_MSR); status |= up->msr_saved_flags; up->msr_saved_flags = 0; if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && - up->port.state != NULL) { + port->state != NULL) { if (status & UART_MSR_TERI) - up->port.icount.rng++; + port->icount.rng++; if (status & UART_MSR_DDSR) - up->port.icount.dsr++; + port->icount.dsr++; if (status & UART_MSR_DDCD) - uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); + uart_handle_dcd_change(port, status & UART_MSR_DCD); if (status & UART_MSR_DCTS) - uart_handle_cts_change(&up->port, status & UART_MSR_CTS); + uart_handle_cts_change(port, status & UART_MSR_CTS); - wake_up_interruptible(&up->port.state->port.delta_msr_wait); + wake_up_interruptible(&port->state->port.delta_msr_wait); } return status; @@ -1517,7 +1521,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) if (iir & UART_IIR_NO_INT) return 0; - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); status = serial_in(up, UART_LSR); @@ -1529,7 +1533,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) if (status & UART_LSR_THRE) serial8250_tx_chars(up); - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&port->lock, flags); return 1; } EXPORT_SYMBOL_GPL(serial8250_handle_irq); @@ -1771,10 +1775,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) unsigned long flags; unsigned int lsr; - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&port->lock, flags); return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; } @@ -1828,13 +1832,13 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) container_of(port, struct uart_8250_port, port); unsigned long flags; - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); if (break_state == -1) up->lcr |= UART_LCR_SBC; else up->lcr &= ~UART_LCR_SBC; serial_out(up, UART_LCR, up->lcr); - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&port->lock, flags); } /* @@ -1935,15 +1939,15 @@ static int serial8250_startup(struct uart_port *port) unsigned char lsr, iir; int retval; - up->port.fifosize = uart_config[up->port.type].fifo_size; + port->fifosize = uart_config[up->port.type].fifo_size; up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->capabilities = uart_config[up->port.type].flags; up->mcr = 0; - if (up->port.iotype != up->cur_iotype) + if (port->iotype != up->cur_iotype) set_io_from_upio(port); - if (up->port.type == PORT_16C950) { + if (port->type == PORT_16C950) { /* Wake up and initialize UART */ up->acr = 0; serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); @@ -1983,17 +1987,17 @@ static int serial8250_startup(struct uart_port *port) * if it is, then bail out, because there's likely no UART * here. */ - if (!(up->port.flags & UPF_BUGGY_UART) && + if (!(port->flags & UPF_BUGGY_UART) && (serial_in(up, UART_LSR) == 0xff)) { printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", - serial_index(&up->port)); + serial_index(port)); return -ENODEV; } /* * For a XR16C850, we need to set the trigger levels */ - if (up->port.type == PORT_16850) { + if (port->type == PORT_16850) { unsigned char fctr; serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); @@ -2007,7 +2011,7 @@ static int serial8250_startup(struct uart_port *port) serial_out(up, UART_LCR, 0); } - if (up->port.irq) { + if (port->irq) { unsigned char iir1; /* * Test for UARTs that do not reassert THRE when the @@ -2017,9 +2021,9 @@ static int serial8250_startup(struct uart_port *port) * the interrupt is enabled. Delays are necessary to * allow register changes to become visible. */ - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); if (up->port.irqflags & IRQF_SHARED) - disable_irq_nosync(up->port.irq); + disable_irq_nosync(port->irq); wait_for_xmitr(up, UART_LSR_THRE); serial_out_sync(up, UART_IER, UART_IER_THRI); @@ -2031,9 +2035,9 @@ static int serial8250_startup(struct uart_port *port) iir = serial_in(up, UART_IIR); serial_out(up, UART_IER, 0); - if (up->port.irqflags & IRQF_SHARED) - enable_irq(up->port.irq); - spin_unlock_irqrestore(&up->port.lock, flags); + if (port->irqflags & IRQF_SHARED) + enable_irq(port->irq); + spin_unlock_irqrestore(&port->lock, flags); /* * If the interrupt is not reasserted, setup a timer to @@ -2062,7 +2066,7 @@ static int serial8250_startup(struct uart_port *port) * hardware interrupt, we use a timer-based system. The original * driver used to do this with IRQ0. */ - if (!up->port.irq) { + if (!port->irq) { up->timer.data = (unsigned long)up; mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); } else { @@ -2076,7 +2080,7 @@ static int serial8250_startup(struct uart_port *port) */ serial_out(up, UART_LCR, UART_LCR_WLEN8); - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); if (up->port.flags & UPF_FOURPORT) { if (!up->port.irq) up->port.mctrl |= TIOCM_OUT1; @@ -2084,10 +2088,10 @@ static int serial8250_startup(struct uart_port *port) /* * Most PC uarts need OUT2 raised to enable interrupts. */ - if (up->port.irq) + if (port->irq) up->port.mctrl |= TIOCM_OUT2; - serial8250_set_mctrl(&up->port, up->port.mctrl); + serial8250_set_mctrl(port, port->mctrl); /* Serial over Lan (SoL) hack: Intel 8257x Gigabit ethernet chips have a @@ -2123,7 +2127,7 @@ static int serial8250_startup(struct uart_port *port) } dont_test_tx_en: - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&port->lock, flags); /* * Clear the interrupt registers again for luck, and clear the @@ -2145,12 +2149,12 @@ dont_test_tx_en: up->ier = UART_IER_RLSI | UART_IER_RDI; serial_out(up, UART_IER, up->ier); - if (up->port.flags & UPF_FOURPORT) { + if (port->flags & UPF_FOURPORT) { unsigned int icp; /* * Enable interrupts on the AST Fourport board */ - icp = (up->port.iobase & 0xfe0) | 0x01f; + icp = (port->iobase & 0xfe0) | 0x01f; outb_p(0x80, icp); inb_p(icp); } @@ -2170,16 +2174,16 @@ static void serial8250_shutdown(struct uart_port *port) up->ier = 0; serial_out(up, UART_IER, 0); - spin_lock_irqsave(&up->port.lock, flags); - if (up->port.flags & UPF_FOURPORT) { + spin_lock_irqsave(&port->lock, flags); + if (port->flags & UPF_FOURPORT) { /* reset interrupts on the AST Fourport board */ - inb((up->port.iobase & 0xfe0) | 0x1f); - up->port.mctrl |= TIOCM_OUT1; + inb((port->iobase & 0xfe0) | 0x1f); + port->mctrl |= TIOCM_OUT1; } else - up->port.mctrl &= ~TIOCM_OUT2; + port->mctrl &= ~TIOCM_OUT2; - serial8250_set_mctrl(&up->port, up->port.mctrl); - spin_unlock_irqrestore(&up->port.lock, flags); + serial8250_set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); /* * Disable break condition and FIFOs @@ -2202,7 +2206,7 @@ static void serial8250_shutdown(struct uart_port *port) del_timer_sync(&up->timer); up->timer.function = serial8250_timeout; - if (up->port.irq) + if (port->irq) serial_unlink_irq_chain(up); } @@ -2277,11 +2281,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0) quot++; - if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) { + if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { if (baud < 2400) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; else - fcr = uart_config[up->port.type].fcr; + fcr = uart_config[port->type].fcr; } /* @@ -2292,7 +2296,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * have sufficient FIFO entries for the latency of the remote * UART to respond. IOW, at least 32 bytes of FIFO. */ - if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) { + if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) { up->mcr &= ~UART_MCR_AFE; if (termios->c_cflag & CRTSCTS) up->mcr |= UART_MCR_AFE; @@ -2302,40 +2306,40 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * Ok, we're now changing the port state. Do it with * interrupts disabled. */ - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); - up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) - up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) - up->port.read_status_mask |= UART_LSR_BI; + port->read_status_mask |= UART_LSR_BI; /* * Characteres to ignore */ - up->port.ignore_status_mask = 0; + port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { - up->port.ignore_status_mask |= UART_LSR_BI; + port->ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - up->port.ignore_status_mask |= UART_LSR_OE; + port->ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) - up->port.ignore_status_mask |= UART_LSR_DR; + port->ignore_status_mask |= UART_LSR_DR; /* * CTS flow control flag and modem status interrupts @@ -2362,7 +2366,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, efr |= UART_EFR_CTS; serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - if (up->port.flags & UPF_EXAR_EFR) + if (port->flags & UPF_EXAR_EFR) serial_out(up, UART_XR_EFR, efr); else serial_out(up, UART_EFR, efr); @@ -2392,20 +2396,20 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR * is written without DLAB set, this mode will be disabled. */ - if (up->port.type == PORT_16750) + if (port->type == PORT_16750) serial_out(up, UART_FCR, fcr); serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ - if (up->port.type != PORT_16750) { + if (port->type != PORT_16750) { if (fcr & UART_FCR_ENABLE_FIFO) { /* emulated UARTs (Lucent Venus 167x) need two steps */ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); } serial_out(up, UART_FCR, fcr); /* set fcr */ } - serial8250_set_mctrl(&up->port, up->port.mctrl); - spin_unlock_irqrestore(&up->port.lock, flags); + serial8250_set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); @@ -2470,26 +2474,26 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt) static int serial8250_request_std_resource(struct uart_8250_port *up) { unsigned int size = serial8250_port_size(up); + struct uart_port *port = &up->port; int ret = 0; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_AU: case UPIO_TSI: case UPIO_MEM32: case UPIO_MEM: - if (!up->port.mapbase) + if (!port->mapbase) break; - if (!request_mem_region(up->port.mapbase, size, "serial")) { + if (!request_mem_region(port->mapbase, size, "serial")) { ret = -EBUSY; break; } - if (up->port.flags & UPF_IOREMAP) { - up->port.membase = ioremap_nocache(up->port.mapbase, - size); - if (!up->port.membase) { - release_mem_region(up->port.mapbase, size); + if (port->flags & UPF_IOREMAP) { + port->membase = ioremap_nocache(port->mapbase, size); + if (!port->membase) { + release_mem_region(port->mapbase, size); ret = -ENOMEM; } } @@ -2497,7 +2501,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) case UPIO_HUB6: case UPIO_PORT: - if (!request_region(up->port.iobase, size, "serial")) + if (!request_region(port->iobase, size, "serial")) ret = -EBUSY; break; } @@ -2507,26 +2511,27 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) static void serial8250_release_std_resource(struct uart_8250_port *up) { unsigned int size = serial8250_port_size(up); + struct uart_port *port = &up->port; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_AU: case UPIO_TSI: case UPIO_MEM32: case UPIO_MEM: - if (!up->port.mapbase) + if (!port->mapbase) break; - if (up->port.flags & UPF_IOREMAP) { - iounmap(up->port.membase); - up->port.membase = NULL; + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; } - release_mem_region(up->port.mapbase, size); + release_mem_region(port->mapbase, size); break; case UPIO_HUB6: case UPIO_PORT: - release_region(up->port.iobase, size); + release_region(port->iobase, size); break; } } @@ -2535,12 +2540,13 @@ static int serial8250_request_rsa_resource(struct uart_8250_port *up) { unsigned long start = UART_RSA_BASE << up->port.regshift; unsigned int size = 8 << up->port.regshift; + struct uart_port *port = &up->port; int ret = -EINVAL; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_HUB6: case UPIO_PORT: - start += up->port.iobase; + start += port->iobase; if (request_region(start, size, "serial-rsa")) ret = 0; else @@ -2555,11 +2561,12 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up) { unsigned long offset = UART_RSA_BASE << up->port.regshift; unsigned int size = 8 << up->port.regshift; + struct uart_port *port = &up->port; - switch (up->port.iotype) { + switch (port->iotype) { case UPIO_HUB6: case UPIO_PORT: - release_region(up->port.iobase + offset, size); + release_region(port->iobase + offset, size); break; } } @@ -2570,7 +2577,7 @@ static void serial8250_release_port(struct uart_port *port) container_of(port, struct uart_8250_port, port); serial8250_release_std_resource(up); - if (up->port.type == PORT_RSA) + if (port->type == PORT_RSA) serial8250_release_rsa_resource(up); } @@ -2581,7 +2588,7 @@ static int serial8250_request_port(struct uart_port *port) int ret = 0; ret = serial8250_request_std_resource(up); - if (ret == 0 && up->port.type == PORT_RSA) { + if (ret == 0 && port->type == PORT_RSA) { ret = serial8250_request_rsa_resource(up); if (ret < 0) serial8250_release_std_resource(up); @@ -2609,22 +2616,22 @@ static void serial8250_config_port(struct uart_port *port, int flags) if (ret < 0) probeflags &= ~PROBE_RSA; - if (up->port.iotype != up->cur_iotype) + if (port->iotype != up->cur_iotype) set_io_from_upio(port); if (flags & UART_CONFIG_TYPE) autoconfig(up, probeflags); /* if access method is AU, it is a 16550 with a quirk */ - if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) + if (port->type == PORT_16550A && port->iotype == UPIO_AU) up->bugs |= UART_BUG_NOMSR; - if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) + if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) autoconfig_irq(up); - if (up->port.type != PORT_RSA && probeflags & PROBE_RSA) + if (port->type != PORT_RSA && probeflags & PROBE_RSA) serial8250_release_rsa_resource(up); - if (up->port.type == PORT_UNKNOWN) + if (port->type == PORT_UNKNOWN) serial8250_release_std_resource(up); } @@ -2698,9 +2705,10 @@ static void __init serial8250_isa_init_ports(void) for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; + struct uart_port *port = &up->port; - up->port.line = i; - spin_lock_init(&up->port.lock); + port->line = i; + spin_lock_init(&port->lock); init_timer(&up->timer); up->timer.function = serial8250_timeout; @@ -2711,7 +2719,7 @@ static void __init serial8250_isa_init_ports(void) up->mcr_mask = ~ALPHA_KLUDGE_MCR; up->mcr_force = ALPHA_KLUDGE_MCR; - up->port.ops = &serial8250_pops; + port->ops = &serial8250_pops; } if (share_irqs) @@ -2720,17 +2728,19 @@ static void __init serial8250_isa_init_ports(void) for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++, up++) { - up->port.iobase = old_serial_port[i].port; - up->port.irq = irq_canonicalize(old_serial_port[i].irq); - up->port.irqflags = old_serial_port[i].irqflags; - up->port.uartclk = old_serial_port[i].baud_base * 16; - up->port.flags = old_serial_port[i].flags; - up->port.hub6 = old_serial_port[i].hub6; - up->port.membase = old_serial_port[i].iomem_base; - up->port.iotype = old_serial_port[i].io_type; - up->port.regshift = old_serial_port[i].iomem_reg_shift; - set_io_from_upio(&up->port); - up->port.irqflags |= irqflag; + struct uart_port *port = &up->port; + + port->iobase = old_serial_port[i].port; + port->irq = irq_canonicalize(old_serial_port[i].irq); + port->irqflags = old_serial_port[i].irqflags; + port->uartclk = old_serial_port[i].baud_base * 16; + port->flags = old_serial_port[i].flags; + port->hub6 = old_serial_port[i].hub6; + port->membase = old_serial_port[i].iomem_base; + port->iotype = old_serial_port[i].io_type; + port->regshift = old_serial_port[i].iomem_reg_shift; + set_io_from_upio(port); + port->irqflags |= irqflag; if (serial8250_isa_config != NULL) serial8250_isa_config(i, &up->port, &up->capabilities); @@ -2791,6 +2801,7 @@ static void serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; + struct uart_port *port = &up->port; unsigned long flags; unsigned int ier; int locked = 1; @@ -2798,13 +2809,13 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) touch_nmi_watchdog(); local_irq_save(flags); - if (up->port.sysrq) { + if (port->sysrq) { /* serial8250_handle_irq() already took the lock */ locked = 0; } else if (oops_in_progress) { - locked = spin_trylock(&up->port.lock); + locked = spin_trylock(&port->lock); } else - spin_lock(&up->port.lock); + spin_lock(&port->lock); /* * First save the IER then disable the interrupts @@ -2816,7 +2827,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) else serial_out(up, UART_IER, 0); - uart_console_write(&up->port, s, count, serial8250_console_putchar); + uart_console_write(port, s, count, serial8250_console_putchar); /* * Finally, wait for transmitter to become empty @@ -2836,7 +2847,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) serial8250_modem_status(up); if (locked) - spin_unlock(&up->port.lock); + spin_unlock(&port->lock); local_irq_restore(flags); } @@ -2981,6 +2992,7 @@ void serial8250_suspend_port(int line) void serial8250_resume_port(int line) { struct uart_8250_port *up = &serial8250_ports[line]; + struct uart_port *port = &up->port; if (up->capabilities & UART_NATSEMI) { /* Ensure it's still in high speed mode */ @@ -2989,9 +3001,9 @@ void serial8250_resume_port(int line) ns16550a_goto_highspeed(up); serial_out(up, UART_LCR, 0); - up->port.uartclk = 921600*16; + port->uartclk = 921600*16; } - uart_resume_port(&serial8250_reg, &up->port); + uart_resume_port(&serial8250_reg, port); } /* -- cgit v1.2.3 From 4fd996a14660f56a6fd92ce7c8fb167d262c994f Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 8 Mar 2012 19:12:13 -0500 Subject: serial: use serial_port_in/out vs serial_in/out in 8250 The serial_in and serial_out helpers are expecting to operate on an 8250_port struct. These in turn go after the contained normal port struct which actually has the actual in/out accessors. But what is happening in some cases, is that a function is passed in a port struct, and it runs container_of to get the 8250_port struct, and then it uses serial_in/out helpers on that. But when you do, it goes full circle, since it jumps back inside the 8250_port to find the contained port struct (which we already knew!). So, if we are operating in a scope where we know the struct port, then use the serial_port_in/out helpers and avoid the bouncing around. If we don't have the struct port handy, and it isn't worth making a local for it, then just leave things as-is which uses the serial_in/out helpers that will resolve the 8250_port onto the struct port. Mostly, gcc figures this out on its own -- so this doesn't bring to the table any revolutionary runtime delta. However, it is somewhat misleading to always hammer away on 8250 structs, when the actual underlying property isn't at all 8250 specific -- and this change makes that clear. Signed-off-by: Paul Gortmaker Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 160 ++++++++++++++++++++--------------------- 1 file changed, 80 insertions(+), 80 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index a0d114d8baef..7898295e4148 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -1287,7 +1287,7 @@ static void serial8250_start_tx(struct uart_port *port) if (!(up->ier & UART_IER_THRI)) { up->ier |= UART_IER_THRI; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); if (up->bugs & UART_BUG_TXEN) { unsigned char lsr; @@ -1316,7 +1316,7 @@ static void serial8250_stop_rx(struct uart_port *port) up->ier &= ~UART_IER_RLSI; up->port.read_status_mask &= ~UART_LSR_DR; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); } static void serial8250_enable_ms(struct uart_port *port) @@ -1329,7 +1329,7 @@ static void serial8250_enable_ms(struct uart_port *port) return; up->ier |= UART_IER_MSI; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); } /* @@ -1523,7 +1523,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) spin_lock_irqsave(&port->lock, flags); - status = serial_in(up, UART_LSR); + status = serial_port_in(port, UART_LSR); DEBUG_INTR("status = %x...", status); @@ -1540,9 +1540,7 @@ EXPORT_SYMBOL_GPL(serial8250_handle_irq); static int serial8250_default_handle_irq(struct uart_port *port) { - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); - unsigned int iir = serial_in(up, UART_IIR); + unsigned int iir = serial_port_in(port, UART_IIR); return serial8250_handle_irq(port, iir); } @@ -1776,7 +1774,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) unsigned int lsr; spin_lock_irqsave(&port->lock, flags); - lsr = serial_in(up, UART_LSR); + lsr = serial_port_in(port, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; spin_unlock_irqrestore(&port->lock, flags); @@ -1823,7 +1821,7 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; - serial_out(up, UART_MCR, mcr); + serial_port_out(port, UART_MCR, mcr); } static void serial8250_break_ctl(struct uart_port *port, int break_state) @@ -1837,7 +1835,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) up->lcr |= UART_LCR_SBC; else up->lcr &= ~UART_LCR_SBC; - serial_out(up, UART_LCR, up->lcr); + serial_port_out(port, UART_LCR, up->lcr); spin_unlock_irqrestore(&port->lock, flags); } @@ -1883,14 +1881,12 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) static int serial8250_get_poll_char(struct uart_port *port) { - struct uart_8250_port *up = - container_of(port, struct uart_8250_port, port); - unsigned char lsr = serial_in(up, UART_LSR); + unsigned char lsr = serial_port_in(port, UART_LSR); if (!(lsr & UART_LSR_DR)) return NO_POLL_CHAR; - return serial_in(up, UART_RX); + return serial_port_in(port, UART_RX); } @@ -1904,21 +1900,21 @@ static void serial8250_put_poll_char(struct uart_port *port, /* * First save the IER then disable the interrupts */ - ier = serial_in(up, UART_IER); + ier = serial_port_in(port, UART_IER); if (up->capabilities & UART_CAP_UUE) - serial_out(up, UART_IER, UART_IER_UUE); + serial_port_out(port, UART_IER, UART_IER_UUE); else - serial_out(up, UART_IER, 0); + serial_port_out(port, UART_IER, 0); wait_for_xmitr(up, BOTH_EMPTY); /* * Send the character out. * If a LF, also do CR... */ - serial_out(up, UART_TX, c); + serial_port_out(port, UART_TX, c); if (c == 10) { wait_for_xmitr(up, BOTH_EMPTY); - serial_out(up, UART_TX, 13); + serial_port_out(port, UART_TX, 13); } /* @@ -1926,7 +1922,7 @@ static void serial8250_put_poll_char(struct uart_port *port, * and restore the IER */ wait_for_xmitr(up, BOTH_EMPTY); - serial_out(up, UART_IER, ier); + serial_port_out(port, UART_IER, ier); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1950,14 +1946,14 @@ static int serial8250_startup(struct uart_port *port) if (port->type == PORT_16C950) { /* Wake up and initialize UART */ up->acr = 0; - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(up, UART_EFR, UART_EFR_ECB); - serial_out(up, UART_IER, 0); - serial_out(up, UART_LCR, 0); + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); + serial_port_out(port, UART_IER, 0); + serial_port_out(port, UART_LCR, 0); serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); - serial_out(up, UART_EFR, UART_EFR_ECB); - serial_out(up, UART_LCR, 0); + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); + serial_port_out(port, UART_LCR, 0); } #ifdef CONFIG_SERIAL_8250_RSA @@ -1977,10 +1973,10 @@ static int serial8250_startup(struct uart_port *port) /* * Clear the interrupt registers. */ - serial_in(up, UART_LSR); - serial_in(up, UART_RX); - serial_in(up, UART_IIR); - serial_in(up, UART_MSR); + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); /* * At this point, there's no way the LSR could still be 0xff; @@ -1988,7 +1984,7 @@ static int serial8250_startup(struct uart_port *port) * here. */ if (!(port->flags & UPF_BUGGY_UART) && - (serial_in(up, UART_LSR) == 0xff)) { + (serial_port_in(port, UART_LSR) == 0xff)) { printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", serial_index(port)); return -ENODEV; @@ -2003,12 +1999,14 @@ static int serial8250_startup(struct uart_port *port) serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX); - serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX); - serial_out(up, UART_TRG, UART_TRG_96); - serial_out(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX); - serial_out(up, UART_TRG, UART_TRG_96); + serial_port_out(port, UART_FCTR, + fctr | UART_FCTR_TRGD | UART_FCTR_RX); + serial_port_out(port, UART_TRG, UART_TRG_96); + serial_port_out(port, UART_FCTR, + fctr | UART_FCTR_TRGD | UART_FCTR_TX); + serial_port_out(port, UART_TRG, UART_TRG_96); - serial_out(up, UART_LCR, 0); + serial_port_out(port, UART_LCR, 0); } if (port->irq) { @@ -2028,12 +2026,12 @@ static int serial8250_startup(struct uart_port *port) wait_for_xmitr(up, UART_LSR_THRE); serial_out_sync(up, UART_IER, UART_IER_THRI); udelay(1); /* allow THRE to set */ - iir1 = serial_in(up, UART_IIR); - serial_out(up, UART_IER, 0); + iir1 = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); serial_out_sync(up, UART_IER, UART_IER_THRI); udelay(1); /* allow a working UART time to re-assert THRE */ - iir = serial_in(up, UART_IIR); - serial_out(up, UART_IER, 0); + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); if (port->irqflags & IRQF_SHARED) enable_irq(port->irq); @@ -2078,7 +2076,7 @@ static int serial8250_startup(struct uart_port *port) /* * Now, initialize the UART */ - serial_out(up, UART_LCR, UART_LCR_WLEN8); + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); spin_lock_irqsave(&port->lock, flags); if (up->port.flags & UPF_FOURPORT) { @@ -2111,10 +2109,10 @@ static int serial8250_startup(struct uart_port *port) * Do a quick test to see if we receive an * interrupt when we enable the TX irq. */ - serial_out(up, UART_IER, UART_IER_THRI); - lsr = serial_in(up, UART_LSR); - iir = serial_in(up, UART_IIR); - serial_out(up, UART_IER, 0); + serial_port_out(port, UART_IER, UART_IER_THRI); + lsr = serial_port_in(port, UART_LSR); + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { if (!(up->bugs & UART_BUG_TXEN)) { @@ -2134,10 +2132,10 @@ dont_test_tx_en: * saved flags to avoid getting false values from polling * routines or the previous session. */ - serial_in(up, UART_LSR); - serial_in(up, UART_RX); - serial_in(up, UART_IIR); - serial_in(up, UART_MSR); + serial_port_in(port, UART_LSR); + serial_port_in(port, UART_RX); + serial_port_in(port, UART_IIR); + serial_port_in(port, UART_MSR); up->lsr_saved_flags = 0; up->msr_saved_flags = 0; @@ -2147,7 +2145,7 @@ dont_test_tx_en: * anyway, so we don't enable them here. */ up->ier = UART_IER_RLSI | UART_IER_RDI; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); if (port->flags & UPF_FOURPORT) { unsigned int icp; @@ -2172,7 +2170,7 @@ static void serial8250_shutdown(struct uart_port *port) * Disable interrupts from this port */ up->ier = 0; - serial_out(up, UART_IER, 0); + serial_port_out(port, UART_IER, 0); spin_lock_irqsave(&port->lock, flags); if (port->flags & UPF_FOURPORT) { @@ -2188,7 +2186,8 @@ static void serial8250_shutdown(struct uart_port *port) /* * Disable break condition and FIFOs */ - serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); + serial_port_out(port, UART_LCR, + serial_port_in(port, UART_LCR) & ~UART_LCR_SBC); serial8250_clear_fifos(up); #ifdef CONFIG_SERIAL_8250_RSA @@ -2202,7 +2201,7 @@ static void serial8250_shutdown(struct uart_port *port) * Read data port to reset things, and then unlink from * the IRQ chain. */ - serial_in(up, UART_RX); + serial_port_in(port, UART_RX); del_timer_sync(&up->timer); up->timer.function = serial8250_timeout; @@ -2353,7 +2352,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (up->capabilities & UART_CAP_RTOIE) up->ier |= UART_IER_RTOIE; - serial_out(up, UART_IER, up->ier); + serial_port_out(port, UART_IER, up->ier); if (up->capabilities & UART_CAP_EFR) { unsigned char efr = 0; @@ -2365,11 +2364,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & CRTSCTS) efr |= UART_EFR_CTS; - serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); if (port->flags & UPF_EXAR_EFR) - serial_out(up, UART_XR_EFR, efr); + serial_port_out(port, UART_XR_EFR, efr); else - serial_out(up, UART_EFR, efr); + serial_port_out(port, UART_EFR, efr); } #ifdef CONFIG_ARCH_OMAP @@ -2377,18 +2376,20 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, if (cpu_is_omap1510() && is_omap_port(up)) { if (baud == 115200) { quot = 1; - serial_out(up, UART_OMAP_OSC_12M_SEL, 1); + serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1); } else - serial_out(up, UART_OMAP_OSC_12M_SEL, 0); + serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0); } #endif - if (up->capabilities & UART_NATSEMI) { - /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */ - serial_out(up, UART_LCR, 0xe0); - } else { - serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ - } + /* + * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2, + * otherwise just set DLAB + */ + if (up->capabilities & UART_NATSEMI) + serial_port_out(port, UART_LCR, 0xe0); + else + serial_port_out(port, UART_LCR, cval | UART_LCR_DLAB); serial_dl_write(up, quot); @@ -2397,16 +2398,15 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, * is written without DLAB set, this mode will be disabled. */ if (port->type == PORT_16750) - serial_out(up, UART_FCR, fcr); + serial_port_out(port, UART_FCR, fcr); - serial_out(up, UART_LCR, cval); /* reset DLAB */ + serial_port_out(port, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ if (port->type != PORT_16750) { - if (fcr & UART_FCR_ENABLE_FIFO) { - /* emulated UARTs (Lucent Venus 167x) need two steps */ - serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); - } - serial_out(up, UART_FCR, fcr); /* set fcr */ + /* emulated UARTs (Lucent Venus 167x) need two steps */ + if (fcr & UART_FCR_ENABLE_FIFO) + serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_port_out(port, UART_FCR, fcr); /* set fcr */ } serial8250_set_mctrl(port, port->mctrl); spin_unlock_irqrestore(&port->lock, flags); @@ -2788,7 +2788,7 @@ static void serial8250_console_putchar(struct uart_port *port, int ch) container_of(port, struct uart_8250_port, port); wait_for_xmitr(up, UART_LSR_THRE); - serial_out(up, UART_TX, ch); + serial_port_out(port, UART_TX, ch); } /* @@ -2820,12 +2820,12 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) /* * First save the IER then disable the interrupts */ - ier = serial_in(up, UART_IER); + ier = serial_port_in(port, UART_IER); if (up->capabilities & UART_CAP_UUE) - serial_out(up, UART_IER, UART_IER_UUE); + serial_port_out(port, UART_IER, UART_IER_UUE); else - serial_out(up, UART_IER, 0); + serial_port_out(port, UART_IER, 0); uart_console_write(port, s, count, serial8250_console_putchar); @@ -2834,7 +2834,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) * and restore the IER */ wait_for_xmitr(up, BOTH_EMPTY); - serial_out(up, UART_IER, ier); + serial_port_out(port, UART_IER, ier); /* * The receive handling will happen properly because the @@ -2996,11 +2996,11 @@ void serial8250_resume_port(int line) if (up->capabilities & UART_NATSEMI) { /* Ensure it's still in high speed mode */ - serial_out(up, UART_LCR, 0xE0); + serial_port_out(port, UART_LCR, 0xE0); ns16550a_goto_highspeed(up); - serial_out(up, UART_LCR, 0); + serial_port_out(port, UART_LCR, 0); port->uartclk = 921600*16; } uart_resume_port(&serial8250_reg, port); -- cgit v1.2.3 From 55e4016dd055e262e4b078b81c80b55386ead0f4 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 8 Mar 2012 19:12:14 -0500 Subject: serial: remove back and forth conversions in serial_out_sync The two callers to serial_out_sync() have a struct port right there in scope, but then pass in a struct 8250_port which then is locally resolved back to a struct port. Delete the needless back and forth and just pass in the struct port directly. Rename the function to have "_port" in its name, so the name <--> args relationship is consistent with the other serial_in/out vs serial_port_in/out function classes. Signed-off-by: Paul Gortmaker Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 7898295e4148..5b149b466ec8 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -467,9 +467,8 @@ static void set_io_from_upio(struct uart_port *p) } static void -serial_out_sync(struct uart_8250_port *up, int offset, int value) +serial_port_out_sync(struct uart_port *p, int offset, int value) { - struct uart_port *p = &up->port; switch (p->iotype) { case UPIO_MEM: case UPIO_MEM32: @@ -2024,11 +2023,11 @@ static int serial8250_startup(struct uart_port *port) disable_irq_nosync(port->irq); wait_for_xmitr(up, UART_LSR_THRE); - serial_out_sync(up, UART_IER, UART_IER_THRI); + serial_port_out_sync(port, UART_IER, UART_IER_THRI); udelay(1); /* allow THRE to set */ iir1 = serial_port_in(port, UART_IIR); serial_port_out(port, UART_IER, 0); - serial_out_sync(up, UART_IER, UART_IER_THRI); + serial_port_out_sync(port, UART_IER, UART_IER_THRI); udelay(1); /* allow a working UART time to re-assert THRE */ iir = serial_port_in(port, UART_IIR); serial_port_out(port, UART_IER, 0); -- cgit v1.2.3 From 9abac8537c2cf435b251ca61e632d6a70a84077e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 11 Mar 2012 15:02:38 +0100 Subject: tty: serial: vt8500: fix annotations for probe/remove Fixes: WARNING: drivers/tty/serial/built-in.o(.data+0x30): Section mismatch in reference from the variable vt8500_platform_driver to the function .init.text:vt8500_serial_probe() The variable vt8500_platform_driver references the function __init vt8500_serial_probe() And mark the remove pointer while we are here. Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/vt8500_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 026cb9ea5cd1..2be006fb3da0 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -544,7 +544,7 @@ static struct uart_driver vt8500_uart_driver = { .cons = VT8500_CONSOLE, }; -static int __init vt8500_serial_probe(struct platform_device *pdev) +static int __devinit vt8500_serial_probe(struct platform_device *pdev) { struct vt8500_port *vt8500_port; struct resource *mmres, *irqres; @@ -605,7 +605,7 @@ static int __devexit vt8500_serial_remove(struct platform_device *pdev) static struct platform_driver vt8500_platform_driver = { .probe = vt8500_serial_probe, - .remove = vt8500_serial_remove, + .remove = __devexit_p(vt8500_serial_remove), .driver = { .name = "vt8500_serial", .owner = THIS_MODULE, -- cgit v1.2.3 From 60f4b002ab209525c2b818703291ac9a14890e17 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 13 Mar 2012 15:51:55 +0800 Subject: serial: bfin-uart: Don't access tty circular buffer in TX DMA interrupt after it is reset. When kernel reboot, tty circular buffer is reset before last TX DMA interrupt is called, while the buffer tail is updated in TX DMA interrupt handler. So, don't update the buffer tail if it is reset. Signed-off-by: Sonic Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bfin_uart.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 26953bfa6922..5832fdef11e9 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -535,11 +535,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) * when start a new tx. */ UART_CLEAR_IER(uart, ETBEI); - xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); uart->port.icount.tx += uart->tx_count; + if (!uart_circ_empty(xmit)) { + xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uart->port); + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&uart->port); + } bfin_serial_dma_tx_chars(uart); } -- cgit v1.2.3 From 9b96fbacda34079dea0638ee1e92c56286f6114a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 13 Mar 2012 13:27:23 +0100 Subject: serial: PL011: clear pending interrupts Chanho Min reported that when the boot loader transfers control to the kernel, there may be pending interrupts causing the UART to lock up in an eternal loop trying to pick tokens from the FIFO (since the RX interrupt flag indicates there are tokens) while in practice there are no tokens - in fact there is only a pending IRQ flag. This patch address the issue with a combination of two patches suggested by Russell King that clears and mask all interrupts at probe() and clears any pending error and RX interrupts at port startup time. We suspect the spurious interrupts are a side-effect of switching the UART from FIFO to non-FIFO mode. Cc: Shreshtha Kumar Sahu Reported-by: Chanho Min Suggested-by: Russell King Signed-off-by: Linus Walleij Reviewed-by: Jong-Sung Kim Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index cc3ea066c43a..20d795d9b591 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1396,6 +1396,10 @@ static int pl011_startup(struct uart_port *port) uap->port.uartclk = clk_get_rate(uap->clk); + /* Clear pending error and receive interrupts */ + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | + UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); + /* * Allocate the IRQ */ @@ -1432,10 +1436,6 @@ static int pl011_startup(struct uart_port *port) cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; writew(cr, uap->port.membase + UART011_CR); - /* Clear pending error interrupts */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, - uap->port.membase + UART011_ICR); - /* * initialise the old status of the modem signals */ @@ -1450,6 +1450,9 @@ static int pl011_startup(struct uart_port *port) * as well. */ spin_lock_irq(&uap->port.lock); + /* Clear out any spuriously appearing RX interrupts */ + writew(UART011_RTIS | UART011_RXIS, + uap->port.membase + UART011_ICR); uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; @@ -1942,6 +1945,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) goto unmap; } + /* Ensure interrupts from this UART are masked and cleared */ + writew(0, uap->port.membase + UART011_IMSC); + writew(0xffff, uap->port.membase + UART011_ICR); + uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; -- cgit v1.2.3 From fb8ebec00b04f921ea1614a7303f1a8e5e9e47c5 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 15 Mar 2012 19:15:15 +0100 Subject: serial: pxa: add clk_prepare/clk_unprepare calls This patch adds clk_prepare/clk_unprepare calls to the serial/pxa driver by using the helper functions clk_prepare_enable and clk_disable_unprepare. Signed-off-by: Philipp Zabel Cc: Haojian Zhuang Cc: Eric Miao Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pxa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 5c8e3bba6c84..e2fd3d8e0ab4 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -579,9 +579,9 @@ serial_pxa_pm(struct uart_port *port, unsigned int state, struct uart_pxa_port *up = (struct uart_pxa_port *)port; if (!state) - clk_enable(up->clk); + clk_prepare_enable(up->clk); else - clk_disable(up->clk); + clk_disable_unprepare(up->clk); } static void serial_pxa_release_port(struct uart_port *port) @@ -668,7 +668,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) struct uart_pxa_port *up = serial_pxa_ports[co->index]; unsigned int ier; - clk_enable(up->clk); + clk_prepare_enable(up->clk); /* * First save the IER then disable the interrupts @@ -685,7 +685,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) wait_for_xmitr(up); serial_out(up, UART_IER, ier); - clk_disable(up->clk); + clk_disable_unprepare(up->clk); } static int __init -- cgit v1.2.3