Merge 4.0-rc5 into tty-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Mar 2015 20:45:24 +0000 (21:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Mar 2015 20:45:24 +0000 (21:45 +0100)
We want the tty/serial fixes in here as well.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
42 files changed:
arch/x86/Kconfig.debug
arch/x86/include/asm/intel-mid.h
arch/x86/include/asm/serial.h
arch/x86/kernel/early_printk.c
arch/x86/platform/intel-mid/Makefile
arch/x86/platform/intel-mid/early_printk_intel_mid.c [deleted file]
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/hsu/Kconfig [new file with mode: 0644]
drivers/dma/hsu/Makefile [new file with mode: 0644]
drivers/dma/hsu/hsu.c [new file with mode: 0644]
drivers/dma/hsu/hsu.h [new file with mode: 0644]
drivers/dma/hsu/pci.c [new file with mode: 0644]
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/ar933x_uart.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/clps711x.c
drivers/tty/serial/earlycon.c
drivers/tty/serial/imx.c
drivers/tty/serial/max3100.c
drivers/tty/serial/mfd.c [deleted file]
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/serial_mctrl_gpio.c
drivers/tty/serial/sprd_serial.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
include/linux/dma/hsu.h [new file with mode: 0644]
include/linux/platform_data/dma-hsu.h [new file with mode: 0644]
include/linux/platform_data/serial-imx.h
include/linux/serial_core.h
include/linux/serial_mfd.h [deleted file]
include/uapi/linux/serial_reg.h
kernel/printk/printk.c

index 20028da8ae188ce16aaabdc1ef6da2fd1eb5b8f0..72484a645f056d1d7a8aa4182b07fc908c3b4162 100644 (file)
@@ -43,10 +43,6 @@ config EARLY_PRINTK
          with klogd/syslogd or the X server. You should normally N here,
          unless you want to debug such a crash.
 
-config EARLY_PRINTK_INTEL_MID
-       bool "Early printk for Intel MID platform support"
-       depends on EARLY_PRINTK && X86_INTEL_MID
-
 config EARLY_PRINTK_DBGP
        bool "Early printk via EHCI debug port"
        depends on EARLY_PRINTK && PCI
index 705d35708a508cd520d579d888719bc296e563b9..7c5af123bdbd21680744000f1a6195644a5140b3 100644 (file)
@@ -136,9 +136,6 @@ extern enum intel_mid_timer_options intel_mid_timer_options;
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX   8
 
-extern struct console early_hsu_console;
-extern void hsu_early_console_init(const char *);
-
 extern void intel_scu_devices_create(void);
 extern void intel_scu_devices_destroy(void);
 
index 460b84f64556dded375c779a59d2c6a521c575c7..8378b8c9109c851c3c7d1b6669e6bf0e9be689bf 100644 (file)
 
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 #ifdef CONFIG_SERIAL_DETECT_IRQ
-# define STD_COMX_FLAGS        (ASYNC_BOOT_AUTOCONF |  ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-# define STD_COM4_FLAGS        (ASYNC_BOOT_AUTOCONF |  0               | ASYNC_AUTO_IRQ)
+# define STD_COMX_FLAGS        (UPF_BOOT_AUTOCONF |    UPF_SKIP_TEST   | UPF_AUTO_IRQ)
+# define STD_COM4_FLAGS        (UPF_BOOT_AUTOCONF |    0               | UPF_AUTO_IRQ)
 #else
-# define STD_COMX_FLAGS        (ASYNC_BOOT_AUTOCONF |  ASYNC_SKIP_TEST | 0             )
-# define STD_COM4_FLAGS        (ASYNC_BOOT_AUTOCONF |  0               | 0             )
+# define STD_COMX_FLAGS        (UPF_BOOT_AUTOCONF |    UPF_SKIP_TEST   | 0             )
+# define STD_COM4_FLAGS        (UPF_BOOT_AUTOCONF |    0               | 0             )
 #endif
 
 #define SERIAL_PORT_DFNS                                                               \
index a62536a1be889019081696b2e7df908b0a4ef9fb..f85e3fb50f287e0d4e5f8e6142131d7e777b71c6 100644 (file)
@@ -375,12 +375,6 @@ static int __init setup_early_printk(char *buf)
                if (!strncmp(buf, "xen", 3))
                        early_console_register(&xenboot_console, keep);
 #endif
-#ifdef CONFIG_EARLY_PRINTK_INTEL_MID
-               if (!strncmp(buf, "hsu", 3)) {
-                       hsu_early_console_init(buf + 3);
-                       early_console_register(&early_hsu_console, keep);
-               }
-#endif
 #ifdef CONFIG_EARLY_PRINTK_EFI
                if (!strncmp(buf, "efi", 3))
                        early_console_register(&early_efi_console, keep);
index 0a8ee703b9fae9cbfd2205376650563bf7b9eecb..0ce1b1913673fa9ea259013471955c1f994d829c 100644 (file)
@@ -1,5 +1,4 @@
 obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o
-obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o
 
 # SFI specific code
 ifdef CONFIG_X86_INTEL_MID
diff --git a/arch/x86/platform/intel-mid/early_printk_intel_mid.c b/arch/x86/platform/intel-mid/early_printk_intel_mid.c
deleted file mode 100644 (file)
index 4e72082..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * early_printk_intel_mid.c - early consoles for Intel MID platforms
- *
- * Copyright (c) 2008-2010, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- */
-
-/*
- * This file implements early console named hsu.
- * hsu is based on a High Speed UART device which only exists in the Medfield
- * platform
- */
-
-#include <linux/serial_reg.h>
-#include <linux/serial_mfd.h>
-#include <linux/console.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/intel-mid.h>
-
-/*
- * Following is the early console based on Medfield HSU (High
- * Speed UART) device.
- */
-#define HSU_PORT_BASE          0xffa28080
-
-static void __iomem *phsu;
-
-void hsu_early_console_init(const char *s)
-{
-       unsigned long paddr, port = 0;
-       u8 lcr;
-
-       /*
-        * Select the early HSU console port if specified by user in the
-        * kernel command line.
-        */
-       if (*s && !kstrtoul(s, 10, &port))
-               port = clamp_val(port, 0, 2);
-
-       paddr = HSU_PORT_BASE + port * 0x80;
-       phsu = (void __iomem *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, paddr);
-
-       /* Disable FIFO */
-       writeb(0x0, phsu + UART_FCR);
-
-       /* Set to default 115200 bps, 8n1 */
-       lcr = readb(phsu + UART_LCR);
-       writeb((0x80 | lcr), phsu + UART_LCR);
-       writeb(0x18, phsu + UART_DLL);
-       writeb(lcr,  phsu + UART_LCR);
-       writel(0x3600, phsu + UART_MUL*4);
-
-       writeb(0x8, phsu + UART_MCR);
-       writeb(0x7, phsu + UART_FCR);
-       writeb(0x3, phsu + UART_LCR);
-
-       /* Clear IRQ status */
-       readb(phsu + UART_LSR);
-       readb(phsu + UART_RX);
-       readb(phsu + UART_IIR);
-       readb(phsu + UART_MSR);
-
-       /* Enable FIFO */
-       writeb(0x7, phsu + UART_FCR);
-}
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static void early_hsu_putc(char ch)
-{
-       unsigned int timeout = 10000; /* 10ms */
-       u8 status;
-
-       while (--timeout) {
-               status = readb(phsu + UART_LSR);
-               if (status & BOTH_EMPTY)
-                       break;
-               udelay(1);
-       }
-
-       /* Only write the char when there was no timeout */
-       if (timeout)
-               writeb(ch, phsu + UART_TX);
-}
-
-static void early_hsu_write(struct console *con, const char *str, unsigned n)
-{
-       int i;
-
-       for (i = 0; i < n && *str; i++) {
-               if (*str == '\n')
-                       early_hsu_putc('\r');
-               early_hsu_putc(*str);
-               str++;
-       }
-}
-
-struct console early_hsu_console = {
-       .name =         "earlyhsu",
-       .write =        early_hsu_write,
-       .flags =        CON_PRINTBUFFER,
-       .index =        -1,
-};
index a874b6ec6650f33275c8a59ddb1d00a78c4271e9..074ffad334a70bcf444974b4f7c2225666f31d2b 100644 (file)
@@ -125,6 +125,8 @@ config FSL_DMA
          EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
          some Txxx and Bxxx parts.
 
+source "drivers/dma/hsu/Kconfig"
+
 config MPC512X_DMA
        tristate "Freescale MPC512x built-in DMA engine support"
        depends on PPC_MPC512x || PPC_MPC831x
index f915f61ec5747193757e6f2b6da61ebd0eea4d83..bf4485800c60d9b9ef138efbc2b410d82155606d 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_HSU_DMA) += hsu/
 obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
 obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
 obj-$(CONFIG_MV_XOR) += mv_xor.o
