Browse Source

Merge 4.0-rc3 into tty-testing

This resolves a merge issue in drivers/tty/serial/8250/8250_pci.c

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Greg Kroah-Hartman 10 years ago
parent
commit
becba85f0e
40 changed files with 1422 additions and 2132 deletions
  1. 0 4
      arch/x86/Kconfig.debug
  2. 0 3
      arch/x86/include/asm/intel-mid.h
  3. 0 6
      arch/x86/kernel/early_printk.c
  4. 0 1
      arch/x86/platform/intel-mid/Makefile
  5. 0 112
      arch/x86/platform/intel-mid/early_printk_intel_mid.c
  6. 2 0
      drivers/dma/Kconfig
  7. 1 0
      drivers/dma/Makefile
  8. 14 0
      drivers/dma/hsu/Kconfig
  9. 5 0
      drivers/dma/hsu/Makefile
  10. 504 0
      drivers/dma/hsu/hsu.c
  11. 118 0
      drivers/dma/hsu/hsu.h
  12. 123 0
      drivers/dma/hsu/pci.c
  13. 2 2
      drivers/tty/serial/8250/8250_core.c
  14. 11 4
      drivers/tty/serial/8250/8250_dw.c
  15. 198 16
      drivers/tty/serial/8250/8250_pci.c
  16. 3 13
      drivers/tty/serial/Kconfig
  17. 0 1
      drivers/tty/serial/Makefile
  18. 130 105
      drivers/tty/serial/amba-pl011.c
  19. 1 1
      drivers/tty/serial/ar933x_uart.c
  20. 17 12
      drivers/tty/serial/atmel_serial.c
  21. 2 2
      drivers/tty/serial/bcm63xx_uart.c
  22. 2 0
      drivers/tty/serial/clps711x.c
  23. 13 26
      drivers/tty/serial/earlycon.c
  24. 121 196
      drivers/tty/serial/imx.c
  25. 1 1
      drivers/tty/serial/max3100.c
  26. 0 1505
      drivers/tty/serial/mfd.c
  27. 9 7
      drivers/tty/serial/mxs-auart.c
  28. 47 2
      drivers/tty/serial/serial_core.c
  29. 13 36
      drivers/tty/serial/serial_mctrl_gpio.c
  30. 5 1
      drivers/tty/serial/sprd_serial.c
  31. 2 1
      drivers/tty/serial/xilinx_uartps.c
  32. 2 2
      drivers/tty/vt/vt.c
  33. 1 1
      drivers/tty/vt/vt_ioctl.c
  34. 48 0
      include/linux/dma/hsu.h
  35. 25 0
      include/linux/platform_data/dma-hsu.h
  36. 0 5
      include/linux/platform_data/serial-imx.h
  37. 2 0
      include/linux/serial_core.h
  38. 0 47
      include/linux/serial_mfd.h
  39. 0 19
      include/uapi/linux/serial_reg.h
  40. 0 1
      kernel/printk/printk.c

+ 0 - 4
arch/x86/Kconfig.debug

@@ -43,10 +43,6 @@ config EARLY_PRINTK
 	  with klogd/syslogd or the X server. You should normally N here,
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
 	  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
 config EARLY_PRINTK_DBGP
 	bool "Early printk via EHCI debug port"
 	bool "Early printk via EHCI debug port"
 	depends on EARLY_PRINTK && PCI
 	depends on EARLY_PRINTK && PCI

+ 0 - 3
arch/x86/include/asm/intel-mid.h

@@ -136,9 +136,6 @@ extern enum intel_mid_timer_options intel_mid_timer_options;
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	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_create(void);
 extern void intel_scu_devices_destroy(void);
 extern void intel_scu_devices_destroy(void);
 
 

+ 0 - 6
arch/x86/kernel/early_printk.c

@@ -375,12 +375,6 @@ static int __init setup_early_printk(char *buf)
 		if (!strncmp(buf, "xen", 3))
 		if (!strncmp(buf, "xen", 3))
 			early_console_register(&xenboot_console, keep);
 			early_console_register(&xenboot_console, keep);
 #endif
 #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
 #ifdef CONFIG_EARLY_PRINTK_EFI
 		if (!strncmp(buf, "efi", 3))
 		if (!strncmp(buf, "efi", 3))
 			early_console_register(&early_efi_console, keep);
 			early_console_register(&early_efi_console, keep);

+ 0 - 1
arch/x86/platform/intel-mid/Makefile

@@ -1,5 +1,4 @@
 obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o
 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
 # SFI specific code
 ifdef CONFIG_X86_INTEL_MID
 ifdef CONFIG_X86_INTEL_MID

+ 0 - 112
arch/x86/platform/intel-mid/early_printk_intel_mid.c

@@ -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,
-};

+ 2 - 0
drivers/dma/Kconfig

@@ -125,6 +125,8 @@ config FSL_DMA
 	  EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
 	  EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
 	  some Txxx and Bxxx parts.
 	  some Txxx and Bxxx parts.
 
 
+source "drivers/dma/hsu/Kconfig"
+
 config MPC512X_DMA
 config MPC512X_DMA
 	tristate "Freescale MPC512x built-in DMA engine support"
 	tristate "Freescale MPC512x built-in DMA engine support"
 	depends on PPC_MPC512x || PPC_MPC831x
 	depends on PPC_MPC512x || PPC_MPC831x

+ 1 - 0
drivers/dma/Makefile

@@ -11,6 +11,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_HSU_DMA) += hsu/
 obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
 obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
 obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
 obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_MV_XOR) += mv_xor.o

+ 14 - 0
drivers/dma/hsu/Kconfig

@@ -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.

+ 5 - 0
drivers/dma/hsu/Makefile

@@ -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

+ 504 - 0
drivers/dma/hsu/hsu.c

@@ -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>");

+ 118 - 0
drivers/dma/hsu/hsu.h

@@ -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__ */

+ 123 - 0
drivers/dma/hsu/pci.c

@@ -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>");

+ 2 - 2
drivers/tty/serial/8250/8250_core.c

