]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/tty/serial/8250/8250_dw.c
Merge remote-tracking branch 'clk/clk-next'
[karo-tx-linux.git] / drivers / tty / serial / 8250 / 8250_dw.c
index df3eddfa53a3b34bcd8d75b87225a31285f6d201..a5d319e4aae65dad90f64bafd33c2ad02bed7034 100644 (file)
@@ -63,6 +63,9 @@ struct dw8250_data {
        struct clk              *pclk;
        struct reset_control    *rst;
        struct uart_8250_dma    dma;
+
+       unsigned int            skip_autocfg:1;
+       unsigned int            uart_16550_compatible:1;
 };
 
 #define BYT_PRV_CLK                    0x800
@@ -240,24 +243,77 @@ out:
        serial8250_do_set_termios(p, termios, old);
 }
 
-static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
+/*
+ * dw8250_fallback_dma_filter will prevent the UART from getting just any free
+ * channel on platforms that have DMA engines, but don't have any channels
+ * assigned to the UART.
+ *
+ * REVISIT: This is a work around for limitation in the DMA Engine API. Once the
+ * core problem is fixed, this function is no longer needed.
+ */
+static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param)
 {
        return false;
 }
 
-static void dw8250_setup_port(struct uart_8250_port *up)
+static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
+{
+       return param == chan->device->dev->parent;
+}
+
+static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
 {
-       struct uart_port        *p = &up->port;
-       u32                     reg = readl(p->membase + DW_UART_UCV);
+       if (p->dev->of_node) {
+               struct device_node *np = p->dev->of_node;
+               int id;
+
+               /* get index of serial line, if found in DT aliases */
+               id = of_alias_get_id(np, "serial");
+               if (id >= 0)
+                       p->line = id;
+#ifdef CONFIG_64BIT
+               if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
+                       p->serial_in = dw8250_serial_inq;
+                       p->serial_out = dw8250_serial_outq;
+                       p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+                       p->type = PORT_OCTEON;
+                       data->usr_reg = 0x27;
+                       data->skip_autocfg = true;
+               }
+#endif
+       } else if (has_acpi_companion(p->dev)) {
+               p->iotype = UPIO_MEM32;
+               p->regshift = 2;
+               p->serial_in = dw8250_serial_in32;
+               p->set_termios = dw8250_set_termios;
+               /* So far none of there implement the Busy Functionality */
+               data->uart_16550_compatible = true;
+       }
+
+       /* Platforms with iDMA */
+       if (platform_get_resource_byname(to_platform_device(p->dev),
+                                        IORESOURCE_MEM, "lpss_priv")) {
+               p->set_termios = dw8250_set_termios;
+               data->dma.rx_param = p->dev->parent;
+               data->dma.tx_param = p->dev->parent;
+               data->dma.fn = dw8250_idma_filter;
+       }
+}
+
+static void dw8250_setup_port(struct uart_port *p)
+{
+       struct uart_8250_port *up = up_to_u8250p(p);
+       u32 reg;
 
        /*
         * If the Component Version Register returns zero, we know that
         * ADDITIONAL_FEATURES are not enabled. No need to go any further.
         */
+       reg = readl(p->membase + DW_UART_UCV);
        if (!reg)
                return;
 
-       dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
+       dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
                (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
 
        reg = readl(p->membase + DW_UART_CPR);
@@ -269,7 +325,6 @@ static void dw8250_setup_port(struct uart_8250_port *up)
                p->type = PORT_16550A;
                p->flags |= UPF_FIXED_TYPE;
                p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
-               up->tx_loadsz = p->fifosize;
                up->capabilities = UART_CAP_FIFO;
        }
 
@@ -277,166 +332,91 @@ static void dw8250_setup_port(struct uart_8250_port *up)
                up->capabilities |= UART_CAP_AFE;
 }
 