diff --git a/drivers/dma/hsu/Kconfig b/drivers/dma/hsu/Kconfig
new file mode 100644 (file)
index 0000000..7e98eff
--- /dev/null
@@ -0,0 +1,14 @@
+# DMA engine configuration for hsu
+config HSU_DMA
+       tristate "High Speed UART DMA support"
+       select DMA_ENGINE
+       select DMA_VIRTUAL_CHANNELS
+
+config HSU_DMA_PCI
+       tristate "High Speed UART DMA PCI driver"
+       depends on PCI
+       select HSU_DMA
+       help
+         Support the High Speed UART DMA on the platfroms that
+         enumerate it as a PCI device. For example, Intel Medfield
+         has integrated this HSU DMA controller.
diff --git a/drivers/dma/hsu/Makefile b/drivers/dma/hsu/Makefile
new file mode 100644 (file)
index 0000000..b8f9af0
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_HSU_DMA)          += hsu_dma.o
+hsu_dma-objs           := hsu.o
+
+obj-$(CONFIG_HSU_DMA_PCI)      += hsu_dma_pci.o
+hsu_dma_pci-objs       := pci.o
diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c
new file mode 100644 (file)
index 0000000..683ba9b
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ * Core driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *
+ * Partially based on the bits found in drivers/tty/serial/mfd.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * DMA channel allocation:
+ * 1. Even number chans are used for DMA Read (UART TX), odd chans for DMA
+ *    Write (UART RX).
+ * 2. 0/1 channel are assigned to port 0, 2/3 chan to port 1, 4/5 chan to
+ *    port 3, and so on.
+ */
+
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "hsu.h"
+
+#define HSU_DMA_BUSWIDTHS                              \
+       BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED)       |       \
+       BIT(DMA_SLAVE_BUSWIDTH_1_BYTE)          |       \
+       BIT(DMA_SLAVE_BUSWIDTH_2_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_3_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_16_BYTES)
+
+static inline void hsu_chan_disable(struct hsu_dma_chan *hsuc)
+{
+       hsu_chan_writel(hsuc, HSU_CH_CR, 0);
+}
+
+static inline void hsu_chan_enable(struct hsu_dma_chan *hsuc)
+{
+       u32 cr = HSU_CH_CR_CHA;
+
+       if (hsuc->direction == DMA_MEM_TO_DEV)
+               cr &= ~HSU_CH_CR_CHD;
+       else if (hsuc->direction == DMA_DEV_TO_MEM)
+               cr |= HSU_CH_CR_CHD;
+
+       hsu_chan_writel(hsuc, HSU_CH_CR, cr);
+}
+
+static void hsu_dma_chan_start(struct hsu_dma_chan *hsuc)
+{
+       struct dma_slave_config *config = &hsuc->config;
+       struct hsu_dma_desc *desc = hsuc->desc;
+       u32 bsr, mtsr;
+       u32 dcr = HSU_CH_DCR_CHSOE | HSU_CH_DCR_CHEI;
+       unsigned int i, count;
+
+       if (hsuc->direction == DMA_MEM_TO_DEV) {
+               bsr = config->dst_maxburst;
+               mtsr = config->dst_addr_width;
+       } else if (hsuc->direction == DMA_DEV_TO_MEM) {
+               bsr = config->src_maxburst;
+               mtsr = config->src_addr_width;
+       } else {
+               /* Not supported direction */
+               return;
+       }
+
+       hsu_chan_disable(hsuc);
+
+       hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
+       hsu_chan_writel(hsuc, HSU_CH_BSR, bsr);
+       hsu_chan_writel(hsuc, HSU_CH_MTSR, mtsr);
+
+       /* Set descriptors */
+       count = (desc->nents - desc->active) % HSU_DMA_CHAN_NR_DESC;
+       for (i = 0; i < count; i++) {
+               hsu_chan_writel(hsuc, HSU_CH_DxSAR(i), desc->sg[i].addr);
+               hsu_chan_writel(hsuc, HSU_CH_DxTSR(i), desc->sg[i].len);
+
+               /* Prepare value for DCR */
+               dcr |= HSU_CH_DCR_DESCA(i);
+               dcr |= HSU_CH_DCR_CHTOI(i);     /* timeout bit, see HSU Errata 1 */
+
+               desc->active++;
+       }
+       /* Only for the last descriptor in the chain */
+       dcr |= HSU_CH_DCR_CHSOD(count - 1);
+       dcr |= HSU_CH_DCR_CHDI(count - 1);
+
+       hsu_chan_writel(hsuc, HSU_CH_DCR, dcr);
+
+       hsu_chan_enable(hsuc);
+}
+
+static void hsu_dma_stop_channel(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_chan_disable(hsuc);
+       hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static void hsu_dma_start_channel(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_dma_chan_start(hsuc);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static void hsu_dma_start_transfer(struct hsu_dma_chan *hsuc)
+{
+       struct virt_dma_desc *vdesc;
+
+       /* Get the next descriptor */
+       vdesc = vchan_next_desc(&hsuc->vchan);
+       if (!vdesc) {
+               hsuc->desc = NULL;
+               return;
+       }
+
+       list_del(&vdesc->node);
+       hsuc->desc = to_hsu_dma_desc(vdesc);
+
+       /* Start the channel with a new descriptor */
+       hsu_dma_start_channel(hsuc);
+}
+
+static u32 hsu_dma_chan_get_sr(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+       u32 sr;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       sr = hsu_chan_readl(hsuc, HSU_CH_SR);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+
+       return sr;
+}
+
+irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
+{
+       struct hsu_dma_chan *hsuc;
+       struct hsu_dma_desc *desc;
+       unsigned long flags;
+       u32 sr;
+
+       /* Sanity check */
+       if (nr >= chip->pdata->nr_channels)
+               return IRQ_NONE;
+
+       hsuc = &chip->hsu->chan[nr];
+
+       /*
+        * No matter what situation, need read clear the IRQ status
+        * There is a bug, see Errata 5, HSD 2900918
+        */
+       sr = hsu_dma_chan_get_sr(hsuc);
+       if (!sr)
+               return IRQ_NONE;
+
+       /* Timeout IRQ, need wait some time, see Errata 2 */
+       if (hsuc->direction == DMA_DEV_TO_MEM && (sr & HSU_CH_SR_DESCTO_ANY))
+               udelay(2);
+
+       sr &= ~HSU_CH_SR_DESCTO_ANY;
+       if (!sr)
+               return IRQ_HANDLED;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       desc = hsuc->desc;
+       if (desc) {
+               if (sr & HSU_CH_SR_CHE) {
+                       desc->status = DMA_ERROR;
+               } else if (desc->active < desc->nents) {
+                       hsu_dma_start_channel(hsuc);
+               } else {
+                       vchan_cookie_complete(&desc->vdesc);
+                       desc->status = DMA_COMPLETE;
+                       hsu_dma_start_transfer(hsuc);
+               }
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(hsu_dma_irq);
+
+static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
+{
+       struct hsu_dma_desc *desc;
+
+       desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
+       if (!desc)
+               return NULL;
+
+       desc->sg = kcalloc(nents, sizeof(*desc->sg), GFP_ATOMIC);
+       if (!desc->sg) {
+               kfree(desc);
+               return NULL;
+       }
+
+       return desc;
+}
+
+static void hsu_dma_desc_free(struct virt_dma_desc *vdesc)
+{
+       struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc);
+
+       kfree(desc->sg);
+       kfree(desc);
+}
+
+static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg(
+               struct dma_chan *chan, struct scatterlist *sgl,
+               unsigned int sg_len, enum dma_transfer_direction direction,
+               unsigned long flags, void *context)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       struct hsu_dma_desc *desc;
+       struct scatterlist *sg;
+       unsigned int i;
+
+       desc = hsu_dma_alloc_desc(sg_len);
+       if (!desc)
+               return NULL;
+
+       for_each_sg(sgl, sg, sg_len, i) {
+               desc->sg[i].addr = sg_dma_address(sg);
+               desc->sg[i].len = sg_dma_len(sg);
+       }
+
+       desc->nents = sg_len;
+       desc->direction = direction;
+       desc->active = 0;
+       desc->status = DMA_IN_PROGRESS;
+
+       return vchan_tx_prep(&hsuc->vchan, &desc->vdesc, flags);
+}
+
+static void hsu_dma_issue_pending(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       if (vchan_issue_pending(&hsuc->vchan) && !hsuc->desc)
+               hsu_dma_start_transfer(hsuc);
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+}
+
+static size_t hsu_dma_desc_size(struct hsu_dma_desc *desc)
+{
+       size_t bytes = 0;
+       unsigned int i;
+
+       for (i = desc->active; i < desc->nents; i++)
+               bytes += desc->sg[i].len;
+
+       return bytes;
+}
+
+static size_t hsu_dma_active_desc_size(struct hsu_dma_chan *hsuc)
+{
+       struct hsu_dma_desc *desc = hsuc->desc;
+       size_t bytes = hsu_dma_desc_size(desc);
+       int i;
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       i = desc->active % HSU_DMA_CHAN_NR_DESC;
+       do {
+               bytes += hsu_chan_readl(hsuc, HSU_CH_DxTSR(i));
+       } while (--i >= 0);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+
+       return bytes;
+}
+
+static enum dma_status hsu_dma_tx_status(struct dma_chan *chan,
+       dma_cookie_t cookie, struct dma_tx_state *state)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       struct virt_dma_desc *vdesc;
+       enum dma_status status;
+       size_t bytes;
+       unsigned long flags;
+
+       status = dma_cookie_status(chan, cookie, state);
+       if (status == DMA_COMPLETE)
+               return status;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       vdesc = vchan_find_desc(&hsuc->vchan, cookie);
+       if (hsuc->desc && cookie == hsuc->desc->vdesc.tx.cookie) {
+               bytes = hsu_dma_active_desc_size(hsuc);
+               dma_set_residue(state, bytes);
+               status = hsuc->desc->status;
+       } else if (vdesc) {
+               bytes = hsu_dma_desc_size(to_hsu_dma_desc(vdesc));
+               dma_set_residue(state, bytes);
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return status;
+}
+
+static int hsu_dma_slave_config(struct dma_chan *chan,
+                               struct dma_slave_config *config)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+
+       /* Check if chan will be configured for slave transfers */
+       if (!is_slave_direction(config->direction))
+               return -EINVAL;
+
+       memcpy(&hsuc->config, config, sizeof(hsuc->config));
+
+       return 0;
+}
+
+static void hsu_dma_chan_deactivate(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_chan_disable(hsuc);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static void hsu_dma_chan_activate(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_chan_enable(hsuc);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static int hsu_dma_pause(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       if (hsuc->desc && hsuc->desc->status == DMA_IN_PROGRESS) {
+               hsu_dma_chan_deactivate(hsuc);
+               hsuc->desc->status = DMA_PAUSED;
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return 0;
+}
+
+static int hsu_dma_resume(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       if (hsuc->desc && hsuc->desc->status == DMA_PAUSED) {
+               hsuc->desc->status = DMA_IN_PROGRESS;
+               hsu_dma_chan_activate(hsuc);
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return 0;
+}
+
+static int hsu_dma_terminate_all(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+       LIST_HEAD(head);
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+
+       hsu_dma_stop_channel(hsuc);
+       hsuc->desc = NULL;
+
+       vchan_get_all_descriptors(&hsuc->vchan, &head);
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+       vchan_dma_desc_free_list(&hsuc->vchan, &head);
+
+       return 0;
+}
+
+static int hsu_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+       return 0;
+}
+
+static void hsu_dma_free_chan_resources(struct dma_chan *chan)
+{
+       vchan_free_chan_resources(to_virt_chan(chan));
+}
+
+int hsu_dma_probe(struct hsu_dma_chip *chip)
+{
+       struct hsu_dma *hsu;
+       struct hsu_dma_platform_data *pdata = chip->pdata;
+       void __iomem *addr = chip->regs + chip->offset;
+       unsigned short i;
+       int ret;
+
+       hsu = devm_kzalloc(chip->dev, sizeof(*hsu), GFP_KERNEL);
+       if (!hsu)
+               return -ENOMEM;
+
+       chip->hsu = hsu;
+
+       if (!pdata) {
+               pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
+               if (!pdata)
+                       return -ENOMEM;
+
+               chip->pdata = pdata;
+
+               /* Guess nr_channels from the IO space length */
+               pdata->nr_channels = (chip->length - chip->offset) /
+                                    HSU_DMA_CHAN_LENGTH;
+       }
+
+       hsu->chan = devm_kcalloc(chip->dev, pdata->nr_channels,
+                                sizeof(*hsu->chan), GFP_KERNEL);
+       if (!hsu->chan)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&hsu->dma.channels);
+       for (i = 0; i < pdata->nr_channels; i++) {
+               struct hsu_dma_chan *hsuc = &hsu->chan[i];
+
+               hsuc->vchan.desc_free = hsu_dma_desc_free;
+               vchan_init(&hsuc->vchan, &hsu->dma);
+
+               hsuc->direction = (i & 0x1) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
+               hsuc->reg = addr + i * HSU_DMA_CHAN_LENGTH;
+
+               spin_lock_init(&hsuc->lock);
+       }
+
+       dma_cap_set(DMA_SLAVE, hsu->dma.cap_mask);
+       dma_cap_set(DMA_PRIVATE, hsu->dma.cap_mask);
+
+       hsu->dma.device_alloc_chan_resources = hsu_dma_alloc_chan_resources;
+       hsu->dma.device_free_chan_resources = hsu_dma_free_chan_resources;
+
+       hsu->dma.device_prep_slave_sg = hsu_dma_prep_slave_sg;
+
+       hsu->dma.device_issue_pending = hsu_dma_issue_pending;
+       hsu->dma.device_tx_status = hsu_dma_tx_status;
+
+       hsu->dma.device_config = hsu_dma_slave_config;
+       hsu->dma.device_pause = hsu_dma_pause;
+       hsu->dma.device_resume = hsu_dma_resume;
+       hsu->dma.device_terminate_all = hsu_dma_terminate_all;
+
+       hsu->dma.src_addr_widths = HSU_DMA_BUSWIDTHS;
+       hsu->dma.dst_addr_widths = HSU_DMA_BUSWIDTHS;
+       hsu->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+       hsu->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+       hsu->dma.dev = chip->dev;
+
+       ret = dma_async_device_register(&hsu->dma);
+       if (ret)
+               return ret;
+
+       dev_info(chip->dev, "Found HSU DMA, %d channels\n", pdata->nr_channels);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hsu_dma_probe);
+
+int hsu_dma_remove(struct hsu_dma_chip *chip)
+{
+       struct hsu_dma *hsu = chip->hsu;
+       unsigned short i;
+
+       dma_async_device_unregister(&hsu->dma);
+
+       for (i = 0; i < chip->pdata->nr_channels; i++) {
+               struct hsu_dma_chan *hsuc = &hsu->chan[i];
+
+               tasklet_kill(&hsuc->vchan.task);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hsu_dma_remove);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("High Speed UART DMA core driver");
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h
new file mode 100644 (file)
index 0000000..0275233
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * Partially based on the bits found in drivers/tty/serial/mfd.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DMA_HSU_H__
+#define __DMA_HSU_H__
+
+#include <linux/spinlock.h>
+#include <linux/dma/hsu.h>
+
+#include "../virt-dma.h"
+
+#define HSU_CH_SR              0x00                    /* channel status */
+#define HSU_CH_CR              0x04                    /* channel control */
+#define HSU_CH_DCR             0x08                    /* descriptor control */
+#define HSU_CH_BSR             0x10                    /* FIFO buffer size */
+#define HSU_CH_MTSR            0x14                    /* minimum transfer size */
+#define HSU_CH_DxSAR(x)                (0x20 + 8 * (x))        /* desc start addr */
+#define HSU_CH_DxTSR(x)                (0x24 + 8 * (x))        /* desc transfer size */
+#define HSU_CH_D0SAR           0x20                    /* desc 0 start addr */
+#define HSU_CH_D0TSR           0x24                    /* desc 0 transfer size */
+#define HSU_CH_D1SAR           0x28
+#define HSU_CH_D1TSR           0x2c
+#define HSU_CH_D2SAR           0x30
+#define HSU_CH_D2TSR           0x34
+#define HSU_CH_D3SAR           0x38
+#define HSU_CH_D3TSR           0x3c
+
+#define HSU_DMA_CHAN_NR_DESC   4
+#define HSU_DMA_CHAN_LENGTH    0x40
+
+/* Bits in HSU_CH_SR */
+#define HSU_CH_SR_DESCTO(x)    BIT(8 + (x))
+#define HSU_CH_SR_DESCTO_ANY   (BIT(11) | BIT(10) | BIT(9) | BIT(8))
+#define HSU_CH_SR_CHE          BIT(15)
+
+/* Bits in HSU_CH_CR */
+#define HSU_CH_CR_CHA          BIT(0)
+#define HSU_CH_CR_CHD          BIT(1)
+
+/* Bits in HSU_CH_DCR */
+#define HSU_CH_DCR_DESCA(x)    BIT(0 + (x))
+#define HSU_CH_DCR_CHSOD(x)    BIT(8 + (x))
+#define HSU_CH_DCR_CHSOTO      BIT(14)
+#define HSU_CH_DCR_CHSOE       BIT(15)
+#define HSU_CH_DCR_CHDI(x)     BIT(16 + (x))
+#define HSU_CH_DCR_CHEI                BIT(23)
+#define HSU_CH_DCR_CHTOI(x)    BIT(24 + (x))
+
+struct hsu_dma_sg {
+       dma_addr_t addr;
+       unsigned int len;
+};
+
+struct hsu_dma_desc {
+       struct virt_dma_desc vdesc;
+       enum dma_transfer_direction direction;
+       struct hsu_dma_sg *sg;
+       unsigned int nents;
+       unsigned int active;
+       enum dma_status status;
+};
+
+static inline struct hsu_dma_desc *to_hsu_dma_desc(struct virt_dma_desc *vdesc)
+{
+       return container_of(vdesc, struct hsu_dma_desc, vdesc);
+}
+
+struct hsu_dma_chan {
+       struct virt_dma_chan vchan;
+
+       void __iomem *reg;
+       spinlock_t lock;
+
+       /* hardware configuration */
+       enum dma_transfer_direction direction;
+       struct dma_slave_config config;
+
+       struct hsu_dma_desc *desc;
+};
+
+static inline struct hsu_dma_chan *to_hsu_dma_chan(struct dma_chan *chan)
+{
+       return container_of(chan, struct hsu_dma_chan, vchan.chan);
+}
+
+static inline u32 hsu_chan_readl(struct hsu_dma_chan *hsuc, int offset)
+{
+       return readl(hsuc->reg + offset);
+}
+
+static inline void hsu_chan_writel(struct hsu_dma_chan *hsuc, int offset,
+                                  u32 value)
+{
+       writel(value, hsuc->reg + offset);
+}
+
+struct hsu_dma {
+       struct dma_device               dma;
+
+       /* channels */
+       struct hsu_dma_chan             *chan;
+};
+
+static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)
+{
+       return container_of(ddev, struct hsu_dma, dma);
+}
+
+#endif /* __DMA_HSU_H__ */
diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c
new file mode 100644 (file)
index 0000000..563b468
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * PCI driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *
+ * Partially based on the bits found in drivers/tty/serial/mfd.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "hsu.h"
+
+#define HSU_PCI_DMASR          0x00
+#define HSU_PCI_DMAISR         0x04
+
+#define HSU_PCI_CHAN_OFFSET    0x100
+
+static irqreturn_t hsu_pci_irq(int irq, void *dev)
+{
+       struct hsu_dma_chip *chip = dev;
+       u32 dmaisr;
+       unsigned short i;
+       irqreturn_t ret = IRQ_NONE;
+
+       dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
+       for (i = 0; i < chip->pdata->nr_channels; i++) {
+               if (dmaisr & 0x1)
+                       ret |= hsu_dma_irq(chip, i);
+               dmaisr >>= 1;
+       }
+
+       return ret;
+}
+
+static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct hsu_dma_chip *chip;
+       int ret;
+
+       ret = pcim_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
+       if (ret) {
+               dev_err(&pdev->dev, "I/O memory remapping failed\n");
+               return ret;
+       }
+
+       pci_set_master(pdev);
+       pci_try_set_mwi(pdev);
+
+       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
+       ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
+       chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->dev = &pdev->dev;
+       chip->regs = pcim_iomap_table(pdev)[0];
+       chip->length = pci_resource_len(pdev, 0);
+       chip->offset = HSU_PCI_CHAN_OFFSET;
+       chip->irq = pdev->irq;
+
+       pci_enable_msi(pdev);
+
+       ret = hsu_dma_probe(chip);
+       if (ret)
+               return ret;
+
+       ret = request_irq(chip->irq, hsu_pci_irq, 0, "hsu_dma_pci", chip);
+       if (ret)
+               goto err_register_irq;
+
+       pci_set_drvdata(pdev, chip);
+
+       return 0;
+
+err_register_irq:
+       hsu_dma_remove(chip);
+       return ret;
+}
+
+static void hsu_pci_remove(struct pci_dev *pdev)
+{
+       struct hsu_dma_chip *chip = pci_get_drvdata(pdev);
+
+       free_irq(chip->irq, chip);
+       hsu_dma_remove(chip);
+}
+
+static const struct pci_device_id hsu_pci_id_table[] = {
+       { PCI_VDEVICE(INTEL, 0x081e), 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, hsu_pci_id_table);
+
+static struct pci_driver hsu_pci_driver = {
+       .name           = "hsu_dma_pci",
+       .id_table       = hsu_pci_id_table,
+       .probe          = hsu_pci_probe,
+       .remove         = hsu_pci_remove,
+};
+
+module_pci_driver(hsu_pci_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("High Speed UART DMA PCI driver");
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
index b00836851061e099d517a3600b838b572ef8743d..656ecc60b5b262df9118512752e654bf5f048f0e 100644 (file)
@@ -53,7 +53,7 @@ struct old_serial_port {
        unsigned int baud_base;
        unsigned int port;
        unsigned int irq;
-       unsigned int flags;
+       upf_t        flags;
        unsigned char hub6;
        unsigned char io_type;
        unsigned char __iomem *iomem_base;
index deae122c9c4bac6a2bb28d6bbc191bfc18d16747..7b502c0a848feca8f3c63597c07745c05675a284 100644 (file)
@@ -895,7 +895,7 @@ static int broken_efr(struct uart_8250_port *up)
        /*
         * Exar ST16C2550 "A2" devices incorrectly detect as
         * having an EFR, and report an ID of 0x0201.  See
-        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html 
+        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
         */
        if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
                return 1;
@@ -1260,7 +1260,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        serial_out(up, UART_LCR, save_lcr);
 
        port->fifosize = uart_config[up->port.type].fifo_size;
-       old_capabilities = up->capabilities; 
+       old_capabilities = up->capabilities;
        up->capabilities = uart_config[port->type].flags;
        up->tx_loadsz = uart_config[port->type].tx_loadsz;
 
index 6ae5b8560e4d764cafb8143a8a4654a81bf21f83..48a8bef058e09e11731fd87f444a2b6a38c545aa 100644 (file)
@@ -425,18 +425,24 @@ static int dw8250_probe(struct platform_device *pdev)
 {
        struct uart_8250_port uart = {};
        struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       int irq = platform_get_irq(pdev, 0);
        struct dw8250_data *data;
        int err;
 
-       if (!regs || !irq) {
-               dev_err(&pdev->dev, "no registers/irq defined\n");
+       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->start;
+       uart.port.irq = irq;
        uart.port.handle_irq = dw8250_handle_irq;
        uart.port.pm = dw8250_do_pm;
        uart.port.type = PORT_8250;
@@ -649,3 +655,4 @@ module_platform_driver(dw8250_platform_driver);
 MODULE_AUTHOR("Jamie Iles");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
+MODULE_ALIAS("platform:dw-apb-uart");
index 892eb32cdef4bd98586d02e2e432c38aea512797..11784e9ad9c2d3adf5d69442f28123c7185f42cc 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/dmaengine.h>
 #include <linux/platform_data/dma-dw.h>
+#include <linux/platform_data/dma-hsu.h>
 
 #include "8250.h"
 
@@ -1525,6 +1526,148 @@ byt_serial_setup(struct serial_private *priv,
        return ret;
 }
 
+#define INTEL_MID_UART_PS              0x30
+#define INTEL_MID_UART_MUL             0x34
+
+static void intel_mid_set_termios_50M(struct uart_port *p,
+                                     struct ktermios *termios,
+                                     struct ktermios *old)
+{
+       unsigned int baud = tty_termios_baud_rate(termios);
+       u32 ps, mul;
+
+       /*
+        * The uart clk is 50Mhz, and the baud rate come from:
+        *      baud = 50M * MUL / (DIV * PS * DLAB)
+        *
+        * For those basic low baud rate we can get the direct
+        * scalar from 2746800, like 115200 = 2746800/24. For those
+        * higher baud rate, we handle them case by case, mainly by
+        * adjusting the MUL/PS registers, and DIV register is kept
+        * as default value 0x3d09 to make things simple.
+        */
+
+       ps = 0x10;
+
+       switch (baud) {
+       case 500000:
+       case 1000000:
+       case 1500000:
+       case 3000000:
+               mul = 0x3a98;
+               p->uartclk = 48000000;
+               break;
+       case 2000000:
+       case 4000000:
+               mul = 0x2710;
+               ps = 0x08;
+               p->uartclk = 64000000;
+               break;
+       case 2500000:
+               mul = 0x30d4;
+               p->uartclk = 40000000;
+               break;
+       case 3500000:
+               mul = 0x3345;
+               ps = 0x0c;
+               p->uartclk = 56000000;
+               break;
+       default:
+               mul = 0x2400;
+               p->uartclk = 29491200;
+       }
+
+       writel(ps, p->membase + INTEL_MID_UART_PS);             /* set PS */
+       writel(mul, p->membase + INTEL_MID_UART_MUL);           /* set MUL */
+
+       serial8250_do_set_termios(p, termios, old);
+}
+
+static bool intel_mid_dma_filter(struct dma_chan *chan, void *param)
+{
+       struct hsu_dma_slave *s = param;
+
+       if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
+               return false;
+
+       chan->private = s;
+       return true;
+}
+
+static int intel_mid_serial_setup(struct serial_private *priv,
+                                 const struct pciserial_board *board,
+                                 struct uart_8250_port *port, int idx,
+                                 int index, struct pci_dev *dma_dev)
+{
+       struct device *dev = port->port.dev;
+       struct uart_8250_dma *dma;
+       struct hsu_dma_slave *tx_param, *rx_param;
+
+       dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
+       if (!dma)
+               return -ENOMEM;
+
+       tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
+       if (!tx_param)
+               return -ENOMEM;
+
+       rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
+       if (!rx_param)
+               return -ENOMEM;
+
+       rx_param->chan_id = index * 2 + 1;
+       tx_param->chan_id = index * 2;
+
+       dma->rxconf.src_maxburst = 64;
+       dma->txconf.dst_maxburst = 64;
+
+       rx_param->dma_dev = &dma_dev->dev;
+       tx_param->dma_dev = &dma_dev->dev;
+
+       dma->fn = intel_mid_dma_filter;
+       dma->rx_param = rx_param;
+       dma->tx_param = tx_param;
+
+       port->port.type = PORT_16750;
+       port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
+       port->dma = dma;
+
+       return pci_default_setup(priv, board, port, idx);
+}
+
+#define PCI_DEVICE_ID_INTEL_PNW_UART1  0x081b
+#define PCI_DEVICE_ID_INTEL_PNW_UART2  0x081c
+#define PCI_DEVICE_ID_INTEL_PNW_UART3  0x081d
+
+static int pnw_serial_setup(struct serial_private *priv,
+                           const struct pciserial_board *board,
+                           struct uart_8250_port *port, int idx)
+{
+       struct pci_dev *pdev = priv->dev;
+       struct pci_dev *dma_dev;
+       int index;
+
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_INTEL_PNW_UART1:
+               index = 0;
+               break;
+       case PCI_DEVICE_ID_INTEL_PNW_UART2:
+               index = 1;
+               break;
+       case PCI_DEVICE_ID_INTEL_PNW_UART3:
+               index = 2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
+
+       port->port.set_termios = intel_mid_set_termios_50M;
+
+       return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
+}
+
 static int
 pci_omegapci_setup(struct serial_private *priv,
                      const struct pciserial_board *board,
@@ -1987,6 +2130,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = byt_serial_setup,
        },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PNW_UART1,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pnw_serial_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PNW_UART2,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pnw_serial_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PNW_UART3,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pnw_serial_setup,
+       },
        {
                .vendor         = PCI_VENDOR_ID_INTEL,
                .device         = PCI_DEVICE_ID_INTEL_BSW_UART1,
@@ -2864,6 +3028,7 @@ enum pci_board_num_t {
        pbn_ADDIDATA_PCIe_8_3906250,
        pbn_ce4100_1_115200,
        pbn_byt,
+       pbn_pnw,
        pbn_qrk,
        pbn_omegapci,
        pbn_NETMOS9900_2s_115200,
@@ -3630,6 +3795,11 @@ static struct pciserial_board pci_boards[] = {
                .uart_offset    = 0x80,
                .reg_shift      = 2,
        },
+       [pbn_pnw] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+       },
        [pbn_qrk] = {
                .flags          = FL_BASE0,
                .num_ports      = 1,
@@ -4006,41 +4176,41 @@ static void pciserial_remove_one(struct pci_dev *dev)
        pci_disable_device(dev);
 }
 
-#ifdef CONFIG_PM
-static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int pciserial_suspend_one(struct device *dev)
 {
-       struct serial_private *priv = pci_get_drvdata(dev);
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct serial_private *priv = pci_get_drvdata(pdev);
 
        if (priv)
                pciserial_suspend_ports(priv);
 
-       pci_save_state(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
        return 0;
 }
 
-static int pciserial_resume_one(struct pci_dev *dev)
+static int pciserial_resume_one(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct serial_private *priv = pci_get_drvdata(pdev);
        int err;
-       struct serial_private *priv = pci_get_drvdata(dev);
-
-       pci_set_power_state(dev, PCI_D0);
-       pci_restore_state(dev);
 
        if (priv) {
                /*
                 * The device may have been disabled.  Re-enable it.
                 */
-               err = pci_enable_device(dev);
+               err = pci_enable_device(pdev);
                /* FIXME: We cannot simply error out here */
                if (err)
-                       dev_err(&dev->dev, "Unable to re-enable ports, trying to continue.\n");
+                       dev_err(dev, "Unable to re-enable ports, trying to continue.\n");
                pciserial_resume_ports(priv);
        }
        return 0;
 }
 #endif
 
+static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one,
+                        pciserial_resume_one);
+
 static struct pci_device_id serial_pci_tbl[] = {
        /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
        {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
@@ -5362,6 +5532,19 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
                pbn_byt },
 
+       /*
+        * Intel Penwell
+        */
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_pnw},
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_pnw},
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_pnw},
+
        /*
         * Intel Quark x1000
         */
@@ -5510,10 +5693,9 @@ static struct pci_driver serial_pci_driver = {
        .name           = "serial",
        .probe          = pciserial_init_one,
        .remove         = pciserial_remove_one,
-#ifdef CONFIG_PM
-       .suspend        = pciserial_suspend_one,
-       .resume         = pciserial_resume_one,
-#endif
+       .driver         = {
+               .pm     = &pciserial_pm_ops,
+       },
        .id_table       = serial_pci_tbl,
        .err_handler    = &serial8250_err_handler,
 };
index d2501f01cd03483b3f83a384027275abb5b5c089..c9dbc626038d6e14a854d5982c369be181d82aa5 100644 (file)
@@ -20,7 +20,7 @@ comment "Non-8250 serial port support"
 
 config SERIAL_AMBA_PL010
        tristate "ARM AMBA PL010 serial port support"
-       depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
+       depends on ARM_AMBA
        select SERIAL_CORE
        help
          This selects the ARM(R) AMBA(R) PrimeCell PL010 UART.  If you have
@@ -483,16 +483,6 @@ config SERIAL_SA1100_CONSOLE
          your boot loader (lilo or loadlin) about how to pass options to the
          kernel at boot time.)
 
-config SERIAL_MFD_HSU
-       tristate "Medfield High Speed UART support"
-       depends on PCI
-       select SERIAL_CORE
-
-config SERIAL_MFD_HSU_CONSOLE
-       bool "Medfile HSU serial console support"
-       depends on SERIAL_MFD_HSU=y
-       select SERIAL_CORE_CONSOLE
-
 config SERIAL_BFIN
        tristate "Blackfin serial port support"
        depends on BLACKFIN
@@ -835,7 +825,7 @@ config SERIAL_MCF_CONSOLE
 
 config SERIAL_PMACZILOG
        tristate "Mac or PowerMac z85c30 ESCC support"
-       depends on (M68K && MAC) || (PPC_OF && PPC_PMAC)
+       depends on (M68K && MAC) || PPC_PMAC
        select SERIAL_CORE
        help
          This driver supports the Zilog z85C30 serial ports found on
@@ -1153,7 +1143,7 @@ config SERIAL_OMAP_CONSOLE
 
 config SERIAL_OF_PLATFORM_NWPSERIAL
        tristate "NWP serial port driver"
-       depends on PPC_OF && PPC_DCR
+       depends on PPC_DCR
        select SERIAL_OF_PLATFORM
        select SERIAL_CORE_CONSOLE
        select SERIAL_CORE
index 599be4b05a268801d31d94b6fb539e45f95af665..f42b4f9845df98d9ee240e87eac69fd10594cbd6 100644 (file)
@@ -78,7 +78,6 @@ obj-$(CONFIG_SERIAL_TIMBERDALE)       += timbuart.o
 obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
 obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
-obj-$(CONFIG_SERIAL_MFD_HSU)   += mfd.o
 obj-$(CONFIG_SERIAL_IFX6X60)   += ifx6x60.o
 obj-$(CONFIG_SERIAL_PCH_UART)  += pch_uart.o
 obj-$(CONFIG_SERIAL_MSM_SMD)   += msm_smd_tty.o
index 8d94c194f090b8ed16ae1e9a418502f224041e36..5a4e9d579585f9c5165839db0fec8e368dfb8133 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/sizes.h>
 #include <linux/io.h>
+#include <linux/workqueue.h>
 
 #define UART_NR                        14
 
@@ -156,7 +157,9 @@ struct uart_amba_port {
        unsigned int            lcrh_tx;        /* vendor-specific */
        unsigned int            lcrh_rx;        /* vendor-specific */
        unsigned int            old_cr;         /* state during shutdown */
+       struct delayed_work     tx_softirq_work;
        bool                    autorts;
+       unsigned int            tx_irq_seen;    /* 0=none, 1=1, 2=2 or more */
        char                    type[12];
 #ifdef CONFIG_DMA_ENGINE
        /* DMA stuff */
@@ -164,6 +167,7 @@ struct uart_amba_port {
        bool                    using_rx_dma;
        struct pl011_dmarx_data dmarx;
        struct pl011_dmatx_data dmatx;
+       bool                    dma_probed;
 #endif
 };
 
@@ -261,10 +265,11 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
        }
 }
 
-static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
+static void pl011_dma_probe(struct uart_amba_port *uap)
 {
        /* DMA is the sole user of the platform data right now */
        struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
+       struct device *dev = uap->port.dev;
        struct dma_slave_config tx_conf = {
                .dst_addr = uap->port.mapbase + UART01x_DR,
                .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@@ -275,9 +280,14 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
        struct dma_chan *chan;
        dma_cap_mask_t mask;
 
-       chan = dma_request_slave_channel(dev, "tx");
+       uap->dma_probed = true;
+       chan = dma_request_slave_channel_reason(dev, "tx");
+       if (IS_ERR(chan)) {
+               if (PTR_ERR(chan) == -EPROBE_DEFER) {
+                       uap->dma_probed = false;
+                       return;
+               }
 
-       if (!chan) {
                /* We need platform data */
                if (!plat || !plat->dma_filter) {
                        dev_info(uap->port.dev, "no DMA platform data\n");
@@ -385,63 +395,17 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
        }
 }
 
-#ifndef MODULE
-/*
- * Stack up the UARTs and let the above initcall be done at device
- * initcall time, because the serial driver is called as an arch
- * initcall, and at this time the DMA subsystem is not yet registered.
- * At this point the driver will switch over to using DMA where desired.
- */
-struct dma_uap {
-       struct list_head node;
-       struct uart_amba_port *uap;
-       struct device *dev;
-};
-
-static LIST_HEAD(pl011_dma_uarts);
-
-static int __init pl011_dma_initcall(void)
-{
-       struct list_head *node, *tmp;
-
-       list_for_each_safe(node, tmp, &pl011_dma_uarts) {
-               struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
-               pl011_dma_probe_initcall(dmau->dev, dmau->uap);
-               list_del(node);
-               kfree(dmau);
-       }
-       return 0;
-}
-
-device_initcall(pl011_dma_initcall);
-
-static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
-{
-       struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
-       if (dmau) {
-               dmau->uap = uap;
-               dmau->dev = dev;
-               list_add_tail(&dmau->node, &pl011_dma_uarts);
-       }
-}
-#else
-static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
-{
-       pl011_dma_probe_initcall(dev, uap);
-}
-#endif
-
 static void pl011_dma_remove(struct uart_amba_port *uap)
 {
-       /* TODO: remove the initcall if it has not yet executed */
        if (uap->dmatx.chan)
                dma_release_channel(uap->dmatx.chan);
        if (uap->dmarx.chan)
                dma_release_channel(uap->dmarx.chan);
 }
 
-/* Forward declare this for the refill routine */
+/* Forward declare these for the refill routine */
 static int pl011_dma_tx_refill(struct uart_amba_port *uap);
+static void pl011_start_tx_pio(struct uart_amba_port *uap);
 
 /*
  * The current DMA TX buffer has been sent.
@@ -479,14 +443,13 @@ static void pl011_dma_tx_callback(void *data)
                return;
        }
 
-       if (pl011_dma_tx_refill(uap) <= 0) {
+       if (pl011_dma_tx_refill(uap) <= 0)
                /*
                 * We didn't queue a DMA buffer for some reason, but we
                 * have data pending to be sent.  Re-enable the TX IRQ.
                 */
-               uap->im |= UART011_TXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
-       }
+               pl011_start_tx_pio(uap);
+
        spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -664,12 +627,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
                if (!uap->dmatx.queued) {
                        if (pl011_dma_tx_refill(uap) > 0) {
                                uap->im &= ~UART011_TXIM;
-                               ret = true;
-                       } else {
-                               uap->im |= UART011_TXIM;
+                               writew(uap->im, uap->port.membase +
+                                      UART011_IMSC);
+                       } else
                                ret = false;
-                       }
-                       writew(uap->im, uap->port.membase + UART011_IMSC);
                } else if (!(uap->dmacr & UART011_TXDMAE)) {
                        uap->dmacr |= UART011_TXDMAE;
                        writew(uap->dmacr,
@@ -1021,6 +982,9 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 {
        int ret;
 
+       if (!uap->dma_probed)
+               pl011_dma_probe(uap);
+
        if (!uap->dmatx.chan)
                return;
 
@@ -1142,7 +1106,7 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
 
 #else
 /* Blank functions if the DMA engine is not available */
-static inline void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
+static inline void pl011_dma_probe(struct uart_amba_port *uap)
 {
 }
 
@@ -1208,15 +1172,24 @@ static void pl011_stop_tx(struct uart_port *port)
        pl011_dma_tx_stop(uap);
 }
 
+static bool pl011_tx_chars(struct uart_amba_port *uap);
+
+/* Start TX with programmed I/O only (no DMA) */
+static void pl011_start_tx_pio(struct uart_amba_port *uap)
+{
+       uap->im |= UART011_TXIM;
+       writew(uap->im, uap->port.membase + UART011_IMSC);
+       if (!uap->tx_irq_seen)
+               pl011_tx_chars(uap);
+}
+
 static void pl011_start_tx(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
 
-       if (!pl011_dma_tx_start(uap)) {
-               uap->im |= UART011_TXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
-       }
+       if (!pl011_dma_tx_start(uap))
+               pl011_start_tx_pio(uap);
 }
 
 static void pl011_stop_rx(struct uart_port *port)
@@ -1274,40 +1247,87 @@ __acquires(&uap->port.lock)
        spin_lock(&uap->port.lock);
 }
 
-static void pl011_tx_chars(struct uart_amba_port *uap)
+/*
+ * Transmit a character
+ * There must be at least one free entry in the TX FIFO to accept the char.
+ *
+ * Returns true if the FIFO might have space in it afterwards;
+ * returns false if the FIFO definitely became full.
+ */
+static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
+{
+       writew(c, uap->port.membase + UART01x_DR);
+       uap->port.icount.tx++;
+
+       if (likely(uap->tx_irq_seen > 1))
+               return true;
+
+       return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
+}
+
+static bool pl011_tx_chars(struct uart_amba_port *uap)
 {
        struct circ_buf *xmit = &uap->port.state->xmit;
        int count;
 
+       if (unlikely(uap->tx_irq_seen < 2))
+               /*
+                * Initial FIFO fill level unknown: we must check TXFF
+                * after each write, so just try to fill up the FIFO.
+                */
+               count = uap->fifosize;
+       else /* tx_irq_seen >= 2 */
+               /*
+                * FIFO initially at least half-empty, so we can simply
+                * write half the FIFO without polling TXFF.
+
+                * Note: the *first* TX IRQ can still race with
+                * pl011_start_tx_pio(), which can result in the FIFO
+                * being fuller than expected in that case.
+                */
+               count = uap->fifosize >> 1;
+
+       /*
+        * If the FIFO is full we're guaranteed a TX IRQ at some later point,
+        * and can't transmit immediately in any case:
+        */
+       if (unlikely(uap->tx_irq_seen < 2 &&
+                    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF))
+               return false;
+
        if (uap->port.x_char) {
-               writew(uap->port.x_char, uap->port.membase + UART01x_DR);
-               uap->port.icount.tx++;
+               pl011_tx_char(uap, uap->port.x_char);
                uap->port.x_char = 0;
-               return;
+               --count;
        }
        if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
                pl011_stop_tx(&uap->port);
-               return;
+               goto done;
        }
 
        /* If we are using DMA mode, try to send some characters. */
        if (pl011_dma_tx_irq(uap))
-               return;
+               goto done;
 
-       count = uap->fifosize >> 1;
-       do {
-               writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
+       while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) {
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               uap->port.icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
-       } while (--count > 0);
+       }
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&uap->port);
 
-       if (uart_circ_empty(xmit))
+       if (uart_circ_empty(xmit)) {
                pl011_stop_tx(&uap->port);
+               goto done;
+       }
+
+       if (unlikely(!uap->tx_irq_seen))
+               schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout);
+
+done:
+       return false;
 }
 
 static void pl011_modem_status(struct uart_amba_port *uap)
@@ -1334,6 +1354,28 @@ static void pl011_modem_status(struct uart_amba_port *uap)
        wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 }
 