@@ -895,7 +895,7 @@ static int broken_efr(struct uart_8250_port *up)
 	/*
 	/*
 	 * Exar ST16C2550 "A2" devices incorrectly detect as
 	 * Exar ST16C2550 "A2" devices incorrectly detect as
 	 * having an EFR, and report an ID of 0x0201.  See
 	 * 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)
 	if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
 		return 1;
 		return 1;
@@ -1260,7 +1260,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 	serial_out(up, UART_LCR, save_lcr);
 	serial_out(up, UART_LCR, save_lcr);
 
 
 	port->fifosize = uart_config[up->port.type].fifo_size;
 	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->capabilities = uart_config[port->type].flags;
 	up->tx_loadsz = uart_config[port->type].tx_loadsz;
 	up->tx_loadsz = uart_config[port->type].tx_loadsz;
 
 

+ 11 - 4
drivers/tty/serial/8250/8250_dw.c

@@ -416,18 +416,24 @@ static int dw8250_probe(struct platform_device *pdev)
 {
 {
 	struct uart_8250_port uart = {};
 	struct uart_8250_port uart = {};
 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	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;
 	struct dw8250_data *data;
 	int err;
 	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;
 		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);
 	spin_lock_init(&uart.port.lock);
 	uart.port.mapbase = regs->start;
 	uart.port.mapbase = regs->start;
-	uart.port.irq = irq->start;
+	uart.port.irq = irq;
 	uart.port.handle_irq = dw8250_handle_irq;
 	uart.port.handle_irq = dw8250_handle_irq;
 	uart.port.pm = dw8250_do_pm;
 	uart.port.pm = dw8250_do_pm;
 	uart.port.type = PORT_8250;
 	uart.port.type = PORT_8250;
@@ -640,3 +646,4 @@ module_platform_driver(dw8250_platform_driver);
 MODULE_AUTHOR("Jamie Iles");
 MODULE_AUTHOR("Jamie Iles");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
 MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
+MODULE_ALIAS("platform:dw-apb-uart");

+ 198 - 16
drivers/tty/serial/8250/8250_pci.c

@@ -27,6 +27,7 @@
 
 
 #include <linux/dmaengine.h>
 #include <linux/dmaengine.h>
 #include <linux/platform_data/dma-dw.h>
 #include <linux/platform_data/dma-dw.h>
+#include <linux/platform_data/dma-hsu.h>
 
 
 #include "8250.h"
 #include "8250.h"
 
 
@@ -1525,6 +1526,148 @@ byt_serial_setup(struct serial_private *priv,
 	return ret;
 	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
 static int
 pci_omegapci_setup(struct serial_private *priv,
 pci_omegapci_setup(struct serial_private *priv,
 		      const struct pciserial_board *board,
 		      const struct pciserial_board *board,
@@ -1987,6 +2130,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
 		.subdevice	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.setup		= byt_serial_setup,
 		.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,
 		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_BSW_UART1,
 		.device		= PCI_DEVICE_ID_INTEL_BSW_UART1,
@@ -2864,6 +3028,7 @@ enum pci_board_num_t {
 	pbn_ADDIDATA_PCIe_8_3906250,
 	pbn_ADDIDATA_PCIe_8_3906250,
 	pbn_ce4100_1_115200,
 	pbn_ce4100_1_115200,
 	pbn_byt,
 	pbn_byt,
+	pbn_pnw,
 	pbn_qrk,
 	pbn_qrk,
 	pbn_omegapci,
 	pbn_omegapci,
 	pbn_NETMOS9900_2s_115200,
 	pbn_NETMOS9900_2s_115200,
@@ -3630,6 +3795,11 @@ static struct pciserial_board pci_boards[] = {
 		.uart_offset	= 0x80,
 		.uart_offset	= 0x80,
 		.reg_shift      = 2,
 		.reg_shift      = 2,
 	},
 	},
+	[pbn_pnw] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+	},
 	[pbn_qrk] = {
 	[pbn_qrk] = {
 		.flags		= FL_BASE0,
 		.flags		= FL_BASE0,
 		.num_ports	= 1,
 		.num_ports	= 1,
@@ -4006,41 +4176,41 @@ static void pciserial_remove_one(struct pci_dev *dev)
 	pci_disable_device(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)
 	if (priv)
 		pciserial_suspend_ports(priv);
 		pciserial_suspend_ports(priv);
 
 
-	pci_save_state(dev);
-	pci_set_power_state(dev, pci_choose_state(dev, state));
 	return 0;
 	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;
 	int err;
-	struct serial_private *priv = pci_get_drvdata(dev);
-
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
 
 
 	if (priv) {
 	if (priv) {
 		/*
 		/*
 		 * The device may have been disabled.  Re-enable it.
 		 * 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 */
 		/* FIXME: We cannot simply error out here */
 		if (err)
 		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);
 		pciserial_resume_ports(priv);
 	}
 	}
 	return 0;
 	return 0;
 }
 }
 #endif
 #endif
 
 
