These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / tty / serial / 8250 / 8250_omap.c
index dce1a23..a2c0734 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/delay.h>
 #include <linux/pm_runtime.h>
 #include <linux/console.h>
 #include <linux/pm_qos.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/dma-mapping.h>
 
 #include "8250.h"
 #define UART_ERRATA_i202_MDR1_ACCESS   (1 << 0)
 #define OMAP_UART_WER_HAS_TX_WAKEUP    (1 << 1)
 #define OMAP_DMA_TX_KICK               (1 << 2)
+/*
+ * See Advisory 21 in AM437x errata SPRZ408B, updated April 2015.
+ * The same errata is applicable to AM335x and DRA7x processors too.
+ */
+#define UART_ERRATA_CLOCK_DISABLE      (1 << 3)
 
 #define OMAP_UART_FCR_RX_TRIG          6
 #define OMAP_UART_FCR_TX_TRIG          4
 #define OMAP_UART_MVR_MAJ_SHIFT                8
 #define OMAP_UART_MVR_MIN_MASK         0x3f
 
+/* SYSC register bitmasks */
+#define OMAP_UART_SYSC_SOFTRESET       (1 << 1)
+
+/* SYSS register bitmasks */
+#define OMAP_UART_SYSS_RESETDONE       (1 << 0)
+
 #define UART_TI752_TLR_TX      0
 #define UART_TI752_TLR_RX      4
 
@@ -98,6 +111,8 @@ struct omap8250_priv {
        struct pm_qos_request pm_qos_request;
        struct work_struct qos_work;
        struct uart_8250_dma omap8250_dma;
+       spinlock_t rx_dma_lock;
+       bool rx_dma_broken;
 };
 
 static u32 uart_read(struct uart_8250_port *up, u32 reg)
@@ -230,6 +245,15 @@ static void omap8250_update_scr(struct uart_8250_port *up,
        serial_out(up, UART_OMAP_SCR, priv->scr);
 }
 
+static void omap8250_update_mdr1(struct uart_8250_port *up,
+                                struct omap8250_priv *priv)
+{
+       if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+               omap_8250_mdr1_errataset(up, priv);
+       else
+               serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+}
+
 static void omap8250_restore_regs(struct uart_8250_port *up)
 {
        struct omap8250_priv *priv = up->port.private_data;
@@ -280,11 +304,9 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
        serial_out(up, UART_XOFF1, priv->xoff);
 
        serial_out(up, UART_LCR, up->lcr);
-       /* need mode A for FCR */
-       if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
-               omap_8250_mdr1_errataset(up, priv);
-       else
-               serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+
+       omap8250_update_mdr1(up, priv);
+
        up->port.ops->set_mctrl(&up->port, up->port.mctrl);
 }
 
