--- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -48,11 +48,9 @@ #include <linux/slab.h> #include <linux/io.h> -#define UART_NR 8 - #define SERIAL_AMBA_MAJOR 204 #define SERIAL_AMBA_MINOR 16 -#define SERIAL_AMBA_NR UART_NR +#define SERIAL_AMBA_NR CONFIG_SERIAL_AMBA_PL010_NUMPORTS #define AMBA_ISR_PASS_LIMIT 256 @@ -78,9 +76,9 @@ static void pl010_stop_tx(struct uart_po struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(uap->port.membase + UART010_CR); + cr = __raw_readl(uap->port.membase + UART010_CR); cr &= ~UART010_CR_TIE; - writel(cr, uap->port.membase + UART010_CR); + __raw_writel(cr, uap->port.membase + UART010_CR); } static void pl010_start_tx(struct uart_port *port) @@ -88,9 +86,9 @@ static void pl010_start_tx(struct uart_p struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(uap->port.membase + UART010_CR); + cr = __raw_readl(uap->port.membase + UART010_CR); cr |= UART010_CR_TIE; - writel(cr, uap->port.membase + UART010_CR); + __raw_writel(cr, uap->port.membase + UART010_CR); } static void pl010_stop_rx(struct uart_port *port) @@ -98,9 +96,9 @@ static void pl010_stop_rx(struct uart_po struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(uap->port.membase + UART010_CR); + cr = __raw_readl(uap->port.membase + UART010_CR); cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); - writel(cr, uap->port.membase + UART010_CR); + __raw_writel(cr, uap->port.membase + UART010_CR); } static void pl010_enable_ms(struct uart_port *port) @@ -108,18 +106,18 @@ static void pl010_enable_ms(struct uart_ struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; - cr = readb(uap->port.membase + UART010_CR); + cr = __raw_readl(uap->port.membase + UART010_CR); cr |= UART010_CR_MSIE; - writel(cr, uap->port.membase + UART010_CR); + __raw_writel(cr, uap->port.membase + UART010_CR); } static void pl010_rx_chars(struct uart_amba_port *uap) { unsigned int status, ch, flag, rsr, max_count = 256; - status = readb(uap->port.membase + UART01x_FR); + status = __raw_readl(uap->port.membase + UART01x_FR); while (UART_RX_DATA(status) && max_count--) { - ch = readb(uap->port.membase + UART01x_DR); + ch = __raw_readl(uap->port.membase + UART01x_DR); flag = TTY_NORMAL; uap->port.icount.rx++; @@ -128,9 +126,9 @@ static void pl010_rx_chars(struct uart_a * Note that the error handling code is * out of the main execution path */ - rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; + rsr = __raw_readl(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { - writel(0, uap->port.membase + UART01x_ECR); + __raw_writel(0, uap->port.membase + UART01x_ECR); if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); @@ -160,7 +158,7 @@ static void pl010_rx_chars(struct uart_a uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag); ignore_char: - status = readb(uap->port.membase + UART01x_FR); + status = __raw_readl(uap->port.membase + UART01x_FR); } spin_unlock(&uap->port.lock); tty_flip_buffer_push(&uap->port.state->port); @@ -173,7 +171,7 @@ static void pl010_tx_chars(struct uart_a int count; if (uap->port.x_char) { - writel(uap->port.x_char, uap->port.membase + UART01x_DR); + __raw_writel(uap->port.x_char, uap->port.membase + UART01x_DR); uap->port.icount.tx++; uap->port.x_char = 0; return; @@ -185,7 +183,7 @@ static void pl010_tx_chars(struct uart_a count = uap->port.fifosize >> 1; do { - writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); + __raw_writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); uap->port.icount.tx++; if (uart_circ_empty(xmit)) @@ -203,9 +201,9 @@ static void pl010_modem_status(struct ua { unsigned int status, delta; - writel(0, uap->port.membase + UART010_ICR); + __raw_writel(0, uap->port.membase + UART010_ICR); - status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + status = __raw_readl(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -233,7 +231,7 @@ static irqreturn_t pl010_int(int irq, vo spin_lock(&uap->port.lock); - status = readb(uap->port.membase + UART010_IIR); + status = __raw_readl(uap->port.membase + UART010_IIR); if (status) { do { if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) @@ -246,7 +244,7 @@ static irqreturn_t pl010_int(int irq, vo if (pass_counter-- == 0) break; - status = readb(uap->port.membase + UART010_IIR); + status = __raw_readl(uap->port.membase + UART010_IIR); } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | UART010_IIR_TIS)); handled = 1; @@ -260,7 +258,7 @@ static irqreturn_t pl010_int(int irq, vo static unsigned int pl010_tx_empty(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned int status = readb(uap->port.membase + UART01x_FR); + unsigned int status = __raw_readl(uap->port.membase + UART01x_FR); return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; } @@ -270,7 +268,7 @@ static unsigned int pl010_get_mctrl(stru unsigned int result = 0; unsigned int status; - status = readb(uap->port.membase + UART01x_FR); + status = __raw_readl(uap->port.membase + UART01x_FR); if (status & UART01x_FR_DCD) result |= TIOCM_CAR; if (status & UART01x_FR_DSR) @@ -296,12 +294,12 @@ static void pl010_break_ctl(struct uart_ unsigned int lcr_h; spin_lock_irqsave(&uap->port.lock, flags); - lcr_h = readb(uap->port.membase + UART010_LCRH); + lcr_h = __raw_readl(uap->port.membase + UART010_LCRH); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - writel(lcr_h, uap->port.membase + UART010_LCRH); + __raw_writel(lcr_h, uap->port.membase + UART010_LCRH); spin_unlock_irqrestore(&uap->port.lock, flags); } @@ -329,12 +327,12 @@ static int pl010_startup(struct uart_por /* * initialise the old status of the modem signals */ - uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + uap->old_status = __raw_readl(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; /* * Finally, enable interrupts */ - writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, + __raw_writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, uap->port.membase + UART010_CR); return 0; @@ -357,10 +355,10 @@ static void pl010_shutdown(struct uart_p /* * disable all interrupts, disable the port */ - writel(0, uap->port.membase + UART010_CR); + __raw_writel(0, uap->port.membase + UART010_CR); /* disable break condition and fifos */ - writel(readb(uap->port.membase + UART010_LCRH) & + __raw_writel(__raw_readl(uap->port.membase + UART010_LCRH) & ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), uap->port.membase + UART010_LCRH); @@ -382,7 +380,7 @@ pl010_set_termios(struct uart_port *port /* * Ask the core to calculate the divisor for us. */ - baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); + baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); quot = uart_get_divisor(port, baud); switch (termios->c_cflag & CSIZE) { @@ -445,25 +443,25 @@ pl010_set_termios(struct uart_port *port uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX; /* first, disable everything */ - old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; + old_cr = __raw_readl(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; if (UART_ENABLE_MS(port, termios->c_cflag)) old_cr |= UART010_CR_MSIE; - writel(0, uap->port.membase + UART010_CR); + __raw_writel(0, uap->port.membase + UART010_CR); /* Set baud rate */ quot -= 1; - writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); - writel(quot & 0xff, uap->port.membase + UART010_LCRL); + __raw_writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); + __raw_writel(quot & 0xff, uap->port.membase + UART010_LCRL); /* * ----------v----------v----------v----------v----- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ - writel(lcr_h, uap->port.membase + UART010_LCRH); - writel(old_cr, uap->port.membase + UART010_CR); + __raw_writel(lcr_h, uap->port.membase + UART010_LCRH); + __raw_writel(old_cr, uap->port.membase + UART010_CR); spin_unlock_irqrestore(&uap->port.lock, flags); } @@ -545,7 +543,7 @@ static struct uart_ops amba_pl010_pops = .verify_port = pl010_verify_port, }; -static struct uart_amba_port *amba_ports[UART_NR]; +static struct uart_amba_port *amba_ports[SERIAL_AMBA_NR]; #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE @@ -555,10 +553,10 @@ static void pl010_console_putchar(struct unsigned int status; do { - status = readb(uap->port.membase + UART01x_FR); + status = __raw_readl(uap->port.membase + UART01x_FR); barrier(); } while (!UART_TX_READY(status)); - writel(ch, uap->port.membase + UART01x_DR); + __raw_writel(ch, uap->port.membase + UART01x_DR); } static void @@ -572,8 +570,8 @@ pl010_console_write(struct console *co, /* * First save the CR then disable the interrupts */ - old_cr = readb(uap->port.membase + UART010_CR); - writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR); + old_cr = __raw_readl(uap->port.membase + UART010_CR); + __raw_writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR); uart_console_write(&uap->port, s, count, pl010_console_putchar); @@ -582,10 +580,10 @@ pl010_console_write(struct console *co, * and restore the TCR */ do { - status = readb(uap->port.membase + UART01x_FR); + status = __raw_readl(uap->port.membase + UART01x_FR); barrier(); } while (status & UART01x_FR_BUSY); - writel(old_cr, uap->port.membase + UART010_CR); + __raw_writel(old_cr, uap->port.membase + UART010_CR); clk_disable(uap->clk); } @@ -594,9 +592,9 @@ static void __init pl010_console_get_options(struct uart_amba_port *uap, int *baud, int *parity, int *bits) { - if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) { + if (__raw_readl(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) { unsigned int lcr_h, quot; - lcr_h = readb(uap->port.membase + UART010_LCRH); + lcr_h = __raw_readl(uap->port.membase + UART010_LCRH); *parity = 'n'; if (lcr_h & UART01x_LCRH_PEN) { @@ -611,8 +609,8 @@ pl010_console_get_options(struct uart_am else *bits = 8; - quot = readb(uap->port.membase + UART010_LCRL) | - readb(uap->port.membase + UART010_LCRM) << 8; + quot = __raw_readl(uap->port.membase + UART010_LCRL) | + __raw_readl(uap->port.membase + UART010_LCRM) << 8; *baud = uap->port.uartclk / (16 * (quot + 1)); } } @@ -631,7 +629,7 @@ static int __init pl010_console_setup(st * if so, search for the first available port that does have * console support. */ - if (co->index >= UART_NR) + if (co->index >= SERIAL_AMBA_NR) co->index = 0; uap = amba_ports[co->index]; if (!uap) @@ -673,7 +671,7 @@ static struct uart_driver amba_reg = { .dev_name = "ttyAM", .major = SERIAL_AMBA_MAJOR, .minor = SERIAL_AMBA_MINOR, - .nr = UART_NR, + .nr = SERIAL_AMBA_NR, .cons = AMBA_CONSOLE, }; --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -25,10 +25,18 @@ config SERIAL_AMBA_PL010 help This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have an Integrator/AP or Integrator/PP2 platform, or if you have a - Cirrus Logic EP93xx CPU, say Y or M here. + Cirrus Logic EP93xx CPU or an Infineon ADM5120 SOC, say Y or M here. If unsure, say N. +config SERIAL_AMBA_PL010_NUMPORTS + int "Maximum number of AMBA PL010 serial ports" + depends on SERIAL_AMBA_PL010 + default "8" + ---help--- + Set this to the number of serial ports you want the AMBA PL010 driver + to support. + config SERIAL_AMBA_PL010_CONSOLE bool "Support for console on AMBA serial port" depends on SERIAL_AMBA_PL010=y