+static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one,
+			 pciserial_resume_one);
+
 static struct pci_device_id serial_pci_tbl[] = {
 static struct pci_device_id serial_pci_tbl[] = {
 	/* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
 	/* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
 	{	PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
 	{	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,
 		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
 		pbn_byt },
 		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
 	 * Intel Quark x1000
 	 */
 	 */
@@ -5510,10 +5693,9 @@ static struct pci_driver serial_pci_driver = {
 	.name		= "serial",
 	.name		= "serial",
 	.probe		= pciserial_init_one,
 	.probe		= pciserial_init_one,
 	.remove		= pciserial_remove_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,
 	.id_table	= serial_pci_tbl,
 	.err_handler	= &serial8250_err_handler,
 	.err_handler	= &serial8250_err_handler,
 };
 };

+ 3 - 13
drivers/tty/serial/Kconfig

@@ -20,7 +20,7 @@ comment "Non-8250 serial port support"
 
 
 config SERIAL_AMBA_PL010
 config SERIAL_AMBA_PL010
 	tristate "ARM AMBA PL010 serial port support"
 	tristate "ARM AMBA PL010 serial port support"
-	depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
+	depends on ARM_AMBA
 	select SERIAL_CORE
 	select SERIAL_CORE
 	help
 	help
 	  This selects the ARM(R) AMBA(R) PrimeCell PL010 UART.  If you have
 	  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
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 	  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
 config SERIAL_BFIN
 	tristate "Blackfin serial port support"
 	tristate "Blackfin serial port support"
 	depends on BLACKFIN
 	depends on BLACKFIN
@@ -835,7 +825,7 @@ config SERIAL_MCF_CONSOLE
 
 
 config SERIAL_PMACZILOG
 config SERIAL_PMACZILOG
 	tristate "Mac or PowerMac z85c30 ESCC support"
 	tristate "Mac or PowerMac z85c30 ESCC support"
-	depends on (M68K && MAC) || (PPC_OF && PPC_PMAC)
+	depends on (M68K && MAC) || PPC_PMAC
 	select SERIAL_CORE
 	select SERIAL_CORE
 	help
 	help
 	  This driver supports the Zilog z85C30 serial ports found on
 	  This driver supports the Zilog z85C30 serial ports found on
@@ -1153,7 +1143,7 @@ config SERIAL_OMAP_CONSOLE
 
 
 config SERIAL_OF_PLATFORM_NWPSERIAL
 config SERIAL_OF_PLATFORM_NWPSERIAL
 	tristate "NWP serial port driver"
 	tristate "NWP serial port driver"
-	depends on PPC_OF && PPC_DCR
+	depends on PPC_DCR
 	select SERIAL_OF_PLATFORM
 	select SERIAL_OF_PLATFORM
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE_CONSOLE
 	select SERIAL_CORE
 	select SERIAL_CORE

+ 0 - 1
drivers/tty/serial/Makefile

@@ -78,7 +78,6 @@ obj-$(CONFIG_SERIAL_TIMBERDALE)	+= timbuart.o
 obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
 obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
 obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
 obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
-obj-$(CONFIG_SERIAL_MFD_HSU)	+= mfd.o
 obj-$(CONFIG_SERIAL_IFX6X60)  	+= ifx6x60.o
 obj-$(CONFIG_SERIAL_IFX6X60)  	+= ifx6x60.o
 obj-$(CONFIG_SERIAL_PCH_UART)	+= pch_uart.o
 obj-$(CONFIG_SERIAL_PCH_UART)	+= pch_uart.o
 obj-$(CONFIG_SERIAL_MSM_SMD)	+= msm_smd_tty.o
 obj-$(CONFIG_SERIAL_MSM_SMD)	+= msm_smd_tty.o

+ 130 - 105
drivers/tty/serial/amba-pl011.c

@@ -58,6 +58,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/sizes.h>
 #include <linux/sizes.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/workqueue.h>
 
 
 #define UART_NR			14
 #define UART_NR			14
 
 
@@ -156,7 +157,9 @@ struct uart_amba_port {
 	unsigned int		lcrh_tx;	/* vendor-specific */
 	unsigned int		lcrh_tx;	/* vendor-specific */
 	unsigned int		lcrh_rx;	/* vendor-specific */
 	unsigned int		lcrh_rx;	/* vendor-specific */
 	unsigned int		old_cr;		/* state during shutdown */
 	unsigned int		old_cr;		/* state during shutdown */
+	struct delayed_work	tx_softirq_work;
 	bool			autorts;
 	bool			autorts;
+	unsigned int		tx_irq_seen;	/* 0=none, 1=1, 2=2 or more */
 	char			type[12];
 	char			type[12];
 #ifdef CONFIG_DMA_ENGINE
 #ifdef CONFIG_DMA_ENGINE
 	/* DMA stuff */
 	/* DMA stuff */
@@ -164,6 +167,7 @@ struct uart_amba_port {
 	bool			using_rx_dma;
 	bool			using_rx_dma;
 	struct pl011_dmarx_data dmarx;
 	struct pl011_dmarx_data dmarx;
 	struct pl011_dmatx_data	dmatx;
 	struct pl011_dmatx_data	dmatx;
+	bool			dma_probed;
 #endif
 #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 */
 	/* DMA is the sole user of the platform data right now */
 	struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
 	struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
+	struct device *dev = uap->port.dev;
 	struct dma_slave_config tx_conf = {
 	struct dma_slave_config tx_conf = {
 		.dst_addr = uap->port.mapbase + UART01x_DR,
 		.dst_addr = uap->port.mapbase + UART01x_DR,
 		.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
 		.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@@ -275,9 +280,15 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
 	struct dma_chan *chan;
 	struct dma_chan *chan;
 	dma_cap_mask_t mask;
 	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) {
+			dev_info(uap->port.dev, "DMA driver not ready\n");
+			uap->dma_probed = false;
+			return;
+		}
 
 
-	if (!chan) {
 		/* We need platform data */
 		/* We need platform data */
 		if (!plat || !plat->dma_filter) {
 		if (!plat || !plat->dma_filter) {
 			dev_info(uap->port.dev, "no DMA platform data\n");
 			dev_info(uap->port.dev, "no DMA platform data\n");
@@ -385,63 +396,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)
 static void pl011_dma_remove(struct uart_amba_port *uap)
 {
 {
-	/* TODO: remove the initcall if it has not yet executed */
 	if (uap->dmatx.chan)
 	if (uap->dmatx.chan)
 		dma_release_channel(uap->dmatx.chan);
 		dma_release_channel(uap->dmatx.chan);
 	if (uap->dmarx.chan)
 	if (uap->dmarx.chan)
 		dma_release_channel(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 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.
  * The current DMA TX buffer has been sent.
@@ -479,14 +444,13 @@ static void pl011_dma_tx_callback(void *data)
 		return;
 		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
 		 * We didn't queue a DMA buffer for some reason, but we
 		 * have data pending to be sent.  Re-enable the TX IRQ.
 		 * 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);
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 }
 
 
@@ -664,12 +628,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 		if (!uap->dmatx.queued) {
 		if (!uap->dmatx.queued) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 			if (pl011_dma_tx_refill(uap) > 0) {
 				uap->im &= ~UART011_TXIM;
 				uap->im &= ~UART011_TXIM;
-				ret = true;
-			} else {
-				uap->im |= UART011_TXIM;
+				writew(uap->im, uap->port.membase +
+				       UART011_IMSC);
+			} else
 				ret = false;
 				ret = false;
-			}
-			writew(uap->im, uap->port.membase + UART011_IMSC);
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 		} else if (!(uap->dmacr & UART011_TXDMAE)) {
 			uap->dmacr |= UART011_TXDMAE;
 			uap->dmacr |= UART011_TXDMAE;
 			writew(uap->dmacr,
 			writew(uap->dmacr,
@@ -1021,6 +983,9 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 {
 {
 	int ret;
 	int ret;
 
 
+	if (!uap->dma_probed)
+		pl011_dma_probe(uap);
+
 	if (!uap->dmatx.chan)
 	if (!uap->dmatx.chan)
 		return;
 		return;
 
 
@@ -1142,7 +1107,7 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
 
 
 #else
 #else
 /* Blank functions if the DMA engine is not available */
 /* 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 +1173,24 @@ static void pl011_stop_tx(struct uart_port *port)
 	pl011_dma_tx_stop(uap);
 	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)
 static void pl011_start_tx(struct uart_port *port)
 {
 {
 	struct uart_amba_port *uap =
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 	    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)
 static void pl011_stop_rx(struct uart_port *port)
@@ -1274,40 +1248,87 @@ __acquires(&uap->port.lock)
 	spin_lock(&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;
 	struct circ_buf *xmit = &uap->port.state->xmit;
 	int count;
 	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) {
 	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;
 		uap->port.x_char = 0;
-		return;
+		--count;
 	}
 	}
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
 		pl011_stop_tx(&uap->port);
 		pl011_stop_tx(&uap->port);
-		return;
+		goto done;
 	}
 	}
 
 
 	/* If we are using DMA mode, try to send some characters. */
 	/* If we are using DMA mode, try to send some characters. */
 	if (pl011_dma_tx_irq(uap))
 	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);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		uap->port.icount.tx++;
 		if (uart_circ_empty(xmit))
 		if (uart_circ_empty(xmit))
 			break;
 			break;
-	} while (--count > 0);
+	}
 
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(&uap->port);
 		uart_write_wakeup(&uap->port);
 
 
-	if (uart_circ_empty(xmit))
+	if (uart_circ_empty(xmit)) {
 		pl011_stop_tx(&uap->port);
 		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)
 static void pl011_modem_status(struct uart_amba_port *uap)
@@ -1334,6 +1355,28 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 	wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 	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)
 static irqreturn_t pl011_int(int irq, void *dev_id)
 {
 {
 	struct uart_amba_port *uap = dev_id;
 	struct uart_amba_port *uap = dev_id;
@@ -1372,8 +1415,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 			if (status & (UART011_DSRMIS|UART011_DCDMIS|
 			if (status & (UART011_DSRMIS|UART011_DCDMIS|
 				      UART011_CTSMIS|UART011_RIMIS))
 				      UART011_CTSMIS|UART011_RIMIS))
 				pl011_modem_status(uap);
 				pl011_modem_status(uap);
-			if (status & UART011_TXIS)
+			if (status & UART011_TXIS) {
+				pl011_tx_irq_seen(uap);
 				pl011_tx_chars(uap);
 				pl011_tx_chars(uap);
+			}
 
 
 			if (pass_counter-- == 0)
 			if (pass_counter-- == 0)
 				break;
 				break;
@@ -1577,7 +1622,7 @@ static int pl011_startup(struct uart_port *port)
 {
 {
 	struct uart_amba_port *uap =
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
 	    container_of(port, struct uart_amba_port, port);
-	unsigned int cr, lcr_h, fbrd, ibrd;
+	unsigned int cr;
 	int retval;
 	int retval;
 
 
 	retval = pl011_hwinit(port);
 	retval = pl011_hwinit(port);
@@ -1595,30 +1640,8 @@ static int pl011_startup(struct uart_port *port)
 
 
 	writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
 	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);
 	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 */
 	/* restore RTS and DTR */
 	cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
 	cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
 	cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
 	cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
@@ -1672,13 +1695,15 @@ static void pl011_shutdown(struct uart_port *port)
 	    container_of(port, struct uart_amba_port, port);
 	    container_of(port, struct uart_amba_port, port);
 	unsigned int cr;
 	unsigned int cr;
 
 
+	cancel_delayed_work_sync(&uap->tx_softirq_work);
+
 	/*
 	/*
 	 * disable all interrupts
 	 * disable all interrupts
 	 */
 	 */
 	spin_lock_irq(&uap->port.lock);
 	spin_lock_irq(&uap->port.lock);
 	uap->im = 0;
 	uap->im = 0;
 	writew(uap->im, uap->port.membase + UART011_IMSC);
 	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);
 	spin_unlock_irq(&uap->port.lock);
 
 
 	pl011_dma_shutdown(uap);
 	pl011_dma_shutdown(uap);
@@ -2218,7 +2243,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	uap->port.ops = &amba_pl011_pops;
 	uap->port.ops = &amba_pl011_pops;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
 	uap->port.line = i;
 	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 */
 	/* Ensure interrupts from this UART are masked and cleared */
 	writew(0, uap->port.membase + UART011_IMSC);
 	writew(0, uap->port.membase + UART011_IMSC);
@@ -2233,7 +2258,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	if (!amba_reg.state) {
 	if (!amba_reg.state) {
 		ret = uart_register_driver(&amba_reg);
 		ret = uart_register_driver(&amba_reg);
 		if (ret < 0) {
 		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;
 			return ret;
 		}
 		}
 	}
 	}
@@ -2242,7 +2268,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	if (ret) {
 	if (ret) {
 		amba_ports[i] = NULL;
 		amba_ports[i] = NULL;
 		uart_unregister_driver(&amba_reg);
 		uart_unregister_driver(&amba_reg);
-		pl011_dma_remove(uap);
 	}
 	}
 
 
 	return ret;
 	return ret;

+ 1 - 1
drivers/tty/serial/ar933x_uart.c

@@ -649,7 +649,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
 			id = 0;
 			id = 0;
 	}
 	}
 
 
-	if (id > CONFIG_SERIAL_AR933X_NR_UARTS)
+	if (id >= CONFIG_SERIAL_AR933X_NR_UARTS)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

+ 17 - 12
drivers/tty/serial/atmel_serial.c

@@ -855,7 +855,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
 	spin_lock_init(&atmel_port->lock_tx);
 	spin_lock_init(&atmel_port->lock_tx);
 	sg_init_table(&atmel_port->sg_tx, 1);
 	sg_init_table(&atmel_port->sg_tx, 1);
 	/* UART circular tx buffer is an aligned page. */
 	/* 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,
 	sg_set_page(&atmel_port->sg_tx,
 			virt_to_page(port->state->xmit.buf),
 			virt_to_page(port->state->xmit.buf),
 			UART_XMIT_SIZE,
 			UART_XMIT_SIZE,
@@ -1034,10 +1034,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
 	spin_lock_init(&atmel_port->lock_rx);
 	spin_lock_init(&atmel_port->lock_rx);
 	sg_init_table(&atmel_port->sg_rx, 1);
 	sg_init_table(&atmel_port->sg_rx, 1);
 	/* UART circular rx buffer is an aligned page. */
 	/* 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,
 	sg_set_page(&atmel_port->sg_rx,
 		    virt_to_page(ring->buf),
 		    virt_to_page(ring->buf),
-		    ATMEL_SERIAL_RINGSIZE,
+		    sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
 		    (int)ring->buf & ~PAGE_MASK);
 		    (int)ring->buf & ~PAGE_MASK);
 	nent = dma_map_sg(port->dev,
 	nent = dma_map_sg(port->dev,
 			  &atmel_port->sg_rx,
 			  &atmel_port->sg_rx,
@@ -1554,7 +1554,7 @@ static void atmel_tasklet_func(unsigned long data)
 	spin_unlock(&port->lock);
 	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 platform_device *pdev)
 {
 {
 	struct device_node *np = pdev->dev.of_node;
 	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;
 		atmel_port->use_dma_tx  = false;
 	}
 	}
 
 
-	return 0;
 }
 }
 
 
 static void atmel_init_rs485(struct uart_port *port,
 static void atmel_init_rs485(struct uart_port *port,
@@ -1777,10 +1776,13 @@ static int atmel_startup(struct uart_port *port)
 	if (retval)
 	if (retval)
 		goto free_irq;
 		goto free_irq;
 
 
+	tasklet_enable(&atmel_port->tasklet);
+
 	/*
 	/*
 	 * Initialize DMA (if necessary)
 	 * Initialize DMA (if necessary)
 	 */
 	 */
 	atmel_init_property(atmel_port, pdev);
 	atmel_init_property(atmel_port, pdev);
+	atmel_set_ops(port);
 
 
 	if (atmel_port->prepare_rx) {
 	if (atmel_port->prepare_rx) {
 		retval = atmel_port->prepare_rx(port);
 		retval = atmel_port->prepare_rx(port);
@@ -1879,6 +1881,7 @@ static void atmel_shutdown(struct uart_port *port)
 	 * Clear out any scheduled tasklets before
 	 * Clear out any scheduled tasklets before
 	 * we destroy the buffers
 	 * we destroy the buffers
 	 */
 	 */
+	tasklet_disable(&atmel_port->tasklet);
 	tasklet_kill(&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 uart_port *port = &atmel_port->uart;
 	struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 	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);
 	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,
 	tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
 			(unsigned long)port);
 			(unsigned long)port);
+	tasklet_disable(&atmel_port->tasklet);
 
 
 	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 	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;
 	struct gpio_desc *gpiod;
 
 
 	p->gpios = mctrl_gpio_init(dev, 0);
 	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++) {
 	for (i = 0; i < UART_GPIO_MAX; i++) {
 		gpiod = mctrl_gpio_to_gpiod(p->gpios, 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);
 	spin_lock_init(&port->lock_suspended);
 
 
 	ret = atmel_init_gpios(port, &pdev->dev);
 	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);
 	ret = atmel_init_port(port, pdev);
 	if (ret)
 	if (ret)

+ 2 - 2
drivers/tty/serial/bcm63xx_uart.c

@@ -854,7 +854,7 @@ static int bcm_uart_probe(struct platform_device *pdev)
 
 
 	ret = uart_add_one_port(&bcm_uart_driver, port);
 	ret = uart_add_one_port(&bcm_uart_driver, port);
 	if (ret) {
 	if (ret) {
-		ports[pdev->id].membase = 0;
+		ports[pdev->id].membase = NULL;
 		return ret;
 		return ret;
 	}
 	}
 	platform_set_drvdata(pdev, port);
 	platform_set_drvdata(pdev, port);
@@ -868,7 +868,7 @@ static int bcm_uart_remove(struct platform_device *pdev)
 	port = platform_get_drvdata(pdev);
 	port = platform_get_drvdata(pdev);
 	uart_remove_one_port(&bcm_uart_driver, port);
 	uart_remove_one_port(&bcm_uart_driver, port);
 	/* mark port as free */
 	/* mark port as free */
-	ports[pdev->id].membase = 0;
+	ports[pdev->id].membase = NULL;
 	return 0;
 	return 0;
 }
 }
 
 

+ 2 - 0
drivers/tty/serial/clps711x.c

@@ -501,6 +501,8 @@ static int uart_clps711x_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, s);
 	platform_set_drvdata(pdev, s);
 
 
 	s->gpios = mctrl_gpio_init(&pdev->dev, 0);
 	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);
 	ret = uart_add_one_port(&clps711x_uart, &s->port);
 	if (ret)
 	if (ret)

+ 13 - 26
drivers/tty/serial/earlycon.c

@@ -54,44 +54,31 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
 	return base;
 	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;
 	struct uart_port *port = &device->port;
-	int mmio, mmio32, length;
+	int length;
 	unsigned long addr;
 	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;
 		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;
 		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;
 		return -EINVAL;
 	}
 	}
 
 
 	port->uartclk = BASE_BAUD * 16;
 	port->uartclk = BASE_BAUD * 16;
 
 
