serial: clear proper MPSC interrupt cause bits
[linux-drm-fsl-dcu.git] / drivers / serial / mpsc.c
index 8eea69f29989947d3c8ca0f16c08a0ee08f965bc..00924feaf621831caa46267ad8b9b278a48a8552 100644 (file)
@@ -183,6 +183,7 @@ struct mpsc_port_info {
        u8 *txb_p;              /* Phys addr of txb */
        int txr_head;           /* Where new data goes */
        int txr_tail;           /* Where sent data comes off */
+       spinlock_t tx_lock;     /* transmit lock */
 
        /* Mirrored values of regs we can't read (if 'mirror_regs' set) */
        u32 MPSC_MPCR_m;
@@ -502,7 +503,8 @@ mpsc_sdma_intr_ack(struct mpsc_port_info *pi)
 
        if (pi->mirror_regs)
                pi->shared_regs->SDMA_INTR_CAUSE_m = 0;
-       writel(0, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE);
+       writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE +
+              pi->port.line);
        return;
 }
 
@@ -555,7 +557,7 @@ mpsc_sdma_start_tx(struct mpsc_port_info *pi)
        if (!mpsc_sdma_tx_active(pi)) {
                txre = (struct mpsc_tx_desc *)(pi->txr +
                        (pi->txr_tail * MPSC_TXRE_SIZE));
-               dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)txre,
@@ -931,7 +933,7 @@ mpsc_init_rings(struct mpsc_port_info *pi)
        }
        txre->link = cpu_to_be32(pi->txr_p);    /* Wrap last back to first */
 
-       dma_cache_sync((void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE,
+       dma_cache_sync(pi->port.dev, (void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE,
                DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
@@ -1005,7 +1007,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi)
 
        rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE));
 
-       dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+       dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
        if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                invalidate_dcache_range((ulong)rxre,
@@ -1029,7 +1031,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi)
                }
 
                bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
-               dma_cache_sync((void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)bp,
@@ -1098,7 +1100,7 @@ next_frame:
                                            SDMA_DESC_CMDSTAT_F |
                                            SDMA_DESC_CMDSTAT_L);
                wmb();
-               dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
+               dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        flush_dcache_range((ulong)rxre,
@@ -1109,7 +1111,7 @@ next_frame:
                pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1);
                rxre = (struct mpsc_rx_desc *)(pi->rxr +
                        (pi->rxr_posn * MPSC_RXRE_SIZE));
-               dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)rxre,
@@ -1143,7 +1145,7 @@ mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr)
                                                           SDMA_DESC_CMDSTAT_EI
                                                           : 0));
        wmb();
-       dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL);
+       dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
        if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                flush_dcache_range((ulong)txre,
@@ -1192,7 +1194,7 @@ mpsc_copy_tx_data(struct mpsc_port_info *pi)
                else /* All tx data copied into ring bufs */
                        return;
 
-               dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
+               dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        flush_dcache_range((ulong)bp,
@@ -1212,12 +1214,15 @@ mpsc_tx_intr(struct mpsc_port_info *pi)
 {
        struct mpsc_tx_desc *txre;
        int rc = 0;
+       unsigned long iflags;
+
+       spin_lock_irqsave(&pi->tx_lock, iflags);
 
        if (!mpsc_sdma_tx_active(pi)) {
                txre = (struct mpsc_tx_desc *)(pi->txr +
                        (pi->txr_tail * MPSC_TXRE_SIZE));
 
-               dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
+               dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        invalidate_dcache_range((ulong)txre,
@@ -1235,7 +1240,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi)
 
                        txre = (struct mpsc_tx_desc *)(pi->txr +
                                (pi->txr_tail * MPSC_TXRE_SIZE));
-                       dma_cache_sync((void *) txre, MPSC_TXRE_SIZE,
+                       dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE,
                                DMA_FROM_DEVICE);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                        if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
@@ -1248,6 +1253,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi)
                mpsc_sdma_start_tx(pi); /* start next desc if ready */
        }
 
+       spin_unlock_irqrestore(&pi->tx_lock, iflags);
        return rc;
 }
 
@@ -1338,11 +1344,16 @@ static void
 mpsc_start_tx(struct uart_port *port)
 {
        struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+       unsigned long iflags;
+
+       spin_lock_irqsave(&pi->tx_lock, iflags);
 
        mpsc_unfreeze(pi);
        mpsc_copy_tx_data(pi);
        mpsc_sdma_start_tx(pi);
 
+       spin_unlock_irqrestore(&pi->tx_lock, iflags);
+
        pr_debug("mpsc_start_tx[%d]\n", port->line);
        return;
 }
@@ -1440,8 +1451,8 @@ mpsc_shutdown(struct uart_port *port)
 }
 
 static void
-mpsc_set_termios(struct uart_port *port, struct termios *termios,
-                struct termios *old)
+mpsc_set_termios(struct uart_port *port, struct ktermios *termios,
+                struct ktermios *old)
 {
        struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
        u32 baud;
@@ -1625,6 +1636,16 @@ mpsc_console_write(struct console *co, const char *s, uint count)
        struct mpsc_port_info *pi = &mpsc_ports[co->index];
        u8 *bp, *dp, add_cr = 0;
        int i;
+       unsigned long iflags;
+
+       spin_lock_irqsave(&pi->tx_lock, iflags);
+
+       while (pi->txr_head != pi->txr_tail) {
+               while (mpsc_sdma_tx_active(pi))
+                       udelay(100);
+               mpsc_sdma_intr_ack(pi);
+               mpsc_tx_intr(pi);
+       }
 
        while (mpsc_sdma_tx_active(pi))
                udelay(100);
@@ -1652,7 +1673,7 @@ mpsc_console_write(struct console *co, const char *s, uint count)
                        count--;
                }
 
-               dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
+               dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL);
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
                if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
                        flush_dcache_range((ulong)bp,
@@ -1668,6 +1689,7 @@ mpsc_console_write(struct console *co, const char *s, uint count)
                pi->txr_tail = (pi->txr_tail + 1) & (MPSC_TXR_ENTRIES - 1);
        }
 
+       spin_unlock_irqrestore(&pi->tx_lock, iflags);
        return;
 }
 
@@ -2005,7 +2027,8 @@ mpsc_drv_probe(struct platform_device *dev)
                if (!(rc = mpsc_drv_map_regs(pi, dev))) {
                        mpsc_drv_get_platform_data(pi, dev, dev->id);
 
-                       if (!(rc = mpsc_make_ready(pi)))
+                       if (!(rc = mpsc_make_ready(pi))) {
+                               spin_lock_init(&pi->tx_lock);
                                if (!(rc = uart_add_one_port(&mpsc_reg,
                                        &pi->port)))
                                        rc = 0;
@@ -2014,6 +2037,7 @@ mpsc_drv_probe(struct platform_device *dev)
                                                (struct uart_port *)pi);
                                        mpsc_drv_unmap_regs(pi);
                                }
+                       }
                        else
                                mpsc_drv_unmap_regs(pi);
                }