From e259a3aecbfb61981175ddc7fc02dd180da7d73e Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Mon, 20 Aug 2007 09:47:41 +0100
Subject: [ARM] pxa: convert PXA serial drivers to use platform resources

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/serial/pxa.c | 139 ++++++++++++++++++++++-----------------------------
 1 file changed, 61 insertions(+), 78 deletions(-)

(limited to 'drivers/serial')

diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index e9c6cb3..59889f6 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -582,7 +582,7 @@ serial_pxa_type(struct uart_port *port)
 
 #ifdef CONFIG_SERIAL_PXA_CONSOLE
 
-static struct uart_pxa_port serial_pxa_ports[];
+static struct uart_pxa_port *serial_pxa_ports[4];
 static struct uart_driver serial_pxa_reg;
 
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@@ -632,7 +632,7 @@ static void serial_pxa_console_putchar(struct uart_port *port, int ch)
 static void
 serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
 {
-	struct uart_pxa_port *up = &serial_pxa_ports[co->index];
+	struct uart_pxa_port *up = serial_pxa_ports[co->index];
 	unsigned int ier;
 
 	/*
@@ -662,7 +662,9 @@ serial_pxa_console_setup(struct console *co, char *options)
 
 	if (co->index == -1 || co->index >= serial_pxa_reg.nr)
 		co->index = 0;
-       	up = &serial_pxa_ports[co->index];
+	up = serial_pxa_ports[co->index];
+	if (!up)
+		return -ENODEV;
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -680,15 +682,6 @@ static struct console serial_pxa_console = {
 	.data		= &serial_pxa_reg,
 };
 
-static int __init
-serial_pxa_console_init(void)
-{
-	register_console(&serial_pxa_console);
-	return 0;
-}
-
-console_initcall(serial_pxa_console_init);
-
 #define PXA_CONSOLE	&serial_pxa_console
 #else
 #define PXA_CONSOLE	NULL
@@ -714,73 +707,13 @@ struct uart_ops serial_pxa_pops = {
 	.verify_port	= serial_pxa_verify_port,
 };
 
-static struct uart_pxa_port serial_pxa_ports[] = {
-     {	/* FFUART */
-	.name	= "FFUART",
-	.cken	= CKEN_FFUART,
-	.port	= {
-		.type		= PORT_PXA,
-		.iotype		= UPIO_MEM,
-		.membase	= (void *)&FFUART,
-		.mapbase	= __PREG(FFUART),
-		.irq		= IRQ_FFUART,
-		.uartclk	= 921600 * 16,
-		.fifosize	= 64,
-		.ops		= &serial_pxa_pops,
-		.line		= 0,
-	},
-  }, {	/* BTUART */
-	.name	= "BTUART",
-	.cken	= CKEN_BTUART,
-	.port	= {
-		.type		= PORT_PXA,
-		.iotype		= UPIO_MEM,
-		.membase	= (void *)&BTUART,
-		.mapbase	= __PREG(BTUART),
-		.irq		= IRQ_BTUART,
-		.uartclk	= 921600 * 16,
-		.fifosize	= 64,
-		.ops		= &serial_pxa_pops,
-		.line		= 1,
-	},
-  }, {	/* STUART */
-	.name	= "STUART",
-	.cken	= CKEN_STUART,
-	.port	= {
-		.type		= PORT_PXA,
-		.iotype		= UPIO_MEM,
-		.membase	= (void *)&STUART,
-		.mapbase	= __PREG(STUART),
-		.irq		= IRQ_STUART,
-		.uartclk	= 921600 * 16,
-		.fifosize	= 64,
-		.ops		= &serial_pxa_pops,
-		.line		= 2,
-	},
-  }, {  /* HWUART */
-	.name	= "HWUART",
-	.cken	= CKEN_HWUART,
-	.port = {
-		.type		= PORT_PXA,
-		.iotype		= UPIO_MEM,
-		.membase	= (void *)&HWUART,
-		.mapbase	= __PREG(HWUART),
-		.irq		= IRQ_HWUART,
-		.uartclk	= 921600 * 16,
-		.fifosize	= 64,
-		.ops		= &serial_pxa_pops,
-		.line		= 3,
-	},
-  }
-};
-
 static struct uart_driver serial_pxa_reg = {
 	.owner		= THIS_MODULE,
 	.driver_name	= "PXA serial",
 	.dev_name	= "ttyS",
 	.major		= TTY_MAJOR,
 	.minor		= 64,
-	.nr		= ARRAY_SIZE(serial_pxa_ports),
+	.nr		= 4,
 	.cons		= PXA_CONSOLE,
 };
 
@@ -806,10 +739,60 @@ static int serial_pxa_resume(struct platform_device *dev)
 
 static int serial_pxa_probe(struct platform_device *dev)
 {
-	serial_pxa_ports[dev->id].port.dev = &dev->dev;
-	uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[dev->id].port);
-	platform_set_drvdata(dev, &serial_pxa_ports[dev->id]);
+	struct uart_pxa_port *sport;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL);
+	if (!sport)
+		return -ENOMEM;
+
+	sport->port.type = PORT_PXA;
+	sport->port.iotype = UPIO_MEM;
+	sport->port.mapbase = mmres->start;
+	sport->port.irq = irqres->start;
+	sport->port.fifosize = 64;
+	sport->port.ops = &serial_pxa_pops;
+	sport->port.line = dev->id;
+	sport->port.dev = &dev->dev;
+	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
+	sport->port.uartclk = 921600 * 16;
+
+	/*
+	 * Is it worth keeping this?
+	 */
+	if (mmres->start == __PREG(FFUART))
+		sport->name = "FFUART";
+	else if (mmres->start == __PREG(BTUART))
+		sport->name = "BTUART";
+	else if (mmres->start == __PREG(STUART))
+		sport->name = "STUART";
+	else if (mmres->start == __PREG(HWUART))
+		sport->name = "HWUART";
+	else
+		sport->name = "???";
+
+	sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1);
+	if (!sport->port.membase) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	serial_pxa_ports[dev->id] = sport;
+
+	uart_add_one_port(&serial_pxa_reg, &sport->port);
+	platform_set_drvdata(dev, sport);
+
 	return 0;
+
+ err_free:
+	kfree(sport);
+	return ret;
 }
 
 static int serial_pxa_remove(struct platform_device *dev)
@@ -818,8 +801,8 @@ static int serial_pxa_remove(struct platform_device *dev)
 
 	platform_set_drvdata(dev, NULL);
 
-	if (sport)
-		uart_remove_one_port(&serial_pxa_reg, &sport->port);
+	uart_remove_one_port(&serial_pxa_reg, &sport->port);
+	kfree(sport);
 
 	return 0;
 }
-- 
cgit v1.1