-	options = strchr(options, ',');
 	if (options) {
 	if (options) {
-		options++;
 		device->baud = simple_strtoul(options, NULL, 0);
 		device->baud = simple_strtoul(options, NULL, 0);
 		length = min(strcspn(options, " ") + 1,
 		length = min(strcspn(options, " ") + 1,
 			     (size_t)(sizeof(device->options)));
 			     (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)
 	if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32)
 		pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
 		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,
 			(unsigned long long)port->mapbase,
 			device->options);
 			device->options);
 	else
 	else

+ 121 - 196
drivers/tty/serial/imx.c

@@ -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
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -18,13 +15,6 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * 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)
 #if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -189,7 +179,7 @@
 
 
 #define UART_NR 8
 #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 {
 enum imx_uart_type {
 	IMX1_UART,
 	IMX1_UART,
 	IMX21_UART,
 	IMX21_UART,
@@ -206,10 +196,8 @@ struct imx_port {
 	struct uart_port	port;
 	struct uart_port	port;
 	struct timer_list	timer;
 	struct timer_list	timer;
 	unsigned int		old_status;
 	unsigned int		old_status;
-	int			txirq, rxirq, rtsirq;
 	unsigned int		have_rtscts:1;
 	unsigned int		have_rtscts:1;
 	unsigned int		dte_mode:1;
 	unsigned int		dte_mode:1;
-	unsigned int		use_irda:1;
 	unsigned int		irda_inv_rx:1;
 	unsigned int		irda_inv_rx:1;
 	unsigned int		irda_inv_tx:1;
 	unsigned int		irda_inv_tx:1;
 	unsigned short		trcv_delay; /* transceiver delay */
 	unsigned short		trcv_delay; /* transceiver delay */
@@ -236,12 +224,6 @@ struct imx_port_ucrs {
 	unsigned int	ucr3;
 	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[] = {
 static struct imx_uart_data imx_uart_devdata[] = {
 	[IMX1_UART] = {
 	[IMX1_UART] = {
 		.uts_reg = IMX1_UTS,
 		.uts_reg = IMX1_UTS,
@@ -273,7 +255,7 @@ static struct platform_device_id imx_uart_devtype[] = {
 };
 };
 MODULE_DEVICE_TABLE(platform, 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,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
 	{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
 	{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
 	{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_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;
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long temp;
 	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
 	 * 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.
 	 * 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)
 	if (sport->dma_is_enabled && sport->dma_is_txing)
 		return;
 		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;
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long temp;
 	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) {
 	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);
 		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->dma_is_enabled) {
 		if (sport->port.x_char) {
 		if (sport->port.x_char) {
 			/* We have X-char to send, so enable TX IRQ and
 			/* 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;
 	unsigned int sts2;
 
 
 	sts = readl(sport->port.membase + USR1);
 	sts = readl(sport->port.membase + USR1);
+	sts2 = readl(sport->port.membase + USR2);
 
 
 	if (sts & USR1_RRDY) {
 	if (sts & USR1_RRDY) {
 		if (sport->dma_is_enabled)
 		if (sport->dma_is_enabled)
@@ -804,8 +753,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
 			imx_rxint(irq, 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);
 		imx_txint(irq, dev_id);
 
 
 	if (sts & USR1_RTSD)
 	if (sts & USR1_RTSD)
@@ -814,11 +765,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
 	if (sts & USR1_AWAKE)
 	if (sts & USR1_AWAKE)
 		writel(USR1_AWAKE, sport->port.membase + USR1);
 		writel(USR1_AWAKE, sport->port.membase + USR1);
 
 
-	sts2 = readl(sport->port.membase + USR2);
 	if (sts2 & USR2_ORE) {
 	if (sts2 & USR2_ORE) {
 		dev_err(sport->port.dev, "Rx FIFO overrun\n");
 		dev_err(sport->port.dev, "Rx FIFO overrun\n");
 		sport->port.icount.overrun++;
 		sport->port.icount.overrun++;
-		writel(sts2 | USR2_ORE, sport->port.membase + USR2);
+		writel(USR2_ORE, sport->port.membase + USR2);
 	}
 	}
 
 
 	return IRQ_HANDLED;
 	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;
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long temp;
 	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;
 	temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
 	if (mctrl & TIOCM_LOOP)
 	if (mctrl & TIOCM_LOOP)
@@ -1156,9 +1108,6 @@ static int imx_startup(struct uart_port *port)
 	 */
 	 */
 	temp = readl(sport->port.membase + UCR4);
 	temp = readl(sport->port.membase + UCR4);
 
 
-	if (USE_IRDA(sport))
-		temp |= UCR4_IRSC;
-
 	/* set the trigger level for CTS */
 	/* set the trigger level for CTS */
 	temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
 	temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
 	temp |= CTSTL << 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);
 		imx_uart_dma_init(sport);
 
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 	spin_lock_irqsave(&sport->port.lock, flags);
+
 	/*
 	/*
 	 * Finally, clear and enable interrupts
 	 * Finally, clear and enable interrupts
 	 */
 	 */
 	writel(USR1_RTSD, sport->port.membase + USR1);
 	writel(USR1_RTSD, sport->port.membase + USR1);
+	writel(USR2_ORE, sport->port.membase + USR2);
 
 
 	if (sport->dma_is_inited && !sport->dma_is_enabled)
 	if (sport->dma_is_inited && !sport->dma_is_enabled)
 		imx_enable_dma(sport);
 		imx_enable_dma(sport);
@@ -1192,17 +1143,8 @@ static int imx_startup(struct uart_port *port)
 	temp = readl(sport->port.membase + UCR1);
 	temp = readl(sport->port.membase + UCR1);
 	temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 	temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 
 
-	if (USE_IRDA(sport)) {
-		temp |= UCR1_IREN;
-		temp &= ~(UCR1_RTSDEN);
-	}
-
 	writel(temp, sport->port.membase + UCR1);
 	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 = readl(sport->port.membase + UCR4);
 	temp |= UCR4_OREN;
 	temp |= UCR4_OREN;
 	writel(temp, sport->port.membase + UCR4);
 	writel(temp, sport->port.membase + UCR4);
@@ -1219,38 +1161,12 @@ static int imx_startup(struct uart_port *port)
 		writel(temp, sport->port.membase + UCR3);
 		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
 	 * Enable modem status interrupts
 	 */
 	 */
 	imx_enable_ms(&sport->port);
 	imx_enable_ms(&sport->port);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	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;
 	return 0;
 }
 }
 
 
@@ -1286,13 +1202,6 @@ static void imx_shutdown(struct uart_port *port)
 	writel(temp, sport->port.membase + UCR2);
 	writel(temp, sport->port.membase + UCR2);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	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.
 	 * Stop our timer.
 	 */
 	 */
@@ -1305,8 +1214,6 @@ static void imx_shutdown(struct uart_port *port)
 	spin_lock_irqsave(&sport->port.lock, flags);
 	spin_lock_irqsave(&sport->port.lock, flags);
 	temp = readl(sport->port.membase + UCR1);
 	temp = readl(sport->port.membase + UCR1);
 	temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
 	temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
-	if (USE_IRDA(sport))
-		temp &= ~(UCR1_IREN);
 
 
 	writel(temp, sport->port.membase + UCR1);
 	writel(temp, sport->port.membase + UCR1);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	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 imx_port *sport = (struct imx_port *)port;
 	struct scatterlist *sgl = &sport->tx_sgl[0];
 	struct scatterlist *sgl = &sport->tx_sgl[0];
 	unsigned long temp;
 	unsigned long temp;
-	int i = 100, ubir, ubmr, ubrc, uts;
+	int i = 100, ubir, ubmr, uts;
 
 
 	if (!sport->dma_chan_tx)
 	if (!sport->dma_chan_tx)
 		return;
 		return;
@@ -1345,7 +1252,6 @@ static void imx_flush_buffer(struct uart_port *port)
 	 */
 	 */
 	ubir = readl(sport->port.membase + UBIR);
 	ubir = readl(sport->port.membase + UBIR);
 	ubmr = readl(sport->port.membase + UBMR);
 	ubmr = readl(sport->port.membase + UBMR);
-	ubrc = readl(sport->port.membase + UBRC);
 	uts = readl(sport->port.membase + IMX21_UTS);
 	uts = readl(sport->port.membase + IMX21_UTS);
 
 
 	temp = readl(sport->port.membase + UCR2);
 	temp = readl(sport->port.membase + UCR2);
@@ -1358,7 +1264,6 @@ static void imx_flush_buffer(struct uart_port *port)
 	/* Restore the registers */
 	/* Restore the registers */
 	writel(ubir, sport->port.membase + UBIR);
 	writel(ubir, sport->port.membase + UBIR);
 	writel(ubmr, sport->port.membase + UBMR);
 	writel(ubmr, sport->port.membase + UBMR);
-	writel(ubrc, sport->port.membase + UBRC);
 	writel(uts, sport->port.membase + IMX21_UTS);
 	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;
 	unsigned long num, denom;
 	uint64_t tdiv64;
 	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.
 	 * 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 (termios->c_cflag & CRTSCTS) {
 		if (sport->have_rtscts) {
 		if (sport->have_rtscts) {
 			ucr2 &= ~UCR2_IRTS;
 			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 {
 		} else {
 			termios->c_cflag &= ~CRTSCTS;
 			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)
 	if (termios->c_cflag & CSTOPB)
 		ucr2 |= UCR2_STPB;
 		ucr2 |= UCR2_STPB;
@@ -1471,24 +1382,16 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 			sport->port.membase + UCR2);
 			sport->port.membase + UCR2);
 	old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
 	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;
 		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,
 	rational_best_approximation(16 * div * baud, sport->port.uartclk,
 		1 << 16, 1 << 16, &num, &denom);
 		1 << 16, 1 << 16, &num, &denom);
@@ -1635,6 +1538,38 @@ static void imx_poll_put_char(struct uart_port *port, unsigned char c)
 }
 }
 #endif
 #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 = {
 static struct uart_ops imx_pops = {
 	.tx_empty	= imx_tx_empty,
 	.tx_empty	= imx_tx_empty,
 	.set_mctrl	= imx_set_mctrl,
 	.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))
 	if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
 		sport->have_rtscts = 1;
 		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))
 	if (of_get_property(np, "fsl,dte-mode", NULL))
 		sport->dte_mode = 1;
 		sport->dte_mode = 1;
 
 
@@ -1958,9 +1890,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
 
 
 	if (pdata->flags & IMXUART_HAVE_RTSCTS)
 	if (pdata->flags & IMXUART_HAVE_RTSCTS)
 		sport->have_rtscts = 1;
 		sport->have_rtscts = 1;
-
-	if (pdata->flags & IMXUART_IRDA)
-		sport->use_irda = 1;
 }
 }
 
 
 static int serial_imx_probe(struct platform_device *pdev)
 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;
 	void __iomem *base;
 	int ret = 0;
 	int ret = 0;
 	struct resource *res;
 	struct resource *res;