@@ -417,7 +439,6 @@ static void omap_8250_set_termios(struct uart_port *port,
        priv->xoff = termios->c_cc[VSTOP];
 
        priv->efr = 0;
-       up->mcr &= ~(UART_MCR_RTS | UART_MCR_XONANY);
        up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
 
        if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
@@ -426,12 +447,9 @@ static void omap_8250_set_termios(struct uart_port *port,
                priv->efr |= UART_EFR_CTS;
        } else  if (up->port.flags & UPF_SOFT_FLOW) {
                /*
-                * IXON Flag:
-                * Enable XON/XOFF flow control on input.
-                * Receiver compares XON1, XOFF1.
+                * OMAP rx s/w flow control is borked; the transmitter remains
+                * stuck off even if rx flow control is subsequently disabled
                 */
-               if (termios->c_iflag & IXON)
-                       priv->efr |= OMAP_UART_SW_RX;
 
                /*
                 * IXOFF Flag:
@@ -442,15 +460,6 @@ static void omap_8250_set_termios(struct uart_port *port,
                        up->port.status |= UPSTAT_AUTOXOFF;
                        priv->efr |= OMAP_UART_SW_TX;
                }
-
-               /*
-                * IXANY Flag:
-                * Enable any character to restart output.
-                * Operation resumes after receiving any
-                * character after recognition of the XOFF character
-                */
-               if (termios->c_iflag & IXANY)
-                       up->mcr |= UART_MCR_XONANY;
        }
        omap8250_restore_regs(up);
 
@@ -528,14 +537,14 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up,
 
        switch (revision) {
        case OMAP_UART_REV_46:
-               priv->habit = UART_ERRATA_i202_MDR1_ACCESS;
+               priv->habit |= UART_ERRATA_i202_MDR1_ACCESS;
                break;
        case OMAP_UART_REV_52:
-               priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+               priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
                                OMAP_UART_WER_HAS_TX_WAKEUP;
                break;
        case OMAP_UART_REV_63:
-               priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+               priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
                        OMAP_UART_WER_HAS_TX_WAKEUP;
                break;
        default:
@@ -551,17 +560,6 @@ static void omap8250_uart_qos_work(struct work_struct *work)
        pm_qos_update_request(&priv->pm_qos_request, priv->latency);
 }
 
-static irqreturn_t omap_wake_irq(int irq, void *dev_id)
-{
-       struct uart_port *port = dev_id;
-       int ret;
-
-       ret = port->handle_irq(port);
-       if (ret)
-               return IRQ_HANDLED;
-       return IRQ_NONE;
-}
-
 #ifdef CONFIG_SERIAL_8250_DMA
 static int omap_8250_dma_handle_irq(struct uart_port *port);
 #endif
@@ -595,11 +593,9 @@ static int omap_8250_startup(struct uart_port *port)
        int ret;
 
        if (priv->wakeirq) {
-               ret = request_irq(priv->wakeirq, omap_wake_irq,
-                                 port->irqflags, "uart wakeup irq", port);
+               ret = dev_pm_set_dedicated_wake_irq(port->dev, priv->wakeirq);
                if (ret)
                        return ret;
-               disable_irq(priv->wakeirq);
        }
 
        pm_runtime_get_sync(port->dev);
@@ -648,8 +644,7 @@ static int omap_8250_startup(struct uart_port *port)
 err:
        pm_runtime_mark_last_busy(port->dev);
        pm_runtime_put_autosuspend(port->dev);
-       if (priv->wakeirq)
-               free_irq(priv->wakeirq, port);
+       dev_pm_clear_wake_irq(port->dev);
        return ret;
 }
 
@@ -681,10 +676,8 @@ static void omap_8250_shutdown(struct uart_port *port)
 
        pm_runtime_mark_last_busy(port->dev);
        pm_runtime_put_autosuspend(port->dev);
-
        free_irq(port->irq, port);
-       if (priv->wakeirq)
-               free_irq(priv->wakeirq, port);
+       dev_pm_clear_wake_irq(port->dev);
 }
 
 static void omap_8250_throttle(struct uart_port *port)
@@ -726,22 +719,35 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir);
 
 static void __dma_rx_do_complete(struct uart_8250_port *p, bool error)
 {
+       struct omap8250_priv    *priv = p->port.private_data;
        struct uart_8250_dma    *dma = p->dma;
        struct tty_port         *tty_port = &p->port.state->port;
        struct dma_tx_state     state;
        int                     count;
+       unsigned long           flags;
+       int                     ret;
 
        dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
                                dma->rx_size, DMA_FROM_DEVICE);
 
+       spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
+       if (!dma->rx_running)
+               goto unlock;
+
        dma->rx_running = 0;
        dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
        dmaengine_terminate_all(dma->rxchan);
 
        count = dma->rx_size - state.residue;
 
-       tty_insert_flip_string(tty_port, dma->rx_buf, count);
-       p->port.icount.rx += count;
+       ret = tty_insert_flip_string(tty_port, dma->rx_buf, count);
+
+       p->port.icount.rx += ret;
+       p->port.icount.buf_overrun += count - ret;
+unlock:
+       spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+
        if (!error)
                omap_8250_rx_dma(p, 0);
 
@@ -753,28 +759,48 @@ static void __dma_rx_complete(void *param)
        __dma_rx_do_complete(param, false);
 }
 
