[linux-yocto] [PATCH 1/2] valleyisland-io: add baytrail io patch for HSUART controller support

rebecca.swee.fun.chang at intel.com rebecca.swee.fun.chang at intel.com
Wed Dec 11 01:41:51 PST 2013


From: "Chang, Rebecca Swee Fun" <rebecca.swee.fun.chang at intel.com>

Baytrail has two HSUART controllers which can be PCI or ACPI enumerated.

Signed-off-by: Chang, Rebecca Swee Fun <rebecca.swee.fun.chang at intel.com>
---
 ...-Add-support-for-HSUART-controllers-on-In.patch | 1295 ++++++++++++++++++++
 1 file changed, 1295 insertions(+)
 create mode 100644 meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch

diff --git a/meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch b/meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch
new file mode 100644
index 0000000..6f9b8e8
--- /dev/null
+++ b/meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch
@@ -0,0 +1,1295 @@
+serial/8250: Add support for HSUART controllers on Baytrail
+
+Baytrail has two HSUART controllers which can be PCI or ACPI enumerated.
+
+Signed-off-by: Chang, Rebecca Swee Fun <rebecca.swee.fun.chang at intel.com>
+---
+ drivers/tty/serial/8250/8250.c       |   72 +++++--
+ drivers/tty/serial/8250/8250.h       |   55 +++++
+ drivers/tty/serial/8250/8250_dma.c   |  222 ++++++++++++++++++++
+ drivers/tty/serial/8250/8250_dw.c    |  378 +++++++++++++++++++++++++++++-----
+ drivers/tty/serial/8250/8250_early.c |    2 +-
+ drivers/tty/serial/8250/8250_pci.c   |  190 +++++++++++++++++
+ drivers/tty/serial/8250/Kconfig      |   10 +-
+ drivers/tty/serial/8250/Makefile     |    1 +
+ include/linux/serial_8250.h          |    4 +
+ 9 files changed, 873 insertions(+), 61 deletions(-)
+ create mode 100644 drivers/tty/serial/8250/8250_dma.c
+
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index f932043..469a83c 100644
+--- a/drivers/tty/serial/8250/8250.c
++++ b/drivers/tty/serial/8250/8250.c
+@@ -1341,7 +1341,9 @@ static void serial8250_start_tx(struct uart_port *port)
+ 	struct uart_8250_port *up =
+ 		container_of(port, struct uart_8250_port, port);
+
+-	if (!(up->ier & UART_IER_THRI)) {
++	if (up->dma && !serial8250_tx_dma(up)) {
++		return;
++	} else if (!(up->ier & UART_IER_THRI)) {
+ 		up->ier |= UART_IER_THRI;
+ 		serial_port_out(port, UART_IER, up->ier);
+
+@@ -1397,7 +1399,6 @@ unsigned char
+ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+ {
+ 	struct uart_port *port = &up->port;
+-	struct tty_struct *tty = port->state->port.tty;
+ 	unsigned char ch;
+ 	int max_count = 256;
+ 	char flag;
+@@ -1462,7 +1463,7 @@ ignore_char:
+ 		lsr = serial_in(up, UART_LSR);
+ 	} while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+ 	spin_unlock(&port->lock);
+-	tty_flip_buffer_push(tty);
++	tty_flip_buffer_push(&port->state->port);
+ 	spin_lock(&port->lock);
+ 	return lsr;
+ }
+@@ -1518,6 +1519,10 @@ unsigned int serial8250_modem_status(struct uart_8250_port *up)
+ 	struct uart_port *port = &up->port;
+ 	unsigned int status = serial_in(up, UART_MSR);
+
++	if (up->ier & UART_IER_MSI && up->mcr & UART_MCR_AFE) {
++		status &= ~(UART_MSR_DCTS);
++		status |= UART_MSR_CTS;
++	}
+ 	status |= up->msr_saved_flags;
+ 	up->msr_saved_flags = 0;
+ 	if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+@@ -1547,20 +1552,34 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+ 	unsigned long flags;
+ 	struct uart_8250_port *up =
+ 		container_of(port, struct uart_8250_port, port);
++	int dma_err = 0;
+
+ 	if (iir & UART_IIR_NO_INT)
+ 		return 0;
+
+ 	spin_lock_irqsave(&port->lock, flags);
+
++	if( (up->port.dev->id == PCI_DEVICE_ID_INTEL_BYT_UART1 ||
++		up->port.dev->id == PCI_DEVICE_ID_INTEL_BYT_UART2) &&
++		(iir & UART_IIR_RLSI) )  {
++
++		readl(port->membase + LPSS_UART_BYTE_CNT);
++		readl(port->membase + LPSS_UART_OVRFLW_INTR_STAT);
++	}
++
+ 	status = serial_port_in(port, UART_LSR);
+
+ 	DEBUG_INTR("status = %x...", status);
+
+-	if (status & (UART_LSR_DR | UART_LSR_BI))
+-		status = serial8250_rx_chars(up, status);
++	if (status & (UART_LSR_DR | UART_LSR_BI)) {
++		if (up->dma)
++			dma_err = serial8250_rx_dma(up, iir);
++
++		if (!up->dma || dma_err)
++			status = serial8250_rx_chars(up, status);
++	}
+ 	serial8250_modem_status(up);
+-	if (status & UART_LSR_THRE)
++	if (status & UART_LSR_THRE && (iir & 0x3f) == UART_IIR_THRI)
+ 		serial8250_tx_chars(up);
+
+ 	spin_unlock_irqrestore(&port->lock, flags);
+@@ -1991,9 +2010,12 @@ static int serial8250_startup(struct uart_port *port)
+ 	if (port->type == PORT_8250_CIR)
+ 		return -ENODEV;
+
+-	port->fifosize = uart_config[up->port.type].fifo_size;
+-	up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+-	up->capabilities = uart_config[up->port.type].flags;
++	if (!port->fifosize)
++		port->fifosize = uart_config[port->type].fifo_size;
++	if (!up->tx_loadsz)
++		up->tx_loadsz = uart_config[port->type].tx_loadsz;
++	if (!up->capabilities)
++		up->capabilities = uart_config[port->type].flags;
+ 	up->mcr = 0;
+
+ 	if (port->iotype != up->cur_iotype)
+@@ -2198,6 +2220,18 @@ dont_test_tx_en:
+ 	up->msr_saved_flags = 0;
+
+ 	/*
++	 * Request DMA channels for both RX and TX.
++	 */
++	if (up->dma) {
++		retval = serial8250_request_dma(up);
++		if (retval) {
++			pr_warn_ratelimited("ttyS%d - failed to request DMA\n",
++					    serial_index(port));
++			up->dma = NULL;
++		}
++	}
++
++	/*
+ 	 * 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.
+@@ -2230,6 +2264,9 @@ static void serial8250_shutdown(struct uart_port *port)
+ 	up->ier = 0;
+ 	serial_port_out(port, UART_IER, 0);
+
++	if (up->dma)
++		serial8250_release_dma(up);
++
+ 	spin_lock_irqsave(&port->lock, flags);
+ 	if (port->flags & UPF_FOURPORT) {
+ 		/* reset interrupts on the AST Fourport board */
+@@ -2344,7 +2381,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+
+ 	if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
+ 		fcr = uart_config[port->type].fcr;
+-		if (baud < 2400 || fifo_bug) {
++		if (baud < 2400 && !up->dma || fifo_bug) {
+ 			fcr &= ~UART_FCR_TRIGGER_MASK;
+ 			fcr |= UART_FCR_TRIGGER_1;
+ 		}
+@@ -2826,9 +2863,12 @@ static void
+ serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
+ {
+ 	up->port.type = type;
+-	up->port.fifosize = uart_config[type].fifo_size;
+-	up->capabilities = uart_config[type].flags;
+-	up->tx_loadsz = uart_config[type].tx_loadsz;
++	if (!up->port.fifosize)
++		up->port.fifosize = uart_config[type].fifo_size;
++	if (!up->tx_loadsz)
++		up->tx_loadsz = uart_config[type].tx_loadsz;
++	if (!up->capabilities)
++		up->capabilities = uart_config[type].flags;
+ }
+
+ static void __init
+@@ -3262,6 +3302,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
+ 		uart->bugs		= up->bugs;
+ 		uart->port.mapbase      = up->port.mapbase;
+ 		uart->port.private_data = up->port.private_data;
++		uart->port.fifosize	= up->port.fifosize;
++		uart->tx_loadsz		= up->tx_loadsz;
++		uart->capabilities	= up->capabilities;
++
+ 		if (up->port.dev)
+ 			uart->port.dev = up->port.dev;
+
+@@ -3287,6 +3331,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
+ 			uart->dl_read = up->dl_read;
+ 		if (up->dl_write)
+ 			uart->dl_write = up->dl_write;
++		if (up->dma)
++			uart->dma = up->dma;
+
+ 		if (serial8250_isa_config != NULL)
+ 			serial8250_isa_config(0, &uart->port,
+diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
+index 12caa12..aa97212 100644
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -12,6 +12,35 @@
+  */
+
+ #include <linux/serial_8250.h>
++#include <linux/dmaengine.h>
++
++struct uart_8250_dma {
++	dma_filter_fn		fn;
++	void			*rx_param;
++	void			*tx_param;
++
++	int			rx_chan_id;
++	int			tx_chan_id;
++
++	struct dma_slave_config	rxconf;
++	struct dma_slave_config	txconf;
++
++	struct dma_chan		*rxchan;
++	struct dma_chan		*txchan;
++
++	dma_addr_t		rx_addr;
++	dma_addr_t		tx_addr;
++
++	dma_cookie_t		rx_cookie;
++	dma_cookie_t		tx_cookie;
++
++	void			*rx_buf;
++
++	size_t			rx_size;
++	size_t			tx_size;
++
++	unsigned char		tx_running:1;
++};
+
+ struct old_serial_port {
+ 	unsigned int uart;
+@@ -59,6 +88,11 @@ struct serial8250_config {
+ #define SERIAL8250_SHARE_IRQS 0
+ #endif
+
++#define PCI_DEVICE_ID_INTEL_BYT_UART1	0x0f0a
++#define PCI_DEVICE_ID_INTEL_BYT_UART2	0x0f0c
++#define LPSS_UART_BYTE_CNT		0x818
++#define LPSS_UART_OVRFLW_INTR_STAT	0x820
++
+ static inline int serial_in(struct uart_8250_port *up, int offset)
+ {
+ 	return up->port.serial_in(&up->port, offset);
+@@ -143,3 +177,24 @@ static inline int is_omap1510_8250(struct uart_8250_port *pt)
+ 	return 0;
+ }
+ #endif
++
++#ifdef CONFIG_SERIAL_8250_DMA
++extern int serial8250_tx_dma(struct uart_8250_port *);
++extern int serial8250_rx_dma(struct uart_8250_port *, unsigned int iir);
++extern int serial8250_request_dma(struct uart_8250_port *);
++extern void serial8250_release_dma(struct uart_8250_port *);
++#else
++static inline int serial8250_tx_dma(struct uart_8250_port *p)
++{
++	return -1;
++}
++static inline int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
++{
++	return -1;
++}
++static inline int serial8250_request_dma(struct uart_8250_port *p)
++{
++	return -1;
++}
++static inline void serial8250_release_dma(struct uart_8250_port *p) { }
++#endif
+diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
+new file mode 100644
+index 0000000..29d45e7
+--- /dev/null
++++ b/drivers/tty/serial/8250/8250_dma.c
+@@ -0,0 +1,222 @@
++/*
++ * 8250_dma.c - DMA Engine API support for 8250.c
++ *
++ * Copyright (C) 2013 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; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial_reg.h>
++#include <linux/dma-mapping.h>
++
++#include "8250.h"
++
++static void __dma_tx_complete(void *param)
++{
++	struct uart_8250_port	*p = param;
++	struct uart_8250_dma	*dma = p->dma;
++	struct circ_buf		*xmit = &p->port.state->xmit;
++
++	dma->tx_running = 0;
++
++	dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
++				UART_XMIT_SIZE, DMA_TO_DEVICE);
++
++	xmit->tail += dma->tx_size;
++	xmit->tail &= UART_XMIT_SIZE - 1;
++	p->port.icount.tx += dma->tx_size;
++
++	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++		uart_write_wakeup(&p->port);
++
++	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port))
++		serial8250_tx_dma(p);
++}
++
++static void __dma_rx_complete(void *param)
++{
++	struct uart_8250_port	*p = param;
++	struct uart_8250_dma	*dma = p->dma;
++	struct tty_port		*tty_port = &p->port.state->port;
++	struct dma_tx_state	state;
++	int			count;
++
++	dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr,
++				dma->rx_size, DMA_FROM_DEVICE);
++
++	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
++	dmaengine_terminate_all(dma->rxchan);
++
++	count = dma->rx_size - state.residue;
++
++	tty_insert_flip_string(tty_port, dma->rx_buf, count);
++	p->port.icount.rx += count;
++
++	tty_flip_buffer_push(tty_port);
++}
++
++int serial8250_tx_dma(struct uart_8250_port *p)
++{
++	struct uart_8250_dma		*dma = p->dma;
++	struct circ_buf			*xmit = &p->port.state->xmit;
++	struct dma_async_tx_descriptor	*desc;
++
++	if (uart_tx_stopped(&p->port) || dma->tx_running
++	    || uart_circ_empty(xmit))
++		return 0;
++
++	dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
++
++	desc = dmaengine_prep_slave_single(dma->txchan,
++					   dma->tx_addr + xmit->tail,
++					   dma->tx_size, DMA_MEM_TO_DEV,
++					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++	if (!desc)
++		return -EBUSY;
++
++	dma->tx_running = 1;
++
++	desc->callback = __dma_tx_complete;
++	desc->callback_param = p;
++
++	dma->tx_cookie = dmaengine_submit(desc);
++
++	dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr,
++				   UART_XMIT_SIZE, DMA_TO_DEVICE);
++
++	dma_async_issue_pending(dma->txchan);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(serial8250_tx_dma);
++
++int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
++{
++	struct uart_8250_dma		*dma = p->dma;
++	struct dma_async_tx_descriptor	*desc;
++	struct dma_tx_state		state;
++	int				dma_status;
++
++	dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
++
++	switch (iir & 0x3f) {
++	case UART_IIR_RLSI:
++		/* 8250.c handles errors and break interrupts */
++		return -EIO;
++	case UART_IIR_RX_TIMEOUT:
++		/*
++		 * If RCVR FIFO trigger level was not reached, complete the
++		 * transfer and let 8250.c copy the remaining data.
++		 */
++		if (dma_status == DMA_IN_PROGRESS) {
++			dmaengine_pause(dma->rxchan);
++			__dma_rx_complete(p);
++		}
++		return -ETIMEDOUT;
++	default:
++		break;
++	}
++
++	if (dma_status)
++		return 0;
++
++	desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
++					   dma->rx_size, DMA_DEV_TO_MEM,
++					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++	if (!desc)
++		return -EBUSY;
++
++	desc->callback = __dma_rx_complete;
++	desc->callback_param = p;
++
++	dma->rx_cookie = dmaengine_submit(desc);
++
++	dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr,
++				   dma->rx_size, DMA_FROM_DEVICE);
++
++	dma_async_issue_pending(dma->rxchan);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(serial8250_rx_dma);
++
++int serial8250_request_dma(struct uart_8250_port *p)
++{
++	struct uart_8250_dma	*dma = p->dma;
++	dma_cap_mask_t		mask;
++
++	dma->rxconf.src_addr = p->port.mapbase + UART_RX;
++	dma->txconf.dst_addr = p->port.mapbase + UART_TX;
++
++	dma_cap_zero(mask);
++	dma_cap_set(DMA_SLAVE, mask);
++
++	/* Get a channel for RX */
++	dma->rxchan = dma_request_channel(mask, dma->fn, dma->rx_param);
++	if (!dma->rxchan)
++		return -ENODEV;
++
++	dmaengine_slave_config(dma->rxchan, &dma->rxconf);
++
++	/* Get a channel for TX */
++	dma->txchan = dma_request_channel(mask, dma->fn, dma->tx_param);
++	if (!dma->txchan) {
++		dma_release_channel(dma->rxchan);
++		return -ENODEV;
++	}
++
++	dmaengine_slave_config(dma->txchan, &dma->txconf);
++
++	/* RX buffer */
++	if (!dma->rx_size)
++		dma->rx_size = PAGE_SIZE;
++
++	dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size,
++					&dma->rx_addr, GFP_KERNEL);
++	if (!dma->rx_buf) {
++		dma_release_channel(dma->rxchan);
++		dma_release_channel(dma->txchan);
++		return -ENOMEM;
++	}
++
++	/* TX buffer */
++	dma->tx_addr = dma_map_single(dma->txchan->device->dev,
++					p->port.state->xmit.buf,
++					UART_XMIT_SIZE,
++					DMA_TO_DEVICE);
++
++	dev_dbg_ratelimited(p->port.dev, "got both dma channels\n");
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(serial8250_request_dma);
++
++void serial8250_release_dma(struct uart_8250_port *p)
++{
++	struct uart_8250_dma *dma = p->dma;
++
++	if (!dma)
++		return;
++
++	/* Release RX resources */
++	dmaengine_terminate_all(dma->rxchan);
++	dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf,
++			  dma->rx_addr);
++	dma_release_channel(dma->rxchan);
++	dma->rxchan = NULL;
++
++	/* Release TX resources */
++	dmaengine_terminate_all(dma->txchan);
++	dma_unmap_single(dma->txchan->device->dev, dma->tx_addr,
++			 UART_XMIT_SIZE, DMA_TO_DEVICE);
++	dma_release_channel(dma->txchan);
++	dma->txchan = NULL;
++	dma->tx_running = 0;
++
++	dev_dbg_ratelimited(p->port.dev, "dma channels released\n");
++}
++EXPORT_SYMBOL_GPL(serial8250_release_dma);
+diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
+index 096d2ef..1d8ed86 100644
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -2,6 +2,7 @@
+  * Synopsys DesignWare 8250 driver.
+  *
+  * Copyright 2011 Picochip, Jamie Iles.
++ * Copyright 2013 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
+@@ -24,10 +25,42 @@
+ #include <linux/of_platform.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
++#include <linux/acpi.h>
++#include <linux/pm_runtime.h>
++#include <linux/clk.h>
++
++#include "8250.h"
++
++static bool use_dma = 1;
++module_param(use_dma, bool, 0);
++MODULE_PARM_DESC(use_dma, "use_dma=1 (enable DMA)/use_dma=0(disable DMA)");
++
++/* Offsets for the DesignWare specific registers */
++#define DW_UART_USR	0x1f /* UART Status Register */
++#define DW_UART_CPR	0xf4 /* Component Parameter Register */
++#define DW_UART_UCV	0xf8 /* UART Component Version */
++
++/* Component Parameter Register bits */
++#define DW_UART_CPR_ABP_DATA_WIDTH	(3 << 0)
++#define DW_UART_CPR_AFCE_MODE		(1 << 4)
++#define DW_UART_CPR_THRE_MODE		(1 << 5)
++#define DW_UART_CPR_SIR_MODE		(1 << 6)
++#define DW_UART_CPR_SIR_LP_MODE		(1 << 7)
++#define DW_UART_CPR_ADDITIONAL_FEATURES	(1 << 8)
++#define DW_UART_CPR_FIFO_ACCESS		(1 << 9)
++#define DW_UART_CPR_FIFO_STAT		(1 << 10)
++#define DW_UART_CPR_SHADOW		(1 << 11)
++#define DW_UART_CPR_ENCODED_PARMS	(1 << 12)
++#define DW_UART_CPR_DMA_EXTRA		(1 << 13)
++#define DW_UART_CPR_FIFO_MODE		(0xff << 16)
++/* Helper for fifo size calculation */
++#define DW_UART_CPR_FIFO_SIZE(a)	(((a >> 16) & 0xff) * 16)
++
+
+ struct dw8250_data {
+ 	int	last_lcr;
+ 	int	line;
++	struct clk *clk;
+ };
+
+ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
+@@ -66,19 +99,79 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
+ 	return readl(p->membase + offset);
+ }
+
+-/* Offset for the DesignWare's UART Status Register. */
+-#define UART_USR	0x1f
++#define LPSS_PRV_CLK                   0x800
++#define LPSS_PRV_CLK_EN                        (1 << 0)
++#define LPSS_PRV_CLK_M_VAL_SHIFT       1
++#define LPSS_PRV_CLK_N_VAL_SHIFT       16
++#define LPSS_PRV_CLK_UPDATE            (1 << 31)
++
++#define LPSS_HSUART_GENERAL_REG		0x808
++#define LPSS_GENERAL_DIS_RTS_N_OVERRIDE	(1 << 3)
++
++static void
++dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
++		   struct ktermios *old)
++{
++	struct uart_8250_port *up =
++		container_of(p, struct uart_8250_port, port);
++	unsigned int baud = tty_termios_baud_rate(termios);
++	unsigned int m = 6912;
++	unsigned int n = 15625;
++	u32 reg;
++
++	/*
++	 * For baud rates 1000000, 2000000 and 4000000 the dividers must be
++	 * adjusted.
++	 */
++	if (baud == 1000000 || baud == 2000000 || baud == 4000000) {
++		m = 64;
++		n = 100;
++
++		p->uartclk = 64000000;
++	} else if (baud == 3000000){
++		m = 48;
++		n = 100;
++
++		p->uartclk = 48000000;
++	}else {
++		p->uartclk = 44236800;
++	}
++
++	/* Reset the clock */
++	reg = (m << LPSS_PRV_CLK_M_VAL_SHIFT) | (n << LPSS_PRV_CLK_N_VAL_SHIFT);
++	writel(reg, p->membase + LPSS_PRV_CLK);
++	reg |= LPSS_PRV_CLK_EN | LPSS_PRV_CLK_UPDATE;
++	writel(reg, p->membase + LPSS_PRV_CLK);
++
++	/* For BYT, hs-uart is capable of auto flow control */
++	up->capabilities |= UART_CAP_AFE;
++
++	/* If auto-handshake mechanism is not enabled,
++	 * disable rts_n override */
++	reg = readl(p->membase + LPSS_HSUART_GENERAL_REG);
++	reg &= ~LPSS_GENERAL_DIS_RTS_N_OVERRIDE;
++	if (termios->c_cflag & CRTSCTS)
++		reg |= LPSS_GENERAL_DIS_RTS_N_OVERRIDE;
++	writel(reg, p->membase + LPSS_HSUART_GENERAL_REG);
++
++	serial8250_do_set_termios(p, termios, old);
++}
+
+ static int dw8250_handle_irq(struct uart_port *p)
+ {
+ 	struct dw8250_data *d = p->private_data;
+ 	unsigned int iir = p->serial_in(p, UART_IIR);
+
++	if(iir & UART_IIR_RLSI) {
++		readl(p->membase + LPSS_UART_BYTE_CNT);
++		readl(p->membase + LPSS_UART_OVRFLW_INTR_STAT);
++	}
++
+ 	if (serial8250_handle_irq(p, iir)) {
+ 		return 1;
+ 	} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
+ 		/* Clear the USR and write the LCR again. */
+-		(void)p->serial_in(p, UART_USR);
++		(void)p->serial_in(p, DW_UART_USR);
+ 		p->serial_out(p, UART_LCR, d->last_lcr);
+
+ 		return 1;
+@@ -87,61 +180,216 @@ static int dw8250_handle_irq(struct uart_port *p)
+ 	return 0;
+ }
+
++static void
++dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
++{
++	if (!state)
++		pm_runtime_get_sync(port->dev);
++
++	serial8250_do_pm(port, state, old);
++
++	if (state)
++		pm_runtime_put_sync_suspend(port->dev);
++}
++
++static int dw8250_probe_of(struct uart_port *p)
++{
++	struct device_node	*np = p->dev->of_node;
++	u32			val;
++
++	if (!of_property_read_u32(np, "reg-io-width", &val)) {
++		switch (val) {
++		case 1:
++			break;
++		case 4:
++			p->iotype = UPIO_MEM32;
++			p->serial_in = dw8250_serial_in32;
++			p->serial_out = dw8250_serial_out32;
++			break;
++		default:
++			dev_err(p->dev, "unsupported reg-io-width (%u)\n", val);
++			return -EINVAL;
++		}
++	}
++
++	if (!of_property_read_u32(np, "reg-shift", &val))
++		p->regshift = val;
++
++	if (of_property_read_u32(np, "clock-frequency", &val)) {
++		dev_err(p->dev, "no clock-frequency property set\n");
++		return -EINVAL;
++	}
++	p->uartclk = val;
++
++	return 0;
++}
++
++#ifdef CONFIG_ACPI
++static bool dw8250_acpi_dma_filter(struct dma_chan *chan, void *parm)
++{
++	return chan->chan_id == *(int *)parm;
++}
++
++static acpi_status
++dw8250_acpi_walk_resource(struct acpi_resource *res, void *data)
++{
++	struct uart_port		*p = data;
++	struct uart_8250_port		*port;
++	struct uart_8250_dma		*dma;
++	struct acpi_resource_fixed_dma	*fixed_dma;
++	struct dma_slave_config		*slave;
++
++	port = container_of(p, struct uart_8250_port, port);
++
++	switch (res->type) {
++	case ACPI_RESOURCE_TYPE_FIXED_DMA:
++		fixed_dma = &res->data.fixed_dma;
++
++		/* TX comes first */
++		if (!port->dma) {
++			dma = devm_kzalloc(p->dev, sizeof(*dma), GFP_KERNEL);
++			if (!dma)
++				return AE_NO_MEMORY;
++
++			port->dma = dma;
++			slave = &dma->txconf;
++
++			slave->direction	= DMA_MEM_TO_DEV;
++			slave->dst_addr_width	= DMA_SLAVE_BUSWIDTH_1_BYTE;
++			slave->slave_id		= fixed_dma->request_lines;
++			slave->dst_maxburst	= port->tx_loadsz / 4;
++
++			dma->tx_chan_id		= fixed_dma->channels;
++			dma->tx_param		= &dma->tx_chan_id;
++			dma->fn			= dw8250_acpi_dma_filter;
++		} else {
++			dma = port->dma;
++			slave = &dma->rxconf;
++
++			slave->direction	= DMA_DEV_TO_MEM;
++			slave->src_addr_width	= DMA_SLAVE_BUSWIDTH_1_BYTE;
++			slave->slave_id		= fixed_dma->request_lines;
++			slave->src_maxburst	= p->fifosize / 4;
++
++			dma->rx_chan_id		= fixed_dma->channels;
++			dma->rx_param		= &dma->rx_chan_id;
++		}
++
++		break;
++	}
++
++	return AE_OK;
++}
++
++static int dw8250_probe_acpi(struct uart_port *p)
++{
++	struct dw8250_data *data = p->private_data;
++	acpi_status status;
++
++	p->iotype = UPIO_MEM32;
++	p->serial_in = dw8250_serial_in32;
++	p->serial_out = dw8250_serial_out32;
++	p->set_termios = dw8250_set_termios;
++	p->regshift = 2;
++	p->uartclk = clk_get_rate(data->clk);
++
++	if (use_dma){
++		status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS,
++				     dw8250_acpi_walk_resource, p);
++		if (ACPI_FAILURE(status)) {
++			dev_err_ratelimited(p->dev, "%s failed \"%s\"\n", __func__,
++				    acpi_format_exception(status));
++			return -ENODEV;
++		}
++	}
++	return 0;
++}
++#else
++static inline int dw8250_probe_acpi(struct uart_port *p)
++{
++	return -ENODEV;
++}
++#endif /* CONFIG_ACPI */
++
++static void dw8250_setup_port(struct uart_8250_port *up)
++{
++	struct uart_port	*p = &up->port;
++	u32			reg = readl(p->membase + DW_UART_UCV);
++
++	/*
++	 * If the Component Version Register returns zero, we know that
++	 * ADDITIONAL_FEATURES are not enabled. No need to go any further.
++	 */
++	if (!reg)
++		return;
++
++	dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
++		(reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
++
++	reg = readl(p->membase + DW_UART_CPR);
++	if (!reg)
++		return;
++
++	/* Select the type based on fifo */
++	if (reg & DW_UART_CPR_FIFO_MODE) {
++		p->type = PORT_16550A;
++		p->flags |= UPF_FIXED_TYPE;
++		p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
++		up->tx_loadsz = p->fifosize;
++	}
++}
++
+ static int dw8250_probe(struct platform_device *pdev)
+ {
+ 	struct uart_8250_port uart = {};
+ 	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+-	struct device_node *np = pdev->dev.of_node;
+-	u32 val;
+ 	struct dw8250_data *data;
++	int err;
+
+ 	if (!regs || !irq) {
+ 		dev_err(&pdev->dev, "no registers/irq defined\n");
+ 		return -EINVAL;
+ 	}
+
+-	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+-	if (!data)
+-		return -ENOMEM;
+-	uart.port.private_data = data;
+-
+ 	spin_lock_init(&uart.port.lock);
+ 	uart.port.mapbase = regs->start;
+ 	uart.port.irq = irq->start;
+ 	uart.port.handle_irq = dw8250_handle_irq;
++	uart.port.pm = dw8250_do_pm;
+ 	uart.port.type = PORT_8250;
+-	uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
+-		UPF_FIXED_PORT | UPF_FIXED_TYPE;
++	uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
+ 	uart.port.dev = &pdev->dev;
+
++	uart.port.membase = ioremap(regs->start, resource_size(regs));
++	if (!uart.port.membase)
++		return -ENOMEM;
++
++	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
+ 	uart.port.iotype = UPIO_MEM;
+ 	uart.port.serial_in = dw8250_serial_in;
+ 	uart.port.serial_out = dw8250_serial_out;
+-	if (!of_property_read_u32(np, "reg-io-width", &val)) {
+-		switch (val) {
+-		case 1:
+-			break;
+-		case 4:
+-			uart.port.iotype = UPIO_MEM32;
+-			uart.port.serial_in = dw8250_serial_in32;
+-			uart.port.serial_out = dw8250_serial_out32;
+-			break;
+-		default:
+-			dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n",
+-				val);
+-			return -EINVAL;
+-		}
+-	}
+-
+-	if (!of_property_read_u32(np, "reg-shift", &val))
+-		uart.port.regshift = val;
++	uart.port.private_data = data;
+
+-	if (of_property_read_u32(np, "clock-frequency", &val)) {
+-		dev_err(&pdev->dev, "no clock-frequency property set\n");
+-		return -EINVAL;
++	data->clk = devm_clk_get(&pdev->dev, NULL);
++	clk_prepare_enable(data->clk);
++
++	dw8250_setup_port(&uart);
++
++	if (pdev->dev.of_node) {
++		err = dw8250_probe_of(&uart.port);
++		if (err)
++			return err;
++	} else if (ACPI_HANDLE(&pdev->dev)) {
++		err = dw8250_probe_acpi(&uart.port);
++		if (err)
++			return err;
++	} else {
++		return -ENODEV;
+ 	}
+-	uart.port.uartclk = val;
+
+ 	data->line = serial8250_register_8250_port(&uart);
+ 	if (data->line < 0)
+@@ -149,6 +397,8 @@ static int dw8250_probe(struct platform_device *pdev)
+
+ 	platform_set_drvdata(pdev, data);
+
++	pm_runtime_forbid(&pdev->dev);
++
+ 	return 0;
+ }
+
+@@ -156,50 +406,86 @@ static int dw8250_remove(struct platform_device *pdev)
+ {
+ 	struct dw8250_data *data = platform_get_drvdata(pdev);
+
++	pm_runtime_get_sync(&pdev->dev);
++
+ 	serial8250_unregister_port(data->line);
++	clk_disable_unprepare(data->clk);
++
++	pm_runtime_disable(&pdev->dev);
++	pm_runtime_put_noidle(&pdev->dev);
+
+ 	return 0;
+ }
+
+ #ifdef CONFIG_PM
+-static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
++static int dw8250_suspend(struct device *dev)
+ {
+-	struct dw8250_data *data = platform_get_drvdata(pdev);
++	struct dw8250_data *data = dev_get_drvdata(dev);
+
+ 	serial8250_suspend_port(data->line);
+
+ 	return 0;
+ }
+
+-static int dw8250_resume(struct platform_device *pdev)
++static int dw8250_resume(struct device *dev)
+ {
+-	struct dw8250_data *data = platform_get_drvdata(pdev);
++	struct dw8250_data *data = dev_get_drvdata(dev);
+
+ 	serial8250_resume_port(data->line);
+
+ 	return 0;
+ }
+-#else
+-#define dw8250_suspend NULL
+-#define dw8250_resume NULL
+ #endif /* CONFIG_PM */
+
+-static const struct of_device_id dw8250_match[] = {
++#ifdef CONFIG_PM_RUNTIME
++static int dw8250_runtime_suspend(struct device *dev)
++{
++	struct dw8250_data *data = dev_get_drvdata(dev);
++
++	clk_disable_unprepare(data->clk);
++
++	return 0;
++}
++
++static int dw8250_runtime_resume(struct device *dev)
++{
++	struct dw8250_data *data = dev_get_drvdata(dev);
++
++	clk_prepare_enable(data->clk);
++
++	return 0;
++}
++#endif
++
++static const struct dev_pm_ops dw8250_pm_ops = {
++	SET_SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume)
++	SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
++};
++
++static const struct of_device_id dw8250_of_match[] = {
+ 	{ .compatible = "snps,dw-apb-uart" },
+ 	{ /* Sentinel */ }
+ };
+-MODULE_DEVICE_TABLE(of, dw8250_match);
++MODULE_DEVICE_TABLE(of, dw8250_of_match);
++
++static const struct acpi_device_id dw8250_acpi_match[] = {
++	{ "80860F0A", 0 },
++	{ "INT33C4", 0 },
++	{ "INT33C5", 0 },
++	{ },
++};
++MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
+
+ static struct platform_driver dw8250_platform_driver = {
+ 	.driver = {
+ 		.name		= "dw-apb-uart",
+ 		.owner		= THIS_MODULE,
+-		.of_match_table	= dw8250_match,
++		.pm		= &dw8250_pm_ops,
++		.of_match_table	= dw8250_of_match,
++		.acpi_match_table = ACPI_PTR(dw8250_acpi_match),
+ 	},
+ 	.probe			= dw8250_probe,
+ 	.remove			= dw8250_remove,
+-	.suspend		= dw8250_suspend,
+-	.resume			= dw8250_resume,
+ };
+
+ module_platform_driver(dw8250_platform_driver);
+diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
+index f53a7db..721904f 100644
+--- a/drivers/tty/serial/8250/8250_early.c
++++ b/drivers/tty/serial/8250/8250_early.c
+@@ -194,7 +194,7 @@ static int __init parse_options(struct early_serial8250_device *device,
+ 		options++;
+ 		device->baud = simple_strtoul(options, NULL, 0);
+ 		length = min(strcspn(options, " "), sizeof(device->options));
+-		strncpy(device->options, options, length);
++		strlcpy(device->options, options, length);
+ 	} else {
+ 		device->baud = probe_baud(port);
+ 		snprintf(device->options, sizeof(device->options), "%u",
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index a27a98e..27b82d4 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -1077,6 +1077,134 @@ ce4100_serial_setup(struct serial_private *priv,
+ 	return ret;
+ }
+
++static bool lpss_dma_filter(struct dma_chan *chan, void *param)
++{
++	return chan->chan_id == *(int*)param;
++}
++
++#define PCI_DEVICE_ID_INTEL_HSW_UART1	0x9c63
++#define PCI_DEVICE_ID_INTEL_HSW_UART2	0x9c64
++
++#define LPSS_PRV_CLK			0x800
++#define LPSS_PRV_CLK_EN			(1 << 0)
++#define LPSS_PRV_CLK_M_VAL_SHIFT	1
++#define LPSS_PRV_CLK_N_VAL_SHIFT	16
++#define LPSS_PRV_CLK_UPDATE		(1 << 31)
++
++#define LPSS_HSUART_GENERAL_REG		0x808
++#define LPSS_GENERAL_DIS_RTS_N_OVERRIDE	(1 << 3)
++
++static void
++lpss_set_termios(struct uart_port *p, struct ktermios *termios,
++		   struct ktermios *old)
++{
++	struct uart_8250_port *up =
++		container_of(p, struct uart_8250_port, port);
++	unsigned int baud = tty_termios_baud_rate(termios);
++	unsigned int m = 6912;
++	unsigned int n = 15625;
++	u32 reg;
++
++	/*
++	 * For baud rates 1000000, 2000000 and 4000000 the dividers must be
++	 * adjusted.
++	 */
++	if (baud == 1000000 || baud == 2000000 || baud == 4000000) {
++		m = 64;
++		n = 100;
++
++		p->uartclk = 64000000;
++	} else if (baud == 3000000){
++                m = 48;
++                n = 100;
++
++                p->uartclk = 48000000;
++	} else {
++		p->uartclk = 44236800;
++	}
++
++	/* Reset the clock */
++	reg = (m << LPSS_PRV_CLK_M_VAL_SHIFT) | (n << LPSS_PRV_CLK_N_VAL_SHIFT);
++	writel(reg, p->membase + LPSS_PRV_CLK);
++	reg |= LPSS_PRV_CLK_EN | LPSS_PRV_CLK_UPDATE;
++	writel(reg, p->membase + LPSS_PRV_CLK);
++
++	/* For BYT, hs-uart is capable of auto flow control */
++	up->capabilities |= UART_CAP_AFE;
++
++	/*
++	 * If auto-handshake mechanism is not enabled,
++	 * disable rts_n override
++	 */
++	reg = readl(p->membase + LPSS_HSUART_GENERAL_REG);
++	reg &= ~LPSS_GENERAL_DIS_RTS_N_OVERRIDE;
++	if (termios->c_cflag & CRTSCTS)
++		reg |= LPSS_GENERAL_DIS_RTS_N_OVERRIDE;
++	writel(reg, p->membase + LPSS_HSUART_GENERAL_REG);
++
++	serial8250_do_set_termios(p, termios, old);
++}
++
++static int
++lpss_serial_setup(struct serial_private *priv,
++		const struct pciserial_board *board,
++		struct uart_8250_port *port, int idx)
++{
++	struct uart_8250_dma *dma;
++	int ret;
++
++	dma = devm_kzalloc(port->port.dev, sizeof(*dma), GFP_KERNEL);
++	if (!dma)
++		return -ENOMEM;
++
++	switch (priv->dev->device) {
++	case PCI_DEVICE_ID_INTEL_BYT_UART1:
++		dma->rx_chan_id = 3;
++		dma->rxconf.slave_id = dma->rx_chan_id;
++		dma->tx_chan_id = 2;
++		dma->txconf.slave_id = dma->tx_chan_id;
++		break;
++	case PCI_DEVICE_ID_INTEL_BYT_UART2:
++		dma->rx_chan_id = 5;
++		dma->rxconf.slave_id = dma->rx_chan_id;
++		dma->tx_chan_id = 4;
++		dma->txconf.slave_id = dma->tx_chan_id;
++		break;
++	case PCI_DEVICE_ID_INTEL_HSW_UART1:
++		dma->rx_chan_id = 5;
++		dma->rxconf.slave_id = 21;
++		dma->tx_chan_id = 4;
++		dma->txconf.slave_id = 20;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	dma->rxconf.direction = DMA_DEV_TO_MEM;
++	dma->rxconf.src_addr_width = 1;
++	dma->rxconf.src_maxburst = 16;
++
++	dma->txconf.direction = DMA_MEM_TO_DEV;
++	dma->txconf.dst_addr_width = 1;
++	dma->rxconf.dst_maxburst = 16;
++
++	dma->fn = lpss_dma_filter;
++	dma->rx_param = &dma->rx_chan_id;
++	dma->tx_param = &dma->tx_chan_id;
++
++	ret = pci_default_setup(priv, board, port, idx);
++	port->port.iotype = UPIO_MEM;
++	port->port.type = PORT_16550A;
++	port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
++	port->port.set_termios = lpss_set_termios;
++	port->port.fifosize = 64;
++	port->tx_loadsz = 64;
++	port->dma = dma;
++	port->port.dev->id = priv->dev->device;
++
++	return ret;
++}
++
+ static int
+ pci_omegapci_setup(struct serial_private *priv,
+ 		      const struct pciserial_board *board,
+@@ -1409,6 +1537,34 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ 		.subdevice	= PCI_ANY_ID,
+ 		.setup		= kt_serial_setup,
+ 	},
++	{
++		.vendor		= PCI_VENDOR_ID_INTEL,
++		.device		= PCI_DEVICE_ID_INTEL_BYT_UART1,
++		.subvendor	= PCI_ANY_ID,
++		.subdevice	= PCI_ANY_ID,
++		.setup		= lpss_serial_setup,
++	},
++	{
++		.vendor		= PCI_VENDOR_ID_INTEL,
++		.device		= PCI_DEVICE_ID_INTEL_BYT_UART2,
++		.subvendor	= PCI_ANY_ID,
++		.subdevice	= PCI_ANY_ID,
++		.setup		= lpss_serial_setup,
++	},
++	{
++		.vendor		= PCI_VENDOR_ID_INTEL,
++		.device		= PCI_DEVICE_ID_INTEL_HSW_UART1,
++		.subvendor	= PCI_ANY_ID,
++		.subdevice	= PCI_ANY_ID,
++		.setup		= lpss_serial_setup,
++	},
++	{
++		.vendor		= PCI_VENDOR_ID_INTEL,
++		.device		= PCI_DEVICE_ID_INTEL_HSW_UART2,
++		.subvendor	= PCI_ANY_ID,
++		.subdevice	= PCI_ANY_ID,
++		.setup		= pci_default_setup,
++	},
+ 	/*
+ 	 * ITE
+ 	 */
+@@ -2170,6 +2326,8 @@ enum pci_board_num_t {
+ 	pbn_ADDIDATA_PCIe_4_3906250,
+ 	pbn_ADDIDATA_PCIe_8_3906250,
+ 	pbn_ce4100_1_115200,
++	pbn_byt,
++	pbn_hsw,
+ 	pbn_omegapci,
+ 	pbn_NETMOS9900_2s_115200,
+ 	pbn_brcm_trumanage,
+@@ -2906,6 +3064,20 @@ static struct pciserial_board pci_boards[] = {
+ 		.base_baud	= 921600,
+ 		.reg_shift      = 2,
+ 	},
++	[pbn_byt] = {
++		.flags		= FL_BASE0,
++		.num_ports	= 1,
++		.base_baud	= 2764800,
++		.uart_offset	= 0x80,
++		.reg_shift      = 2,
++	},
++	[pbn_hsw] = {
++		.flags		= FL_BASE0,
++		.num_ports	= 1,
++		.base_baud	= 6250000,
++		.uart_offset	= 0x80,
++		.reg_shift      = 2,
++	},
+ 	[pbn_omegapci] = {
+ 		.flags		= FL_BASE0,
+ 		.num_ports	= 8,
+@@ -4493,6 +4665,24 @@ static struct pci_device_id serial_pci_tbl[] = {
+ 	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
+ 		PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
+ 		pbn_ce4100_1_115200 },
++	/* Intel BYT */
++	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART1,
++		PCI_ANY_ID,  PCI_ANY_ID,
++		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
++		pbn_byt },
++	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART2,
++		PCI_ANY_ID,  PCI_ANY_ID,
++		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
++		pbn_byt },
++	/* Intel Haswell-ULT */
++	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_UART1,
++		PCI_ANY_ID,  PCI_ANY_ID,
++		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
++		pbn_hsw },
++	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_UART2,
++		PCI_ANY_ID,  PCI_ANY_ID,
++		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
++		pbn_hsw },
+
+ 	/*
+ 	 * Cronyx Omega PCI
+diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
+index c31133a..2748125 100644
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -84,6 +84,14 @@ config SERIAL_8250_GSC
+ 	depends on SERIAL_8250 && GSC
+ 	default SERIAL_8250
+
++config SERIAL_8250_DMA
++	bool "DMA support for 16550 compatible UART controllers" if EXPERT
++	depends on SERIAL_8250 && DMADEVICES=y
++	default SERIAL_8250
++	help
++	  This builds DMA support that can be used with 8250/16650
++	  compatible UART controllers that support DMA signaling.
++
+ config SERIAL_8250_PCI
+ 	tristate "8250/16550 PCI device support" if EXPERT
+ 	depends on SERIAL_8250 && PCI
+@@ -265,7 +273,7 @@ config SERIAL_8250_FSL
+
+ config SERIAL_8250_DW
+ 	tristate "Support for Synopsys DesignWare 8250 quirks"
+-	depends on SERIAL_8250 && OF
++	depends on SERIAL_8250
+ 	help
+ 	  Selecting this option will enable handling of the extra features
+ 	  present in the Synopsys DesignWare APB UART.
+diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
+index 108fe7f..a23838a 100644
+--- a/drivers/tty/serial/8250/Makefile
++++ b/drivers/tty/serial/8250/Makefile
+@@ -5,6 +5,7 @@
+ obj-$(CONFIG_SERIAL_8250)		+= 8250_core.o
+ 8250_core-y				:= 8250.o
+ 8250_core-$(CONFIG_SERIAL_8250_PNP)	+= 8250_pnp.o
++8250_core-$(CONFIG_SERIAL_8250_DMA)	+= 8250_dma.o
+ obj-$(CONFIG_SERIAL_8250_GSC)		+= 8250_gsc.o
+ obj-$(CONFIG_SERIAL_8250_PCI)		+= 8250_pci.o
+ obj-$(CONFIG_SERIAL_8250_HP300)		+= 8250_hp300.o
+diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
+index c490d20..af47a8a 100644
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -59,6 +59,8 @@ enum {
+ 	PLAT8250_DEV_SM501,
+ };
+
++struct uart_8250_dma;
++
+ /*
+  * This should be used by drivers which want to register
+  * their own 8250 ports without registering their own
+@@ -91,6 +93,8 @@ struct uart_8250_port {
+ #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ 	unsigned char		msr_saved_flags;
+
++	struct uart_8250_dma	*dma;
++
+ 	/* 8250 specific callbacks */
+ 	int			(*dl_read)(struct uart_8250_port *);
+ 	void			(*dl_write)(struct uart_8250_port *, int);
+--
+1.7.10.4
+
-- 
1.7.10.4



More information about the linux-yocto mailing list