All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support
@ 2013-01-10  9:25 Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 1/8] serial: 8250: Allow drivers to deliver capabilities Heikki Krogerus
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

Changes since v2:
- ACPI support for 8250_dw.c
- dmaengine API support for 8250

It looks like there are a few UART drivers that are more or less
identical with 8250.c except they include DMA support, so if we had
DMA support in 8250.c there may be no need for them. Since dmaengine
is now supported on most platforms, I decided to suggest this
solution.

I tried to make the DMA support as simple as I could. Single transfers
with single descriptors. This should be sufficient in most cases.


Heikki Krogerus (8):
  serial: 8250: Allow drivers to deliver capabilities
  serial: 8250_dw: Don't use UPF_FIXED_TYPE
  serial: 8250_dw: Map IO memory
  serial: 8250_dw: Move device tree code to separate function
  serial: 8250_dw: Set FIFO size dynamically
  serial: 8250_dw: Add ACPI 5.0 support
  serial: 8250: Add support for dmaengine
  serial: 8250_dw: Enable DMA support with ACPI

 drivers/tty/serial/8250/8250.c     |   53 ++++++--
 drivers/tty/serial/8250/8250.h     |   50 ++++++++
 drivers/tty/serial/8250/8250_dma.c |  213 +++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/8250_dw.c  |  248 ++++++++++++++++++++++++++++++------
 drivers/tty/serial/8250/Kconfig    |   10 +-
 drivers/tty/serial/8250/Makefile   |    1 +
 include/linux/serial_8250.h        |    4 +
 7 files changed, 532 insertions(+), 47 deletions(-)
 create mode 100644 drivers/tty/serial/8250/8250_dma.c

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCHv3 1/8] serial: 8250: Allow drivers to deliver capabilities
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 2/8] serial: 8250_dw: Don't use UPF_FIXED_TYPE Heikki Krogerus
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

Modern UARTs are able to provide information about their
capabilities such as FIFO size. This allows the drivers to
deliver this information to 8250.c when they are registering
ports.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Acked-by: Alan Cox <alan@linux.intel.com>
---
 drivers/tty/serial/8250/8250.c |   22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index d085e3a..da3f828 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -1980,9 +1980,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)
@@ -2815,9 +2818,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
@@ -3251,6 +3257,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;
 
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCHv3 2/8] serial: 8250_dw: Don't use UPF_FIXED_TYPE
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 1/8] serial: 8250: Allow drivers to deliver capabilities Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 3/8] serial: 8250_dw: Map IO memory Heikki Krogerus
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

Allow 8250.c to determine the port type for us. This allows
the driver take advantage of FIFO on Designware UARTs that
have it.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Acked-by: Alan Cox <alan@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dw.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 1d0dba2..ff83ea5 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -112,7 +112,7 @@ static int dw8250_probe(struct platform_device *pdev)
 	uart.port.handle_irq = dw8250_handle_irq;
 	uart.port.type = PORT_8250;
 	uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
-		UPF_FIXED_PORT | UPF_FIXED_TYPE;
+		UPF_FIXED_PORT;
 	uart.port.dev = &pdev->dev;
 
 	uart.port.iotype = UPIO_MEM;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCHv3 3/8] serial: 8250_dw: Map IO memory
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 1/8] serial: 8250: Allow drivers to deliver capabilities Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 2/8] serial: 8250_dw: Don't use UPF_FIXED_TYPE Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 4/8] serial: 8250_dw: Move device tree code to separate function Heikki Krogerus
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

This needs to be done in order to later access the
Designware specific registers.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Acked-by: Alan Cox <alan@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dw.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index ff83ea5..e174901 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -111,10 +111,13 @@ static int dw8250_probe(struct platform_device *pdev)
 	uart.port.irq = irq->start;
 	uart.port.handle_irq = dw8250_handle_irq;
 	uart.port.type = PORT_8250;
-	uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP |
-		UPF_FIXED_PORT;
+	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;
+
 	uart.port.iotype = UPIO_MEM;
 	uart.port.serial_in = dw8250_serial_in;
 	uart.port.serial_out = dw8250_serial_out;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCHv3 4/8] serial: 8250_dw: Move device tree code to separate function
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
                   ` (2 preceding siblings ...)
  2013-01-10  9:25 ` [PATCHv3 3/8] serial: 8250_dw: Map IO memory Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 5/8] serial: 8250_dw: Set FIFO size dynamically Heikki Krogerus
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

Trivial cleanup. This makes it easier to add different
methods to enumerate the device, for example ACPI 5.0
enumeration.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Acked-by: Alan Cox <alan@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dw.c |   78 ++++++++++++++++++++++---------------
 1 file changed, 47 insertions(+), 31 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index e174901..d96e02e 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -87,25 +87,51 @@ static int dw8250_handle_irq(struct uart_port *p)
 	return 0;
 }
 
+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;
+}
+
 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;