+	int txirq, rxirq, rtsirq;
 
 
 	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
 	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
 	if (!sport)
 	if (!sport)
@@ -1985,17 +1915,21 @@ static int serial_imx_probe(struct platform_device *pdev)
 	if (IS_ERR(base))
 	if (IS_ERR(base))
 		return PTR_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.dev = &pdev->dev;
 	sport->port.mapbase = res->start;
 	sport->port.mapbase = res->start;
 	sport->port.membase = base;
 	sport->port.membase = base;
 	sport->port.type = PORT_IMX,
 	sport->port.type = PORT_IMX,
 	sport->port.iotype = UPIO_MEM;
 	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.fifosize = 32;
 	sport->port.ops = &imx_pops;
 	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;
 	sport->port.flags = UPF_BOOT_AUTOCONF;
 	init_timer(&sport->timer);
 	init_timer(&sport->timer);
 	sport->timer.function = imx_timeout;
 	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
 	 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
 	 * chips only have one interrupt.
 	 * 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);
 				       dev_name(&pdev->dev), sport);
 		if (ret)
 		if (ret)
 			return 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);
 				       dev_name(&pdev->dev), sport);
 		if (ret)
 		if (ret)
 			return 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 {
 	} 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);
 				       dev_name(&pdev->dev), sport);
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;