+static void pl011_tx_softirq(struct work_struct *work)
+{
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct uart_amba_port *uap =
+               container_of(dwork, struct uart_amba_port, tx_softirq_work);
+
+       spin_lock(&uap->port.lock);
+       while (pl011_tx_chars(uap)) ;
+       spin_unlock(&uap->port.lock);
+}
+
+static void pl011_tx_irq_seen(struct uart_amba_port *uap)
+{
+       if (likely(uap->tx_irq_seen > 1))
+               return;
+
+       uap->tx_irq_seen++;
+       if (uap->tx_irq_seen < 2)
+               /* first TX IRQ */
+               cancel_delayed_work(&uap->tx_softirq_work);
+}
+
 static irqreturn_t pl011_int(int irq, void *dev_id)
 {
        struct uart_amba_port *uap = dev_id;
@@ -1372,8 +1414,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
                        if (status & (UART011_DSRMIS|UART011_DCDMIS|
                                      UART011_CTSMIS|UART011_RIMIS))
                                pl011_modem_status(uap);
-                       if (status & UART011_TXIS)
+                       if (status & UART011_TXIS) {
+                               pl011_tx_irq_seen(uap);
                                pl011_tx_chars(uap);
+                       }
 
                        if (pass_counter-- == 0)
                                break;
@@ -1577,7 +1621,7 @@ static int pl011_startup(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
-       unsigned int cr, lcr_h, fbrd, ibrd;
+       unsigned int cr;
        int retval;
 
        retval = pl011_hwinit(port);
@@ -1595,30 +1639,8 @@ static int pl011_startup(struct uart_port *port)
 
        writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
 
-       /*
-        * Provoke TX FIFO interrupt into asserting. Taking care to preserve
-        * baud rate and data format specified by FBRD, IBRD and LCRH as the
-        * UART may already be in use as a console.
-        */
        spin_lock_irq(&uap->port.lock);
 
-       fbrd = readw(uap->port.membase + UART011_FBRD);
-       ibrd = readw(uap->port.membase + UART011_IBRD);
-       lcr_h = readw(uap->port.membase + uap->lcrh_rx);
-
-       cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
-       writew(cr, uap->port.membase + UART011_CR);
-       writew(0, uap->port.membase + UART011_FBRD);
-       writew(1, uap->port.membase + UART011_IBRD);
-       pl011_write_lcr_h(uap, 0);
-       writew(0, uap->port.membase + UART01x_DR);
-       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
-               barrier();
-
-       writew(fbrd, uap->port.membase + UART011_FBRD);
-       writew(ibrd, uap->port.membase + UART011_IBRD);
-       pl011_write_lcr_h(uap, lcr_h);
-
        /* restore RTS and DTR */
        cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
        cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
@@ -1672,13 +1694,15 @@ static void pl011_shutdown(struct uart_port *port)
            container_of(port, struct uart_amba_port, port);
        unsigned int cr;
 
+       cancel_delayed_work_sync(&uap->tx_softirq_work);
+
        /*
         * disable all interrupts
         */
        spin_lock_irq(&uap->port.lock);
        uap->im = 0;
        writew(uap->im, uap->port.membase + UART011_IMSC);
-       writew(0xffff, uap->port.membase + UART011_ICR);
+       writew(0xffff & ~UART011_TXIS, uap->port.membase + UART011_ICR);
        spin_unlock_irq(&uap->port.lock);
 
        pl011_dma_shutdown(uap);
@@ -2218,7 +2242,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        uap->port.ops = &amba_pl011_pops;
        uap->port.flags = UPF_BOOT_AUTOCONF;
        uap->port.line = i;
-       pl011_dma_probe(&dev->dev, uap);
+       INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq);
 
        /* Ensure interrupts from this UART are masked and cleared */
        writew(0, uap->port.membase + UART011_IMSC);
@@ -2233,7 +2257,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        if (!amba_reg.state) {
                ret = uart_register_driver(&amba_reg);
                if (ret < 0) {
-                       pr_err("Failed to register AMBA-PL011 driver\n");
+                       dev_err(&dev->dev,
+                               "Failed to register AMBA-PL011 driver\n");
                        return ret;
                }
        }
@@ -2242,7 +2267,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        if (ret) {
                amba_ports[i] = NULL;
                uart_unregister_driver(&amba_reg);
-               pl011_dma_remove(uap);
        }
 
        return ret;
index 77fc9faa74a41f508414440e2c41fc155058d1ce..1519d2ca7705f23eb785b083ed8364b0d46e1de3 100644 (file)
@@ -649,7 +649,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
                        id = 0;
        }
 