@@ -121,30 +147,20 @@ static int dw8250_probe(struct platform_device *pdev)
 	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 (pdev->dev.of_node) {
+		err = dw8250_probe_of(&uart.port);
+		if (err)
+			return err;
+	} else {
+		return -ENODEV;
 	}
 
-	if (!of_property_read_u32(np, "reg-shift", &val))
-		uart.port.regshift = val;
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-	if (of_property_read_u32(np, "clock-frequency", &val)) {
-		dev_err(&pdev->dev, "no clock-frequency property set\n");
-		return -EINVAL;
-	}
-	uart.port.uartclk = val;
+	uart.port.private_data = data;
 
 	data->line = serial8250_register_8250_port(&uart);
 	if (data->line < 0)
@@ -187,17 +203,17 @@ static int dw8250_resume(struct platform_device *pdev)
 #define dw8250_resume NULL
 #endif /* CONFIG_PM */
 
-static const struct of_device_id dw8250_match[] = {
+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 struct platform_driver dw8250_platform_driver = {
 	.driver = {
 		.name		= "dw-apb-uart",
 		.owner		= THIS_MODULE,
-		.of_match_table	= dw8250_match,
+		.of_match_table	= dw8250_of_match,
 	},
 	.probe			= dw8250_probe,
 	.remove			= dw8250_remove,
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCHv3 5/8] serial: 8250_dw: Set FIFO size dynamically
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
                   ` (3 preceding siblings ...)
  2013-01-10  9:25 ` [PATCHv3 4/8] serial: 8250_dw: Move device tree code to separate function Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 6/8] serial: 8250_dw: Add ACPI 5.0 support Heikki Krogerus
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

Designware UART provides optional Component Parameter
Register that lists most of the capabilities of the UART,
including FIFO size. This uses that register to set FIFO
size for the port before registering it.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Acked-by: Alan Cox <alan@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dw.c |   57 ++++++++++++++++++++++++++++++++++---
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index d96e02e..e104092 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -25,6 +25,28 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+/* 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;
@@ -66,9 +88,6 @@ 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
-
 static int dw8250_handle_irq(struct uart_port *p)
 {
 	struct dw8250_data *d = p->private_data;
@@ -78,7 +97,7 @@ static int dw8250_handle_irq(struct uart_port *p)
 		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, d->last_lcr, UART_LCR);
 
 		return 1;
@@ -119,6 +138,34 @@ static int dw8250_probe_of(struct uart_port *p)
 	return 0;
 }
 
+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 = {};
@@ -156,6 +203,8 @@ static int dw8250_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	dw8250_setup_port(&uart);
+
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCHv3 6/8] serial: 8250_dw: Add ACPI 5.0 support
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
                   ` (4 preceding siblings ...)
  2013-01-10  9:25 ` [PATCHv3 5/8] serial: 8250_dw: Set FIFO size dynamically Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 7/8] serial: 8250: Add support for dmaengine Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 8/8] serial: 8250_dw: Enable DMA support with ACPI Heikki Krogerus
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

This adds support for ACPI 5.0 enumerated Designware UARTs.
ACPI does not deliver information about uart clk, so
delivering it with the driver_data.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dw.c |   41 +++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig   |    2 +-
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index e104092..f6eeff0 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,12 +25,16 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
 
 /* 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 */
 
+/* Intel Low Power Subsystem specific */
+#define LPSS_PRV_CLOCK_PARAMS 0x800
+
 /* Component Parameter Register bits */
 #define DW_UART_CPR_ABP_DATA_WIDTH	(3 << 0)
 #define DW_UART_CPR_AFCE_MODE		(1 << 4)
@@ -138,6 +143,30 @@ static int dw8250_probe_of(struct uart_port *p)
 	return 0;
 }
 
+static int dw8250_probe_acpi(struct uart_port *p)
+{
+	const struct acpi_device_id *id;
+	u32 reg;
+
+	id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
+	if (!id)
+		return -ENODEV;
+
+	p->iotype = UPIO_MEM32;
+	p->serial_in = dw8250_serial_in32;
+	p->serial_out = dw8250_serial_out32;
+	p->regshift = 2;
+	p->uartclk = (unsigned int)id->driver_data;
+
+	/* Fix Haswell issue where the clocks do not get enabled */
+	if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) {
+		reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS);
+		writel(reg | 1, p->membase + LPSS_PRV_CLOCK_PARAMS);
+	}
+
+	return 0;
+}
+
 static void dw8250_setup_port(struct uart_8250_port *up)
 {
 	struct uart_port	*p = &up->port;
@@ -199,6 +228,10 @@ static int dw8250_probe(struct platform_device *pdev)
 		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;
 	}
@@ -258,11 +291,19 @@ static const struct of_device_id dw8250_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, dw8250_of_match);
 
