serial: sirf: add support for new SiRFmarco SMP SoC
authorBarry Song <Baohua.Song@csr.com>
Tue, 25 Dec 2012 09:32:04 +0000 (17:32 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Jan 2013 05:54:40 +0000 (21:54 -0800)
CSR SiRFmarco's UART IP is same with SiRFprimaII except that
it has two more uart ports.
this patch makes the old driver support new SiRFmarco as well:
1. add .compatible = "sirf,marco-uart" to OF match table
2. add two ports in the port table
3. take spin_lock in isr to avoid the conflict of threads opening
uart on CPU1 and isr running on CPU0.
For 3, we did see some problems on SiRFmarco as SiRFmarco is a
SMP SoC but the old SiRFprimaII is UP.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/sirfsoc_uart.c
drivers/tty/serial/sirfsoc_uart.h

index 5da5cb962769df537c02392a3e96e41bb117837b..142217cd01f47850e93f974f13b2383f7f80e5af 100644 (file)
@@ -75,6 +75,20 @@ static struct sirfsoc_uart_port sirfsoc_uart_ports[SIRFSOC_UART_NR] = {
                        .line           = 2,
                },
        },
+       [3] = {
+               .port = {
+                       .iotype         = UPIO_MEM,
+                       .flags          = UPF_BOOT_AUTOCONF,
+                       .line           = 3,
+               },
+       },
+       [4] = {
+               .port = {
+                       .iotype         = UPIO_MEM,
+                       .flags          = UPF_BOOT_AUTOCONF,
+                       .line           = 4,
+               },
+       },
 };
 
 static inline struct sirfsoc_uart_port *to_sirfport(struct uart_port *port)
@@ -245,6 +259,7 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
        struct uart_port *port = &sirfport->port;
        struct uart_state *state = port->state;
        struct circ_buf *xmit = &port->state->xmit;
+       spin_lock(&port->lock);
        intr_status = rd_regl(port, SIRFUART_INT_STATUS);
        wr_regl(port, SIRFUART_INT_STATUS, intr_status);
        intr_status &= rd_regl(port, SIRFUART_INT_EN);
@@ -254,6 +269,7 @@ static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id)
                                goto recv_char;
                        uart_insert_char(port, intr_status,
                                        SIRFUART_RX_OFLOW, 0, TTY_BREAK);
+                       spin_unlock(&port->lock);
                        return IRQ_HANDLED;
                }
                if (intr_status & SIRFUART_RX_OFLOW)
@@ -286,6 +302,7 @@ recv_char:
                sirfsoc_uart_pio_rx_chars(port, SIRFSOC_UART_IO_RX_MAX_CNT);
        if (intr_status & SIRFUART_TX_INT_EN) {
                if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+                       spin_unlock(&port->lock);
                        return IRQ_HANDLED;
                } else {
                        sirfsoc_uart_pio_tx_chars(sirfport,
@@ -296,6 +313,7 @@ recv_char:
                                sirfsoc_uart_stop_tx(port);
                }
        }
+       spin_unlock(&port->lock);
        return IRQ_HANDLED;
 }
 
@@ -729,6 +747,7 @@ static int sirfsoc_uart_resume(struct platform_device *pdev)
 
 static struct of_device_id sirfsoc_uart_ids[] = {
        { .compatible = "sirf,prima2-uart", },
+       { .compatible = "sirf,marco-uart", },
        {}
 };
 MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match);
index 6e207fdc2fed7615daa0d2cedbaf4013afca4463..6431640c3163a62011356575aac2112522c5dc44 100644 (file)
 #define SIRFSOC_UART_MINOR                     0
 #define SIRFUART_PORT_NAME                     "sirfsoc-uart"
 #define SIRFUART_MAP_SIZE                      0x200
-#define SIRFSOC_UART_NR                                3
+#define SIRFSOC_UART_NR                                5
 #define SIRFSOC_PORT_TYPE                      0xa5
 
 /* Baud Rate Calculation */