+static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
+{
+       struct omap8250_priv    *priv = p->port.private_data;
+       struct uart_8250_dma    *dma = p->dma;
+       unsigned long           flags;
+       int ret;
+
+       spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
+       if (!dma->rx_running) {
+               spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+               return;
+       }
+
+       ret = dmaengine_pause(dma->rxchan);
+       if (WARN_ON_ONCE(ret))
+               priv->rx_dma_broken = true;
+
+       spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+
+       __dma_rx_do_complete(p, true);
+}
+
 static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
 {
+       struct omap8250_priv            *priv = p->port.private_data;
        struct uart_8250_dma            *dma = p->dma;
+       int                             err = 0;
        struct dma_async_tx_descriptor  *desc;
+       unsigned long                   flags;
 
        switch (iir & 0x3f) {
        case UART_IIR_RLSI:
                /* 8250_core handles errors and break interrupts */
-               if (dma->rx_running) {
-                       dmaengine_pause(dma->rxchan);
-                       __dma_rx_do_complete(p, true);
-               }
+               omap_8250_rx_dma_flush(p);
                return -EIO;
        case UART_IIR_RX_TIMEOUT:
                /*
                 * If RCVR FIFO trigger level was not reached, complete the
                 * transfer and let 8250_core copy the remaining data.
                 */
-               if (dma->rx_running) {
-                       dmaengine_pause(dma->rxchan);
-                       __dma_rx_do_complete(p, true);
-               }
+               omap_8250_rx_dma_flush(p);
                return -ETIMEDOUT;
        case UART_IIR_RDI:
                /*
@@ -786,24 +812,28 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
                 * the DMA won't do anything soon so we have to cancel the DMA
                 * transfer and purge the FIFO manually.
                 */
-               if (dma->rx_running) {
-                       dmaengine_pause(dma->rxchan);
-                       __dma_rx_do_complete(p, true);
-               }
+               omap_8250_rx_dma_flush(p);
                return -ETIMEDOUT;
 
        default:
                break;
        }
 
+       if (priv->rx_dma_broken)
+               return -EINVAL;
+
+       spin_lock_irqsave(&priv->rx_dma_lock, flags);
+
        if (dma->rx_running)
-               return 0;
+               goto out;
 
        desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
                                           dma->rx_size, DMA_DEV_TO_MEM,
                                           DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc)
-               return -EBUSY;
+       if (!desc) {
+               err = -EBUSY;
+               goto out;
+       }
 
        dma->rx_running = 1;
        desc->callback = __dma_rx_complete;
@@ -815,7 +845,9 @@ static int omap_8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
                                   dma->rx_size, DMA_FROM_DEVICE);
 
        dma_async_issue_pending(dma->rxchan);
-       return 0;
+out:
+       spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
+       return err;
 }
 
 static int omap_8250_tx_dma(struct uart_8250_port *p);
@@ -1038,6 +1070,20 @@ static int omap8250_no_handle_irq(struct uart_port *port)
        return 0;
 }
 
+static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
+static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE;
+
+static const struct of_device_id omap8250_dt_ids[] = {
+       { .compatible = "ti,omap2-uart" },
+       { .compatible = "ti,omap3-uart" },
+       { .compatible = "ti,omap4-uart" },
+       { .compatible = "ti,am3352-uart", .data = &am3352_habit, },
+       { .compatible = "ti,am4372-uart", .data = &am4372_habit, },
+       { .compatible = "ti,dra742-uart", .data = &am4372_habit, },
+       {},
+};
+MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
+
 static int omap8250_probe(struct platform_device *pdev)
 {
        struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1102,11 +1148,17 @@ static int omap8250_probe(struct platform_device *pdev)
        up.port.unthrottle = omap_8250_unthrottle;
 
        if (pdev->dev.of_node) {
+               const struct of_device_id *id;
+
                ret = of_alias_get_id(pdev->dev.of_node, "serial");
 
                of_property_read_u32(pdev->dev.of_node, "clock-frequency",
                                     &up.port.uartclk);
                priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+
+               id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
+               if (id && id->data)
+                       priv->habit |= *(u8 *)id->data;
        } else {
                ret = pdev->id;
        }
@@ -1129,6 +1181,8 @@ static int omap8250_probe(struct platform_device *pdev)
                           priv->latency);
        INIT_WORK(&priv->qos_work, omap8250_uart_qos_work);
 
+       spin_lock_init(&priv->rx_dma_lock);
+
        device_init_wakeup(&pdev->dev, true);
        pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
@@ -1162,6 +1216,11 @@ static int omap8250_probe(struct platform_device *pdev)
 
                        if (of_machine_is_compatible("ti,am33xx"))
                                priv->habit |= OMAP_DMA_TX_KICK;
+                       /*
+                        * pause is currently not supported atleast on omap-sdma
+                        * and edma on most earlier kernels.
+                        */
+                       priv->rx_dma_broken = true;
                }
        }
 #endif
