diff options
Diffstat (limited to 'drivers/serial/8250.c')
-rw-r--r-- | drivers/serial/8250.c | 109 |
1 files changed, 79 insertions, 30 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index ee74c934de8..b25e6e49053 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -454,21 +454,40 @@ static void tsi_serial_out(struct uart_port *p, int offset, int value) writeb(value, p->membase + offset); } +/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */ +static inline void dwapb_save_out_value(struct uart_port *p, int offset, + int value) +{ + struct uart_8250_port *up = + container_of(p, struct uart_8250_port, port); + + if (offset == UART_LCR) + up->lcr = value; +} + +/* Read the IER to ensure any interrupt is cleared before returning from ISR. */ +static inline void dwapb_check_clear_ier(struct uart_port *p, int offset) +{ + if (offset == UART_TX || offset == UART_IER) + p->serial_in(p, UART_IER); +} + static void dwapb_serial_out(struct uart_port *p, int offset, int value) { int save_offset = offset; offset = map_8250_out_reg(p, offset) << p->regshift; - /* Save the LCR value so it can be re-written when a - * Busy Detect interrupt occurs. */ - if (save_offset == UART_LCR) { - struct uart_8250_port *up = (struct uart_8250_port *)p; - up->lcr = value; - } + dwapb_save_out_value(p, save_offset, value); writeb(value, p->membase + offset); - /* Read the IER to ensure any interrupt is cleared before - * returning from ISR. */ - if (save_offset == UART_TX || save_offset == UART_IER) - value = p->serial_in(p, UART_IER); + dwapb_check_clear_ier(p, save_offset); +} + +static void dwapb32_serial_out(struct uart_port *p, int offset, int value) +{ + int save_offset = offset; + offset = map_8250_out_reg(p, offset) << p->regshift; + dwapb_save_out_value(p, save_offset, value); + writel(value, p->membase + offset); + dwapb_check_clear_ier(p, save_offset); } static unsigned int io_serial_in(struct uart_port *p, int offset) @@ -485,7 +504,8 @@ static void io_serial_out(struct uart_port *p, int offset, int value) static void set_io_from_upio(struct uart_port *p) { - struct uart_8250_port *up = (struct uart_8250_port *)p; + struct uart_8250_port *up = + container_of(p, struct uart_8250_port, port); switch (p->iotype) { case UPIO_HUB6: p->serial_in = hub6_serial_in; @@ -518,6 +538,11 @@ static void set_io_from_upio(struct uart_port *p) p->serial_out = dwapb_serial_out; break; + case UPIO_DWAPB32: + p->serial_in = mem32_serial_in; + p->serial_out = dwapb32_serial_out; + break; + default: p->serial_in = io_serial_in; p->serial_out = io_serial_out; @@ -536,6 +561,7 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) case UPIO_MEM32: case UPIO_AU: case UPIO_DWAPB: + case UPIO_DWAPB32: p->serial_out(p, offset, value); p->serial_in(p, UART_LCR); /* safe, no side-effects */ break; @@ -1319,7 +1345,8 @@ static inline void __stop_tx(struct uart_8250_port *p) static void serial8250_stop_tx(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); __stop_tx(up); @@ -1336,7 +1363,8 @@ static void transmit_chars(struct uart_8250_port *up); static void serial8250_start_tx(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); if (!(up->ier & UART_IER_THRI)) { up->ier |= UART_IER_THRI; @@ -1364,7 +1392,8 @@ static void serial8250_start_tx(struct uart_port *port) static void serial8250_stop_rx(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); up->ier &= ~UART_IER_RLSI; up->port.read_status_mask &= ~UART_LSR_DR; @@ -1373,7 +1402,8 @@ static void serial8250_stop_rx(struct uart_port *port) static void serial8250_enable_ms(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); /* no MSR capabilities */ if (up->bugs & UART_BUG_NOMSR) @@ -1581,7 +1611,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) handled = 1; end = NULL; - } else if (up->port.iotype == UPIO_DWAPB && + } else if ((up->port.iotype == UPIO_DWAPB || + up->port.iotype == UPIO_DWAPB32) && (iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* The DesignWare APB UART has an Busy Detect (0x07) * interrupt meaning an LCR write attempt occured while the @@ -1781,7 +1812,8 @@ static void serial8250_backup_timeout(unsigned long data) static unsigned int serial8250_tx_empty(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned long flags; unsigned int lsr; @@ -1795,7 +1827,8 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) static unsigned int serial8250_get_mctrl(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned int status; unsigned int ret; @@ -1815,7 +1848,8 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port) static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned char mcr = 0; if (mctrl & TIOCM_RTS) @@ -1836,7 +1870,8 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) static void serial8250_break_ctl(struct uart_port *port, int break_state) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned long flags; spin_lock_irqsave(&up->port.lock, flags); @@ -1890,7 +1925,8 @@ 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 = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned char lsr = serial_inp(up, UART_LSR); if (!(lsr & UART_LSR_DR)) @@ -1904,7 +1940,8 @@ static void serial8250_put_poll_char(struct uart_port *port, unsigned char c) { unsigned int ier; - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); /* * First save the IER then disable the interrupts @@ -1938,11 +1975,14 @@ static void serial8250_put_poll_char(struct uart_port *port, static int serial8250_startup(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned long flags; unsigned char lsr, iir; int retval; + up->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; @@ -2166,7 +2206,8 @@ dont_test_tx_en: static void serial8250_shutdown(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned long flags; /* @@ -2235,7 +2276,8 @@ void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); unsigned char cval, fcr = 0; unsigned long flags; unsigned int baud, quot; @@ -2435,7 +2477,8 @@ serial8250_set_ldisc(struct uart_port *port, int new) void serial8250_do_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { - struct uart_8250_port *p = (struct uart_8250_port *)port; + struct uart_8250_port *p = + container_of(port, struct uart_8250_port, port); serial8250_set_sleep(p, state != 0); } @@ -2476,6 +2519,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) case UPIO_MEM32: case UPIO_MEM: case UPIO_DWAPB: + case UPIO_DWAPB32: if (!up->port.mapbase) break; @@ -2513,6 +2557,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up) case UPIO_MEM32: case UPIO_MEM: case UPIO_DWAPB: + case UPIO_DWAPB32: if (!up->port.mapbase) break; @@ -2566,7 +2611,8 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up) static void serial8250_release_port(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); serial8250_release_std_resource(up); if (up->port.type == PORT_RSA) @@ -2575,7 +2621,8 @@ static void serial8250_release_port(struct uart_port *port) static int serial8250_request_port(struct uart_port *port) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); int ret = 0; ret = serial8250_request_std_resource(up); @@ -2590,7 +2637,8 @@ static int serial8250_request_port(struct uart_port *port) static void serial8250_config_port(struct uart_port *port, int flags) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); int probeflags = PROBE_ANY; int ret; @@ -2771,7 +2819,8 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) static void serial8250_console_putchar(struct uart_port *port, int ch) { - struct uart_8250_port *up = (struct uart_8250_port *)port; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); wait_for_xmitr(up, UART_LSR_THRE); serial_out(up, UART_TX, ch); |