+ 1 - 1
drivers/tty/serial/max3100.c

@@ -782,7 +782,7 @@ static int max3100_probe(struct spi_device *spi)
 	pdata = dev_get_platdata(&spi->dev);
 	pdata = dev_get_platdata(&spi->dev);
 	max3100s[i]->crystal = pdata->crystal;
 	max3100s[i]->crystal = pdata->crystal;
 	max3100s[i]->loopback = pdata->loopback;
 	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)
 	if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
 		max3100s[i]->poll_time = 1;
 		max3100s[i]->poll_time = 1;
 	max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;
 	max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;

+ 0 - 1505
drivers/tty/serial/mfd.c

@@ -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);

+ 9 - 7
drivers/tty/serial/mxs-auart.c

@@ -1155,14 +1155,14 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
 	return 0;
 	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;
 	enum mctrl_gpio_idx i;
 	struct gpio_desc *gpiod;
 	struct gpio_desc *gpiod;
 
 
 	s->gpios = mctrl_gpio_init(dev, 0);
 	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 */
 	/* Block (enabled before) DMA option if RTS or CTS is GPIO line */
 	if (!RTS_AT_AUART() || !CTS_AT_AUART()) {
 	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;
 			s->gpio_irq[i] = -EINVAL;
 	}
 	}
 
 