@@ -1193,31 +1252,6 @@ static int omap8250_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-
-static inline void omap8250_enable_wakeirq(struct omap8250_priv *priv,
-                                          bool enable)
-{
-       if (!priv->wakeirq)
-               return;
-
-       if (enable)
-               enable_irq(priv->wakeirq);
-       else
-               disable_irq_nosync(priv->wakeirq);
-}
-
-static void omap8250_enable_wakeup(struct omap8250_priv *priv,
-                                  bool enable)
-{
-       if (enable == priv->wakeups_enabled)
-               return;
-
-       omap8250_enable_wakeirq(priv, enable);
-       priv->wakeups_enabled = enable;
-}
-#endif
-
 #ifdef CONFIG_PM_SLEEP
 static int omap8250_prepare(struct device *dev)
 {
@@ -1244,11 +1278,6 @@ static int omap8250_suspend(struct device *dev)
 
        serial8250_suspend_port(priv->line);
        flush_work(&priv->qos_work);
-
-       if (device_may_wakeup(dev))
-               omap8250_enable_wakeup(priv, true);
-       else
-               omap8250_enable_wakeup(priv, false);
        return 0;
 }
 
@@ -1256,9 +1285,6 @@ static int omap8250_resume(struct device *dev)
 {
        struct omap8250_priv *priv = dev_get_drvdata(dev);
 
-       if (device_may_wakeup(dev))
-               omap8250_enable_wakeup(priv, false);
-
        serial8250_resume_port(priv->line);
        return 0;
 }
@@ -1272,17 +1298,46 @@ static int omap8250_lost_context(struct uart_8250_port *up)
 {
        u32 val;
 
-       val = serial_in(up, UART_OMAP_MDR1);
+       val = serial_in(up, UART_OMAP_SCR);
        /*
-        * If we lose context, then MDR1 is set to its reset value which is
-        * UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x
-        * or 16x but never to disable again.
+        * If we lose context, then SCR is set to its reset value of zero.
+        * After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1,
+        * among other bits, to never set the register back to zero again.
         */
-       if (val == UART_OMAP_MDR1_DISABLE)
+       if (!val)
                return 1;
        return 0;
 }
 
+/* TODO: in future, this should happen via API in drivers/reset/ */
+static int omap8250_soft_reset(struct device *dev)
+{
+       struct omap8250_priv *priv = dev_get_drvdata(dev);
+       struct uart_8250_port *up = serial8250_get_port(priv->line);
+       int timeout = 100;
+       int sysc;
+       int syss;
+
+       sysc = serial_in(up, UART_OMAP_SYSC);
+
+       /* softreset the UART */
+       sysc |= OMAP_UART_SYSC_SOFTRESET;
+       serial_out(up, UART_OMAP_SYSC, sysc);
+
+       /* By experiments, 1us enough for reset complete on AM335x */
+       do {
+               udelay(1);
+               syss = serial_in(up, UART_OMAP_SYSS);
+       } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
+
+       if (!timeout) {
+               dev_err(dev, "timed out waiting for reset done\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 static int omap8250_runtime_suspend(struct device *dev)
 {
        struct omap8250_priv *priv = dev_get_drvdata(dev);
@@ -1300,8 +1355,18 @@ static int omap8250_runtime_suspend(struct device *dev)
                        return -EBUSY;
        }
 
-       omap8250_enable_wakeup(priv, true);
-       if (up->dma)
+       if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
+               int ret;
+
+               ret = omap8250_soft_reset(dev);
+               if (ret)
+                       return ret;
+
+               /* Restore to UART mode after reset (for wakeup) */
+               omap8250_update_mdr1(up, priv);
+       }
+
+       if (up->dma && up->dma->rxchan)
                omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
 
        priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
@@ -1321,13 +1386,12 @@ static int omap8250_runtime_resume(struct device *dev)
                return 0;
 
        up = serial8250_get_port(priv->line);
-       omap8250_enable_wakeup(priv, false);
        loss_cntx = omap8250_lost_context(up);
 
        if (loss_cntx)
                omap8250_restore_regs(up);
 
-       if (up->dma)
+       if (up->dma && up->dma->rxchan)
                omap_8250_rx_dma(up, 0);
 
        priv->latency = priv->calc_latency;
@@ -1384,14 +1448,6 @@ static const struct dev_pm_ops omap8250_dev_pm_ops = {
        .complete       = omap8250_complete,
 };
 
-static const struct of_device_id omap8250_dt_ids[] = {
-       { .compatible = "ti,omap2-uart" },
-       { .compatible = "ti,omap3-uart" },
-       { .compatible = "ti,omap4-uart" },
-       {},
-};
-MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
-
 static struct platform_driver omap8250_platform_driver = {
        .driver = {
                .name           = "omap8250",