aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/drivers/char/ns16550.c14
-rw-r--r--xen/include/xen/8250-uart.h2
2 files changed, 16 insertions, 0 deletions
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index 45da924381..5892eb7a85 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -61,6 +61,7 @@ static struct ns16550 {
struct timer resume_timer;
unsigned int timeout_ms;
bool_t intr_works;
+ bool_t dw_usr_bsy;
#ifdef HAS_PCI
/* PCI card parameters. */
unsigned int pb_bdf[3]; /* pci bridge BDF */
@@ -237,6 +238,16 @@ static void ns16550_setup_preirq(struct ns16550 *uart)
/* No interrupts. */
ns_write_reg(uart, UART_IER, 0);
+ if ( uart->dw_usr_bsy &&
+ (ns_read_reg(uart, UART_IIR) & UART_IIR_BSY) == UART_IIR_BSY )
+ {
+ /* DesignWare 8250 detects if LCR is written while the UART is
+ * busy and raises a "busy detect" interrupt. Read the UART
+ * Status Register to clear this state.
+ */
+ ns_read_reg(uart, UART_USR);
+ }
+
/* Line control and baud-rate generator. */
ns_write_reg(uart, UART_LCR, lcr | UART_LCR_DLAB);
if ( uart->baud != BAUD_AUTO )
@@ -787,6 +798,8 @@ static int __init ns16550_uart_dt_init(struct dt_device_node *dev,
/* The common bit of the driver mostly deals with irq not dt_irq. */
uart->irq = uart->dt_irq.irq;
+ uart->dw_usr_bsy = dt_device_is_compatible(dev, "snps,dw-apb-uart");
+
uart->vuart.base_addr = uart->io_base;
uart->vuart.size = uart->io_size;
uart->vuart.data_off = UART_THR <<uart->reg_shift;
@@ -804,6 +817,7 @@ static int __init ns16550_uart_dt_init(struct dt_device_node *dev,
static const char const *ns16550_dt_compat[] __initconst =
{
"ns16550",
+ "snps,dw-apb-uart",
NULL
};
diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
index 8693d15467..a682bae797 100644
--- a/xen/include/xen/8250-uart.h
+++ b/xen/include/xen/8250-uart.h
@@ -32,6 +32,7 @@
#define UART_MCR 0x04 /* Modem control */
#define UART_LSR 0x05 /* line status */
#define UART_MSR 0x06 /* Modem status */
+#define UART_USR 0x1f /* Status register (DW) */
#define UART_DLL 0x00 /* divisor latch (ls) (DLAB=1) */
#define UART_DLM 0x01 /* divisor latch (ms) (DLAB=1) */
@@ -48,6 +49,7 @@
#define UART_IIR_RDA 0x04 /* - rx data recv'd */
#define UART_IIR_THR 0x02 /* - tx reg. empty */
#define UART_IIR_MSI 0x00 /* - MODEM status */
+#define UART_IIR_BSY 0x07 /* - busy detect (DW) */
/* FIFO Control Register */
#define UART_FCR_ENABLE 0x01 /* enable FIFO */