[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v3 1/2] xen/ns16550: identify XScale UARTs from device tree



Identify XScale UARTs using intel,xscale-uart, since IER bit 6 has other
meanings on some UART variants. Keep UUE set when writing IER so the
UART stays enabled when switching to polling, and enable RTOIE along
with receive interrupts.

Signed-off-by: Zhang Zheng <zhangzheng@xxxxxxxxxxx>
---
 xen/drivers/char/ns16550.c  | 29 +++++++++++++++++++++--------
 xen/include/xen/8250-uart.h |  2 ++
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index be388c8e65..1f54155d67 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -64,6 +64,7 @@ static struct ns16550 {
     bool intr_works;
     bool force_polling;
     bool dw_usr_bsy;
+    bool xscale;
 #ifdef NS16550_PCI
     /* PCI card parameters. */
     bool pb_bdf_enable;     /* if =1, pb-bdf effective, port behind bridge */
@@ -168,6 +169,14 @@ static void ns_write_reg(const struct ns16550 *uart, 
unsigned int reg, u8 c)
     }
 }
 
+static void ns_write_ier(const struct ns16550 *uart, u8 ier)
+{
+    if ( uart->xscale )
+        ier |= UART_IER_UUE;
+
+    ns_write_reg(uart, UART_IER, ier);
+}
+
 static int ns16550_ioport_invalid(struct ns16550 *uart)
 {
     return ns_read_reg(uart, UART_IER) == 0xff;
@@ -218,7 +227,7 @@ static void cf_check ns16550_interrupt(int irq, void 
*dev_id)
 
             /* Disable interrupt generation on the device and arm the timer. */
             uart->force_polling = true;
-            ns_write_reg(uart, UART_IER, 0);
+            ns_write_ier(uart, 0);
             set_timer(&uart->timer, now + MILLISECS(uart->timeout_ms));
             printk(XENLOG_WARNING
                    "uart interrupt taking more than %ums, switched to 
polling\n",
@@ -350,7 +359,7 @@ static void ns16550_setup_preirq(struct ns16550 *uart)
     lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity;
 
     /* No interrupts. */
-    ns_write_reg(uart, UART_IER, 0);
+    ns_write_ier(uart, 0);
 
     /* Handle the DesignWare 8250 'busy-detect' quirk. */
     handle_dw_usr_busy_quirk(uart);
@@ -446,7 +455,8 @@ static void ns16550_setup_postirq(struct ns16550 *uart)
                      UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS);
 
         /* Enable receive interrupts. */
-        ns_write_reg(uart, UART_IER, UART_IER_ERDAI);
+        ns_write_ier(uart, UART_IER_ERDAI |
+                     (uart->xscale ? UART_IER_RTOIE : 0));
     }
 
     if ( uart->irq >= 0 )
@@ -654,7 +664,7 @@ static void cf_check ns16550_start_tx(struct serial_port 
*port)
 
     /* Unmask transmit holding register empty interrupt if currently masked. */
     if ( !(ier & UART_IER_ETHREI) )
-        ns_write_reg(uart, UART_IER, ier | UART_IER_ETHREI);
+        ns_write_ier(uart, ier | UART_IER_ETHREI);
 }
 
 static void cf_check ns16550_stop_tx(struct serial_port *port)
@@ -664,7 +674,7 @@ static void cf_check ns16550_stop_tx(struct serial_port 
*port)
 
     /* Mask off transmit holding register empty interrupt if currently 
unmasked. */
     if ( ier & UART_IER_ETHREI )
-        ns_write_reg(uart, UART_IER, ier & ~UART_IER_ETHREI);
+        ns_write_ier(uart, ier & ~UART_IER_ETHREI);
 }
 
 #ifdef CONFIG_ARM
@@ -749,16 +759,16 @@ static int __init check_existence(struct ns16550 *uart)
      * there's no point trying anything else.
      */
     scratch = ns_read_reg(uart, UART_IER);
-    ns_write_reg(uart, UART_IER, 0);
+    ns_write_ier(uart, 0);
 
     /*
      * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
      * 16C754B) allow only to modify them if an EFR bit is set.
      */
     scratch2 = ns_read_reg(uart, UART_IER) & 0x0f;
-    ns_write_reg(uart,UART_IER, 0x0F);
+    ns_write_ier(uart, 0x0f);
     scratch3 = ns_read_reg(uart, UART_IER) & 0x0f;
-    ns_write_reg(uart, UART_IER, scratch);
+    ns_write_ier(uart, scratch);
     if ( (scratch2 != 0) || (scratch3 != 0x0F) )
         return 0;
 
@@ -2034,6 +2044,8 @@ static int __init ns16550_uart_dt_init(struct 
dt_device_node *dev,
 
     uart->dw_usr_bsy = dt_device_is_compatible(dev, "snps,dw-apb-uart");
 
+    uart->xscale = dt_device_is_compatible(dev, "intel,xscale-uart");
+
 #ifdef CONFIG_ARM
     uart->vuart.base_addr = uart->io_base;
     uart->vuart.size = uart->io_size;
@@ -2055,6 +2067,7 @@ static const struct dt_device_match ns16550_dt_match[] 
__initconst =
     DT_MATCH_COMPATIBLE("ns16550"),
     DT_MATCH_COMPATIBLE("ns16550a"),
     DT_MATCH_COMPATIBLE("snps,dw-apb-uart"),
+    DT_MATCH_COMPATIBLE("intel,xscale-uart"),
     DT_MATCH_COMPATIBLE("brcm,bcm2835-aux-uart"),
     { /* sentinel */ },
 };
diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
index d13352940c..5709a6c91b 100644
--- a/xen/include/xen/8250-uart.h
+++ b/xen/include/xen/8250-uart.h
@@ -42,6 +42,8 @@
 #define UART_IER_ETHREI   0x02    /* tx reg. empty        */
 #define UART_IER_ELSI     0x04    /* rx line status       */
 #define UART_IER_EMSI     0x08    /* MODEM status         */
+#define UART_IER_RTOIE    0x10    /* Receive timeout interrupt enable (XScale) 
*/
+#define UART_IER_UUE      0x40    /* UART unit enable (XScale) */
 
 /* Interrupt Identification Register */
 #define UART_IIR_NOINT    0x01    /* no interrupt pending */
-- 
2.54.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.