|
@@ -454,22 +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 =
|
|
|
- container_of(p, struct uart_8250_port, port);
|
|
|
- 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)
|
|
@@ -520,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;
|
|
@@ -538,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;
|
|
@@ -1587,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
|
|
@@ -2492,6 +2517,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;
|
|
|
|
|
@@ -2529,6 +2555,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;
|
|
|
|