summaryrefslogtreecommitdiff
path: root/drivers/serial/8250.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/8250.c')
-rw-r--r--drivers/serial/8250.c109
1 files changed, 79 insertions, 30 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index ee74c934de89..b25e6e490530 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);