-	return true;
+	return 0;
 }
 }
 
 
 static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s)
 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);
 	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");
+		got out_free_irq;
+	}
 
 
 	/*
 	/*
 	 * Get the GPIO lines IRQ
 	 * Get the GPIO lines IRQ

+ 47 - 2
drivers/tty/serial/serial_core.c

@@ -1118,8 +1118,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
 
 
 		cprev = cnow;
 		cprev = cnow;
 	}
 	}
-
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->delta_msr_wait, &wait);
 	remove_wait_queue(&port->delta_msr_wait, &wait);
 
 
 	return ret;
 	return ret;
@@ -1809,6 +1808,52 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
 	return ports + idx;
 	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.
  *	uart_parse_options - Parse serial port baud/parity/bits/flow control.
  *	@options: pointer to option string
  *	@options: pointer to option string

+ 13 - 36
drivers/tty/serial/serial_mctrl_gpio.c

@@ -48,9 +48,6 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
 	int value_array[UART_GPIO_MAX];
 	int value_array[UART_GPIO_MAX];
 	unsigned int count = 0;
 	unsigned int count = 0;
 
 
-	if (IS_ERR_OR_NULL(gpios))
-		return;
-
 	for (i = 0; i < UART_GPIO_MAX; i++)
 	for (i = 0; i < UART_GPIO_MAX; i++)
 		if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
 		if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
 		    mctrl_gpios_desc[i].dir_out) {
 		    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,
 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
 				      enum mctrl_gpio_idx gidx)
 				      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);
 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;
 	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++) {
 	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]))
 			if (gpiod_get_value(gpios->gpio[i]))
 				*mctrl |= mctrl_gpios_desc[i].mctrl;
 				*mctrl |= mctrl_gpios_desc[i].mctrl;
 			else
 			else
@@ -107,27 +94,20 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
 		return ERR_PTR(-ENOMEM);
 		return ERR_PTR(-ENOMEM);
 
 
 	for (i = 0; i < UART_GPIO_MAX; i++) {
 	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)
 		if (mctrl_gpios_desc[i].dir_out)
-			err = gpiod_direction_output(gpios->gpio[i], 0);
+			flags = GPIOD_OUT_LOW;
 		else
 		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 PTR_ERR(gpios->gpio[i]);
 	}
 	}
 
 
 	return gpios;
 	return gpios;
@@ -138,9 +118,6 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
 {
 	enum mctrl_gpio_idx i;
 	enum mctrl_gpio_idx i;
 
 
-	if (IS_ERR_OR_NULL(gpios))
-		return;
-
 	for (i = 0; i < UART_GPIO_MAX; i++)
 	for (i = 0; i < UART_GPIO_MAX; i++)
 		if (!IS_ERR_OR_NULL(gpios->gpio[i]))
 		if (!IS_ERR_OR_NULL(gpios->gpio[i]))
 			devm_gpiod_put(dev, gpios->gpio[i]);
 			devm_gpiod_put(dev, gpios->gpio[i]);

+ 5 - 1
drivers/tty/serial/sprd_serial.c

@@ -493,6 +493,8 @@ static int sprd_verify_port(struct uart_port *port,
 		return -EINVAL;
 		return -EINVAL;
 	if (port->irq != ser->irq)
 	if (port->irq != ser->irq)
 		return -EINVAL;
 		return -EINVAL;
+	if (port->iotype != ser->io_type)
+		return -EINVAL;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -707,7 +709,7 @@ static int sprd_probe(struct platform_device *pdev)
 	up->dev = &pdev->dev;
 	up->dev = &pdev->dev;
 	up->line = index;
 	up->line = index;
 	up->type = PORT_SPRD;
 	up->type = PORT_SPRD;
-	up->iotype = SERIAL_IO_PORT;
+	up->iotype = UPIO_MEM;
 	up->uartclk = SPRD_DEF_RATE;
 	up->uartclk = SPRD_DEF_RATE;
 	up->fifosize = SPRD_FIFO_SIZE;
 	up->fifosize = SPRD_FIFO_SIZE;
 	up->ops = &serial_sprd_ops;
 	up->ops = &serial_sprd_ops;
@@ -754,6 +756,7 @@ static int sprd_probe(struct platform_device *pdev)
 	return ret;
 	return ret;
 }
 }
 
 
+#ifdef CONFIG_PM_SLEEP
 static int sprd_suspend(struct device *dev)
 static int sprd_suspend(struct device *dev)
 {
 {
 	struct sprd_uart_port *sup = dev_get_drvdata(dev);
 	struct sprd_uart_port *sup = dev_get_drvdata(dev);
@@ -771,6 +774,7 @@ static int sprd_resume(struct device *dev)
 
 
 	return 0;
 	return 0;
 }
 }
+#endif
 
 
 static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume);
 static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume);
 
 

+ 2 - 1
drivers/tty/serial/xilinx_uartps.c

@@ -1154,7 +1154,8 @@ static int __init cdns_uart_console_setup(struct console *co, char *options)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (!port->mapbase) {
 	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;
 		return -ENODEV;
 	}
 	}
 
 

+ 2 - 2
drivers/tty/vt/vt.c

@@ -1237,7 +1237,7 @@ static void default_attr(struct vc_data *vc)
 
 
 struct rgb { u8 r; u8 g; u8 b; };
 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;
 	struct rgb c;
 	if (i < 8) {            /* Standard colours. */
 	if (i < 8) {            /* Standard colours. */
@@ -1573,7 +1573,7 @@ static void setterm_command(struct vc_data *vc)
 		case 11: /* set bell duration in msec */
 		case 11: /* set bell duration in msec */
 			if (vc->vc_npar >= 1)
 			if (vc->vc_npar >= 1)
 				vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
 				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
 			else
 				vc->vc_bell_duration = DEFAULT_BELL_DURATION;
 				vc->vc_bell_duration = DEFAULT_BELL_DURATION;
 			break;
 			break;

+ 1 - 1
drivers/tty/vt/vt_ioctl.c

@@ -388,7 +388,7 @@ int vt_ioctl(struct tty_struct *tty,
 		 * Generate the tone for the appropriate number of ticks.
 		 * Generate the tone for the appropriate number of ticks.
 		 * If the time is zero, turn off sound ourselves.
 		 * 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;
 		count = ticks ? (arg & 0xffff) : 0;
 		if (count)
 		if (count)
 			count = PIT_TICK_RATE / count;
 			count = PIT_TICK_RATE / count;

+ 48 - 0
include/linux/dma/hsu.h

@@ -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 */

+ 25 - 0
include/linux/platform_data/dma-hsu.h

@@ -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 */

+ 0 - 5
include/linux/platform_data/serial-imx.h

@@ -20,14 +20,9 @@
 #define ASMARM_ARCH_UART_H
 #define ASMARM_ARCH_UART_H
 
 
 #define IMXUART_HAVE_RTSCTS (1<<0)
 #define IMXUART_HAVE_RTSCTS (1<<0)
-#define IMXUART_IRDA        (1<<1)
 
 
 struct imxuart_platform_data {
 struct imxuart_platform_data {
 	unsigned int flags;
 	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
 #endif

+ 2 - 0
include/linux/serial_core.h

@@ -354,6 +354,8 @@ early_param("earlycon", name ## _setup_earlycon);
 
 
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
 				   struct console *c);
 				   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,
 void uart_parse_options(char *options, int *baud, int *parity, int *bits,
 			int *flow);
 			int *flow);
 int uart_set_options(struct uart_port *port, struct console *co, int baud,
 int uart_set_options(struct uart_port *port, struct console *co, int baud,

+ 0 - 47
include/linux/serial_mfd.h

@@ -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

+ 0 - 19
include/uapi/linux/serial_reg.h

@@ -241,25 +241,6 @@
 #define UART_FCR_PXAR16	0x80	/* receive FIFO threshold = 16 */
 #define UART_FCR_PXAR16	0x80	/* receive FIFO threshold = 16 */
 #define UART_FCR_PXAR32	0xc0	/* receive FIFO threshold = 32 */
 #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
  * These register definitions are for the 16C950
  */
  */

+ 0 - 1
kernel/printk/printk.c

@@ -2480,7 +2480,6 @@ void register_console(struct console *newcon)
 		    newcon->setup(newcon, console_cmdline[i].options) != 0)
 		    newcon->setup(newcon, console_cmdline[i].options) != 0)
 			break;
 			break;
 		newcon->flags |= CON_ENABLED;
 		newcon->flags |= CON_ENABLED;
-		newcon->index = c->index;
 		if (i == selected_console) {
 		if (i == selected_console) {
 			newcon->flags |= CON_CONSDEV;
 			newcon->flags |= CON_CONSDEV;
 			preferred_console = selected_console;
 			preferred_console = selected_console;