+static const struct acpi_device_id dw8250_acpi_match[] = {
+	{ "INT33C4", 100000000 },
+	{ "INT33C5", 100000000 },
+	{ },
+};
+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_of_match,
+		.acpi_match_table = ACPI_PTR(dw8250_acpi_match),
 	},
 	.probe			= dw8250_probe,
 	.remove			= dw8250_remove,
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index c31133a..11adff1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -265,7 +265,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.
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCHv3 7/8] serial: 8250: Add support for dmaengine
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
                   ` (5 preceding siblings ...)
  2013-01-10  9:25 ` [PATCHv3 6/8] serial: 8250_dw: Add ACPI 5.0 support Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  2013-01-10  9:25 ` [PATCHv3 8/8] serial: 8250_dw: Enable DMA support with ACPI Heikki Krogerus
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

Add support for dmaengine API. The drivers can implement the
struct uart_8250_dma member in struct uart_8250_port and
8250.c can take care of the rest.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
 drivers/tty/serial/8250/8250.c     |   31 +++++-
 drivers/tty/serial/8250/8250.h     |   50 +++++++++
 drivers/tty/serial/8250/8250_dma.c |  213 ++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig    |    8 ++
 drivers/tty/serial/8250/Makefile   |    1 +
 include/linux/serial_8250.h        |    4 +
 6 files changed, 304 insertions(+), 3 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 da3f828..f952993 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -1335,7 +1335,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);
 
@@ -1536,6 +1538,7 @@ 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;
@@ -1546,8 +1549,13 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
 
 	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)
 		serial8250_tx_chars(up);
@@ -2190,6 +2198,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.
@@ -2222,6 +2242,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 */
@@ -3286,6 +3309,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 3b4ea84..363d549 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;
@@ -142,3 +171,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..95516a1
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_dma.c
@@ -0,0 +1,213 @@
+/*
+ * 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);
+		uart_write_wakeup(&p->port);
+	}
+}
+
+static void __dma_rx_complete(void *param)
+{
+	struct uart_8250_port	*p = param;
+	struct uart_8250_dma	*dma = p->dma;
+	struct tty_struct	*tty = p->port.state->port.tty;
+	struct dma_tx_state	state;
+
+	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);
+
+	tty_insert_flip_string(tty, dma->rx_buf, dma->rx_size - state.residue);
+	p->port.icount.rx += dma->rx_size - state.residue;
+
+	tty_flip_buffer_push(tty);
+}
+
+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 (dma->tx_running) {
+		uart_write_wakeup(&p->port);
+		return -EBUSY;
+	}
+
+	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;
+
+	/*
+	 * If RCVR FIFO trigger level was not reached, complete the transfer and
+	 * let 8250.c copy the remaining data.
+	 */
+	if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
+		dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie,
+						&state);
+		if (dma_status == DMA_IN_PROGRESS) {
+			dmaengine_pause(dma->rxchan);
+			__dma_rx_complete(p);
+		}
+		return -ETIMEDOUT;
+	}
+
+	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/Kconfig b/drivers/tty/serial/8250/Kconfig
index 11adff1..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
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


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCHv3 8/8] serial: 8250_dw: Enable DMA support with ACPI
  2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
                   ` (6 preceding siblings ...)
  2013-01-10  9:25 ` [PATCHv3 7/8] serial: 8250: Add support for dmaengine Heikki Krogerus
@ 2013-01-10  9:25 ` Heikki Krogerus
  7 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2013-01-10  9:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, Jamie Iles, linux-serial, linux-kernel

With ACPI 5.0 we can use the FixedDMA Resource Descriptor to
extract the needed information for DMA support.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dw.c |   65 +++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index f6eeff0..ceacf5e 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -27,6 +27,8 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 
+#include "8250.h"
+
 /* Offsets for the DesignWare specific registers */
 #define DW_UART_USR	0x1f /* UART Status Register */
 #define DW_UART_CPR	0xf4 /* Component Parameter Register */
@@ -143,9 +145,64 @@ static int dw8250_probe_of(struct uart_port *p)
 	return 0;
 }
 
+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;
+
+			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;
+
+			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)
 {
 	const struct acpi_device_id *id;
+	acpi_status status;
 	u32 reg;
 
 	id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
@@ -158,6 +215,14 @@ static int dw8250_probe_acpi(struct uart_port *p)
 	p->regshift = 2;
 	p->uartclk = (unsigned int)id->driver_data;
 
+	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;
+	}
+
 	/* Fix Haswell issue where the clocks do not get enabled */
 	if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) {
 		reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS);
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-01-10  9:29 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-10  9:25 [PATCHv3 0/8] serial: 8250: 8250_dw changes and dmaengine support Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 1/8] serial: 8250: Allow drivers to deliver capabilities Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 2/8] serial: 8250_dw: Don't use UPF_FIXED_TYPE Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 3/8] serial: 8250_dw: Map IO memory Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 4/8] serial: 8250_dw: Move device tree code to separate function Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 5/8] serial: 8250_dw: Set FIFO size dynamically Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 6/8] serial: 8250_dw: Add ACPI 5.0 support Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 7/8] serial: 8250: Add support for dmaengine Heikki Krogerus
2013-01-10  9:25 ` [PATCHv3 8/8] serial: 8250_dw: Enable DMA support with ACPI Heikki Krogerus

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.