-static int dw8250_probe_of(struct uart_port *p,
-                          struct dw8250_data *data)
+static int dw8250_probe(struct platform_device *pdev)
 {
-       struct device_node      *np = p->dev->of_node;
-       struct uart_8250_port *up = up_to_u8250p(p);
-       u32                     val;
-       bool has_ucv = true;
-       int id;
+       struct uart_8250_port uart = {};
+       struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       int irq = platform_get_irq(pdev, 0);
+       struct uart_port *p = &uart.port;
+       struct dw8250_data *data;
+       int err;
+       u32 val;
 
-#ifdef CONFIG_64BIT
-       if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
-               p->serial_in = dw8250_serial_inq;
-               p->serial_out = dw8250_serial_outq;
-               p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
-               p->type = PORT_OCTEON;
-               data->usr_reg = 0x27;
-               has_ucv = false;
-       } else
-#endif
-       if (!of_property_read_u32(np, "reg-io-width", &val)) {
-               switch (val) {
-               case 1:
-                       break;
-               case 4:
-                       p->iotype = UPIO_MEM32;
-                       p->serial_in = dw8250_serial_in32;
-                       p->serial_out = dw8250_serial_out32;
-                       break;
-               default:
-                       dev_err(p->dev, "unsupported reg-io-width (%u)\n", val);
-                       return -EINVAL;
-               }
+       if (!regs) {
+               dev_err(&pdev->dev, "no registers defined\n");
+               return -EINVAL;
        }
-       if (has_ucv)
-               dw8250_setup_port(up);
 
-       /* if we have a valid fifosize, try hooking up DMA here */
-       if (p->fifosize) {
-               up->dma = &data->dma;
-
-               up->dma->rxconf.src_maxburst = p->fifosize / 4;
-               up->dma->txconf.dst_maxburst = p->fifosize / 4;
+       if (irq < 0) {
+               if (irq != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "cannot get irq\n");
+               return irq;
        }
 
-       if (!of_property_read_u32(np, "reg-shift", &val))
+       spin_lock_init(&p->lock);
+       p->mapbase      = regs->start;
+       p->irq          = irq;
+       p->handle_irq   = dw8250_handle_irq;
+       p->pm           = dw8250_do_pm;
+       p->type         = PORT_8250;
+       p->flags        = UPF_SHARE_IRQ | UPF_FIXED_PORT;
+       p->dev          = &pdev->dev;
+       p->iotype       = UPIO_MEM;
+       p->serial_in    = dw8250_serial_in;
+       p->serial_out   = dw8250_serial_out;
+
+       p->membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+       if (!p->membase)
+               return -ENOMEM;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->dma.fn = dw8250_fallback_dma_filter;
+       data->usr_reg = DW_UART_USR;
+       p->private_data = data;
+
+       data->uart_16550_compatible = device_property_read_bool(p->dev,
+                                               "snps,uart-16550-compatible");
+
+       err = device_property_read_u32(p->dev, "reg-shift", &val);
+       if (!err)
                p->regshift = val;
 
-       /* get index of serial line, if found in DT aliases */
-       id = of_alias_get_id(np, "serial");
-       if (id >= 0)
-               p->line = id;
+       err = device_property_read_u32(p->dev, "reg-io-width", &val);
+       if (!err && val == 4) {
+               p->iotype = UPIO_MEM32;
+               p->serial_in = dw8250_serial_in32;
+               p->serial_out = dw8250_serial_out32;
+       }
 
-       if (of_property_read_bool(np, "dcd-override")) {
+       if (device_property_read_bool(p->dev, "dcd-override")) {
                /* Always report DCD as active */
                data->msr_mask_on |= UART_MSR_DCD;
                data->msr_mask_off |= UART_MSR_DDCD;
        }
 
-       if (of_property_read_bool(np, "dsr-override")) {
+       if (device_property_read_bool(p->dev, "dsr-override")) {
                /* Always report DSR as active */
                data->msr_mask_on |= UART_MSR_DSR;
                data->msr_mask_off |= UART_MSR_DDSR;
        }
 
-       if (of_property_read_bool(np, "cts-override")) {
+       if (device_property_read_bool(p->dev, "cts-override")) {
                /* Always report CTS as active */
                data->msr_mask_on |= UART_MSR_CTS;
                data->msr_mask_off |= UART_MSR_DCTS;
        }
 
-       if (of_property_read_bool(np, "ri-override")) {
+       if (device_property_read_bool(p->dev, "ri-override")) {
                /* Always report Ring indicator as inactive */
                data->msr_mask_off |= UART_MSR_RI;
                data->msr_mask_off |= UART_MSR_TERI;
        }
 
-       return 0;
-}
-
-static bool dw8250_idma_filter(struct dma_chan *chan, void *param)
-{
-       struct device *dev = param;
-
-       if (dev != chan->device->dev->parent)
-               return false;
-
-       return true;
-}
-
-static int dw8250_probe_acpi(struct uart_8250_port *up,
-                            struct dw8250_data *data)
-{
-       struct uart_port *p = &up->port;
-
-       dw8250_setup_port(up);
-
-       p->iotype = UPIO_MEM32;
-       p->serial_in = dw8250_serial_in32;
-       p->serial_out = dw8250_serial_out32;
-       p->regshift = 2;
-
-       /* Platforms with iDMA */
-       if (platform_get_resource_byname(to_platform_device(up->port.dev),
-                                        IORESOURCE_MEM, "lpss_priv")) {
-               data->dma.rx_param = up->port.dev->parent;
-               data->dma.tx_param = up->port.dev->parent;
-               data->dma.fn = dw8250_idma_filter;
-       }
-
-       up->dma = &data->dma;
-       up->dma->rxconf.src_maxburst = p->fifosize / 4;
-       up->dma->txconf.dst_maxburst = p->fifosize / 4;
-
-       up->port.set_termios = dw8250_set_termios;
-
-       return 0;
-}
-
-static int dw8250_probe(struct platform_device *pdev)
-{
-       struct uart_8250_port uart = {};
-       struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       int irq = platform_get_irq(pdev, 0);
-       struct dw8250_data *data;
-       int err;
-
-       if (!regs) {
-               dev_err(&pdev->dev, "no registers defined\n");
-               return -EINVAL;
-       }
-
-       if (irq < 0) {
-               if (irq != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "cannot get irq\n");
-               return irq;
-       }
-
-       spin_lock_init(&uart.port.lock);
-       uart.port.mapbase = regs->start;
-       uart.port.irq = irq;
-       uart.port.handle_irq = dw8250_handle_irq;
-       uart.port.pm = dw8250_do_pm;
-       uart.port.type = PORT_8250;
-       uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
-       uart.port.dev = &pdev->dev;
-
-       uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
-                                        resource_size(regs));
-       if (!uart.port.membase)
-               return -ENOMEM;
-
-       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       data->usr_reg = DW_UART_USR;
-
        /* Always ask for fixed clock rate from a property. */
-       device_property_read_u32(&pdev->dev, "clock-frequency",
-                                &uart.port.uartclk);
+       device_property_read_u32(p->dev, "clock-frequency", &p->uartclk);
 
        /* If there is separate baudclk, get the rate from it. */
        data->clk = devm_clk_get(&pdev->dev, "baudclk");
@@ -450,11 +430,11 @@ static int dw8250_probe(struct platform_device *pdev)
                        dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
                                 err);
                else
-                       uart.port.uartclk = clk_get_rate(data->clk);
+                       p->uartclk = clk_get_rate(data->clk);
        }
 
        /* If no clock rate is defined, fail. */
-       if (!uart.port.uartclk) {
+       if (!p->uartclk) {
                dev_err(&pdev->dev, "clock rate not defined\n");
                return -EINVAL;
        }
@@ -480,26 +460,22 @@ static int dw8250_probe(struct platform_device *pdev)
        if (!IS_ERR(data->rst))
                reset_control_deassert(data->rst);
 
-       data->dma.rx_param = data;
-       data->dma.tx_param = data;
-       data->dma.fn = dw8250_dma_filter;
+       dw8250_quirks(p, data);
 
-       uart.port.iotype = UPIO_MEM;
-       uart.port.serial_in = dw8250_serial_in;
-       uart.port.serial_out = dw8250_serial_out;
-       uart.port.private_data = data;
+       /* If the Busy Functionality is not implemented, don't handle it */
+       if (data->uart_16550_compatible) {
+               p->serial_out = NULL;
+               p->handle_irq = NULL;
+       }
 
-       if (pdev->dev.of_node) {
-               err = dw8250_probe_of(&uart.port, data);
-               if (err)
-                       goto err_reset;
-       } else if (ACPI_HANDLE(&pdev->dev)) {
-               err = dw8250_probe_acpi(&uart, data);
-               if (err)
-                       goto err_reset;
-       } else {
-               err = -ENODEV;
-               goto err_reset;
+       if (!data->skip_autocfg)
+               dw8250_setup_port(p);
+
+       /* If we have a valid fifosize, try hooking up DMA */
+       if (p->fifosize) {
+               data->dma.rxconf.src_maxburst = p->fifosize / 4;
+               data->dma.txconf.dst_maxburst = p->fifosize / 4;
+               uart.dma = &data->dma;
        }
 
        data->line = serial8250_register_8250_port(&uart);