Subject: imx uart: remove statically initialized tables
From: Sascha Hauer <s.hauer@pengutronix.de>

This patch removes the statically initialized tables from the i.MX serial
driver and makes the driver fully dependent on the information provided by
the platform_device.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

---
 arch/arm/mach-imx/mx1ads.c |   10 +++
 drivers/serial/imx.c       |  129 ++++++++++++++++++---------------------------
 2 files changed, 64 insertions(+), 75 deletions(-)

Index: linux-2.6.26-rc6/arch/arm/mach-imx/mx1ads.c
===================================================================
--- linux-2.6.26-rc6.orig/arch/arm/mach-imx/mx1ads.c
+++ linux-2.6.26-rc6/arch/arm/mach-imx/mx1ads.c
@@ -69,6 +69,11 @@ static struct resource imx_uart1_resourc
 		.end	= (UART1_MINT_TX),
 		.flags	= IORESOURCE_IRQ,
 	},
+	[3] = {
+		.start	= (UART1_MINT_RTS),
+		.end	= (UART1_MINT_RTS),
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device imx_uart1_device = {
@@ -97,6 +102,11 @@ static struct resource imx_uart2_resourc
 		.end	= (UART2_MINT_TX),
 		.flags	= IORESOURCE_IRQ,
 	},
+	[3] = {
+		.start	= (UART2_MINT_RTS),
+		.end	= (UART2_MINT_RTS),
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device imx_uart2_device = {
Index: linux-2.6.26-rc6/drivers/serial/imx.c
===================================================================
--- linux-2.6.26-rc6.orig/drivers/serial/imx.c
+++ linux-2.6.26-rc6/drivers/serial/imx.c
@@ -176,6 +176,8 @@
 
 #define DRIVER_NAME "IMX-uart"
 
+#define UART_NR 8
+
 struct imx_port {
 	struct uart_port	port;
 	struct timer_list	timer;
@@ -813,65 +815,7 @@ static struct uart_ops imx_pops = {
 	.verify_port	= imx_verify_port,
 };
 
-static struct imx_port imx_ports[] = {
-	{
-	.txirq  = UART1_MINT_TX,
-	.rxirq  = UART1_MINT_RX,
-	.rtsirq = UART1_MINT_RTS,
-	.port	= {
-		.type		= PORT_IMX,
-		.iotype		= UPIO_MEM,
-		.membase	= (void *)IMX_UART1_BASE,
-		.mapbase	= 0x00206000,
-		.irq		= UART1_MINT_RX,
-		.fifosize	= 32,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.ops		= &imx_pops,
-		.line		= 0,
-	},
-	}, {
-	.txirq  = UART2_MINT_TX,
-	.rxirq  = UART2_MINT_RX,
-	.rtsirq = UART2_MINT_RTS,
-	.port	= {
-		.type		= PORT_IMX,
-		.iotype		= UPIO_MEM,
-		.membase	= (void *)IMX_UART2_BASE,
-		.mapbase	= 0x00207000,
-		.irq		= UART2_MINT_RX,
-		.fifosize	= 32,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.ops		= &imx_pops,
-		.line		= 1,
-	},
-	}
-};
-
-/*
- * Setup the IMX serial ports.
- * Note also that we support "console=ttySMXx" where "x" is either 0 or 1.
- * Which serial port this ends up being depends on the machine you're
- * running this kernel on.  I'm not convinced that this is a good idea,
- * but that's the way it traditionally works.
- *
- */
-static void __init imx_init_ports(void)
-{
-	static int first = 1;
-	int i;
-
-	if (!first)
-		return;
-	first = 0;
-
-	for (i = 0; i < ARRAY_SIZE(imx_ports); i++) {
-		init_timer(&imx_ports[i].timer);
-		imx_ports[i].timer.function = imx_timeout;
-		imx_ports[i].timer.data     = (unsigned long)&imx_ports[i];
-
-		imx_ports[i].port.uartclk = imx_get_perclk1();
-	}
-}
+static struct imx_port *imx_ports[UART_NR];
 
 #ifdef CONFIG_SERIAL_IMX_CONSOLE
 static void imx_console_putchar(struct uart_port *port, int ch)
@@ -890,7 +834,7 @@ static void imx_console_putchar(struct u
 static void
 imx_console_write(struct console *co, const char *s, unsigned int count)
 {
-	struct imx_port *sport = &imx_ports[co->index];
+	struct imx_port *sport = imx_ports[co->index];
 	unsigned int old_ucr1, old_ucr2;
 
 	/*
@@ -996,7 +940,7 @@ imx_console_setup(struct console *co, ch
 	 */
 	if (co->index == -1 || co->index >= ARRAY_SIZE(imx_ports))
 		co->index = 0;
-	sport = &imx_ports[co->index];
+	sport = imx_ports[co->index];
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -1019,14 +963,6 @@ static struct console imx_console = {
 	.data		= &imx_reg,
 };
 
-static int __init imx_rs_console_init(void)
-{
-	imx_init_ports();
-	register_console(&imx_console);
-	return 0;
-}
-console_initcall(imx_rs_console_init);
-
 #define IMX_CONSOLE	&imx_console
 #else
 #define IMX_CONSOLE	NULL
@@ -1064,21 +1000,63 @@ static int serial_imx_resume(struct plat
 
 static int serial_imx_probe(struct platform_device *pdev)
 {
+	struct imx_port *sport;
 	struct imxuart_platform_data *pdata;
+	void __iomem *base;
+	int ret = 0;
+	struct resource *res;
+
+	sport = kzalloc(sizeof(*sport), GFP_KERNEL);
+	if (!sport)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENODEV;
+		goto free;
+	}
+
+	base = ioremap(res->start, PAGE_SIZE);
+	if (!base) {
+		ret = -ENOMEM;
+		goto free;
+	}
+
+	sport->port.dev = &pdev->dev;
+	sport->port.mapbase = res->start;
+	sport->port.membase = base;
+	sport->port.type = PORT_IMX,
+	sport->port.iotype = UPIO_MEM;
+	sport->port.irq = platform_get_irq(pdev, 0);
+	sport->rxirq = platform_get_irq(pdev, 0);
+	sport->txirq = platform_get_irq(pdev, 1);
+	sport->rtsirq = platform_get_irq(pdev, 2);
+	sport->port.fifosize = 32;
+	sport->port.ops = &imx_pops;
+	sport->port.flags = UPF_BOOT_AUTOCONF;
+	sport->port.line = pdev->id;
+	init_timer(&sport->timer);
+	sport->timer.function = imx_timeout;
+	sport->timer.data     = (unsigned long)sport;
+	sport->port.uartclk = imx_get_perclk1();
 
-	imx_ports[pdev->id].port.dev = &pdev->dev;
+	imx_ports[pdev->id] = sport;
 
 	pdata = pdev->dev.platform_data;
 	if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
-		imx_ports[pdev->id].have_rtscts = 1;
+		sport->have_rtscts = 1;
 
 	if (pdata->init)
 		pdata->init(pdev);
 
-	uart_add_one_port(&imx_reg, &imx_ports[pdev->id].port);
-	platform_set_drvdata(pdev, &imx_ports[pdev->id]);
+	uart_add_one_port(&imx_reg, &sport->port);
+	platform_set_drvdata(pdev, &sport->port);
 
 	return 0;
+free:
+	kfree(sport);
+
+	return ret;
 }
 
 static int serial_imx_remove(struct platform_device *pdev)
@@ -1096,6 +1074,9 @@ static int serial_imx_remove(struct plat
 	if (pdata->exit)
 		pdata->exit(pdev);
 
+	iounmap(sport->port.membase);
+	kfree(sport);
+
 	return 0;
 }
 
@@ -1117,8 +1098,6 @@ static int __init imx_serial_init(void)
 
 	printk(KERN_INFO "Serial: IMX driver\n");
 
-	imx_init_ports();
-
 	ret = uart_register_driver(&imx_reg);
 	if (ret)
 		return ret;