-       if (id > CONFIG_SERIAL_AR933X_NR_UARTS)
+       if (id >= CONFIG_SERIAL_AR933X_NR_UARTS)
                return -EINVAL;
 
        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
index 4e959c43f6804d12f8677d916e1f050bdc740457..d58fe4763d9e1bdacf07577e3043414e22f8ecbc 100644 (file)
@@ -855,7 +855,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
        spin_lock_init(&atmel_port->lock_tx);
        sg_init_table(&atmel_port->sg_tx, 1);
        /* UART circular tx buffer is an aligned page. */
-       BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+       BUG_ON(!PAGE_ALIGNED(port->state->xmit.buf));
        sg_set_page(&atmel_port->sg_tx,
                        virt_to_page(port->state->xmit.buf),
                        UART_XMIT_SIZE,
@@ -1034,10 +1034,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
        spin_lock_init(&atmel_port->lock_rx);
        sg_init_table(&atmel_port->sg_rx, 1);
        /* UART circular rx buffer is an aligned page. */
-       BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+       BUG_ON(!PAGE_ALIGNED(ring->buf));
        sg_set_page(&atmel_port->sg_rx,
                    virt_to_page(ring->buf),
-                   ATMEL_SERIAL_RINGSIZE,
+                   sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
                    (int)ring->buf & ~PAGE_MASK);
        nent = dma_map_sg(port->dev,
                          &atmel_port->sg_rx,
@@ -1554,7 +1554,7 @@ static void atmel_tasklet_func(unsigned long data)
        spin_unlock(&port->lock);
 }
 
-static int atmel_init_property(struct atmel_uart_port *atmel_port,
+static void atmel_init_property(struct atmel_uart_port *atmel_port,
                                struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -1595,7 +1595,6 @@ static int atmel_init_property(struct atmel_uart_port *atmel_port,
                atmel_port->use_dma_tx  = false;
        }
 
-       return 0;
 }
 
 static void atmel_init_rs485(struct uart_port *port,
@@ -1777,10 +1776,13 @@ static int atmel_startup(struct uart_port *port)
        if (retval)
                goto free_irq;
 
+       tasklet_enable(&atmel_port->tasklet);
+
        /*
         * Initialize DMA (if necessary)
         */
        atmel_init_property(atmel_port, pdev);
+       atmel_set_ops(port);
 
        if (atmel_port->prepare_rx) {
                retval = atmel_port->prepare_rx(port);
@@ -1879,6 +1881,7 @@ static void atmel_shutdown(struct uart_port *port)
         * Clear out any scheduled tasklets before
         * we destroy the buffers
         */
+       tasklet_disable(&atmel_port->tasklet);
        tasklet_kill(&atmel_port->tasklet);
 
        /*
@@ -2256,8 +2259,8 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
        struct uart_port *port = &atmel_port->uart;
        struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 
-       if (!atmel_init_property(atmel_port, pdev))
-               atmel_set_ops(port);
+       atmel_init_property(atmel_port, pdev);
+       atmel_set_ops(port);
 
        atmel_init_rs485(port, pdev);
 
@@ -2272,6 +2275,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
 
        tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
                        (unsigned long)port);
+       tasklet_disable(&atmel_port->tasklet);
 
        memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 
@@ -2581,8 +2585,8 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
        struct gpio_desc *gpiod;
 
        p->gpios = mctrl_gpio_init(dev, 0);
-       if (IS_ERR_OR_NULL(p->gpios))
-               return -1;
+       if (IS_ERR(p->gpios))
+               return PTR_ERR(p->gpios);
 
        for (i = 0; i < UART_GPIO_MAX; i++) {
                gpiod = mctrl_gpio_to_gpiod(p->gpios, i);
@@ -2635,9 +2639,10 @@ static int atmel_serial_probe(struct platform_device *pdev)
        spin_lock_init(&port->lock_suspended);
 
        ret = atmel_init_gpios(port, &pdev->dev);
-       if (ret < 0)
-               dev_err(&pdev->dev, "%s",
-                       "Failed to initialize GPIOs. The serial port may not work as expected");
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to initialize GPIOs.");
+               goto err;
+       }
 
        ret = atmel_init_port(port, pdev);
        if (ret)
index 01d83df08e3d394f7a028ca1e37fa2429eab2644..681e0f3d5e0ef895b0f618a24a40cf138f8f0eca 100644 (file)
@@ -854,7 +854,7 @@ static int bcm_uart_probe(struct platform_device *pdev)
 
        ret = uart_add_one_port(&bcm_uart_driver, port);
        if (ret) {
-               ports[pdev->id].membase = 0;
+               ports[pdev->id].membase = NULL;
                return ret;
        }
        platform_set_drvdata(pdev, port);
@@ -868,7 +868,7 @@ static int bcm_uart_remove(struct platform_device *pdev)
        port = platform_get_drvdata(pdev);
        uart_remove_one_port(&bcm_uart_driver, port);
        /* mark port as free */
-       ports[pdev->id].membase = 0;
+       ports[pdev->id].membase = NULL;
        return 0;
 }
 
index 6e11c275f2ab70d4fe326cf55c8177839408b03d..d5d2dd7c79174820432363d4a7076566eafc2204 100644 (file)
@@ -501,6 +501,8 @@ static int uart_clps711x_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, s);
 
        s->gpios = mctrl_gpio_init(&pdev->dev, 0);
+       if (IS_ERR(s->gpios))
+           return PTR_ERR(s->gpios);
 
        ret = uart_add_one_port(&clps711x_uart, &s->port);
        if (ret)
index 64fe25a4285c2d1fe0f13c9ea9c91880fdd40ad9..58d6bcdaf31c9c879824d30402a57987c96ea614 100644 (file)
@@ -54,44 +54,31 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
        return base;
 }
 
-static int __init parse_options(struct earlycon_device *device,
-                               char *options)
+static int __init parse_options(struct earlycon_device *device, char *options)
 {
        struct uart_port *port = &device->port;
-       int mmio, mmio32, length;
+       int length;
        unsigned long addr;
 
-       if (!options)
-               return -ENODEV;
+       if (uart_parse_earlycon(options, &port->iotype, &addr, &options))
+               return -EINVAL;
 
-       mmio = !strncmp(options, "mmio,", 5);
-       mmio32 = !strncmp(options, "mmio32,", 7);
-       if (mmio || mmio32) {
-               port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
-               options += mmio ? 5 : 7;
-               addr = simple_strtoul(options, NULL, 0);
+       switch (port->iotype) {
+       case UPIO_MEM32:
+               port->regshift = 2;     /* fall-through */
+       case UPIO_MEM:
                port->mapbase = addr;
-               if (mmio32)
-                       port->regshift = 2;
-       } else if (!strncmp(options, "io,", 3)) {
-               port->iotype = UPIO_PORT;
-               options += 3;
-               addr = simple_strtoul(options, NULL, 0);
+               break;
+       case UPIO_PORT:
                port->iobase = addr;
-               mmio = 0;
-       } else if (!strncmp(options, "0x", 2)) {
-               port->iotype = UPIO_MEM;
-               addr = simple_strtoul(options, NULL, 0);
-               port->mapbase = addr;
-       } else {
+               break;
+       default:
                return -EINVAL;
        }
 
        port->uartclk = BASE_BAUD * 16;
 
-       options = strchr(options, ',');
        if (options) {
-               options++;
                device->baud = simple_strtoul(options, NULL, 0);
                length = min(strcspn(options, " ") + 1,
                             (size_t)(sizeof(device->options)));
@@ -100,7 +87,7 @@ static int __init parse_options(struct earlycon_device *device,
 
        if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32)
                pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
-                       mmio32 ? "32" : "",
+                       (port->iotype == UPIO_MEM32) ? "32" : "",
                        (unsigned long long)port->mapbase,
                        device->options);
        else
index 0eb29b1c47ac8ea313456df38a45f6720e62246b..c8cfa06371280af6abfd63bd379ee5c121523ad7 100644 (file)
@@ -1,13 +1,10 @@
 /*
- *  Driver for Motorola IMX serial ports
+ * Driver for Motorola/Freescale IMX serial ports
  *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  *
- *  Author: Sascha Hauer <sascha@saschahauer.de>
- *  Copyright (C) 2004 Pengutronix
- *
- *  Copyright (C) 2009 emlix GmbH
- *  Author: Fabian Godehardt (added IrDA support for iMX)
+ * Author: Sascha Hauer <sascha@saschahauer.de>
+ * Copyright (C) 2004 Pengutronix
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * [29-Mar-2005] Mike Lee
- * Added hardware handshake
  */
 
 #if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 
 #define UART_NR 8
 
-/* i.mx21 type uart runs on all i.mx except i.mx1 */
+/* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
 enum imx_uart_type {
        IMX1_UART,
        IMX21_UART,
@@ -206,10 +196,8 @@ struct imx_port {
        struct uart_port        port;
        struct timer_list       timer;
        unsigned int            old_status;
-       int                     txirq, rxirq, rtsirq;
        unsigned int            have_rtscts:1;
        unsigned int            dte_mode:1;
-       unsigned int            use_irda:1;
        unsigned int            irda_inv_rx:1;
        unsigned int            irda_inv_tx:1;
        unsigned short          trcv_delay; /* transceiver delay */
@@ -236,12 +224,6 @@ struct imx_port_ucrs {
        unsigned int    ucr3;
 };
 
-#ifdef CONFIG_IRDA
-#define USE_IRDA(sport)        ((sport)->use_irda)
-#else
-#define USE_IRDA(sport)        (0)
-#endif
-
 static struct imx_uart_data imx_uart_devdata[] = {
        [IMX1_UART] = {
                .uts_reg = IMX1_UTS,
@@ -273,7 +255,7 @@ static struct platform_device_id imx_uart_devtype[] = {
 };
 MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
 
-static struct of_device_id imx_uart_dt_ids[] = {
+static const struct of_device_id imx_uart_dt_ids[] = {
        { .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
        { .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
        { .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
@@ -376,48 +358,6 @@ static void imx_stop_tx(struct uart_port *port)
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
 
-       if (USE_IRDA(sport)) {
-               /* half duplex - wait for end of transmission */
-               int n = 256;
-               while ((--n > 0) &&
-                     !(readl(sport->port.membase + USR2) & USR2_TXDC)) {
-                       udelay(5);
-                       barrier();
-               }
-               /*
-                * irda transceiver - wait a bit more to avoid
-                * cutoff, hardware dependent
-                */
-               udelay(sport->trcv_delay);
-
-               /*
-                * half duplex - reactivate receive mode,
-                * flush receive pipe echo crap
-                */
-               if (readl(sport->port.membase + USR2) & USR2_TXDC) {
-                       temp = readl(sport->port.membase + UCR1);
-                       temp &= ~(UCR1_TXMPTYEN | UCR1_TRDYEN);
-                       writel(temp, sport->port.membase + UCR1);
-
-                       temp = readl(sport->port.membase + UCR4);
-                       temp &= ~(UCR4_TCEN);
-                       writel(temp, sport->port.membase + UCR4);
-
-                       while (readl(sport->port.membase + URXD0) &
-                              URXD_CHARRDY)
-                               barrier();
-
-                       temp = readl(sport->port.membase + UCR1);
-                       temp |= UCR1_RRDYEN;
-                       writel(temp, sport->port.membase + UCR1);
-
-                       temp = readl(sport->port.membase + UCR4);
-                       temp |= UCR4_DREN;
-                       writel(temp, sport->port.membase + UCR4);
-               }
-               return;
-       }
-
        /*
         * We are maybe in the SMP context, so if the DMA TX thread is running
         * on other cpu, we have to wait for it to finish.
@@ -425,8 +365,23 @@ static void imx_stop_tx(struct uart_port *port)
        if (sport->dma_is_enabled && sport->dma_is_txing)
                return;
 
-       temp = readl(sport->port.membase + UCR1);
-       writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
+       temp = readl(port->membase + UCR1);
+       writel(temp & ~UCR1_TXMPTYEN, port->membase + UCR1);
+
+       /* in rs485 mode disable transmitter if shifter is empty */
+       if (port->rs485.flags & SER_RS485_ENABLED &&
+           readl(port->membase + USR2) & USR2_TXDC) {
+               temp = readl(port->membase + UCR2);
+               if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+                       temp &= ~UCR2_CTS;
+               else
+                       temp |= UCR2_CTS;
+               writel(temp, port->membase + UCR2);
+
+               temp = readl(port->membase + UCR4);
+               temp &= ~UCR4_TCEN;
+               writel(temp, port->membase + UCR4);
+       }
 }
 
 /*
@@ -620,15 +575,18 @@ static void imx_start_tx(struct uart_port *port)
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
 
-       if (USE_IRDA(sport)) {
-               /* half duplex in IrDA mode; have to disable receive mode */
-               temp = readl(sport->port.membase + UCR4);
-               temp &= ~(UCR4_DREN);
-               writel(temp, sport->port.membase + UCR4);
+       if (port->rs485.flags & SER_RS485_ENABLED) {
+               /* enable transmitter and shifter empty irq */
+               temp = readl(port->membase + UCR2);
+               if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
+                       temp &= ~UCR2_CTS;
+               else
+                       temp |= UCR2_CTS;
+               writel(temp, port->membase + UCR2);
 
-               temp = readl(sport->port.membase + UCR1);
-               temp &= ~(UCR1_RRDYEN);
-               writel(temp, sport->port.membase + UCR1);
+               temp = readl(port->membase + UCR4);
+               temp |= UCR4_TCEN;
+               writel(temp, port->membase + UCR4);
        }
 
        if (!sport->dma_is_enabled) {
@@ -636,16 +594,6 @@ static void imx_start_tx(struct uart_port *port)
                writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
        }
 
-       if (USE_IRDA(sport)) {
-               temp = readl(sport->port.membase + UCR1);
-               temp |= UCR1_TRDYEN;
-               writel(temp, sport->port.membase + UCR1);
-
-               temp = readl(sport->port.membase + UCR4);
-               temp |= UCR4_TCEN;
-               writel(temp, sport->port.membase + UCR4);
-       }
-
        if (sport->dma_is_enabled) {
                if (sport->port.x_char) {
                        /* We have X-char to send, so enable TX IRQ and
@@ -796,6 +744,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
        unsigned int sts2;
 
        sts = readl(sport->port.membase + USR1);
+       sts2 = readl(sport->port.membase + USR2);
 
        if (sts & USR1_RRDY) {
                if (sport->dma_is_enabled)
@@ -804,8 +753,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
                        imx_rxint(irq, dev_id);
        }
 
-       if (sts & USR1_TRDY &&
-                       readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
+       if ((sts & USR1_TRDY &&
+            readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) ||
+           (sts2 & USR2_TXDC &&
+            readl(sport->port.membase + UCR4) & UCR4_TCEN))
                imx_txint(irq, dev_id);
 
        if (sts & USR1_RTSD)
@@ -814,11 +765,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
        if (sts & USR1_AWAKE)
                writel(USR1_AWAKE, sport->port.membase + USR1);
 
-       sts2 = readl(sport->port.membase + USR2);
        if (sts2 & USR2_ORE) {
                dev_err(sport->port.dev, "Rx FIFO overrun\n");
                sport->port.icount.overrun++;
-               writel(sts2 | USR2_ORE, sport->port.membase + USR2);
+               writel(USR2_ORE, sport->port.membase + USR2);
        }
 
        return IRQ_HANDLED;
@@ -866,11 +816,13 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
 
-       temp = readl(sport->port.membase + UCR2) & ~(UCR2_CTS | UCR2_CTSC);
-       if (mctrl & TIOCM_RTS)
-               temp |= UCR2_CTS | UCR2_CTSC;
-
-       writel(temp, sport->port.membase + UCR2);
+       if (!(port->rs485.flags & SER_RS485_ENABLED)) {
+               temp = readl(sport->port.membase + UCR2);
+               temp &= ~(UCR2_CTS | UCR2_CTSC);
+               if (mctrl & TIOCM_RTS)
+                       temp |= UCR2_CTS | UCR2_CTSC;
+               writel(temp, sport->port.membase + UCR2);
+       }
 
        temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
        if (mctrl & TIOCM_LOOP)
@@ -1156,9 +1108,6 @@ static int imx_startup(struct uart_port *port)
         */
        temp = readl(sport->port.membase + UCR4);
 
-       if (USE_IRDA(sport))
-               temp |= UCR4_IRSC;
-
        /* set the trigger level for CTS */
        temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
        temp |= CTSTL << UCR4_CTSTL_SHF;
@@ -1181,10 +1130,12 @@ static int imx_startup(struct uart_port *port)
                imx_uart_dma_init(sport);
 
        spin_lock_irqsave(&sport->port.lock, flags);
+
        /*
         * Finally, clear and enable interrupts
         */
        writel(USR1_RTSD, sport->port.membase + USR1);
+       writel(USR2_ORE, sport->port.membase + USR2);
 
        if (sport->dma_is_inited && !sport->dma_is_enabled)
                imx_enable_dma(sport);
@@ -1192,17 +1143,8 @@ static int imx_startup(struct uart_port *port)
        temp = readl(sport->port.membase + UCR1);
        temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 
-       if (USE_IRDA(sport)) {
-               temp |= UCR1_IREN;
-               temp &= ~(UCR1_RTSDEN);
-       }
-
        writel(temp, sport->port.membase + UCR1);
 
-       /* Clear any pending ORE flag before enabling interrupt */
-       temp = readl(sport->port.membase + USR2);
-       writel(temp | USR2_ORE, sport->port.membase + USR2);
-
        temp = readl(sport->port.membase + UCR4);
        temp |= UCR4_OREN;
        writel(temp, sport->port.membase + UCR4);
@@ -1219,38 +1161,12 @@ static int imx_startup(struct uart_port *port)
                writel(temp, sport->port.membase + UCR3);
        }
 
-       if (USE_IRDA(sport)) {
-               temp = readl(sport->port.membase + UCR4);
-               if (sport->irda_inv_rx)
-                       temp |= UCR4_INVR;
-               else
-                       temp &= ~(UCR4_INVR);
-               writel(temp | UCR4_DREN, sport->port.membase + UCR4);
-
-               temp = readl(sport->port.membase + UCR3);
-               if (sport->irda_inv_tx)
-                       temp |= UCR3_INVT;
-               else
-                       temp &= ~(UCR3_INVT);
-               writel(temp, sport->port.membase + UCR3);
-       }
-
        /*
         * Enable modem status interrupts
         */
        imx_enable_ms(&sport->port);
        spin_unlock_irqrestore(&sport->port.lock, flags);
 
-       if (USE_IRDA(sport)) {
-               struct imxuart_platform_data *pdata;
-               pdata = dev_get_platdata(sport->port.dev);
-               sport->irda_inv_rx = pdata->irda_inv_rx;
-               sport->irda_inv_tx = pdata->irda_inv_tx;
-               sport->trcv_delay = pdata->transceiver_delay;
-               if (pdata->irda_enable)
-                       pdata->irda_enable(1);
-       }
-
        return 0;
 }
 
@@ -1286,13 +1202,6 @@ static void imx_shutdown(struct uart_port *port)
        writel(temp, sport->port.membase + UCR2);
        spin_unlock_irqrestore(&sport->port.lock, flags);
 
-       if (USE_IRDA(sport)) {
-               struct imxuart_platform_data *pdata;
-               pdata = dev_get_platdata(sport->port.dev);
-               if (pdata->irda_enable)
-                       pdata->irda_enable(0);
-       }
-
        /*
         * Stop our timer.
         */
@@ -1305,8 +1214,6 @@ static void imx_shutdown(struct uart_port *port)
        spin_lock_irqsave(&sport->port.lock, flags);
        temp = readl(sport->port.membase + UCR1);
        temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
-       if (USE_IRDA(sport))
-               temp &= ~(UCR1_IREN);
 
        writel(temp, sport->port.membase + UCR1);
        spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1320,7 +1227,7 @@ static void imx_flush_buffer(struct uart_port *port)
        struct imx_port *sport = (struct imx_port *)port;
        struct scatterlist *sgl = &sport->tx_sgl[0];
        unsigned long temp;
-       int i = 100, ubir, ubmr, ubrc, uts;
+       int i = 100, ubir, ubmr, uts;
 
        if (!sport->dma_chan_tx)
                return;
@@ -1345,7 +1252,6 @@ static void imx_flush_buffer(struct uart_port *port)
         */
        ubir = readl(sport->port.membase + UBIR);
        ubmr = readl(sport->port.membase + UBMR);
-       ubrc = readl(sport->port.membase + UBRC);
        uts = readl(sport->port.membase + IMX21_UTS);
 
        temp = readl(sport->port.membase + UCR2);
@@ -1358,7 +1264,6 @@ static void imx_flush_buffer(struct uart_port *port)
        /* Restore the registers */
        writel(ubir, sport->port.membase + UBIR);
        writel(ubmr, sport->port.membase + UBMR);
-       writel(ubrc, sport->port.membase + UBRC);
        writel(uts, sport->port.membase + IMX21_UTS);
 }
 
@@ -1374,15 +1279,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        unsigned long num, denom;
        uint64_t tdiv64;
 
-       /*
-        * If we don't support modem control lines, don't allow
-        * these to be set.
-        */
-       if (0) {
-               termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
-               termios->c_cflag |= CLOCAL;
-       }
-
        /*
         * We only support CS7 and CS8.
         */
@@ -1401,11 +1297,26 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        if (termios->c_cflag & CRTSCTS) {
                if (sport->have_rtscts) {
                        ucr2 &= ~UCR2_IRTS;
-                       ucr2 |= UCR2_CTSC;
+
+                       if (port->rs485.flags & SER_RS485_ENABLED) {
+                               /*
+                                * RTS is mandatory for rs485 operation, so keep
+                                * it under manual control and keep transmitter
+                                * disabled.
+                                */
+                               if (!(port->rs485.flags &
+                                     SER_RS485_RTS_AFTER_SEND))
+                                       ucr2 |= UCR2_CTS;
+                       } else {
+                               ucr2 |= UCR2_CTSC;
+                       }
                } else {
                        termios->c_cflag &= ~CRTSCTS;
                }
-       }
+       } else if (port->rs485.flags & SER_RS485_ENABLED)
+               /* disable transmitter */
+               if (!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND))
+                       ucr2 |= UCR2_CTS;
 
        if (termios->c_cflag & CSTOPB)
                ucr2 |= UCR2_STPB;
@@ -1471,24 +1382,16 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
                        sport->port.membase + UCR2);
        old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
 
-       if (USE_IRDA(sport)) {
-               /*
-                * use maximum available submodule frequency to
-                * avoid missing short pulses due to low sampling rate
-                */
+       /* custom-baudrate handling */
+       div = sport->port.uartclk / (baud * 16);
+       if (baud == 38400 && quot != div)
+               baud = sport->port.uartclk / (quot * 16);
+
+       div = sport->port.uartclk / (baud * 16);
+       if (div > 7)
+               div = 7;
+       if (!div)
                div = 1;
-       } else {
-               /* custom-baudrate handling */
-               div = sport->port.uartclk / (baud * 16);
-               if (baud == 38400 && quot != div)
-                       baud = sport->port.uartclk / (quot * 16);
-
-               div = sport->port.uartclk / (baud * 16);
-               if (div > 7)
-                       div = 7;
-               if (!div)
-                       div = 1;
-       }
 
        rational_best_approximation(16 * div * baud, sport->port.uartclk,
                1 << 16, 1 << 16, &num, &denom);
@@ -1635,6 +1538,38 @@ static void imx_poll_put_char(struct uart_port *port, unsigned char c)
 }
 #endif
 
+static int imx_rs485_config(struct uart_port *port,
+                           struct serial_rs485 *rs485conf)
+{
+       struct imx_port *sport = (struct imx_port *)port;
+
+       /* unimplemented */
+       rs485conf->delay_rts_before_send = 0;
+       rs485conf->delay_rts_after_send = 0;
+       rs485conf->flags |= SER_RS485_RX_DURING_TX;
+
+       /* RTS is required to control the transmitter */
+       if (!sport->have_rtscts)
+               rs485conf->flags &= ~SER_RS485_ENABLED;
+
+       if (rs485conf->flags & SER_RS485_ENABLED) {
+               unsigned long temp;
+
+               /* disable transmitter */
+               temp = readl(sport->port.membase + UCR2);
+               temp &= ~UCR2_CTSC;
+               if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
+                       temp &= ~UCR2_CTS;
+               else
+                       temp |= UCR2_CTS;
+               writel(temp, sport->port.membase + UCR2);
+       }
+
+       port->rs485 = *rs485conf;
+
+       return 0;
+}
+
 static struct uart_ops imx_pops = {
        .tx_empty       = imx_tx_empty,
        .set_mctrl      = imx_set_mctrl,
@@ -1927,9 +1862,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
        if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
                sport->have_rtscts = 1;
 
-       if (of_get_property(np, "fsl,irda-mode", NULL))
-               sport->use_irda = 1;
-
        if (of_get_property(np, "fsl,dte-mode", NULL))
                sport->dte_mode = 1;
 
@@ -1958,9 +1890,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
 
        if (pdata->flags & IMXUART_HAVE_RTSCTS)
                sport->have_rtscts = 1;
-
-       if (pdata->flags & IMXUART_IRDA)
-               sport->use_irda = 1;
 }
 
 static int serial_imx_probe(struct platform_device *pdev)
@@ -1969,6 +1898,7 @@ static int serial_imx_probe(struct platform_device *pdev)
        void __iomem *base;
        int ret = 0;
        struct resource *res;
+       int txirq, rxirq, rtsirq;
 
        sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
        if (!sport)
@@ -1985,17 +1915,21 @@ static int serial_imx_probe(struct platform_device *pdev)
        if (IS_ERR(base))
                return PTR_ERR(base);
 
+       rxirq = platform_get_irq(pdev, 0);
+       txirq = platform_get_irq(pdev, 1);
+       rtsirq = platform_get_irq(pdev, 2);
+
        sport->port.dev = &pdev->dev;
        sport->port.mapbase = res->start;
        sport->port.membase = base;
        sport->port.type = PORT_IMX,
        sport->port.iotype = UPIO_MEM;
-       sport->port.irq = platform_get_irq(pdev, 0);
-       sport->rxirq = platform_get_irq(pdev, 0);
-       sport->txirq = platform_get_irq(pdev, 1);
-       sport->rtsirq = platform_get_irq(pdev, 2);
+       sport->port.irq = rxirq;
        sport->port.fifosize = 32;
        sport->port.ops = &imx_pops;
+       sport->port.rs485_config = imx_rs485_config;
+       sport->port.rs485.flags =
+               SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX;
        sport->port.flags = UPF_BOOT_AUTOCONF;
        init_timer(&sport->timer);
        sport->timer.function = imx_timeout;
@@ -2021,27 +1955,18 @@ static int serial_imx_probe(struct platform_device *pdev)
         * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
         * chips only have one interrupt.
         */
-       if (sport->txirq > 0) {
-               ret = devm_request_irq(&pdev->dev, sport->rxirq, imx_rxint, 0,
+       if (txirq > 0) {
+               ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
                                       dev_name(&pdev->dev), sport);
                if (ret)
                        return ret;
 
-               ret = devm_request_irq(&pdev->dev, sport->txirq, imx_txint, 0,
+               ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
                                       dev_name(&pdev->dev), sport);
                if (ret)
                        return ret;
-
-               /* do not use RTS IRQ on IrDA */
-               if (!USE_IRDA(sport)) {
-                       ret = devm_request_irq(&pdev->dev, sport->rtsirq,
-                                              imx_rtsint, 0,
-                                              dev_name(&pdev->dev), sport);
-                       if (ret)
-                               return ret;
-               }
        } else {
-               ret = devm_request_irq(&pdev->dev, sport->port.irq, imx_int, 0,
+               ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0,
                                       dev_name(&pdev->dev), sport);
                if (ret)
                        return ret;
index 79f9a9eff5455e561d3cdb98e57d0aee16281d38..077377259a2ce459f515c41da7f4e016d2804459 100644 (file)
@@ -782,7 +782,7 @@ static int max3100_probe(struct spi_device *spi)
        pdata = dev_get_platdata(&spi->dev);
        max3100s[i]->crystal = pdata->crystal;
        max3100s[i]->loopback = pdata->loopback;
-       max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;
+       max3100s[i]->poll_time = msecs_to_jiffies(pdata->poll_time);
        if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
                max3100s[i]->poll_time = 1;
        max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
deleted file mode 100644 (file)
index 8fe4501..0000000
+++ /dev/null
@@ -1,1505 +0,0 @@
-/*
- * mfd.c: driver for High Speed UART device of Intel Medfield platform
- *
- * Refer pxa.c, 8250.c and some other drivers in drivers/serial/
- *
- * (C) Copyright 2010 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- */
-
-/* Notes:
- * 1. DMA channel allocation: 0/1 channel are assigned to port 0,
- *    2/3 chan to port 1, 4/5 chan to port 3. Even number chans
- *    are used for RX, odd chans for TX
- *
- * 2. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always
- *    asserted, only when the HW is reset the DDCD and DDSR will
- *    be triggered
- */
-
-#if defined(CONFIG_SERIAL_MFD_HSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/slab.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial_mfd.h>
-#include <linux/dma-mapping.h>
-#include <linux/pci.h>
-#include <linux/nmi.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-#include <linux/pm_runtime.h>
-
-#define HSU_DMA_BUF_SIZE       2048
-
-#define chan_readl(chan, offset)       readl(chan->reg + offset)
-#define chan_writel(chan, offset, val) writel(val, chan->reg + offset)
-
-#define mfd_readl(obj, offset)         readl(obj->reg + offset)
-#define mfd_writel(obj, offset, val)   writel(val, obj->reg + offset)
-
-static int hsu_dma_enable;
-module_param(hsu_dma_enable, int, 0);
-MODULE_PARM_DESC(hsu_dma_enable,
-                "It is a bitmap to set working mode, if bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode.");
-
-struct hsu_dma_buffer {
-       u8              *buf;
-       dma_addr_t      dma_addr;
-       u32             dma_size;
-       u32             ofs;
-};
-
-struct hsu_dma_chan {
-       u32     id;
-       enum dma_data_direction dirt;
-       struct uart_hsu_port    *uport;
-       void __iomem            *reg;
-};
-
-struct uart_hsu_port {
-       struct uart_port        port;
-       unsigned char           ier;
-       unsigned char           lcr;
-       unsigned char           mcr;
-       unsigned int            lsr_break_flag;
-       char                    name[12];
-       int                     index;
-       struct device           *dev;
-
-       struct hsu_dma_chan     *txc;
-       struct hsu_dma_chan     *rxc;
-       struct hsu_dma_buffer   txbuf;
-       struct hsu_dma_buffer   rxbuf;
-       int                     use_dma;        /* flag for DMA/PIO */
-       int                     running;
-       int                     dma_tx_on;
-};
-
-/* Top level data structure of HSU */
-struct hsu_port {
-       void __iomem    *reg;
-       unsigned long   paddr;
-       unsigned long   iolen;
-       u32             irq;
-
-       struct uart_hsu_port    port[3];
-       struct hsu_dma_chan     chans[10];
-
-       struct dentry *debugfs;
-};
-
-static inline unsigned int serial_in(struct uart_hsu_port *up, int offset)
-{
-       unsigned int val;
-
-       if (offset > UART_MSR) {
-               offset <<= 2;
-               val = readl(up->port.membase + offset);
-       } else
-               val = (unsigned int)readb(up->port.membase + offset);
-
-       return val;
-}
-
-static inline void serial_out(struct uart_hsu_port *up, int offset, int value)
-{
-       if (offset > UART_MSR) {
-               offset <<= 2;
-               writel(value, up->port.membase + offset);
-       } else {
-               unsigned char val = value & 0xff;
-               writeb(val, up->port.membase + offset);
-       }
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#define HSU_REGS_BUFSIZE       1024
-
-
-static ssize_t port_show_regs(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos)
-{
-       struct uart_hsu_port *up = file->private_data;
-       char *buf;
-       u32 len = 0;
-       ssize_t ret;
-
-       buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
-       if (!buf)
-               return 0;
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MFD HSU port[%d] regs:\n", up->index);
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "=================================\n");
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "IER: \t\t0x%08x\n", serial_in(up, UART_IER));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "PS: \t\t0x%08x\n", serial_in(up, UART_PS));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
-
-       if (len > HSU_REGS_BUFSIZE)
-               len = HSU_REGS_BUFSIZE;
-
-       ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos)
-{
-       struct hsu_dma_chan *chan = file->private_data;
-       char *buf;
-       u32 len = 0;
-       ssize_t ret;
-
-       buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
-       if (!buf)
-               return 0;
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MFD HSU DMA channel [%d] regs:\n", chan->id);
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "=================================\n");
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
-
-       if (len > HSU_REGS_BUFSIZE)
-               len = HSU_REGS_BUFSIZE;
-
-       ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
-       kfree(buf);
-       return ret;
-}
-
-static const struct file_operations port_regs_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = port_show_regs,
-       .llseek         = default_llseek,
-};
-
-static const struct file_operations dma_regs_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = dma_show_regs,
-       .llseek         = default_llseek,
-};
-
-static int hsu_debugfs_init(struct hsu_port *hsu)
-{
-       int i;
-       char name[32];
-
-       hsu->debugfs = debugfs_create_dir("hsu", NULL);
-       if (!hsu->debugfs)
-               return -ENOMEM;
-
-       for (i = 0; i < 3; i++) {
-               snprintf(name, sizeof(name), "port_%d_regs", i);
-               debugfs_create_file(name, S_IFREG | S_IRUGO,
-                       hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops);
-       }
-
-       for (i = 0; i < 6; i++) {
-               snprintf(name, sizeof(name), "dma_chan_%d_regs", i);
-               debugfs_create_file(name, S_IFREG | S_IRUGO,
-                       hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops);
-       }
-
-       return 0;
-}
-
-static void hsu_debugfs_remove(struct hsu_port *hsu)
-{
-       if (hsu->debugfs)
-               debugfs_remove_recursive(hsu->debugfs);
-}
-
-#else
-static inline int hsu_debugfs_init(struct hsu_port *hsu)
-{
-       return 0;
-}
-
-static inline void hsu_debugfs_remove(struct hsu_port *hsu)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
-
-static void serial_hsu_enable_ms(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-
-       up->ier |= UART_IER_MSI;
-       serial_out(up, UART_IER, up->ier);
-}
-
-static void hsu_dma_tx(struct uart_hsu_port *up)
-{
-       struct circ_buf *xmit = &up->port.state->xmit;
-       struct hsu_dma_buffer *dbuf = &up->txbuf;
-       int count;
-
-       /* test_and_set_bit may be better, but anyway it's in lock protected mode */
-       if (up->dma_tx_on)
-               return;
-
-       /* Update the circ buf info */
-       xmit->tail += dbuf->ofs;
-       xmit->tail &= UART_XMIT_SIZE - 1;
-
-       up->port.icount.tx += dbuf->ofs;
-       dbuf->ofs = 0;
-
-       /* Disable the channel */
-       chan_writel(up->txc, HSU_CH_CR, 0x0);
-
-       if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) {
-               dma_sync_single_for_device(up->port.dev,
-                                          dbuf->dma_addr,
-                                          dbuf->dma_size,
-                                          DMA_TO_DEVICE);
-
-               count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
-               dbuf->ofs = count;
-
-               /* Reprogram the channel */
-               chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail);
-               chan_writel(up->txc, HSU_CH_D0TSR, count);
-
-               /* Reenable the channel */
-               chan_writel(up->txc, HSU_CH_DCR, 0x1
-                                                | (0x1 << 8)
-                                                | (0x1 << 16)
-                                                | (0x1 << 24));
-               up->dma_tx_on = 1;
-               chan_writel(up->txc, HSU_CH_CR, 0x1);
-       }
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
-}
-
-/* The buffer is already cache coherent */
-static void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc,
-                                       struct hsu_dma_buffer *dbuf)
-{
-       dbuf->ofs = 0;
-
-       chan_writel(rxc, HSU_CH_BSR, 32);
-       chan_writel(rxc, HSU_CH_MOTSR, 4);
-
-       chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr);
-       chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size);
-       chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8)
-                                        | (0x1 << 16)
-                                        | (0x1 << 24)  /* timeout bit, see HSU Errata 1 */
-                                        );
-       chan_writel(rxc, HSU_CH_CR, 0x3);
-}
-
-/* Protected by spin_lock_irqsave(port->lock) */
-static void serial_hsu_start_tx(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-
-       if (up->use_dma) {
-               hsu_dma_tx(up);
-       } else if (!(up->ier & UART_IER_THRI)) {
-               up->ier |= UART_IER_THRI;
-               serial_out(up, UART_IER, up->ier);
-       }
-}
-
-static void serial_hsu_stop_tx(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       struct hsu_dma_chan *txc = up->txc;
-
-       if (up->use_dma)
-               chan_writel(txc, HSU_CH_CR, 0x0);
-       else if (up->ier & UART_IER_THRI) {
-               up->ier &= ~UART_IER_THRI;
-               serial_out(up, UART_IER, up->ier);
-       }
-}
-
-/* This is always called in spinlock protected mode, so
- * modify timeout timer is safe here */
-static void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts,
-                       unsigned long *flags)
-{
-       struct hsu_dma_buffer *dbuf = &up->rxbuf;
-       struct hsu_dma_chan *chan = up->rxc;
-       struct uart_port *port = &up->port;
-       struct tty_port *tport = &port->state->port;
-       int count;
-
-       /*
-        * First need to know how many is already transferred,
-        * then check if its a timeout DMA irq, and return
-        * the trail bytes out, push them up and reenable the
-        * channel
-        */
-
-       /* Timeout IRQ, need wait some time, see Errata 2 */
-       if (int_sts & 0xf00)
-               udelay(2);
-
-       /* Stop the channel */
-       chan_writel(chan, HSU_CH_CR, 0x0);
-
-       count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
-       if (!count) {
-               /* Restart the channel before we leave */
-               chan_writel(chan, HSU_CH_CR, 0x3);
-               return;
-       }
-
-       dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
-                       dbuf->dma_size, DMA_FROM_DEVICE);
-
-       /*
-        * Head will only wrap around when we recycle
-        * the DMA buffer, and when that happens, we
-        * explicitly set tail to 0. So head will
-        * always be greater than tail.
-        */
-       tty_insert_flip_string(tport, dbuf->buf, count);
-       port->icount.rx += count;
-
-       dma_sync_single_for_device(up->port.dev, dbuf->dma_addr,
-                       dbuf->dma_size, DMA_FROM_DEVICE);
-
-       /* Reprogram the channel */
-       chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr);
-       chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size);
-       chan_writel(chan, HSU_CH_DCR, 0x1
-                                        | (0x1 << 8)
-                                        | (0x1 << 16)
-                                        | (0x1 << 24)  /* timeout bit, see HSU Errata 1 */
-                                        );
-       spin_unlock_irqrestore(&up->port.lock, *flags);
-       tty_flip_buffer_push(tport);
-       spin_lock_irqsave(&up->port.lock, *flags);
-
-       chan_writel(chan, HSU_CH_CR, 0x3);
-
-}
-
-static void serial_hsu_stop_rx(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       struct hsu_dma_chan *chan = up->rxc;
-
-       if (up->use_dma)
-               chan_writel(chan, HSU_CH_CR, 0x2);
-       else {
-               up->ier &= ~UART_IER_RLSI;
-               up->port.read_status_mask &= ~UART_LSR_DR;
-               serial_out(up, UART_IER, up->ier);
-       }
-}
-
-static inline void receive_chars(struct uart_hsu_port *up, int *status,
-               unsigned long *flags)
-{
-       unsigned int ch, flag;
-       unsigned int max_count = 256;
-
-       do {
-               ch = serial_in(up, UART_RX);
-               flag = TTY_NORMAL;
-               up->port.icount.rx++;
-
-               if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-                                      UART_LSR_FE | UART_LSR_OE))) {
-
-                       dev_warn(up->dev, "We really rush into ERR/BI case"
-                               "status = 0x%02x", *status);
-                       /* For statistics only */
-                       if (*status & UART_LSR_BI) {
-                               *status &= ~(UART_LSR_FE | UART_LSR_PE);
-                               up->port.icount.brk++;
-                               /*
-                                * We do the SysRQ and SAK checking
-                                * here because otherwise the break
-                                * may get masked by ignore_status_mask
-                                * or read_status_mask.
-                                */
-                               if (uart_handle_break(&up->port))
-                                       goto ignore_char;
-                       } else if (*status & UART_LSR_PE)
-                               up->port.icount.parity++;
-                       else if (*status & UART_LSR_FE)
-                               up->port.icount.frame++;
-                       if (*status & UART_LSR_OE)
-                               up->port.icount.overrun++;
-
-                       /* Mask off conditions which should be ignored. */
-                       *status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
-                       if (up->port.cons &&
-                               up->port.cons->index == up->port.line) {
-                               /* Recover the break flag from console xmit */
-                               *status |= up->lsr_break_flag;
-                               up->lsr_break_flag = 0;
-                       }
-#endif
-                       if (*status & UART_LSR_BI) {
-                               flag = TTY_BREAK;
-                       } else if (*status & UART_LSR_PE)
-                               flag = TTY_PARITY;
-                       else if (*status & UART_LSR_FE)
-                               flag = TTY_FRAME;
-               }
-
-               if (uart_handle_sysrq_char(&up->port, ch))
-                       goto ignore_char;
-
-               uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-       ignore_char:
-               *status = serial_in(up, UART_LSR);
-       } while ((*status & UART_LSR_DR) && max_count--);
-
-       spin_unlock_irqrestore(&up->port.lock, *flags);
-       tty_flip_buffer_push(&up->port.state->port);
-       spin_lock_irqsave(&up->port.lock, *flags);
-}
-
-static void transmit_chars(struct uart_hsu_port *up)
-{
-       struct circ_buf *xmit = &up->port.state->xmit;
-       int count;
-
-       if (up->port.x_char) {
-               serial_out(up, UART_TX, up->port.x_char);
-               up->port.icount.tx++;
-               up->port.x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-               serial_hsu_stop_tx(&up->port);
-               return;
-       }
-
-       /* The IRQ is for TX FIFO half-empty */
-       count = up->port.fifosize / 2;
-
-       do {
-               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-
-               up->port.icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
-
-       if (uart_circ_empty(xmit))
-               serial_hsu_stop_tx(&up->port);
-}
-
-static inline void check_modem_status(struct uart_hsu_port *up)
-{
-       int status;
-
-       status = serial_in(up, UART_MSR);
-
-       if ((status & UART_MSR_ANY_DELTA) == 0)
-               return;
-
-       if (status & UART_MSR_TERI)
-               up->port.icount.rng++;
-       if (status & UART_MSR_DDSR)
-               up->port.icount.dsr++;
-       /* We may only get DDCD when HW init and reset */
-       if (status & UART_MSR_DDCD)
-               uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-       /* Will start/stop_tx accordingly */
-       if (status & UART_MSR_DCTS)
-               uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-       wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static irqreturn_t port_irq(int irq, void *dev_id)
-{
-       struct uart_hsu_port *up = dev_id;
-       unsigned int iir, lsr;
-       unsigned long flags;
-
-       if (unlikely(!up->running))
-               return IRQ_NONE;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       if (up->use_dma) {
-               lsr = serial_in(up, UART_LSR);
-               if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
-                                      UART_LSR_FE | UART_LSR_OE)))
-                       dev_warn(up->dev,
-                               "Got lsr irq while using DMA, lsr = 0x%2x\n",
-                               lsr);
-               check_modem_status(up);
-               spin_unlock_irqrestore(&up->port.lock, flags);
-               return IRQ_HANDLED;
-       }
-
-       iir = serial_in(up, UART_IIR);
-       if (iir & UART_IIR_NO_INT) {
-               spin_unlock_irqrestore(&up->port.lock, flags);
-               return IRQ_NONE;
-       }
-
-       lsr = serial_in(up, UART_LSR);
-       if (lsr & UART_LSR_DR)
-               receive_chars(up, &lsr, &flags);
-       check_modem_status(up);
-
-       /* lsr will be renewed during the receive_chars */
-       if (lsr & UART_LSR_THRE)
-               transmit_chars(up);
-
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       return IRQ_HANDLED;
-}
-
-static inline void dma_chan_irq(struct hsu_dma_chan *chan)
-{
-       struct uart_hsu_port *up = chan->uport;
-       unsigned long flags;
-       u32 int_sts;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       if (!up->use_dma || !up->running)
-               goto exit;
-
-       /*
-        * No matter what situation, need read clear the IRQ status
-        * There is a bug, see Errata 5, HSD 2900918
-        */
-       int_sts = chan_readl(chan, HSU_CH_SR);
-
-       /* Rx channel */
-       if (chan->dirt == DMA_FROM_DEVICE)
-               hsu_dma_rx(up, int_sts, &flags);
-
-       /* Tx channel */
-       if (chan->dirt == DMA_TO_DEVICE) {
-               chan_writel(chan, HSU_CH_CR, 0x0);
-               up->dma_tx_on = 0;
-               hsu_dma_tx(up);
-       }
-
-exit:
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       return;
-}
-
-static irqreturn_t dma_irq(int irq, void *dev_id)
-{
-       struct hsu_port *hsu = dev_id;
-       u32 int_sts, i;
-
-       int_sts = mfd_readl(hsu, HSU_GBL_DMAISR);
-
-       /* Currently we only have 6 channels may be used */
-       for (i = 0; i < 6; i++) {
-               if (int_sts & 0x1)
-                       dma_chan_irq(&hsu->chans[i]);
-               int_sts >>= 1;
-       }
-
-       return IRQ_HANDLED;
-}
-
-static unsigned int serial_hsu_tx_empty(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-       unsigned int ret;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       return ret;
-}
-
-static unsigned int serial_hsu_get_mctrl(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned char status;
-       unsigned int ret;
-
-       status = serial_in(up, UART_MSR);
-
-       ret = 0;
-       if (status & UART_MSR_DCD)
-               ret |= TIOCM_CAR;
-       if (status & UART_MSR_RI)
-               ret |= TIOCM_RNG;
-       if (status & UART_MSR_DSR)
-               ret |= TIOCM_DSR;
-       if (status & UART_MSR_CTS)
-               ret |= TIOCM_CTS;
-       return ret;
-}
-
-static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned char mcr = 0;
-
-       if (mctrl & TIOCM_RTS)
-               mcr |= UART_MCR_RTS;
-       if (mctrl & TIOCM_DTR)
-               mcr |= UART_MCR_DTR;
-       if (mctrl & TIOCM_OUT1)
-               mcr |= UART_MCR_OUT1;
-       if (mctrl & TIOCM_OUT2)
-               mcr |= UART_MCR_OUT2;
-       if (mctrl & TIOCM_LOOP)
-               mcr |= UART_MCR_LOOP;
-
-       mcr |= up->mcr;
-
-       serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_hsu_break_ctl(struct uart_port *port, int break_state)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       if (break_state == -1)
-               up->lcr |= UART_LCR_SBC;
-       else
-               up->lcr &= ~UART_LCR_SBC;
-       serial_out(up, UART_LCR, up->lcr);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/*
- * What special to do:
- * 1. chose the 64B fifo mode
- * 2. start dma or pio depends on configuration
- * 3. we only allocate dma memory when needed
- */
-static int serial_hsu_startup(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-
-       pm_runtime_get_sync(up->dev);
-
-       /*
-        * Clear the FIFO buffers and disable them.
-        * (they will be reenabled in set_termios())
-        */
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-                       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-       serial_out(up, UART_FCR, 0);
-
-       /* Clear the interrupt registers. */
-       (void) serial_in(up, UART_LSR);
-       (void) serial_in(up, UART_RX);
-       (void) serial_in(up, UART_IIR);
-       (void) serial_in(up, UART_MSR);
-
-       /* Now, initialize the UART, default is 8n1 */
-       serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       up->port.mctrl |= TIOCM_OUT2;
-       serial_hsu_set_mctrl(&up->port, up->port.mctrl);
-
-       /*
-        * Finally, enable interrupts.  Note: Modem status interrupts
-        * are set via set_termios(), which will be occurring imminently
-        * anyway, so we don't enable them here.
-        */
-       if (!up->use_dma)
-               up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE;
-       else
-               up->ier = 0;
-       serial_out(up, UART_IER, up->ier);
-
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /* DMA init */
-       if (up->use_dma) {
-               struct hsu_dma_buffer *dbuf;
-               struct circ_buf *xmit = &port->state->xmit;
-
-               up->dma_tx_on = 0;
-
-               /* First allocate the RX buffer */
-               dbuf = &up->rxbuf;
-               dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL);
-               if (!dbuf->buf) {
-                       up->use_dma = 0;
-                       goto exit;
-               }
-               dbuf->dma_addr = dma_map_single(port->dev,
-                                               dbuf->buf,
-                                               HSU_DMA_BUF_SIZE,
-                                               DMA_FROM_DEVICE);
-               dbuf->dma_size = HSU_DMA_BUF_SIZE;
-
-               /* Start the RX channel right now */
-               hsu_dma_start_rx_chan(up->rxc, dbuf);
-
-               /* Next init the TX DMA */
-               dbuf = &up->txbuf;
-               dbuf->buf = xmit->buf;
-               dbuf->dma_addr = dma_map_single(port->dev,
-                                              dbuf->buf,
-                                              UART_XMIT_SIZE,
-                                              DMA_TO_DEVICE);
-               dbuf->dma_size = UART_XMIT_SIZE;
-
-               /* This should not be changed all around */
-               chan_writel(up->txc, HSU_CH_BSR, 32);
-               chan_writel(up->txc, HSU_CH_MOTSR, 4);
-               dbuf->ofs = 0;
-       }
-
-exit:
-        /* And clear the interrupt registers again for luck. */
-       (void) serial_in(up, UART_LSR);
-       (void) serial_in(up, UART_RX);
-       (void) serial_in(up, UART_IIR);
-       (void) serial_in(up, UART_MSR);
-
-       up->running = 1;
-       return 0;
-}
-
-static void serial_hsu_shutdown(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-
-       /* Disable interrupts from this port */
-       up->ier = 0;
-       serial_out(up, UART_IER, 0);
-       up->running = 0;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       up->port.mctrl &= ~TIOCM_OUT2;
-       serial_hsu_set_mctrl(&up->port, up->port.mctrl);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /* Disable break condition and FIFOs */
-       serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-                                 UART_FCR_CLEAR_RCVR |
-                                 UART_FCR_CLEAR_XMIT);
-       serial_out(up, UART_FCR, 0);
-
-       pm_runtime_put(up->dev);
-}
-
-static void
-serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
-                      struct ktermios *old)
-{
-       struct uart_hsu_port *up =
-                       container_of(port, struct uart_hsu_port, port);
-       unsigned char cval, fcr = 0;
-       unsigned long flags;
-       unsigned int baud, quot;
-       u32 ps, mul;
-
-       switch (termios->c_cflag & CSIZE) {
-       case CS5:
-               cval = UART_LCR_WLEN5;
-               break;
-       case CS6:
-               cval = UART_LCR_WLEN6;
-               break;
-       case CS7:
-               cval = UART_LCR_WLEN7;
-               break;
-       default:
-       case CS8:
-               cval = UART_LCR_WLEN8;
-               break;
-       }
-
-       /* CMSPAR isn't supported by this driver */
-       termios->c_cflag &= ~CMSPAR;
-
-       if (termios->c_cflag & CSTOPB)
-               cval |= UART_LCR_STOP;
-       if (termios->c_cflag & PARENB)
-               cval |= UART_LCR_PARITY;
-       if (!(termios->c_cflag & PARODD))
-               cval |= UART_LCR_EPAR;
-
-       /*
-        * The base clk is 50Mhz, and the baud rate come from:
-        *      baud = 50M * MUL / (DIV * PS * DLAB)
-        *
-        * For those basic low baud rate we can get the direct
-        * scalar from 2746800, like 115200 = 2746800/24. For those
-        * higher baud rate, we handle them case by case, mainly by
-        * adjusting the MUL/PS registers, and DIV register is kept
-        * as default value 0x3d09 to make things simple
-        */
-       baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
-
-       quot = 1;
-       ps = 0x10;
-       mul = 0x3600;
-       switch (baud) {
-       case 3500000:
-               mul = 0x3345;
-               ps = 0xC;
-               break;
-       case 1843200:
-               mul = 0x2400;
-               break;
-       case 3000000:
-       case 2500000:
-       case 2000000:
-       case 1500000:
-       case 1000000:
-       case 500000:
-               /* mul/ps/quot = 0x9C4/0x10/0x1 will make a 500000 bps */
-               mul = baud / 500000 * 0x9C4;
-               break;
-       default:
-               /* Use uart_get_divisor to get quot for other baud rates */
-               quot = 0;
-       }
-
-       if (!quot)
-               quot = uart_get_divisor(port, baud);
-
-       if ((up->port.uartclk / quot) < (2400 * 16))
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
-       else if ((up->port.uartclk / quot) < (230400 * 16))
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B;
-       else
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B;
-
-       fcr |= UART_FCR_HSU_64B_FIFO;
-
-       /*
-        * Ok, we're now changing the port state.  Do it with
-        * interrupts disabled.
-        */
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       /* Update the per-port timeout */
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-       if (termios->c_iflag & INPCK)
-               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-       if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-               up->port.read_status_mask |= UART_LSR_BI;
-
-       /* Characters to ignore */
-       up->port.ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-       if (termios->c_iflag & IGNBRK) {
-               up->port.ignore_status_mask |= UART_LSR_BI;
-               /*
-                * If we're ignoring parity and break indicators,
-                * ignore overruns too (for real raw support).
-                */
-               if (termios->c_iflag & IGNPAR)
-                       up->port.ignore_status_mask |= UART_LSR_OE;
-       }
-
-       /* Ignore all characters if CREAD is not set */
-       if ((termios->c_cflag & CREAD) == 0)
-               up->port.ignore_status_mask |= UART_LSR_DR;
-
-       /*
-        * CTS flow control flag and modem status interrupts, disable
-        * MSI by default
-        */
-       up->ier &= ~UART_IER_MSI;
-       if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-               up->ier |= UART_IER_MSI;
-
-       serial_out(up, UART_IER, up->ier);
-
-       if (termios->c_cflag & CRTSCTS)
-               up->mcr |= UART_MCR_AFE | UART_MCR_RTS;
-       else
-               up->mcr &= ~UART_MCR_AFE;
-
-       serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
-       serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
-       serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
-       serial_out(up, UART_LCR, cval);                 /* reset DLAB */
-       serial_out(up, UART_MUL, mul);                  /* set MUL */
-       serial_out(up, UART_PS, ps);                    /* set PS */
-       up->lcr = cval;                                 /* Save LCR */
-       serial_hsu_set_mctrl(&up->port, up->port.mctrl);
-       serial_out(up, UART_FCR, fcr);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_hsu_pm(struct uart_port *port, unsigned int state,
-             unsigned int oldstate)
-{
-}
-
-static void serial_hsu_release_port(struct uart_port *port)
-{
-}
-
-static int serial_hsu_request_port(struct uart_port *port)
-{
-       return 0;
-}
-
-static void serial_hsu_config_port(struct uart_port *port, int flags)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       up->port.type = PORT_MFD;
-}
-
-static int
-serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-       /* We don't want the core code to modify any port params */
-       return -EINVAL;
-}
-
-static const char *
-serial_hsu_type(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       return up->name;
-}
-
-/* Mainly for uart console use */
-static struct uart_hsu_port *serial_hsu_ports[3];
-static struct uart_driver serial_hsu_reg;
-
-#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/* Wait for transmitter & holding register to empty */
-static inline void wait_for_xmitr(struct uart_hsu_port *up)
-{
-       unsigned int status, tmout = 1000;
-
-       /* Wait up to 1ms for the character to be sent. */
-       do {
-               status = serial_in(up, UART_LSR);
-
-               if (status & UART_LSR_BI)
-                       up->lsr_break_flag = UART_LSR_BI;
-
-               if (--tmout == 0)
-                       break;
-               udelay(1);
-       } while (!(status & BOTH_EMPTY));
-
-       /* Wait up to 1s for flow control if necessary */
-       if (up->port.flags & UPF_CONS_FLOW) {
-               tmout = 1000000;
-               while (--tmout &&
-                      ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-                       udelay(1);
-       }
-}
-
-static void serial_hsu_console_putchar(struct uart_port *port, int ch)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-
-       wait_for_xmitr(up);
-       serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *     The console_lock must be held when we get here.
- */
-static void
-serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
-{
-       struct uart_hsu_port *up = serial_hsu_ports[co->index];
-       unsigned long flags;
-       unsigned int ier;
-       int locked = 1;
-
-       touch_nmi_watchdog();
-
-       local_irq_save(flags);
-       if (up->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress) {
-               locked = spin_trylock(&up->port.lock);
-       } else
-               spin_lock(&up->port.lock);
-
-       /* First save the IER then disable the interrupts */
-       ier = serial_in(up, UART_IER);
-       serial_out(up, UART_IER, 0);
-
-       uart_console_write(&up->port, s, count, serial_hsu_console_putchar);
-
-       /*
-        * Finally, wait for transmitter to become empty
-        * and restore the IER
-        */
-       wait_for_xmitr(up);
-       serial_out(up, UART_IER, ier);
-
-       if (locked)
-               spin_unlock(&up->port.lock);
-       local_irq_restore(flags);
-}
-
-static struct console serial_hsu_console;
-
-static int __init
-serial_hsu_console_setup(struct console *co, char *options)
-{
-       struct uart_hsu_port *up;
-       int baud = 115200;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       if (co->index == -1 || co->index >= serial_hsu_reg.nr)
-               co->index = 0;
-       up = serial_hsu_ports[co->index];
-       if (!up)
-               return -ENODEV;
-
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-       return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_hsu_console = {
-       .name           = "ttyMFD",
-       .write          = serial_hsu_console_write,
-       .device         = uart_console_device,
-       .setup          = serial_hsu_console_setup,
-       .flags          = CON_PRINTBUFFER,
-       .index          = -1,
-       .data           = &serial_hsu_reg,
-};
-
-#define SERIAL_HSU_CONSOLE     (&serial_hsu_console)
-#else
-#define SERIAL_HSU_CONSOLE     NULL
-#endif
-
-static struct uart_ops serial_hsu_pops = {
-       .tx_empty       = serial_hsu_tx_empty,
-       .set_mctrl      = serial_hsu_set_mctrl,
-       .get_mctrl      = serial_hsu_get_mctrl,
-       .stop_tx        = serial_hsu_stop_tx,
-       .start_tx       = serial_hsu_start_tx,
-       .stop_rx        = serial_hsu_stop_rx,
-       .enable_ms      = serial_hsu_enable_ms,
-       .break_ctl      = serial_hsu_break_ctl,
-       .startup        = serial_hsu_startup,
-       .shutdown       = serial_hsu_shutdown,
-       .set_termios    = serial_hsu_set_termios,
-       .pm             = serial_hsu_pm,
-       .type           = serial_hsu_type,
-       .release_port   = serial_hsu_release_port,
-       .request_port   = serial_hsu_request_port,
-       .config_port    = serial_hsu_config_port,
-       .verify_port    = serial_hsu_verify_port,
-};
-
-static struct uart_driver serial_hsu_reg = {
-       .owner          = THIS_MODULE,
-       .driver_name    = "MFD serial",
-       .dev_name       = "ttyMFD",
-       .major          = TTY_MAJOR,
-       .minor          = 128,
-       .nr             = 3,
-       .cons           = SERIAL_HSU_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       void *priv = pci_get_drvdata(pdev);
-       struct uart_hsu_port *up;
-
-       /* Make sure this is not the internal dma controller */
-       if (priv && (pdev->device != 0x081E)) {
-               up = priv;
-               uart_suspend_port(&serial_hsu_reg, &up->port);
-       }
-
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-        return 0;
-}
-
-static int serial_hsu_resume(struct pci_dev *pdev)
-{
-       void *priv = pci_get_drvdata(pdev);
-       struct uart_hsu_port *up;
-       int ret;
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-
-       ret = pci_enable_device(pdev);
-       if (ret)
-               dev_warn(&pdev->dev,
-                       "HSU: can't re-enable device, try to continue\n");
-
-       if (priv && (pdev->device != 0x081E)) {
-               up = priv;
-               uart_resume_port(&serial_hsu_reg, &up->port);
-       }
-       return 0;
-}
-
-static int serial_hsu_runtime_idle(struct device *dev)
-{
-       pm_schedule_suspend(dev, 500);
-       return -EBUSY;
-}
-
-static int serial_hsu_runtime_suspend(struct device *dev)
-{
-       return 0;
-}
-
-static int serial_hsu_runtime_resume(struct device *dev)
-{
-       return 0;
-}
-#else
-#define serial_hsu_suspend             NULL
-#define serial_hsu_resume              NULL
-#define serial_hsu_runtime_idle                NULL
-#define serial_hsu_runtime_suspend     NULL
-#define serial_hsu_runtime_resume      NULL
-#endif
-
-static const struct dev_pm_ops serial_hsu_pm_ops = {
-       .runtime_suspend = serial_hsu_runtime_suspend,
-       .runtime_resume = serial_hsu_runtime_resume,
-       .runtime_idle = serial_hsu_runtime_idle,
-};
-
-/* temp global pointer before we settle down on using one or four PCI dev */
-static struct hsu_port *phsu;
-
-static int serial_hsu_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
-{
-       struct uart_hsu_port *uport;
-       int index, ret;
-
-       printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n",
-               pdev->vendor, pdev->device);
-
-       switch (pdev->device) {
-       case 0x081B:
-               index = 0;
-               break;
-       case 0x081C:
-               index = 1;
-               break;
-       case 0x081D:
-               index = 2;
-               break;
-       case 0x081E:
-               /* internal DMA controller */
-               index = 3;
-               break;
-       default:
-               dev_err(&pdev->dev, "HSU: out of index!");
-               return -ENODEV;
-       }
-
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-
-       if (index == 3) {
-               /* DMA controller */
-               ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu);
-               if (ret) {
-                       dev_err(&pdev->dev, "can not get IRQ\n");
-                       goto err_disable;
-               }
-               pci_set_drvdata(pdev, phsu);
-       } else {
-               /* UART port 0~2 */
-               uport = &phsu->port[index];
-               uport->port.irq = pdev->irq;
-               uport->port.dev = &pdev->dev;
-               uport->dev = &pdev->dev;
-
-               ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport);
-               if (ret) {
-                       dev_err(&pdev->dev, "can not get IRQ\n");
-                       goto err_disable;
-               }
-               uart_add_one_port(&serial_hsu_reg, &uport->port);
-
-               pci_set_drvdata(pdev, uport);
-       }
-
-       pm_runtime_put_noidle(&pdev->dev);
-       pm_runtime_allow(&pdev->dev);
-
-       return 0;
-
-err_disable:
-       pci_disable_device(pdev);
-       return ret;
-}
-
-static void hsu_global_init(void)
-{
-       struct hsu_port *hsu;
-       struct uart_hsu_port *uport;
-       struct hsu_dma_chan *dchan;
-       int i, ret;
-
-       hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL);
-       if (!hsu)
-               return;
-
-       /* Get basic io resource and map it */
-       hsu->paddr = 0xffa28000;
-       hsu->iolen = 0x1000;
-
-       if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global")))
-               pr_warn("HSU: error in request mem region\n");
-
-       hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen);
-       if (!hsu->reg) {
-               pr_err("HSU: error in ioremap\n");
-               ret = -ENOMEM;
-               goto err_free_region;
-       }
-
-       /* Initialise the 3 UART ports */
-       uport = hsu->port;
-       for (i = 0; i < 3; i++) {
-               uport->port.type = PORT_MFD;
-               uport->port.iotype = UPIO_MEM;
-               uport->port.mapbase = (resource_size_t)hsu->paddr
-                                       + HSU_PORT_REG_OFFSET
-                                       + i * HSU_PORT_REG_LENGTH;
-               uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET
-                                       + i * HSU_PORT_REG_LENGTH;
-
-               sprintf(uport->name, "hsu_port%d", i);
-               uport->port.fifosize = 64;
-               uport->port.ops = &serial_hsu_pops;
-               uport->port.line = i;
-               uport->port.flags = UPF_IOREMAP;
-               /* set the scalable maxim support rate to 2746800 bps */
-               uport->port.uartclk = 115200 * 24 * 16;
-
-               uport->running = 0;
-               uport->txc = &hsu->chans[i * 2];
-               uport->rxc = &hsu->chans[i * 2 + 1];
-
-               serial_hsu_ports[i] = uport;
-               uport->index = i;
-
-               if (hsu_dma_enable & (1<<i))
-                       uport->use_dma = 1;
-               else
-                       uport->use_dma = 0;
-
-               uport++;
-       }
-
-       /* Initialise 6 dma channels */
-       dchan = hsu->chans;
-       for (i = 0; i < 6; i++) {
-               dchan->id = i;
-               dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-               dchan->uport = &hsu->port[i/2];
-               dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +
-                               i * HSU_DMA_CHANS_REG_LENGTH;
-
-               dchan++;
-       }
-
-       phsu = hsu;
-       hsu_debugfs_init(hsu);
-       return;
-
-err_free_region:
-       release_mem_region(hsu->paddr, hsu->iolen);
-       kfree(hsu);
-       return;
-}
-
-static void serial_hsu_remove(struct pci_dev *pdev)
-{
-       void *priv = pci_get_drvdata(pdev);
-       struct uart_hsu_port *up;
-
-       if (!priv)
-               return;
-
-       pm_runtime_forbid(&pdev->dev);
-       pm_runtime_get_noresume(&pdev->dev);
-
-       /* For port 0/1/2, priv is the address of uart_hsu_port */
-       if (pdev->device != 0x081E) {
-               up = priv;
-               uart_remove_one_port(&serial_hsu_reg, &up->port);
-       }
-
-       free_irq(pdev->irq, priv);
-       pci_disable_device(pdev);
-}
-
-/* First 3 are UART ports, and the 4th is the DMA */
-static const struct pci_device_id pci_ids[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) },
-       {},
-};
-
-static struct pci_driver hsu_pci_driver = {
-       .name =         "HSU serial",
-       .id_table =     pci_ids,
-       .probe =        serial_hsu_probe,
-       .remove =       serial_hsu_remove,
-       .suspend =      serial_hsu_suspend,
-       .resume =       serial_hsu_resume,
-       .driver = {
-               .pm = &serial_hsu_pm_ops,
-       },
-};
-
-static int __init hsu_pci_init(void)
-{
-       int ret;
-
-       hsu_global_init();
-
-       ret = uart_register_driver(&serial_hsu_reg);
-       if (ret)
-               return ret;
-
-       return pci_register_driver(&hsu_pci_driver);
-}
-
-static void __exit hsu_pci_exit(void)
-{
-       pci_unregister_driver(&hsu_pci_driver);
-       uart_unregister_driver(&serial_hsu_reg);
-
-       hsu_debugfs_remove(phsu);
-
-       kfree(phsu);
-}
-
-module_init(hsu_pci_init);
-module_exit(hsu_pci_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(pci, pci_ids);
index d1298b6cc68e4e6f1f610959f57f94cf350650fd..20a863bde78de3c9a1d07b29f158ff6e04ae7dc6 100644 (file)
@@ -1155,14 +1155,14 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
        return 0;
 }
 
-static bool mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
+static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
 {
        enum mctrl_gpio_idx i;
        struct gpio_desc *gpiod;
 
        s->gpios = mctrl_gpio_init(dev, 0);
-       if (IS_ERR_OR_NULL(s->gpios))
-               return false;
+       if (IS_ERR(s->gpios))
+               return PTR_ERR(s->gpios);
 
        /* Block (enabled before) DMA option if RTS or CTS is GPIO line */
        if (!RTS_AT_AUART() || !CTS_AT_AUART()) {
@@ -1180,7 +1180,7 @@ static bool mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
                        s->gpio_irq[i] = -EINVAL;
        }
 
-       return true;
+       return 0;
 }
 
 static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s)
@@ -1276,9 +1276,11 @@ static int mxs_auart_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, s);
 
-       if (!mxs_auart_init_gpios(s, &pdev->dev))
-               dev_err(&pdev->dev,
-                       "Failed to initialize GPIOs. The serial port may not work as expected\n");
+       ret = mxs_auart_init_gpios(s, &pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
+               return ret;
+       }
 
        /*
         * Get the GPIO lines IRQ
index 6a1055ae343727e964cbb6af44909b42cd526afb..8379e3fa01625d14ae69f63053d0da26d53b3276 100644 (file)
@@ -1118,8 +1118,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
 
                cprev = cnow;
        }
-
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->delta_msr_wait, &wait);
 
        return ret;
@@ -1809,6 +1808,52 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
        return ports + idx;
 }
 
+/**
+ *     uart_parse_earlycon - Parse earlycon options
+ *     @p:       ptr to 2nd field (ie., just beyond '<name>,')
+ *     @iotype:  ptr for decoded iotype (out)
+ *     @addr:    ptr for decoded mapbase/iobase (out)
+ *     @options: ptr for <options> field; NULL if not present (out)
+ *
+ *     Decodes earlycon kernel command line parameters of the form
+ *        earlycon=<name>,io|mmio|mmio32,<addr>,<options>
+ *        console=<name>,io|mmio|mmio32,<addr>,<options>
+ *
+ *     The optional form
+ *        earlycon=<name>,0x<addr>,<options>
+ *        console=<name>,0x<addr>,<options>
+ *     is also accepted; the returned @iotype will be UPIO_MEM.
+ *
+ *     Returns 0 on success or -EINVAL on failure
+ */
+int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
+                       char **options)
+{
+       if (strncmp(p, "mmio,", 5) == 0) {
+               *iotype = UPIO_MEM;
+               p += 5;
+       } else if (strncmp(p, "mmio32,", 7) == 0) {
+               *iotype = UPIO_MEM32;
+               p += 7;
+       } else if (strncmp(p, "io,", 3) == 0) {
+               *iotype = UPIO_PORT;
+               p += 3;
+       } else if (strncmp(p, "0x", 2) == 0) {
+               *iotype = UPIO_MEM;
+       } else {
+               return -EINVAL;
+       }
+
+       *addr = simple_strtoul(p, NULL, 0);
+       p = strchr(p, ',');
+       if (p)
+               p++;
+
+       *options = p;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(uart_parse_earlycon);
+
 /**
  *     uart_parse_options - Parse serial port baud/parity/bits/flow control.
  *     @options: pointer to option string
index a38596c5194e4b6f6a1feb26183e4b9cd8366f2f..0ec756c62bcf1f859a7692c9cf2fe580cff8b56f 100644 (file)
@@ -48,9 +48,6 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
        int value_array[UART_GPIO_MAX];
        unsigned int count = 0;
 
-       if (IS_ERR_OR_NULL(gpios))
-               return;
-
        for (i = 0; i < UART_GPIO_MAX; i++)
                if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
                    mctrl_gpios_desc[i].dir_out) {
@@ -65,10 +62,7 @@ EXPORT_SYMBOL_GPL(mctrl_gpio_set);
 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
                                      enum mctrl_gpio_idx gidx)
 {
-       if (!IS_ERR_OR_NULL(gpios) && !IS_ERR_OR_NULL(gpios->gpio[gidx]))
-               return gpios->gpio[gidx];
-       else
-               return NULL;
+       return gpios->gpio[gidx];
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod);
 
@@ -76,15 +70,8 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
 {
        enum mctrl_gpio_idx i;
 
-       /*
-        * return it unchanged if the structure is not allocated
-        */
-       if (IS_ERR_OR_NULL(gpios))
-               return *mctrl;
-
        for (i = 0; i < UART_GPIO_MAX; i++) {
-               if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
-                   !mctrl_gpios_desc[i].dir_out) {
+               if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) {
                        if (gpiod_get_value(gpios->gpio[i]))
                                *mctrl |= mctrl_gpios_desc[i].mctrl;
                        else
@@ -100,34 +87,26 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
 {
        struct mctrl_gpios *gpios;
        enum mctrl_gpio_idx i;
-       int err;
 
        gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL);
        if (!gpios)
                return ERR_PTR(-ENOMEM);
 
        for (i = 0; i < UART_GPIO_MAX; i++) {
-               gpios->gpio[i] = devm_gpiod_get_index(dev,
-                                                     mctrl_gpios_desc[i].name,
-                                                     idx);
-
-               /*
-                * The GPIOs are maybe not all filled,
-                * this is not an error.
-                */
-               if (IS_ERR_OR_NULL(gpios->gpio[i]))
-                       continue;
+               enum gpiod_flags flags;
 
                if (mctrl_gpios_desc[i].dir_out)
-                       err = gpiod_direction_output(gpios->gpio[i], 0);
+                       flags = GPIOD_OUT_LOW;
                else
-                       err = gpiod_direction_input(gpios->gpio[i]);
-               if (err) {
-                       dev_dbg(dev, "Unable to set direction for %s GPIO",
-                               mctrl_gpios_desc[i].name);
-                       devm_gpiod_put(dev, gpios->gpio[i]);
-                       gpios->gpio[i] = NULL;
-               }
+                       flags = GPIOD_IN;
+
+               gpios->gpio[i] =
+                       devm_gpiod_get_index_optional(dev,
+                                                     mctrl_gpios_desc[i].name,
+                                                     idx, flags);
+
+               if (IS_ERR(gpios->gpio[i]))
+                       return ERR_CAST(gpios->gpio[i]);
        }
 
        return gpios;
@@ -138,9 +117,6 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
        enum mctrl_gpio_idx i;
 
-       if (IS_ERR_OR_NULL(gpios))
-               return;
-
        for (i = 0; i < UART_GPIO_MAX; i++)
                if (!IS_ERR_OR_NULL(gpios->gpio[i]))
                        devm_gpiod_put(dev, gpios->gpio[i]);
index bca975f5093b73fd5ebf3e0f4ec8c42e97dfea35..582d2729f7008078064da5ddec8bc456b5102003 100644 (file)
@@ -493,6 +493,8 @@ static int sprd_verify_port(struct uart_port *port,
                return -EINVAL;
        if (port->irq != ser->irq)
                return -EINVAL;
+       if (port->iotype != ser->io_type)
+               return -EINVAL;
        return 0;
 }
 
@@ -707,7 +709,7 @@ static int sprd_probe(struct platform_device *pdev)
        up->dev = &pdev->dev;
        up->line = index;
        up->type = PORT_SPRD;
-       up->iotype = SERIAL_IO_PORT;
+       up->iotype = UPIO_MEM;
        up->uartclk = SPRD_DEF_RATE;
        up->fifosize = SPRD_FIFO_SIZE;
        up->ops = &serial_sprd_ops;
@@ -754,6 +756,7 @@ static int sprd_probe(struct platform_device *pdev)
        return ret;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int sprd_suspend(struct device *dev)
 {
        struct sprd_uart_port *sup = dev_get_drvdata(dev);
@@ -771,6 +774,7 @@ static int sprd_resume(struct device *dev)
 
        return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume);
 
index cff531a51a783f8501bae180fd5788ce45a00c34..8f9c5430f4706df7890327ca3cd31041c629ebaa 100644 (file)
@@ -1154,7 +1154,8 @@ static int __init cdns_uart_console_setup(struct console *co, char *options)
                return -EINVAL;
 
        if (!port->mapbase) {
-               pr_debug("console on ttyPS%i not present\n", co->index);
+               pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n",
+                        co->index);
                return -ENODEV;
        }
 
index 6e00572cbeb9386bd357a5ec466e5c2eb259fc4c..edf17b4e385fe88f6e222649ac27d33c48c246ce 100644 (file)
@@ -1237,7 +1237,7 @@ static void default_attr(struct vc_data *vc)
 
 struct rgb { u8 r; u8 g; u8 b; };
 
-struct rgb rgb_from_256(int i)
+static struct rgb rgb_from_256(int i)
 {
        struct rgb c;
        if (i < 8) {            /* Standard colours. */
@@ -1573,7 +1573,7 @@ static void setterm_command(struct vc_data *vc)
                case 11: /* set bell duration in msec */
                        if (vc->vc_npar >= 1)
                                vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
-                                       vc->vc_par[1] * HZ / 1000 : 0;
+                                       msecs_to_jiffies(vc->vc_par[1]) : 0;
                        else
                                vc->vc_bell_duration = DEFAULT_BELL_DURATION;
                        break;
index 2bd78e2ac8ecba07dbf42788b6c61506ee8b2b20..97d5a74558a3a4477e3c5cfb29dd88591fefbe92 100644 (file)
@@ -388,7 +388,7 @@ int vt_ioctl(struct tty_struct *tty,
                 * Generate the tone for the appropriate number of ticks.
                 * If the time is zero, turn off sound ourselves.
                 */
-               ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
+               ticks = msecs_to_jiffies((arg >> 16) & 0xffff);
                count = ticks ? (arg & 0xffff) : 0;
                if (count)
                        count = PIT_TICK_RATE / count;
diff --git a/include/linux/dma/hsu.h b/include/linux/dma/hsu.h
new file mode 100644 (file)
index 0000000..234393a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DMA_HSU_H
+#define _DMA_HSU_H
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <linux/platform_data/dma-hsu.h>
+
+struct hsu_dma;
+
+/**
+ * struct hsu_dma_chip - representation of HSU DMA hardware
+ * @dev:                struct device of the DMA controller
+ * @irq:                irq line
+ * @regs:               memory mapped I/O space
+ * @length:             I/O space length
+ * @offset:             offset of the I/O space where registers are located
+ * @hsu:                struct hsu_dma that is filed by ->probe()
+ * @pdata:              platform data for the DMA controller if provided
+ */
+struct hsu_dma_chip {
+       struct device                   *dev;
+       int                             irq;
+       void __iomem                    *regs;
+       unsigned int                    length;
+       unsigned int                    offset;
+       struct hsu_dma                  *hsu;
+       struct hsu_dma_platform_data    *pdata;
+};
+
+/* Export to the internal users */
+irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
+
+/* Export to the platform drivers */
+int hsu_dma_probe(struct hsu_dma_chip *chip);
+int hsu_dma_remove(struct hsu_dma_chip *chip);
+
+#endif /* _DMA_HSU_H */
diff --git a/include/linux/platform_data/dma-hsu.h b/include/linux/platform_data/dma-hsu.h
new file mode 100644 (file)
index 0000000..8a1f6a4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PLATFORM_DATA_DMA_HSU_H
+#define _PLATFORM_DATA_DMA_HSU_H
+
+#include <linux/device.h>
+
+struct hsu_dma_slave {
+       struct device   *dma_dev;
+       int             chan_id;
+};
+
+struct hsu_dma_platform_data {
+       unsigned short  nr_channels;
+};
+
+#endif /* _PLATFORM_DATA_DMA_HSU_H */
index 3cc2e3c40914dd3b29b5f68d7c5efd675c2d229b..a938eba2f18e619c7e67696352904457ac54dead 100644 (file)
 #define ASMARM_ARCH_UART_H
 
 #define IMXUART_HAVE_RTSCTS (1<<0)
-#define IMXUART_IRDA        (1<<1)
 
 struct imxuart_platform_data {
        unsigned int flags;
-       void (*irda_enable)(int enable);
-       unsigned int irda_inv_rx:1;
-       unsigned int irda_inv_tx:1;
-       unsigned short transceiver_delay;
 };
 
 #endif
index d10965f0d8a4af6526a07046ba040ae9708279a4..b0148e7bcbfa0ad8bc5686f2ea8d60b5c663f99a 100644 (file)
@@ -354,6 +354,8 @@ early_param("earlycon", name ## _setup_earlycon);
 
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
                                   struct console *c);
+int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
+                       char **options);
 void uart_parse_options(char *options, int *baud, int *parity, int *bits,
                        int *flow);
 int uart_set_options(struct uart_port *port, struct console *co, int baud,
diff --git a/include/linux/serial_mfd.h b/include/linux/serial_mfd.h
deleted file mode 100644 (file)
index 2b071e0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _SERIAL_MFD_H_
-#define _SERIAL_MFD_H_
-
-/* HW register offset definition */
-#define UART_FOR       0x08
-#define UART_PS                0x0C
-#define UART_MUL       0x0D
-#define UART_DIV       0x0E
-
-#define HSU_GBL_IEN    0x0
-#define HSU_GBL_IST    0x4
-
-#define HSU_GBL_INT_BIT_PORT0  0x0
-#define HSU_GBL_INT_BIT_PORT1  0x1
-#define HSU_GBL_INT_BIT_PORT2  0x2
-#define HSU_GBL_INT_BIT_IRI    0x3
-#define HSU_GBL_INT_BIT_HDLC   0x4
-#define HSU_GBL_INT_BIT_DMA    0x5
-
-#define HSU_GBL_ISR    0x8
-#define HSU_GBL_DMASR  0x400
-#define HSU_GBL_DMAISR 0x404
-
-#define HSU_PORT_REG_OFFSET    0x80
-#define HSU_PORT0_REG_OFFSET   0x80
-#define HSU_PORT1_REG_OFFSET   0x100
-#define HSU_PORT2_REG_OFFSET   0x180
-#define HSU_PORT_REG_LENGTH    0x80
-
-#define HSU_DMA_CHANS_REG_OFFSET       0x500
-#define HSU_DMA_CHANS_REG_LENGTH       0x40
-
-#define HSU_CH_SR              0x0     /* channel status reg */
-#define HSU_CH_CR              0x4     /* control reg */
-#define HSU_CH_DCR             0x8     /* descriptor control reg */
-#define HSU_CH_BSR             0x10    /* max fifo buffer size reg */
-#define HSU_CH_MOTSR           0x14    /* minimum ocp transfer size */
-#define HSU_CH_D0SAR           0x20    /* desc 0 start addr */
-#define HSU_CH_D0TSR           0x24    /* desc 0 transfer size */
-#define HSU_CH_D1SAR           0x28
-#define HSU_CH_D1TSR           0x2C
-#define HSU_CH_D2SAR           0x30
-#define HSU_CH_D2TSR           0x34
-#define HSU_CH_D3SAR           0x38
-#define HSU_CH_D3TSR           0x3C
-
-#endif
index 00adb01fa5f38f53858ea2bb265f2b040948f4cf..e9b4cb0cd7edae5aaf029288db27fe56a8ff05c5 100644 (file)
 #define UART_FCR_PXAR16        0x80    /* receive FIFO threshold = 16 */
 #define UART_FCR_PXAR32        0xc0    /* receive FIFO threshold = 32 */
 
-/*
- * Intel MID on-chip HSU (High Speed UART) defined bits
- */
-#define UART_FCR_HSU_64_1B     0x00    /* receive FIFO treshold = 1 */
-#define UART_FCR_HSU_64_16B    0x40    /* receive FIFO treshold = 16 */
-#define UART_FCR_HSU_64_32B    0x80    /* receive FIFO treshold = 32 */
-#define UART_FCR_HSU_64_56B    0xc0    /* receive FIFO treshold = 56 */
-
-#define UART_FCR_HSU_16_1B     0x00    /* receive FIFO treshold = 1 */
-#define UART_FCR_HSU_16_4B     0x40    /* receive FIFO treshold = 4 */
-#define UART_FCR_HSU_16_8B     0x80    /* receive FIFO treshold = 8 */
-#define UART_FCR_HSU_16_14B    0xc0    /* receive FIFO treshold = 14 */
-
-#define UART_FCR_HSU_64B_FIFO  0x20    /* chose 64 bytes FIFO */
-#define UART_FCR_HSU_16B_FIFO  0x00    /* chose 16 bytes FIFO */
-
-#define UART_FCR_HALF_EMPT_TXI 0x00    /* trigger TX_EMPT IRQ for half empty */
-#define UART_FCR_FULL_EMPT_TXI 0x08    /* trigger TX_EMPT IRQ for full empty */
-
 /*
  * These register definitions are for the 16C950
  */
index bb0635bd74f26a2ecb9f651de9e0c4113e4f2476..26f899809539abb4743b9024e382aad19702588a 100644 (file)
@@ -2480,7 +2480,6 @@ void register_console(struct console *newcon)
                    newcon->setup(newcon, console_cmdline[i].options) != 0)
                        break;
                newcon->flags |= CON_ENABLED;
-               newcon->index = c->index;
                if (i == selected_console) {
                        newcon->flags |= CON_CONSDEV;
                        preferred_console = selected_console;