All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
@ 2011-04-20  1:10 Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 01/23] at91: Add common devices framework Ryan Mallon
                   ` (25 more replies)
  0 siblings, 26 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Each AT91 variant (AT91RM9200, AT91SAM9260, etc) currently has its own
devices file, which includes the MMIO address, interrupt
configuration, GPIO setup, etc for each device. This results in a large
amount of duplicated code.

This patch set introduces a framework for adding shared devices for the
AT91 platform and replaces the multiple device setup implementations for
each device with single implementations in the new framework. This has
a net reduction of nearly 5000 lines of code.

Each of the arch/arm/mach-at91/*_devices.c files becomes a collection of
structures (with some initialisation callbacks where necessary) with a
table of devices which are present on the particular AT91 variant. All
structures/functions are marked as __init/__initdata so there is little
additional memory overhead. This also means that the #ifdefs around each
device can be removed from the *_devices.c files (but remain in the new
common devices.c file) without overhead.

I have build tested the patch series for all of the  AT91 variants 
and devices, and have boot tested it on the AT91SAM9260 (Snapper 9260
board) and tested basic device functionality.

Ryan Mallon (23):
  at91: Add common devices framework
  at91: Make Ethernet device common
  at91: Make USB OHCI/EHCI devices common
  at91: Make UDC device common
  at91: Make MMC device common
  at91: Make NAND device common
  at91: Make TWI device common
  at91: Make SPI device common
  at91: Make TCB device common
  at91: Make RTT device common
  at91: Make watchdog device common
  at91: Make UART devices common
  at91: Make PWM device common
  at91: Make SSC device common
  at91: Make AC97 device common
  at91: Make LCD controller device common
  at91: Make touchscreen device common
  at91: Make HDMAC device common
  at91: Make RTC device common
  at91: Make high speed USB gadget device common
  at91: Make compact flash device common
  at91: Move at91sam9263 CAN device to common devices
  at91: Remove mAgic and ISI device code

 arch/arm/mach-at91/Makefile               |    2 +-
 arch/arm/mach-at91/at572d940hf.c          |    4 +
 arch/arm/mach-at91/at572d940hf_devices.c  | 1022 +++-------------
 arch/arm/mach-at91/at91cap9.c             |    4 +
 arch/arm/mach-at91/at91cap9_devices.c     | 1411 ++++----------------
 arch/arm/mach-at91/at91rm9200.c           |    4 +
 arch/arm/mach-at91/at91rm9200_devices.c   | 1321 ++++---------------
 arch/arm/mach-at91/at91sam9260.c          |    4 +
 arch/arm/mach-at91/at91sam9260_devices.c  | 1471 ++++-----------------
 arch/arm/mach-at91/at91sam9261.c          |    4 +
 arch/arm/mach-at91/at91sam9261_devices.c  | 1172 ++++--------------
 arch/arm/mach-at91/at91sam9263.c          |    4 +
 arch/arm/mach-at91/at91sam9263_devices.c  | 1589 +++++------------------
 arch/arm/mach-at91/at91sam9g45.c          |    4 +
 arch/arm/mach-at91/at91sam9g45_devices.c  | 1779 +++++---------------------
 arch/arm/mach-at91/at91sam9rl.c           |    4 +
 arch/arm/mach-at91/at91sam9rl_devices.c   | 1332 ++++----------------
 arch/arm/mach-at91/board-1arm.c           |    6 +-
 arch/arm/mach-at91/board-afeb-9260v1.c    |   10 +-
 arch/arm/mach-at91/board-at572d940hf_ek.c |   12 +-
 arch/arm/mach-at91/board-cam60.c          |    2 +-
 arch/arm/mach-at91/board-cap9adk.c        |    4 +-
 arch/arm/mach-at91/board-carmeva.c        |    6 +-
 arch/arm/mach-at91/board-cpu9krea.c       |   16 +-
 arch/arm/mach-at91/board-cpuat91.c        |   12 +-
 arch/arm/mach-at91/board-csb337.c         |    4 +-
 arch/arm/mach-at91/board-csb637.c         |    4 +-
 arch/arm/mach-at91/board-eb9200.c         |    8 +-
 arch/arm/mach-at91/board-ecbat91.c        |    6 +-
 arch/arm/mach-at91/board-eco920.c         |    2 +-
 arch/arm/mach-at91/board-flexibity.c      |    2 +-
 arch/arm/mach-at91/board-foxg20.c         |   16 +-
 arch/arm/mach-at91/board-gsia18s.c        |   14 +-
 arch/arm/mach-at91/board-kafa.c           |    6 +-
 arch/arm/mach-at91/board-kb9202.c         |   10 +-
 arch/arm/mach-at91/board-neocore926.c     |    6 +-
 arch/arm/mach-at91/board-pcontrol-g20.c   |   10 +-
 arch/arm/mach-at91/board-picotux200.c     |    6 +-
 arch/arm/mach-at91/board-qil-a9260.c      |   10 +-
 arch/arm/mach-at91/board-rm9200dk.c       |    6 +-
 arch/arm/mach-at91/board-rm9200ek.c       |    6 +-
 arch/arm/mach-at91/board-sam9-l9260.c     |    8 +-
 arch/arm/mach-at91/board-sam9260ek.c      |   10 +-
 arch/arm/mach-at91/board-sam9261ek.c      |    6 +-
 arch/arm/mach-at91/board-sam9263ek.c      |    6 +-
 arch/arm/mach-at91/board-sam9g20ek.c      |   10 +-
 arch/arm/mach-at91/board-sam9m10g45ek.c   |    2 +-
 arch/arm/mach-at91/board-sam9rlek.c       |    4 +-
 arch/arm/mach-at91/board-snapper9260.c    |   14 +-
 arch/arm/mach-at91/board-stamp9g20.c      |   20 +-
 arch/arm/mach-at91/board-usb-a9260.c      |    4 +-
 arch/arm/mach-at91/board-usb-a9263.c      |    4 +-
 arch/arm/mach-at91/board-yl-9200.c        |   10 +-
 arch/arm/mach-at91/devices.c              | 2002 +++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h              |  237 ++++
 arch/arm/mach-at91/include/mach/board.h   |   21 +-
 56 files changed, 4483 insertions(+), 9190 deletions(-)
 create mode 100644 arch/arm/mach-at91/devices.c
 create mode 100644 arch/arm/mach-at91/devices.h

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

* [RFC PATCH 01/23] at91: Add common devices framework
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 02/23] at91: Make Ethernet device common Ryan Mallon
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Each AT91 variant (AT91RM9200, AT91SAM9260, etc) currently has its own
devices file, which includes the MMIO address, interrupt
configuration, GPIO setup, etc for each device. This results in a large
amount of duplicated code.

This patch introduces a framework for adding shared devices for the
AT91 platform. The subsequent patches in this series replace the
multiple device setup implementations for each device with single
implementations in the new framework.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/Makefile  |    2 +-
 arch/arm/mach-at91/devices.c |   70 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h |   36 +++++++++++++++++++++
 3 files changed, 107 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-at91/devices.c
 create mode 100644 arch/arm/mach-at91/devices.h

diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index a83835e..14962f2 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y		:= irq.o gpio.o
+obj-y		:= irq.o gpio.o devices.o
 obj-m		:=
 obj-n		:=
 obj-		:=
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
new file mode 100644
index 0000000..653e0a9
--- /dev/null
+++ b/arch/arm/mach-at91/devices.c
@@ -0,0 +1,70 @@
+/*
+ * arch/arm/mach-at91/devices.c
+ *
+ *  Copyright (C) 2011 Bluewater Systems
+ *  Copyright (C) 2011 Ryan Mallon <ryan@bluewatersys.com>
+ * 
+ * Based on code from arch/arm/mach-at91/*_devices.c
+ *
+ * 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/platform_device.h>
+#include <linux/gpio.h>
+
+#include "devices.h"
+
+static __initdata struct at91_device_table *devices;
+
+static __init void at91_config_pins(struct at91_pin_config *pins, int nr_pins)
+{
+	int i;
+
+	for (i = 0; i < nr_pins; i++) {		
+		switch (pins[i].mode) {
+		case AT91_PIN_PERIPH_A:
+			at91_set_A_periph(pins[i].pin, pins[i].pullup);
+			break;
+
+		case AT91_PIN_PERIPH_B:
+			at91_set_B_periph(pins[i].pin, pins[i].pullup);
+			break;
+
+		default:
+			/* GPIO */
+			if (pins[i].direction == GPIOF_DIR_OUT)
+				at91_set_gpio_output(pins[i].pin,
+						     pins[i].value);
+			else
+				at91_set_gpio_input(pins[i].pin,
+						    pins[i].pullup);
+			break;
+		}
+	}
+}
+
+static inline void __init init_resource_mem(struct resource *res,
+					    unsigned mmio_base)
+{
+	BUG_ON(res->flags != IORESOURCE_MEM);
+	res->start = mmio_base;
+	res->end  += mmio_base - 1;
+}
+
+static inline void __init init_resource_irq(struct resource *res, int irq)
+{
+	if (irq) {
+		BUG_ON(res->flags != IORESOURCE_IRQ);
+		res->start = irq;
+		res->end   = irq;
+	}
+}
+
+void __init at91_init_devices(struct at91_device_table *device_table)
+{
+	devices = device_table;
+}
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
new file mode 100644
index 0000000..738f736
--- /dev/null
+++ b/arch/arm/mach-at91/devices.h
@@ -0,0 +1,36 @@
+/*
+ * arch/arm/mach-at91/devices.h
+ *
+ *  Copyright (C) 2011 Bluewater Systems
+ *  Copyright (C) 2011 Ryan Mallon <ryan@bluewatersys.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _AT91_DEVICES_H
+#define _AT91_DEVICES_H
+
+enum {
+	AT91_PIN_PERIPH_A,
+	AT91_PIN_PERIPH_B,
+	AT91_PIN_GPIO,
+};
+
+struct at91_pin_config {
+	int pin;
+	int mode;
+	int pullup;
+	int direction;
+	int value;
+};
+
+struct at91_device_table {
+};
+
+extern void __init at91_init_devices(struct at91_device_table *device_table);
+
+#endif /* _AT91_DEVICES_H */
-- 
1.7.0.4

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 01/23] at91: Add common devices framework Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  2:10   ` H Hartley Sweeten
  2011-04-20  8:36   ` Uwe Kleine-König
  2011-04-20  1:10 ` [RFC PATCH 03/23] at91: Make USB OHCI/EHCI devices common Ryan Mallon
                   ` (23 subsequent siblings)
  25 siblings, 2 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual Ethernet device code for each at91 variant with
a single implementation in devices.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf.c         |    4 +
 arch/arm/mach-at91/at572d940hf_devices.c |   83 +++++++----------------
 arch/arm/mach-at91/at91cap9.c            |    4 +
 arch/arm/mach-at91/at91cap9_devices.c    |  103 ++++++++++------------------
 arch/arm/mach-at91/at91rm9200.c          |    4 +
 arch/arm/mach-at91/at91rm9200_devices.c  |  103 ++++++++++------------------
 arch/arm/mach-at91/at91sam9260.c         |    4 +
 arch/arm/mach-at91/at91sam9260_devices.c |  104 +++++++++++------------------
 arch/arm/mach-at91/at91sam9261_devices.c |    1 -
 arch/arm/mach-at91/at91sam9263.c         |    4 +
 arch/arm/mach-at91/at91sam9263_devices.c |  102 ++++++++++------------------
 arch/arm/mach-at91/at91sam9g45.c         |    4 +
 arch/arm/mach-at91/at91sam9g45_devices.c |  108 +++++++++++-------------------
 arch/arm/mach-at91/devices.c             |   61 +++++++++++++++++
 arch/arm/mach-at91/devices.h             |   10 +++
 15 files changed, 309 insertions(+), 390 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf.c b/arch/arm/mach-at91/at572d940hf.c
index a6b9c68..48c1ec2 100644
--- a/arch/arm/mach-at91/at572d940hf.c
+++ b/arch/arm/mach-at91/at572d940hf.c
@@ -34,6 +34,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void at572d940hf_init_devices(void);
+
 static struct map_desc at572d940hf_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -307,6 +309,8 @@ void __init at572d940hf_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at572d940hf_io_desc, ARRAY_SIZE(at572d940hf_io_desc));
 
+	at572d940hf_init_devices();
+
 	at91_arch_reset = at572d940hf_reset;
 	at91_extern_irq = (1 << AT572D940HF_ID_IRQ0) | (1 << AT572D940HF_ID_IRQ1)
 			| (1 << AT572D940HF_ID_IRQ2);
diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index 0fc20a2..12af1d5 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -35,6 +35,7 @@
 
 #include "generic.h"
 #include "sam9_smc.h"
+#include "devices.h"
 
 
 /* --------------------------------------------------------------------
@@ -138,68 +139,26 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
  *  Ethernet
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_EMAC,
-		.end	= AT572D940HF_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_EMAC,
-		.end	= AT572D940HF_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config eth_rmii_pins[] = {
+	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
+	{AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
+	{AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
+	{AT91_PIN_PA19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
+	{AT91_PIN_PA20, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
+	{AT91_PIN_PA23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
+	{AT91_PIN_PA21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
+	{AT91_PIN_PA22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
+	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
+	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
 };
 
-static struct platform_device at572d940hf_eth_device = {
-	.name		= "macb",
-	.id		= -1,
-	.dev		= {
-			.dma_mask		= &eth_dmamask,
-			.coherent_dma_mask	= DMA_BIT_MASK(32),
-			.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
+static struct __initdata at91_dev_table_ethernet device_eth = {
+	.mmio_base	= AT91SAM9260_BASE_EMAC,
+	.irq		= AT91SAM9260_ID_EMAC,
+	.rmii_pins	= eth_rmii_pins,
+	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Only RMII is supported */
-	data->is_rmii = 1;
-
-	/* Pins used for RMII */
-	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ETXCK_EREFCK */
-	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ERXDV */
-	at91_set_A_periph(AT91_PIN_PA18, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PA19, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PA20, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PA23, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PA21, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PA22, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PA13, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PA14, 0);	/* EMDC */
-
-	eth_data = *data;
-	platform_device_register(&at572d940hf_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  MMC / SD
  * -------------------------------------------------------------------- */
@@ -952,6 +911,14 @@ void __init at91_add_device_mAgic(void)
 void __init at91_add_device_mAgic(void) {}
 #endif
 
+static struct at91_device_table __initdata at572d940hf_device_table = {
+	.ethernet	= &device_eth,
+};
+
+void __init at572d940hf_init_devices(void)
+{
+	at91_init_devices(&at572d940hf_device_table);
+}
 
 /* -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
index 7337617..6413530 100644
--- a/arch/arm/mach-at91/at91cap9.c
+++ b/arch/arm/mach-at91/at91cap9.c
@@ -28,6 +28,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void at91cap9_init_devices(void);
+
 static struct map_desc at91cap9_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -308,6 +310,8 @@ void __init at91cap9_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at91cap9_io_desc, ARRAY_SIZE(at91cap9_io_desc));
 
+	at91cap9_init_devices();
+
 	at91_arch_reset = at91cap9_reset;
 	pm_power_off = at91cap9_poweroff;
 	at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 9ffbf3a..183f320 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -29,7 +29,7 @@
 #include <mach/at91sam9_smc.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /* --------------------------------------------------------------------
  *  USB Host
@@ -196,75 +196,38 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
  *  Ethernet
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_EMAC,
-		.end	= AT91CAP9_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_EMAC,
-		.end	= AT91CAP9_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config eth_rmii_pins[] = {
+	{AT91_PIN_PB21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
+	{AT91_PIN_PB22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
+	{AT91_PIN_PB25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
+	{AT91_PIN_PB26, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
+	{AT91_PIN_PB27, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
+	{AT91_PIN_PB28, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
+	{AT91_PIN_PB23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
+	{AT91_PIN_PB24, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
+	{AT91_PIN_PB30, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
+	{AT91_PIN_PB29, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
 };
 
-static struct platform_device at91cap9_eth_device = {
-	.name		= "macb",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &eth_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
+static struct __initdata at91_pin_config eth_mii_pins[] = {
+	{AT91_PIN_PC25, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECRS */
+	{AT91_PIN_PC26, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
+	{AT91_PIN_PC22, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
+	{AT91_PIN_PC23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
+	{AT91_PIN_PC27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
+	{AT91_PIN_PC20, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
+	{AT91_PIN_PC21, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
+	{AT91_PIN_PC24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Pins used for MII and RMII */
-	at91_set_A_periph(AT91_PIN_PB21, 0);	/* ETXCK_EREFCK */
-	at91_set_A_periph(AT91_PIN_PB22, 0);	/* ERXDV */
-	at91_set_A_periph(AT91_PIN_PB25, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PB26, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PB27, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PB28, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PB23, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PB24, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PB30, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PB29, 0);	/* EMDC */
-
-	if (!data->is_rmii) {
-		at91_set_B_periph(AT91_PIN_PC25, 0);	/* ECRS */
-		at91_set_B_periph(AT91_PIN_PC26, 0);	/* ECOL */
-		at91_set_B_periph(AT91_PIN_PC22, 0);	/* ERX2 */
-		at91_set_B_periph(AT91_PIN_PC23, 0);	/* ERX3 */
-		at91_set_B_periph(AT91_PIN_PC27, 0);	/* ERXCK */
-		at91_set_B_periph(AT91_PIN_PC20, 0);	/* ETX2 */
-		at91_set_B_periph(AT91_PIN_PC21, 0);	/* ETX3 */
-		at91_set_B_periph(AT91_PIN_PC24, 0);	/* ETXER */
-	}
-
-	eth_data = *data;
-	platform_device_register(&at91cap9_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
-#endif
-
+static struct __initdata at91_dev_table_ethernet device_eth = {
+	.mmio_base	= AT91CAP9_BASE_EMAC,
+	.irq		= AT91CAP9_ID_EMAC,
+	.rmii_pins	= eth_rmii_pins,
+	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
+	.mii_pins	= eth_mii_pins,
+	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
+};
 
 /* --------------------------------------------------------------------
  *  MMC / SD
@@ -1254,6 +1217,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+static struct at91_device_table __initdata at91cap9_device_table = {
+	.ethernet	= &device_eth,
+};
+
+void __init at91cap9_init_devices(void)
+{
+	at91_init_devices(&at91cap9_device_table);
+}
 
 /* -------------------------------------------------------------------- */
 /*
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 2e9ecad..dea90df 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -22,6 +22,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void at91rm9200_init_devices(void);
+
 static struct map_desc at91rm9200_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -275,6 +277,8 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks
 	/* Map peripherals */
 	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
 
+	at91rm9200_init_devices();
+
 	at91_arch_reset = at91rm9200_reset;
 	at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
 			| (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 7b53922..1b93312 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -23,7 +23,7 @@
 #include <mach/at91rm9200_mc.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /* --------------------------------------------------------------------
  *  USB Host
@@ -125,75 +125,38 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
  *  Ethernet
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_EMAC,
-		.end	= AT91_VA_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_EMAC,
-		.end	= AT91RM9200_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config eth_rmii_pins[] = {
+	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
+	{AT91_PIN_PA15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
+	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
+	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
+	{AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
+	{AT91_PIN_PA11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ECRS_ECRSDV */
+	{AT91_PIN_PA10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
+	{AT91_PIN_PA9,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
+	{AT91_PIN_PA8,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
+	{AT91_PIN_PA7,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
 };
 
-static struct platform_device at91rm9200_eth_device = {
-	.name		= "at91_ether",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &eth_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
+static struct __initdata at91_pin_config eth_mii_pins[] = {
+	{AT91_PIN_PB19, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
+	{AT91_PIN_PB18, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
+	{AT91_PIN_PB17, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXDV */
+	{AT91_PIN_PB16, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
+	{AT91_PIN_PB15, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
+	{AT91_PIN_PB14, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
+	{AT91_PIN_PB13, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
+	{AT91_PIN_PB12, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Pins used for MII and RMII */
-	at91_set_A_periph(AT91_PIN_PA16, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PA15, 0);	/* EMDC */
-	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PA11, 0);	/* ECRS_ECRSDV */
-	at91_set_A_periph(AT91_PIN_PA10, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PA9, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PA8, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PA7, 0);	/* ETXCK_EREFCK */
-
-	if (!data->is_rmii) {
-		at91_set_B_periph(AT91_PIN_PB19, 0);	/* ERXCK */
-		at91_set_B_periph(AT91_PIN_PB18, 0);	/* ECOL */
-		at91_set_B_periph(AT91_PIN_PB17, 0);	/* ERXDV */
-		at91_set_B_periph(AT91_PIN_PB16, 0);	/* ERX3 */
-		at91_set_B_periph(AT91_PIN_PB15, 0);	/* ERX2 */
-		at91_set_B_periph(AT91_PIN_PB14, 0);	/* ETXER */
-		at91_set_B_periph(AT91_PIN_PB13, 0);	/* ETX3 */
-		at91_set_B_periph(AT91_PIN_PB12, 0);	/* ETX2 */
-	}
-
-	eth_data = *data;
-	platform_device_register(&at91rm9200_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
-#endif
-
+static struct __initdata at91_dev_table_ethernet device_eth = {
+	.mmio_base	= AT91_VA_BASE_EMAC,
+	.irq		= AT91RM9200_ID_EMAC,
+	.rmii_pins	= eth_rmii_pins,
+	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
+	.mii_pins	= eth_mii_pins,
+	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
+};
 
 /* --------------------------------------------------------------------
  *  Compact Flash / PCMCIA
@@ -1170,6 +1133,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+static struct at91_device_table __initdata at91rm9200_device_table = {
+	.ethernet	= &device_eth,
+};
+
+void __init at91rm9200_init_devices(void)
+{
+	at91_init_devices(&at91rm9200_device_table);
+}
 
 /* -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 195208b..7445f48 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -25,6 +25,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void at91sam9260_init_devices(void);
+
 static struct map_desc at91sam9260_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -315,6 +317,8 @@ void __init at91sam9260_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
 
+	at91sam9260_init_devices();
+
 	if (cpu_is_at91sam9xe())
 		at91sam9xe_initialize();
 	else if (cpu_is_at91sam9g20())
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 07eb7b0..b4f00ea 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -24,7 +24,7 @@
 #include <mach/at91sam9_smc.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /* --------------------------------------------------------------------
  *  USB Host
@@ -126,75 +126,38 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
  *  Ethernet
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_EMAC,
-		.end	= AT91SAM9260_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_EMAC,
-		.end	= AT91SAM9260_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config eth_rmii_pins[] = {
+	{AT91_PIN_PA19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
+	{AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
+	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
+	{AT91_PIN_PA15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
+	{AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
+	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
+	{AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
+	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
+	{AT91_PIN_PA21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
+	{AT91_PIN_PA20, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
 };
 
-static struct platform_device at91sam9260_eth_device = {
-	.name		= "macb",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &eth_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
+static struct __initdata at91_pin_config eth_mii_pins[] = {
+	{AT91_PIN_PA28, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECRS */
+	{AT91_PIN_PA29, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
+	{AT91_PIN_PA25, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
+	{AT91_PIN_PA26, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
+	{AT91_PIN_PA27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
+	{AT91_PIN_PA23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
+	{AT91_PIN_PA24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
+	{AT91_PIN_PA22, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Pins used for MII and RMII */
-	at91_set_A_periph(AT91_PIN_PA19, 0);	/* ETXCK_EREFCK */
-	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ERXDV */
-	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PA15, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PA18, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PA21, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PA20, 0);	/* EMDC */
-
-	if (!data->is_rmii) {
-		at91_set_B_periph(AT91_PIN_PA28, 0);	/* ECRS */
-		at91_set_B_periph(AT91_PIN_PA29, 0);	/* ECOL */
-		at91_set_B_periph(AT91_PIN_PA25, 0);	/* ERX2 */
-		at91_set_B_periph(AT91_PIN_PA26, 0);	/* ERX3 */
-		at91_set_B_periph(AT91_PIN_PA27, 0);	/* ERXCK */
-		at91_set_B_periph(AT91_PIN_PA23, 0);	/* ETX2 */
-		at91_set_B_periph(AT91_PIN_PA24, 0);	/* ETX3 */
-		at91_set_B_periph(AT91_PIN_PA22, 0);	/* ETXER */
-	}
-
-	eth_data = *data;
-	platform_device_register(&at91sam9260_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
-#endif
-
+static struct __initdata at91_dev_table_ethernet device_eth = {
+	.mmio_base	= AT91SAM9260_BASE_EMAC,
+	.irq		= AT91SAM9260_ID_EMAC,
+	.rmii_pins	= eth_rmii_pins,
+	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
+	.mii_pins	= eth_mii_pins,
+	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
+};
 
 /* --------------------------------------------------------------------
  *  MMC / SD
@@ -1326,6 +1289,15 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
 void __init at91_add_device_cf(struct at91_cf_data * data) {}
 #endif
 
+static struct at91_device_table __initdata at91sam9260_device_table = {
+	.ethernet	= &device_eth,
+};
+
+void __init at91sam9260_init_devices(void)
+{
+	at91_init_devices(&at91sam9260_device_table);
+}
+
 /* -------------------------------------------------------------------- */
 /*
  * These devices are always present and don't need any board-specific
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 59fc483..3c0959f 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -1044,7 +1044,6 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
-
 /* -------------------------------------------------------------------- */
 
 /*
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 249f900..739fc1f 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -24,6 +24,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void at91sam9263_init_devices(void);
+
 static struct map_desc at91sam9263_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -284,6 +286,8 @@ void __init at91sam9263_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
 
+	at91sam9263_init_devices();
+
 	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9263_poweroff;
 	at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index fb5c23a..9ff2573 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -26,6 +26,7 @@
 #include <mach/at91sam9_smc.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 /* --------------------------------------------------------------------
@@ -136,75 +137,38 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
  *  Ethernet
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_EMAC,
-		.end	= AT91SAM9263_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_EMAC,
-		.end	= AT91SAM9263_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config eth_rmii_pins[] = {
+	{AT91_PIN_PE21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
+	{AT91_PIN_PC25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
+	{AT91_PIN_PE25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
+	{AT91_PIN_PE26, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
+	{AT91_PIN_PE27, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
+	{AT91_PIN_PE28, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
+	{AT91_PIN_PE23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
+	{AT91_PIN_PE24, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
+	{AT91_PIN_PE30, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
+	{AT91_PIN_PE29, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
 };
 
-static struct platform_device at91sam9263_eth_device = {
-	.name		= "macb",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &eth_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
+static struct __initdata at91_pin_config eth_mii_pins[] = {
+	{AT91_PIN_PE22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ECRS */
+	{AT91_PIN_PC26, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
+	{AT91_PIN_PC22, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
+	{AT91_PIN_PC23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
+	{AT91_PIN_PC27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
+	{AT91_PIN_PC20, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
+	{AT91_PIN_PC21, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
+	{AT91_PIN_PC24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
 };
 
-void __init at91_add_device_eth(struct at91_eth_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Pins used for MII and RMII */
-	at91_set_A_periph(AT91_PIN_PE21, 0);	/* ETXCK_EREFCK */
-	at91_set_B_periph(AT91_PIN_PC25, 0);	/* ERXDV */
-	at91_set_A_periph(AT91_PIN_PE25, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PE26, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PE27, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PE28, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PE23, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PE24, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PE30, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PE29, 0);	/* EMDC */
-
-	if (!data->is_rmii) {
-		at91_set_A_periph(AT91_PIN_PE22, 0);	/* ECRS */
-		at91_set_B_periph(AT91_PIN_PC26, 0);	/* ECOL */
-		at91_set_B_periph(AT91_PIN_PC22, 0);	/* ERX2 */
-		at91_set_B_periph(AT91_PIN_PC23, 0);	/* ERX3 */
-		at91_set_B_periph(AT91_PIN_PC27, 0);	/* ERXCK */
-		at91_set_B_periph(AT91_PIN_PC20, 0);	/* ETX2 */
-		at91_set_B_periph(AT91_PIN_PC21, 0);	/* ETX3 */
-		at91_set_B_periph(AT91_PIN_PC24, 0);	/* ETXER */
-	}
-
-	eth_data = *data;
-	platform_device_register(&at91sam9263_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
-#endif
-
+static struct __initdata at91_dev_table_ethernet device_eth = {
+	.mmio_base	= AT91SAM9263_BASE_EMAC,
+	.irq		= AT91SAM9263_ID_EMAC,
+	.rmii_pins	= eth_rmii_pins,
+	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
+	.mii_pins	= eth_mii_pins,
+	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
+};
 
 /* --------------------------------------------------------------------
  *  MMC / SD
@@ -1425,6 +1389,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+static struct at91_device_table __initdata at91sam9263_device_table = {
+	.ethernet	= &device_eth,
+};
+
+void __init at91sam9263_init_devices(void)
+{
+	at91_init_devices(&at91sam9263_device_table);
+}
 
 /* -------------------------------------------------------------------- */
 /*
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index c67b47f..357e5d7 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -25,6 +25,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void at91sam9g45_init_devices(void);
+
 static struct map_desc at91sam9g45_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -311,6 +313,8 @@ void __init at91sam9g45_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at91sam9g45_io_desc, ARRAY_SIZE(at91sam9g45_io_desc));
 
+	at91sam9g45_init_devices();
+
 	at91_arch_reset = at91sam9g45_reset;
 	pm_power_off = at91sam9g45_poweroff;
 	at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 1e8f275..76e95f8 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -29,6 +29,7 @@
 #include <mach/atmel-mci.h>
 
 #include "generic.h"
+#include "devices.h"
 
 
 /* --------------------------------------------------------------------
@@ -281,76 +282,39 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
  *  Ethernet
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct at91_eth_data eth_data;
-
-static struct resource eth_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_EMAC,
-		.end	= AT91SAM9G45_BASE_EMAC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_EMAC,
-		.end	= AT91SAM9G45_ID_EMAC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config eth_rmii_pins[] = {
+	{AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
+	{AT91_PIN_PA15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
+	{AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
+	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
+	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
+	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
+	{AT91_PIN_PA10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
+	{AT91_PIN_PA11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
+	{AT91_PIN_PA19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
+	{AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
+};
+
+static struct __initdata at91_pin_config eth_mii_pins[] = {
+	{AT91_PIN_PA29, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECRS */
+	{AT91_PIN_PA30, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
+	{AT91_PIN_PA8,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
+	{AT91_PIN_PA9,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
+	{AT91_PIN_PA28, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
+	{AT91_PIN_PA6,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
+	{AT91_PIN_PA7,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
+	{AT91_PIN_PA27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
+};
+
+static struct __initdata at91_dev_table_ethernet device_eth = {
+	.mmio_base	= AT91SAM9G45_BASE_EMAC,
+	.irq		= AT91SAM9G45_ID_EMAC,
+	.rmii_pins	= eth_rmii_pins,
+	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
+	.mii_pins	= eth_mii_pins,
+	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
 };
 
-static struct platform_device at91sam9g45_eth_device = {
-	.name		= "macb",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &eth_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &eth_data,
-	},
-	.resource	= eth_resources,
-	.num_resources	= ARRAY_SIZE(eth_resources),
-};
-
-void __init at91_add_device_eth(struct at91_eth_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->phy_irq_pin) {
-		at91_set_gpio_input(data->phy_irq_pin, 0);
-		at91_set_deglitch(data->phy_irq_pin, 1);
-	}
-
-	/* Pins used for MII and RMII */
-	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ETXCK_EREFCK */
-	at91_set_A_periph(AT91_PIN_PA15, 0);	/* ERXDV */
-	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ERX0 */
-	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ERX1 */
-	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ERXER */
-	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ETXEN */
-	at91_set_A_periph(AT91_PIN_PA10, 0);	/* ETX0 */
-	at91_set_A_periph(AT91_PIN_PA11, 0);	/* ETX1 */
-	at91_set_A_periph(AT91_PIN_PA19, 0);	/* EMDIO */
-	at91_set_A_periph(AT91_PIN_PA18, 0);	/* EMDC */
-
-	if (!data->is_rmii) {
-		at91_set_B_periph(AT91_PIN_PA29, 0);	/* ECRS */
-		at91_set_B_periph(AT91_PIN_PA30, 0);	/* ECOL */
-		at91_set_B_periph(AT91_PIN_PA8,  0);	/* ERX2 */
-		at91_set_B_periph(AT91_PIN_PA9,  0);	/* ERX3 */
-		at91_set_B_periph(AT91_PIN_PA28, 0);	/* ERXCK */
-		at91_set_B_periph(AT91_PIN_PA6,  0);	/* ETX2 */
-		at91_set_B_periph(AT91_PIN_PA7,  0);	/* ETX3 */
-		at91_set_B_periph(AT91_PIN_PA27, 0);	/* ETXER */
-	}
-
-	eth_data = *data;
-	platform_device_register(&at91sam9g45_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct at91_eth_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  MMC / SD
  * -------------------------------------------------------------------- */
@@ -1587,6 +1551,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+static struct at91_device_table __initdata at91sam9g45_device_table = {
+	.ethernet	= &device_eth,
+};
+
+void __init at91sam9g45_init_devices(void)
+{
+	at91_init_devices(&at91sam9g45_device_table);
+}
 
 /* -------------------------------------------------------------------- */
 /*
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 653e0a9..07fefc8 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -14,8 +14,11 @@
  */
 
 #include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 
+#include <mach/board.h>
+
 #include "devices.h"
 
 static __initdata struct at91_device_table *devices;
@@ -64,6 +67,64 @@ static inline void __init init_resource_irq(struct resource *res, int irq)
 	}
 }
 
+/* --------------------------------------------------------------------
+ *  Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = DMA_BIT_MASK(32);
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_eth_device = {
+	.name		= "macb",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &eth_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &eth_data,
+	},
+	.resource	= eth_resources,
+	.num_resources	= ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+	struct at91_dev_table_ethernet *info = devices->ethernet;
+
+	BUG_ON(!info);
+	init_resource_mem(&eth_resources[0], info->mmio_base);
+	init_resource_irq(&eth_resources[1], info->irq);
+
+	if (!data)
+		return;
+
+	if (data->phy_irq_pin) {
+		at91_set_gpio_input(data->phy_irq_pin, 0);
+		at91_set_deglitch(data->phy_irq_pin, 1);
+	}
+
+	/* Pins used for MII and RMII */
+	at91_config_pins(info->rmii_pins, info->nr_rmii_pins);
+	if (!data->is_rmii && info->mii_pins)
+		at91_config_pins(info->mii_pins, info->nr_mii_pins);
+
+	eth_data = *data;
+	platform_device_register(&at91_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 738f736..7bed3e7 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -28,7 +28,17 @@ struct at91_pin_config {
 	int value;
 };
 
+struct at91_dev_table_ethernet {
+	unsigned 		mmio_base;
+	int 			irq;
+	struct at91_pin_config	*rmii_pins;
+	int 			nr_rmii_pins;
+	struct at91_pin_config	*mii_pins;
+	int 			nr_mii_pins;
+};
+
 struct at91_device_table {
+	struct at91_dev_table_ethernet		*ethernet;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 03/23] at91: Make USB OHCI/EHCI devices common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 01/23] at91: Add common devices framework Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 02/23] at91: Make Ethernet device common Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 04/23] at91: Make UDC device common Ryan Mallon
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual USB OHCI and EHCI (AT91SAM9G45 only) device code for
each at91 variant with a single implementation in devices.c. Rename
at91_add_device_usbh to at91_add_device_usbh_ohci (as it is on AT91SAM9G45)
to make the API consistent for all variants.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c  |   45 +----------
 arch/arm/mach-at91/at91cap9_devices.c     |   54 ++------------
 arch/arm/mach-at91/at91rm9200_devices.c   |   44 +----------
 arch/arm/mach-at91/at91sam9260_devices.c  |   44 +----------
 arch/arm/mach-at91/at91sam9261.c          |    4 +
 arch/arm/mach-at91/at91sam9261_devices.c  |   54 +++----------
 arch/arm/mach-at91/at91sam9263_devices.c  |   52 +------------
 arch/arm/mach-at91/at91sam9g45_devices.c  |  105 ++------------------------
 arch/arm/mach-at91/board-1arm.c           |    2 +-
 arch/arm/mach-at91/board-afeb-9260v1.c    |    2 +-
 arch/arm/mach-at91/board-at572d940hf_ek.c |    2 +-
 arch/arm/mach-at91/board-cam60.c          |    2 +-
 arch/arm/mach-at91/board-cap9adk.c        |    2 +-
 arch/arm/mach-at91/board-carmeva.c        |    2 +-
 arch/arm/mach-at91/board-cpu9krea.c       |    2 +-
 arch/arm/mach-at91/board-cpuat91.c        |    2 +-
 arch/arm/mach-at91/board-csb337.c         |    2 +-
 arch/arm/mach-at91/board-csb637.c         |    2 +-
 arch/arm/mach-at91/board-eb9200.c         |    2 +-
 arch/arm/mach-at91/board-ecbat91.c        |    2 +-
 arch/arm/mach-at91/board-eco920.c         |    2 +-
 arch/arm/mach-at91/board-flexibity.c      |    2 +-
 arch/arm/mach-at91/board-foxg20.c         |    2 +-
 arch/arm/mach-at91/board-gsia18s.c        |    2 +-
 arch/arm/mach-at91/board-kafa.c           |    2 +-
 arch/arm/mach-at91/board-kb9202.c         |    2 +-
 arch/arm/mach-at91/board-neocore926.c     |    2 +-
 arch/arm/mach-at91/board-pcontrol-g20.c   |    2 +-
 arch/arm/mach-at91/board-picotux200.c     |    2 +-
 arch/arm/mach-at91/board-qil-a9260.c      |    2 +-
 arch/arm/mach-at91/board-rm9200dk.c       |    2 +-
 arch/arm/mach-at91/board-rm9200ek.c       |    2 +-
 arch/arm/mach-at91/board-sam9-l9260.c     |    2 +-
 arch/arm/mach-at91/board-sam9260ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9261ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9263ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9g20ek.c      |    2 +-
 arch/arm/mach-at91/board-snapper9260.c    |    2 +-
 arch/arm/mach-at91/board-stamp9g20.c      |    4 +-
 arch/arm/mach-at91/board-usb-a9260.c      |    2 +-
 arch/arm/mach-at91/board-usb-a9263.c      |    2 +-
 arch/arm/mach-at91/board-yl-9200.c        |    2 +-
 arch/arm/mach-at91/devices.c              |  117 +++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h              |   13 +++
 arch/arm/mach-at91/include/mach/board.h   |    1 -
 45 files changed, 213 insertions(+), 390 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index 12af1d5..169e5c4 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -42,49 +42,11 @@
  *  USB Host
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_UHP_BASE,
-		.end	= AT572D940HF_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_UHP,
-		.end	= AT572D940HF_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
+	.mmio_base	= AT572D940HF_UHP_BASE,
+	.irq		= AT572D940HF_ID_UHP,
 };
 
-static struct platform_device at572d940hf_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	if (!data)
-		return;
-
-	usbh_data = *data;
-	platform_device_register(&at572d940hf_usbh_device);
-
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
@@ -913,6 +875,7 @@ void __init at91_add_device_mAgic(void) {}
 
 static struct at91_device_table __initdata at572d940hf_device_table = {
 	.ethernet	= &device_eth,
+	.usbh_ohci	= &device_usbh_ohci,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 183f320..c88633c 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -35,58 +35,17 @@
  *  USB Host
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_UHP_BASE,
-		.end	= AT91CAP9_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_UHP,
-		.end	= AT91CAP9_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
+static void __init at91cap9_usb_ohci_init(void)
 {
-	int i;
-
-	if (!data)
-		return;
-
 	if (cpu_is_at91cap9_revB())
 		irq_set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH);
-
-	/* Enable VBus control for UHP ports */
-	for (i = 0; i < data->ports; i++) {
-		if (data->vbus_pin[i])
-			at91_set_gpio_output(data->vbus_pin[i], 0);
-	}
-
-	usbh_data = *data;
-	platform_device_register(&at91_usbh_device);
 }
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
 
+static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
+	.mmio_base	= AT91CAP9_UHP_BASE,
+	.irq		= AT91CAP9_ID_UHP,
+	.device_init	= at91cap9_usb_ohci_init,
+};
 
 /* --------------------------------------------------------------------
  *  USB HS Device (Gadget)
@@ -1219,6 +1178,7 @@ void __init at91_add_device_serial(void) {}
 
 static struct at91_device_table __initdata at91cap9_device_table = {
 	.ethernet	= &device_eth,
+	.usbh_ohci	= &device_usbh_ohci,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 1b93312..428b9da 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -29,48 +29,11 @@
  *  USB Host
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_UHP_BASE,
-		.end	= AT91RM9200_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_UHP,
-		.end	= AT91RM9200_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
+static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
+	.mmio_base	= AT91RM9200_UHP_BASE,
+	.irq		= AT91RM9200_ID_UHP,
 };
 
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	if (!data)
-		return;
-
-	usbh_data = *data;
-	platform_device_register(&at91rm9200_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
@@ -1135,6 +1098,7 @@ void __init at91_add_device_serial(void) {}
 
 static struct at91_device_table __initdata at91rm9200_device_table = {
 	.ethernet	= &device_eth,
+	.usbh_ohci	= &device_usbh_ohci,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index b4f00ea..b71e6b0 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -30,48 +30,11 @@
  *  USB Host
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_UHP_BASE,
-		.end	= AT91SAM9260_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_UHP,
-		.end	= AT91SAM9260_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
+static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
+	.mmio_base	= AT91SAM9260_UHP_BASE,
+	.irq		= AT91SAM9260_ID_UHP,
 };
 
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	if (!data)
-		return;
-
-	usbh_data = *data;
-	platform_device_register(&at91_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
@@ -1291,6 +1254,7 @@ void __init at91_add_device_cf(struct at91_cf_data * data) {}
 
 static struct at91_device_table __initdata at91sam9260_device_table = {
 	.ethernet	= &device_eth,
+	.usbh_ohci	= &device_usbh_ohci,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index fcad886..dd0a96d 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -25,6 +25,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void at91sam9261_init_devices(void);
+
 static struct map_desc at91sam9261_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -272,6 +274,8 @@ void __init at91sam9261_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
 
+	at91sam9261_init_devices();
+
 	if (cpu_is_at91sam9g10())
 		iotable_init(at91sam9g10_sram_desc, ARRAY_SIZE(at91sam9g10_sram_desc));
 	else
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 3c0959f..16d5b91 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -27,54 +27,17 @@
 #include <mach/at91sam9_smc.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /* --------------------------------------------------------------------
  *  USB Host
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_UHP_BASE,
-		.end	= AT91SAM9261_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_UHP,
-		.end	= AT91SAM9261_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
+static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
+	.mmio_base	= AT91SAM9261_UHP_BASE,
+	.irq		= AT91SAM9261_ID_UHP,
 };
 
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	if (!data)
-		return;
-
-	usbh_data = *data;
-	platform_device_register(&at91sam9261_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
@@ -1044,6 +1007,15 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+static struct at91_device_table __initdata at91sam9261_device_table = {
+	.usbh_ohci	= &device_usbh_ohci,
+};
+
+void __init at91sam9261_init_devices(void)
+{
+	at91_init_devices(&at91sam9261_device_table);
+}
+
 /* -------------------------------------------------------------------- */
 
 /*
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 9ff2573..1f851f6 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -33,56 +33,11 @@
  *  USB Host
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_UHP_BASE,
-		.end	= AT91SAM9263_UHP_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_UHP,
-		.end	= AT91SAM9263_ID_UHP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_usbh_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_data,
-	},
-	.resource	= usbh_resources,
-	.num_resources	= ARRAY_SIZE(usbh_resources),
+static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
+	.mmio_base	= AT91SAM9263_UHP_BASE,
+	.irq		= AT91SAM9263_ID_UHP,
 };
 
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-	int i;
-
-	if (!data)
-		return;
-
-	/* Enable VBus control for UHP ports */
-	for (i = 0; i < data->ports; i++) {
-		if (data->vbus_pin[i])
-			at91_set_gpio_output(data->vbus_pin[i], 0);
-	}
-
-	usbh_data = *data;
-	platform_device_register(&at91_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
@@ -1391,6 +1346,7 @@ void __init at91_add_device_serial(void) {}
 
 static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ethernet	= &device_eth,
+	.usbh_ohci	= &device_usbh_ohci,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 76e95f8..2961249 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -83,112 +83,21 @@ void __init at91_add_device_hdmac(void) {}
  *  USB Host (OHCI)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_ohci_data;
-
-static struct resource usbh_ohci_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_OHCI_BASE,
-		.end	= AT91SAM9G45_OHCI_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_UHPHS,
-		.end	= AT91SAM9G45_ID_UHPHS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_usbh_ohci_device = {
-	.name		= "at91_ohci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ohci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_ohci_data,
-	},
-	.resource	= usbh_ohci_resources,
-	.num_resources	= ARRAY_SIZE(usbh_ohci_resources),
+static struct __initdata at91_dev_table_usb_ohci device_usb_ohci = {
+	.mmio_base	= AT91SAM9G45_OHCI_BASE,
+	.irq		= AT91SAM9G45_ID_UHPHS,
 };
 
-void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
-{
-	int i;
-
-	if (!data)
-		return;
-
-	/* Enable VBus control for UHP ports */
-	for (i = 0; i < data->ports; i++) {
-		if (data->vbus_pin[i])
-			at91_set_gpio_output(data->vbus_pin[i], 0);
-	}
-
-	usbh_ohci_data = *data;
-	platform_device_register(&at91_usbh_ohci_device);
-}
-#else
-void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB Host HS (EHCI)
  *  Needs an OHCI host for low and full speed management
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
-static u64 ehci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_ehci_data;
-
-static struct resource usbh_ehci_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_EHCI_BASE,
-		.end	= AT91SAM9G45_EHCI_BASE + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_UHPHS,
-		.end	= AT91SAM9G45_ID_UHPHS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_usbh_ehci_device = {
-	.name		= "atmel-ehci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &ehci_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &usbh_ehci_data,
-	},
-	.resource	= usbh_ehci_resources,
-	.num_resources	= ARRAY_SIZE(usbh_ehci_resources),
+static struct __initdata at91_dev_table_basic_device device_usb_ehci = {
+	.mmio_base	= AT91SAM9G45_EHCI_BASE,
+	.irq		= AT91SAM9G45_ID_UHPHS,
 };
 
-void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data)
-{
-	int i;
-
-	if (!data)
-		return;
-
-	/* Enable VBus control for UHP ports */
-	for (i = 0; i < data->ports; i++) {
-		if (data->vbus_pin[i])
-			at91_set_gpio_output(data->vbus_pin[i], 0);
-	}
-
-	usbh_ehci_data = *data;
-	at91_clock_associate("uhphs_clk", &at91_usbh_ehci_device.dev, "ehci_clk");
-	platform_device_register(&at91_usbh_ehci_device);
-}
-#else
-void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
@@ -1553,6 +1462,8 @@ void __init at91_add_device_serial(void) {}
 
 static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.ethernet	= &device_eth,
+	.usbh_ohci	= &device_usb_ohci,
+	.usbh_ehci	= &device_usb_ehci,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 8a3fc84..244e8bb 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -85,7 +85,7 @@ static void __init onearm_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&onearm_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&onearm_usbh_data);
+	at91_add_device_usbh_ohci(&onearm_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&onearm_udc_data);
 }
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index cba7f77..88d08ae 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -189,7 +189,7 @@ static void __init afeb9260_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&afeb9260_usbh_data);
+	at91_add_device_usbh_ohci(&afeb9260_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&afeb9260_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c
index 3929f1c..c9ab05d 100644
--- a/arch/arm/mach-at91/board-at572d940hf_ek.c
+++ b/arch/arm/mach-at91/board-at572d940hf_ek.c
@@ -297,7 +297,7 @@ static void __init eb_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&eb_usbh_data);
+	at91_add_device_usbh_ohci(&eb_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&eb_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index b54e3e6..014271d 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -191,7 +191,7 @@ static void __init cam60_board_init(void)
 	/* USB Host */
 	/* enable USB power supply circuit */
 	at91_set_gpio_output(AT91_PIN_PB18, 1);
-	at91_add_device_usbh(&cam60_usbh_data);
+	at91_add_device_usbh_ohci(&cam60_usbh_data);
 	/* NAND */
 	cam60_add_device_nand();
 }
diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
index e727444..0d60378 100644
--- a/arch/arm/mach-at91/board-cap9adk.c
+++ b/arch/arm/mach-at91/board-cap9adk.c
@@ -374,7 +374,7 @@ static void __init cap9adk_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&cap9adk_usbh_data);
+	at91_add_device_usbh_ohci(&cap9adk_usbh_data);
 	/* USB HS */
 	at91_add_device_usba(&cap9adk_usba_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index 2e74a19..9d007a8 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -145,7 +145,7 @@ static void __init carmeva_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&carmeva_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&carmeva_usbh_data);
+	at91_add_device_usbh_ohci(&carmeva_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&carmeva_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 3838594..65c6513 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -351,7 +351,7 @@ static void __init cpu9krea_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&cpu9krea_usbh_data);
+	at91_add_device_usbh_ohci(&cpu9krea_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&cpu9krea_udc_data);
 	/* NAND */
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index 2f4dd8c..ce3525d 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -162,7 +162,7 @@ static void __init cpuat91_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&cpuat91_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&cpuat91_usbh_data);
+	at91_add_device_usbh_ohci(&cpuat91_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&cpuat91_udc_data);
 	/* MMC */
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 464839d..ff7b8c0 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -235,7 +235,7 @@ static void __init csb337_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&csb337_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&csb337_usbh_data);
+	at91_add_device_usbh_ohci(&csb337_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&csb337_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index 431688c..74d5b7e 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -125,7 +125,7 @@ static void __init csb637_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&csb637_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&csb637_usbh_data);
+	at91_add_device_usbh_ohci(&csb637_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&csb637_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 6cf6566..3705082 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -105,7 +105,7 @@ static void __init eb9200_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&eb9200_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&eb9200_usbh_data);
+	at91_add_device_usbh_ohci(&eb9200_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&eb9200_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index de2fd04..df4a07f 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -154,7 +154,7 @@ static void __init ecb_at91board_init(void)
 	at91_add_device_eth(&ecb_at91eth_data);
 
 	/* USB Host */
-	at91_add_device_usbh(&ecb_at91usbh_data);
+	at91_add_device_usbh_ohci(&ecb_at91usbh_data);
 
 	/* I2C */
 	at91_add_device_i2c(NULL, 0);
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index a158a0c..7988b58 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -114,7 +114,7 @@ static void __init eco920_board_init(void)
 {
 	at91_add_device_serial();
 	at91_add_device_eth(&eco920_eth_data);
-	at91_add_device_usbh(&eco920_usbh_data);
+	at91_add_device_usbh_ohci(&eco920_usbh_data);
 	at91_add_device_udc(&eco920_udc_data);
 
 	at91_add_device_mmc(0, &eco920_mmc_data);
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index c8a62dc..096d5d2 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -140,7 +140,7 @@ static void __init flexibity_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&flexibity_usbh_data);
+	at91_add_device_usbh_ohci(&flexibity_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&flexibity_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index dfc7dfe..6688ec2 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -244,7 +244,7 @@ static void __init foxg20_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&foxg20_usbh_data);
+	at91_add_device_usbh_ohci(&foxg20_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&foxg20_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index bc28136..8b1d498 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -561,7 +561,7 @@ static int __init gsia18s_power_off_init(void)
 static void __init gsia18s_board_init(void)
 {
 	stamp9g20_board_init();
-	at91_add_device_usbh(&usbh_data);
+	at91_add_device_usbh_ohci(&usbh_data);
 	at91_add_device_udc(&udc_data);
 	at91_add_device_eth(&macb_data);
 	gsia18s_leds_init();
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index d2e1f4e..a0cac24 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -83,7 +83,7 @@ static void __init kafa_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&kafa_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&kafa_usbh_data);
+	at91_add_device_usbh_ohci(&kafa_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&kafa_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index a13d206..59eafa2 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -121,7 +121,7 @@ static void __init kb9202_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&kb9202_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&kb9202_usbh_data);
+	at91_add_device_usbh_ohci(&kb9202_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&kb9202_udc_data);
 	/* MMC */
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index fe5f1d4..bffbbdf 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -351,7 +351,7 @@ static void __init neocore926_board_init(void)
 	at91_add_device_serial();
 
 	/* USB Host */
-	at91_add_device_usbh(&neocore926_usbh_data);
+	at91_add_device_usbh_ohci(&neocore926_usbh_data);
 
 	/* USB Device */
 	at91_add_device_udc(&neocore926_udc_data);
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index feb6578..4c5848d 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -205,7 +205,7 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {
 static void __init pcontrol_g20_board_init(void)
 {
 	stamp9g20_board_init();
-	at91_add_device_usbh(&usbh_data);
+	at91_add_device_usbh_ohci(&usbh_data);
 	at91_add_device_eth(&macb_data);
 	at91_add_device_i2c(pcontrol_g20_i2c_devices,
 		ARRAY_SIZE(pcontrol_g20_i2c_devices));
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 55dad3a..419456d 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -111,7 +111,7 @@ static void __init picotux200_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&picotux200_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&picotux200_usbh_data);
+	at91_add_device_usbh_ohci(&picotux200_usbh_data);
 	/* I2C */
 	at91_add_device_i2c(NULL, 0);
 	/* MMC */
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index 69d15a8..255a984 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -244,7 +244,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index 4c1047c..3d54963 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -197,7 +197,7 @@ static void __init dk_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&dk_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&dk_usbh_data);
+	at91_add_device_usbh_ohci(&dk_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&dk_udc_data);
 	at91_set_multi_drive(dk_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 9df1be8..25fe19f 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -167,7 +167,7 @@ static void __init ek_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&ek_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	at91_set_multi_drive(ek_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index 25a26be..589e2f4 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -195,7 +195,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index de1816e..b98e766 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -332,7 +332,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 14acc90..e631172 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -586,7 +586,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index bfe490d..fae6ebf 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -423,7 +423,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index ca8198b..c25e44c 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -379,7 +379,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 17f7d9b..ca14290 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -169,7 +169,7 @@ static void __init snapper9260_board_init(void)
 	at91_add_device_i2c(snapper9260_i2c_devices,
 			    ARRAY_SIZE(snapper9260_i2c_devices));
 	at91_add_device_serial();
-	at91_add_device_usbh(&snapper9260_usbh_data);
+	at91_add_device_usbh_ohci(&snapper9260_usbh_data);
 	at91_add_device_udc(&snapper9260_udc_data);
 	at91_add_device_eth(&snapper9260_macb_data);
 	at91_add_device_ssc(AT91SAM9260_ID_SSC, (ATMEL_SSC_TF | ATMEL_SSC_TK |
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index f8902b1..1e7a73a 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -268,7 +268,7 @@ static void __init portuxg20_board_init(void)
 {
 	stamp9g20_board_init();
 	/* USB Host */
-	at91_add_device_usbh(&usbh_data);
+	at91_add_device_usbh_ohci(&usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&portuxg20_udc_data);
 	/* Ethernet */
@@ -285,7 +285,7 @@ static void __init stamp9g20evb_board_init(void)
 {
 	stamp9g20_board_init();
 	/* USB Host */
-	at91_add_device_usbh(&usbh_data);
+	at91_add_device_usbh_ohci(&usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&stamp9g20evb_udc_data);
 	/* Ethernet */
diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c
index 07784ba..9b5cbf5 100644
--- a/arch/arm/mach-at91/board-usb-a9260.c
+++ b/arch/arm/mach-at91/board-usb-a9260.c
@@ -208,7 +208,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* NAND */
diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a9263.c
index b614508..535af00 100644
--- a/arch/arm/mach-at91/board-usb-a9263.c
+++ b/arch/arm/mach-at91/board-usb-a9263.c
@@ -222,7 +222,7 @@ static void __init ek_board_init(void)
 	/* Serial */
 	at91_add_device_serial();
 	/* USB Host */
-	at91_add_device_usbh(&ek_usbh_data);
+	at91_add_device_usbh_ohci(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index e0f0080..bd5ebfd 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -567,7 +567,7 @@ static void __init yl9200_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&yl9200_eth_data);
 	/* USB Host */
-	at91_add_device_usbh(&yl9200_usbh_data);
+	at91_add_device_usbh_ohci(&yl9200_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&yl9200_udc_data);
 	/* I2C */
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 07fefc8..7d1f680 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -15,8 +15,10 @@
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
 #include <linux/gpio.h>
 
+#include <mach/cpu.h>
 #include <mach/board.h>
 
 #include "devices.h"
@@ -68,6 +70,121 @@ static inline void __init init_resource_irq(struct resource *res, int irq)
 }
 
 /* --------------------------------------------------------------------
+ *  USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+	[0] = {
+		.end	= SZ_1M,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_usbh_device = {
+	.name		= "at91_ohci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &ohci_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &usbh_data,
+	},
+	.resource	= usbh_resources,
+	.num_resources	= ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
+{
+	struct at91_dev_table_usb_ohci *info = devices->usbh_ohci;
+	int i;
+
+	BUG_ON(!info);
+	init_resource_mem(&usbh_resources[0], info->mmio_base);
+	init_resource_irq(&usbh_resources[1], info->irq);
+
+	if (!data)
+		return;
+
+	if (info->device_init)
+		info->device_init();
+
+	/* Enable VBus control for UHP ports */
+	for (i = 0; i < data->ports; i++) {
+		if (data->vbus_pin[i])
+			at91_set_gpio_output(data->vbus_pin[i], 0);
+	}
+
+	usbh_data = *data;
+	platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
+ *  USB Host HS (EHCI)
+ *  Needs an OHCI host for low and full speed management
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+static struct at91_usbh_data usbh_ehci_data;
+
+static struct resource usbh_ehci_resources[] = {
+	[0] = {
+		.end	= SZ_1M,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_usbh_ehci_device = {
+	.name		= "atmel-ehci",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &ehci_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &usbh_ehci_data,
+	},
+	.resource	= usbh_ehci_resources,
+	.num_resources	= ARRAY_SIZE(usbh_ehci_resources),
+};
+
+void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data)
+{
+	struct at91_dev_table_basic_device *info = devices->usb_ehci;
+	int i;
+
+	BUG_ON(!info);
+	init_resource_mem(&usb_ehci_resources[0], info->mmio_base);
+	init_resource_irq(&usb_ehci_resources[1], info->irq);
+
+	if (!data)
+		return;
+
+	/* Enable VBus control for UHP ports */
+	for (i = 0; i < data->ports; i++) {
+		if (data->vbus_pin[i])
+			at91_set_gpio_output(data->vbus_pin[i], 0);
+	}
+
+	usbh_ehci_data = *data;
+	at91_clock_associate("uhphs_clk", &at91_usbh_ehci_device.dev, "ehci_clk");
+	platform_device_register(&at91_usbh_ehci_device);
+}
+#else
+void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 7bed3e7..eb4de05 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -28,6 +28,11 @@ struct at91_pin_config {
 	int value;
 };
 
+struct at91_dev_table_basic_device {
+	unsigned 		mmio_base;
+	int 			irq;
+};
+
 struct at91_dev_table_ethernet {
 	unsigned 		mmio_base;
 	int 			irq;
@@ -37,8 +42,16 @@ struct at91_dev_table_ethernet {
 	int 			nr_mii_pins;
 };
 
+struct at91_dev_table_usb_ohci {
+	unsigned 		mmio_base;
+	int 			irq;
+	void			(*device_init)(void);
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
+	struct at91_dev_table_usb_ohci		*usbh_ohci;
+	struct at91_dev_table_basic_device	*usbh_ehci;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 2b499eb..dd0855d 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -99,7 +99,6 @@ struct at91_usbh_data {
 	u8		ports;		/* number of ports on root hub */
 	u8		vbus_pin[2];	/* port power-control pin */
 };
-extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data);
 
-- 
1.7.0.4

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

* [RFC PATCH 04/23] at91: Make UDC device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (2 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 03/23] at91: Make USB OHCI/EHCI devices common Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [PATCH 05/23] at91: Make MMC device (at91_mci) common Ryan Mallon
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual UDC device code for each at91 variant with a
single implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |   52 +++--------------------------
 arch/arm/mach-at91/at91rm9200_devices.c  |   48 ++-------------------------
 arch/arm/mach-at91/at91sam9260_devices.c |   48 ++-------------------------
 arch/arm/mach-at91/at91sam9261_devices.c |   47 ++------------------------
 arch/arm/mach-at91/at91sam9263_devices.c |   48 ++-------------------------
 arch/arm/mach-at91/devices.c             |   52 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |    1 +
 7 files changed, 75 insertions(+), 221 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index 169e5c4..ad74f57 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -51,52 +51,11 @@ static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_UDP,
-		.end	= AT572D940HF_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_UDP,
-		.end	= AT572D940HF_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at572d940hf_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
+static struct __initdata at91_dev_table_basic_device device_udc = {
+	.mmio_base	= AT572D940HF_BASE_UDP,
+	.irq		= AT572D940HF_ID_UDP,
 };
 
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-
-	/* Pullup pin is handled internally */
-
-	udc_data = *data;
-	platform_device_register(&at572d940hf_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
@@ -115,8 +74,8 @@ static struct __initdata at91_pin_config eth_rmii_pins[] = {
 };
 
 static struct __initdata at91_dev_table_ethernet device_eth = {
-	.mmio_base	= AT91SAM9260_BASE_EMAC,
-	.irq		= AT91SAM9260_ID_EMAC,
+	.mmio_base	= AT572D940HF_BASE_EMAC,
+	.irq		= AT572D940HF_ID_EMAC,
 	.rmii_pins	= eth_rmii_pins,
 	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
 };
@@ -876,6 +835,7 @@ void __init at91_add_device_mAgic(void) {}
 static struct at91_device_table __initdata at572d940hf_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
+	.udc		= &device_udc,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 428b9da..8230d83 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -38,52 +38,11 @@ static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_UDP,
-		.end	= AT91RM9200_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_UDP,
-		.end	= AT91RM9200_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
+static struct __initdata at91_dev_table_basic_device device_udc = {
+	.mmio_base	= AT91RM9200_BASE_UDP,
+	.irq		= AT91RM9200_ID_UDP,
 };
 
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-	if (data->pullup_pin)
-		at91_set_gpio_output(data->pullup_pin, 0);
-
-	udc_data = *data;
-	platform_device_register(&at91rm9200_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
@@ -1099,6 +1058,7 @@ void __init at91_add_device_serial(void) {}
 static struct at91_device_table __initdata at91rm9200_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
+	.udc		= &device_udc,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index b71e6b0..d743335 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -39,52 +39,11 @@ static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_UDP,
-		.end	= AT91SAM9260_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_UDP,
-		.end	= AT91SAM9260_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
+static struct __initdata at91_dev_table_basic_device device_udc = {
+	.mmio_base	= AT91SAM9260_BASE_UDP,
+	.irq		= AT91SAM9260_ID_UDP,
 };
 
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-
-	/* Pullup pin is handled internally by USB device peripheral */
-
-	udc_data = *data;
-	platform_device_register(&at91_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
@@ -1255,6 +1214,7 @@ void __init at91_add_device_cf(struct at91_cf_data * data) {}
 static struct at91_device_table __initdata at91sam9260_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
+	.udc		= &device_udc,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 16d5b91..ab194c0 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -42,51 +42,11 @@ static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_UDP,
-		.end	= AT91SAM9261_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_UDP,
-		.end	= AT91SAM9261_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
+static struct __initdata at91_dev_table_basic_device device_udc = {
+	.mmio_base	= AT91SAM9261_BASE_UDP,
+	.irq		= AT91SAM9261_ID_UDP,
 };
 
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-
-	/* Pullup pin is handled internally by USB device peripheral */
-
-	udc_data = *data;
-	platform_device_register(&at91sam9261_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  MMC / SD
  * -------------------------------------------------------------------- */
@@ -1009,6 +969,7 @@ void __init at91_add_device_serial(void) {}
 
 static struct at91_device_table __initdata at91sam9261_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
+	.udc		= &device_udc,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 1f851f6..530e4c6 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -42,52 +42,11 @@ static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
  *  USB Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_USB_GADGET_AT91
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_UDP,
-		.end	= AT91SAM9263_BASE_UDP + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_UDP,
-		.end	= AT91SAM9263_ID_UDP,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_udc_device = {
-	.name		= "at91_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &udc_data,
-	},
-	.resource	= udc_resources,
-	.num_resources	= ARRAY_SIZE(udc_resources),
+static struct __initdata at91_dev_table_basic_device device_udc = {
+	.mmio_base	= AT91SAM9263_BASE_UDP,
+	.irq		= AT91SAM9263_ID_UDP,
 };
 
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-	if (!data)
-		return;
-
-	if (data->vbus_pin) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-	}
-
-	/* Pullup pin is handled internally by USB device peripheral */
-
-	udc_data = *data;
-	platform_device_register(&at91_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
@@ -1347,6 +1306,7 @@ void __init at91_add_device_serial(void) {}
 static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
+	.udc		= &device_udc,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 7d1f680..28dc002 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -185,6 +185,58 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
 #endif
 
 /* --------------------------------------------------------------------
+ *  USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+#ifdef CONFIG_USB_GADGET_AT91
+
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_udc_device = {
+	.name		= "at91_udc",
+	.id		= -1,
+	.dev		= {
+				.platform_data		= &udc_data,
+	},
+	.resource	= udc_resources,
+	.num_resources	= ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+	struct at91_dev_table_basic_device *info = devices->udc;
+
+	BUG_ON(!info);
+	init_resource_mem(&udc_resources[0], info->mmio_base);
+	init_resource_irq(&udc_resources[1], info->irq);
+
+	if (!data)
+		return;
+
+	if (data->vbus_pin) {
+		at91_set_gpio_input(data->vbus_pin, 0);
+		at91_set_deglitch(data->vbus_pin, 1);
+	}
+	if (data->pullup_pin)
+		at91_set_gpio_output(data->pullup_pin, 0);
+
+	udc_data = *data;
+	platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index eb4de05..9203f58 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -52,6 +52,7 @@ struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
 	struct at91_dev_table_basic_device	*usbh_ehci;
+	struct at91_dev_table_basic_device	*udc;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [PATCH 05/23] at91: Make MMC device (at91_mci) common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (3 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 04/23] at91: Make UDC device common Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:12   ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 05/23] at91: Make MMC device common Ryan Mallon
                   ` (20 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual MMC code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |   79 ++--------
 arch/arm/mach-at91/at91cap9_devices.c    |  134 ++++-------------
 arch/arm/mach-at91/at91rm9200_devices.c  |   96 +++----------
 arch/arm/mach-at91/at91sam9260_devices.c |  192 +++---------------------
 arch/arm/mach-at91/at91sam9261_devices.c |   76 ++--------
 arch/arm/mach-at91/at91sam9263_devices.c |  173 ++++++----------------
 arch/arm/mach-at91/at91sam9g45_devices.c |  189 +++++-------------------
 arch/arm/mach-at91/at91sam9rl.c          |    4 +
 arch/arm/mach-at91/at91sam9rl_devices.c  |   85 +++--------
 arch/arm/mach-at91/devices.c             |  237 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   15 ++
 11 files changed, 455 insertions(+), 825 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index ad74f57..fa735f3 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -84,72 +84,22 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_MCI,
-		.end	= AT572D940HF_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_MCI,
-		.end	= AT572D940HF_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at572d940hf_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT572D940HF_BASE_MCI,
+	.irq		= AT572D940HF_ID_MCI,
+	.clock_pin	= {AT91_PIN_PC22, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 /* mmc_id 0, slot a */
+		 .cmd_pin	= {AT91_PIN_PC23, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PC24, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PC25, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PC26, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PC27, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
+	 },
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PC22, 0);
-
-	/* CMD */
-	at91_set_A_periph(AT91_PIN_PC23, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_A_periph(AT91_PIN_PC24, 1);
-	if (data->wire4) {
-		at91_set_A_periph(AT91_PIN_PC25, 1);
-		at91_set_A_periph(AT91_PIN_PC26, 1);
-		at91_set_A_periph(AT91_PIN_PC27, 1);
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at572d940hf_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -836,6 +786,7 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index c88633c..2b83683 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -192,118 +192,38 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_MCI0,
-		.end	= AT91CAP9_BASE_MCI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_MCI0,
-		.end	= AT91CAP9_ID_MCI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91cap9_mmc0_device = {
-	.name		= "at91_mci",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc0_data,
+static struct __initdata at91_dev_table_mmc device_mmc0 = {
+	.mmio_base	= AT91CAP9_BASE_MCI0,
+	.irq		= AT91CAP9_ID_MCI0,
+	.clock_asc	= "mci0_clk",
+	.clock_pin	= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc0_resources,
-	.num_resources	= ARRAY_SIZE(mmc0_resources),
 };
 
-static struct resource mmc1_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_MCI1,
-		.end	= AT91CAP9_BASE_MCI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_MCI1,
-		.end	= AT91CAP9_ID_MCI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_mmc device_mmc1 = {
+	.mmio_base	= AT91CAP9_BASE_MCI1,
+	.irq		= AT91CAP9_ID_MCI1,
+	.clock_asc	= "mci1_clk",
+	.clock_pin	= {AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA17, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA18, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA19, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA20, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91cap9_mmc1_device = {
-	.name		= "at91_mci",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc1_data,
-	},
-	.resource	= mmc1_resources,
-	.num_resources	= ARRAY_SIZE(mmc1_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	if (mmc_id == 0) {		/* MCI0 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA2, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA0, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA3, 1);
-			at91_set_A_periph(AT91_PIN_PA4, 1);
-			at91_set_A_periph(AT91_PIN_PA5, 1);
-		}
-
-		mmc0_data = *data;
-		at91_clock_associate("mci0_clk", &at91cap9_mmc0_device.dev, "mci_clk");
-		platform_device_register(&at91cap9_mmc0_device);
-	} else {			/* MCI1 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA16, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA17, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA18, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA19, 1);
-			at91_set_A_periph(AT91_PIN_PA20, 1);
-			at91_set_A_periph(AT91_PIN_PA21, 1);
-		}
-
-		mmc1_data = *data;
-		at91_clock_associate("mci1_clk", &at91cap9_mmc1_device.dev, "mci_clk");
-		platform_device_register(&at91cap9_mmc1_device);
-	}
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1179,6 +1099,8 @@ void __init at91_add_device_serial(void) {}
 static struct at91_device_table __initdata at91cap9_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
+	.mmc[0]		= &device_mmc0,
+	.mmc[1]		= &device_mmc1,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 8230d83..adcb222 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -170,85 +170,30 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_MCI,
-		.end	= AT91RM9200_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91RM9200_BASE_MCI,
+	.irq		= AT91RM9200_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA27, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA28, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA29, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PB3,  AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PB4,  AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PB5,  AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
-	[1] = {
-		.start	= AT91RM9200_ID_MCI,
-		.end	= AT91RM9200_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA8, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA9,  AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA10, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA11, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA12, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA27, 0);
-
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA8, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA9, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA10, 1);
-			at91_set_B_periph(AT91_PIN_PA11, 1);
-			at91_set_B_periph(AT91_PIN_PA12, 1);
-		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA28, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA29, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PB3, 1);
-			at91_set_B_periph(AT91_PIN_PB4, 1);
-			at91_set_B_periph(AT91_PIN_PB5, 1);
-		}
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91rm9200_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1059,6 +1004,7 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index d743335..03c548f 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -85,181 +85,30 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_MCI,
-		.end	= AT91SAM9260_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91SAM9260_BASE_MCI,
+	.irq		= AT91SAM9260_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA8, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA7, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA9,  AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA10, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA11, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	[1] = {
-		.start	= AT91SAM9260_ID_MCI,
-		.end	= AT91SAM9260_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9260_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA8, 0);
-
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA0, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA5, 1);
-			at91_set_B_periph(AT91_PIN_PA4, 1);
-			at91_set_B_periph(AT91_PIN_PA3, 1);
-		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA7, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA6, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA9, 1);
-			at91_set_A_periph(AT91_PIN_PA10, 1);
-			at91_set_A_periph(AT91_PIN_PA11, 1);
-		}
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9260_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  MMC / SD Slot for Atmel MCI Driver
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_MCI,
-		.end	= AT91SAM9260_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_MCI,
-		.end	= AT91SAM9260_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_mmc_device = {
-	.name		= "atmel_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-	unsigned int i;
-	unsigned int slot_count = 0;
-
-	if (!data)
-		return;
-
-	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
-		if (data->slot[i].bus_width) {
-			/* input/irq */
-			if (data->slot[i].detect_pin) {
-				at91_set_gpio_input(data->slot[i].detect_pin, 1);
-				at91_set_deglitch(data->slot[i].detect_pin, 1);
-			}
-			if (data->slot[i].wp_pin)
-				at91_set_gpio_input(data->slot[i].wp_pin, 1);
-
-			switch (i) {
-			case 0:
-				/* CMD */
-				at91_set_A_periph(AT91_PIN_PA7, 1);
-				/* DAT0, maybe DAT1..DAT3 */
-				at91_set_A_periph(AT91_PIN_PA6, 1);
-				if (data->slot[i].bus_width == 4) {
-					at91_set_A_periph(AT91_PIN_PA9, 1);
-					at91_set_A_periph(AT91_PIN_PA10, 1);
-					at91_set_A_periph(AT91_PIN_PA11, 1);
-				}
-				slot_count++;
-				break;
-			case 1:
-				/* CMD */
-				at91_set_B_periph(AT91_PIN_PA1, 1);
-				/* DAT0, maybe DAT1..DAT3 */
-				at91_set_B_periph(AT91_PIN_PA0, 1);
-				if (data->slot[i].bus_width == 4) {
-					at91_set_B_periph(AT91_PIN_PA5, 1);
-					at91_set_B_periph(AT91_PIN_PA4, 1);
-					at91_set_B_periph(AT91_PIN_PA3, 1);
-				}
-				slot_count++;
-				break;
-			default:
-				printk(KERN_ERR
-					"AT91: SD/MMC slot %d not available\n", i);
-				break;
-			}
-		}
-	}
-
-	if (slot_count) {
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA8, 0);
-
-		mmc_data = *data;
-		platform_device_register(&at91sam9260_mmc_device);
-	}
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1215,6 +1064,7 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index ab194c0..b6d4578 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -51,72 +51,21 @@ static struct __initdata at91_dev_table_basic_device device_udc = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_MCI,
-		.end	= AT91SAM9261_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_MCI,
-		.end	= AT91SAM9261_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91SAM9261_BASE_MCI,
+	.irq		= AT91SAM9261_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA2, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA6, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9261_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_B_periph(AT91_PIN_PA2, 0);
-
-	/* CMD */
-	at91_set_B_periph(AT91_PIN_PA1, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_B_periph(AT91_PIN_PA0, 1);
-	if (data->wire4) {
-		at91_set_B_periph(AT91_PIN_PA4, 1);
-		at91_set_B_periph(AT91_PIN_PA5, 1);
-		at91_set_B_periph(AT91_PIN_PA6, 1);
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9261_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -970,6 +919,7 @@ void __init at91_add_device_serial(void) {}
 static struct at91_device_table __initdata at91sam9261_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 530e4c6..5e09258 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -88,143 +88,56 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_MCI0,
-		.end	= AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_mmc device_mmc0 = {
+	.mmio_base	= AT91SAM9263_BASE_MCI0,
+	.irq		= AT91SAM9263_ID_MCI0,
+	.clock_asc	= "mci0_clk",
+	.clock_pin	= {AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	[1] = {
-		.start	= AT91SAM9263_ID_MCI0,
-		.end	= AT91SAM9263_ID_MCI0,
-		.flags	= IORESOURCE_IRQ,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA16, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA17, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA18, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA19, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA20, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9263_mmc0_device = {
-	.name		= "at91_mci",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc0_data,
+static struct __initdata at91_dev_table_mmc device_mmc1 = {
+	.mmio_base	= AT91SAM9263_BASE_MCI1,
+	.irq		= AT91SAM9263_ID_MCI1,
+	.clock_asc	= "mci1_clk",
+	.clock_pin	= {AT91_PIN_PA6, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA7, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA8, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA9, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA10, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA11, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc0_resources,
-	.num_resources	= ARRAY_SIZE(mmc0_resources),
-};
-
-static struct resource mmc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_MCI1,
-		.end	= AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_MCI1,
-		.end	= AT91SAM9263_ID_MCI1,
-		.flags	= IORESOURCE_IRQ,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA22, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA25, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9263_mmc1_device = {
-	.name		= "at91_mci",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc1_data,
-	},
-	.resource	= mmc1_resources,
-	.num_resources	= ARRAY_SIZE(mmc1_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	if (mmc_id == 0) {		/* MCI0 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA12, 0);
-
-		if (data->slot_b) {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA16, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA17, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA18, 1);
-				at91_set_A_periph(AT91_PIN_PA19, 1);
-				at91_set_A_periph(AT91_PIN_PA20, 1);
-			}
-		} else {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA1, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA0, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA3, 1);
-				at91_set_A_periph(AT91_PIN_PA4, 1);
-				at91_set_A_periph(AT91_PIN_PA5, 1);
-			}
-		}
-
-		mmc0_data = *data;
-		at91_clock_associate("mci0_clk", &at91sam9263_mmc0_device.dev, "mci_clk");
-		platform_device_register(&at91sam9263_mmc0_device);
-	} else {			/* MCI1 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA6, 0);
-
-		if (data->slot_b) {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA21, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA22, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA23, 1);
-				at91_set_A_periph(AT91_PIN_PA24, 1);
-				at91_set_A_periph(AT91_PIN_PA25, 1);
-			}
-		} else {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA7, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA8, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA9, 1);
-				at91_set_A_periph(AT91_PIN_PA10, 1);
-				at91_set_A_periph(AT91_PIN_PA11, 1);
-			}
-		}
-
-		mmc1_data = *data;
-		at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
-		platform_device_register(&at91sam9263_mmc1_device);
-	}
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  Compact Flash (PCMCIA or IDE)
  * -------------------------------------------------------------------- */
@@ -1307,6 +1220,8 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc0,
+	.mmc[1]		= &device_mmc1,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 2961249..01636f0 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -228,165 +228,46 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_MCI0,
-		.end	= AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_MCI0,
-		.end	= AT91SAM9G45_ID_MCI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_mmc0_device = {
-	.name		= "atmel_mci",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc0_data,
+static struct __initdata at91_dev_table_mmc device_mmc0 = {
+	.mmio_base	= AT91SAM9G45_BASE_MCI0,
+	.irq		= AT91SAM9G45_ID_MCI0,
+	.clock_asc	= "mci0_clk",
+	.clock_pin	= {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA6, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA7, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA8, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA9, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc0_resources,
-	.num_resources	= ARRAY_SIZE(mmc0_resources),
 };
 
-static struct resource mmc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_MCI1,
-		.end	= AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_MCI1,
-		.end	= AT91SAM9G45_ID_MCI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_mmc1_device = {
-	.name		= "atmel_mci",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc1_data,
+static struct __initdata at91_dev_table_mmc device_mmc1 = {
+	.mmio_base	= AT91SAM9G45_BASE_MCI1,
+	.irq		= AT91SAM9G45_ID_MCI1,
+	.clock_asc	= "mci1_clk",
+	.clock_pin	= {AT91_PIN_PA31, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA22, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA25, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA26, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA27, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA28, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA29, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA30, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc1_resources,
-	.num_resources	= ARRAY_SIZE(mmc1_resources),
 };
 
-/* Consider only one slot : slot 0 */
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-
-	if (!data)
-		return;
-
-	/* Must have at least one usable slot */
-	if (!data->slot[0].bus_width)
-		return;
-
-#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
-	{
-	struct at_dma_slave	*atslave;
-	struct mci_dma_data	*alt_atslave;
-
-	alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
-	atslave = &alt_atslave->sdata;
-
-	/* DMA slave channel configuration */
-	atslave->dma_dev = &at_hdmac_device.dev;
-	atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
-	atslave->cfg = ATC_FIFOCFG_HALFFIFO
-			| ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
-	atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
-	if (mmc_id == 0)	/* MCI0 */
-		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
-			      | ATC_DST_PER(AT_DMA_ID_MCI0);
-
-	else			/* MCI1 */
-		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
-			      | ATC_DST_PER(AT_DMA_ID_MCI1);
-
-	data->dma_slave = alt_atslave;
-	}
-#endif
-
-
-	/* input/irq */
-	if (data->slot[0].detect_pin) {
-		at91_set_gpio_input(data->slot[0].detect_pin, 1);
-		at91_set_deglitch(data->slot[0].detect_pin, 1);
-	}
-	if (data->slot[0].wp_pin)
-		at91_set_gpio_input(data->slot[0].wp_pin, 1);
-
-	if (mmc_id == 0) {		/* MCI0 */
-
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA0, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
-		at91_set_A_periph(AT91_PIN_PA2, 1);
-		if (data->slot[0].bus_width == 4) {
-			at91_set_A_periph(AT91_PIN_PA3, 1);
-			at91_set_A_periph(AT91_PIN_PA4, 1);
-			at91_set_A_periph(AT91_PIN_PA5, 1);
-			if (data->slot[0].bus_width == 8) {
-				at91_set_A_periph(AT91_PIN_PA6, 1);
-				at91_set_A_periph(AT91_PIN_PA7, 1);
-				at91_set_A_periph(AT91_PIN_PA8, 1);
-				at91_set_A_periph(AT91_PIN_PA9, 1);
-			}
-		}
-
-		mmc0_data = *data;
-		at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk");
-		platform_device_register(&at91sam9g45_mmc0_device);
-
-	} else {			/* MCI1 */
-
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA31, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA22, 1);
-
-		/* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
-		at91_set_A_periph(AT91_PIN_PA23, 1);
-		if (data->slot[0].bus_width == 4) {
-			at91_set_A_periph(AT91_PIN_PA24, 1);
-			at91_set_A_periph(AT91_PIN_PA25, 1);
-			at91_set_A_periph(AT91_PIN_PA26, 1);
-			if (data->slot[0].bus_width == 8) {
-				at91_set_A_periph(AT91_PIN_PA27, 1);
-				at91_set_A_periph(AT91_PIN_PA28, 1);
-				at91_set_A_periph(AT91_PIN_PA29, 1);
-				at91_set_A_periph(AT91_PIN_PA30, 1);
-			}
-		}
-
-		mmc1_data = *data;
-		at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk");
-		platform_device_register(&at91sam9g45_mmc1_device);
-
-	}
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1464,6 +1345,8 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usb_ohci,
 	.usbh_ehci	= &device_usb_ehci,
+	.mmc[0]		= &device_mmc0,
+	.mmc[1]		= &device_mmc1,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 6a9d24e..9ca108a 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -24,6 +24,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void __init at91sam9rl_init_devices(void);
+
 static struct map_desc at91sam9rl_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -259,6 +261,8 @@ void __init at91sam9rl_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at91sam9rl_io_desc, ARRAY_SIZE(at91sam9rl_io_desc));
 
+	at91sam9rl_init_devices();
+
 	cidr = at91_sys_read(AT91_DBGU_CIDR);
 
 	switch (cidr & AT91_CIDR_SRAMSIZ) {
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 53aaa94..70c8669 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -24,7 +24,7 @@
 #include <mach/at_hdmac.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /* --------------------------------------------------------------------
  *  HDMAC - AHB DMA Controller
@@ -170,72 +170,21 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_MCI,
-		.end	= AT91SAM9RL_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_MCI,
-		.end	= AT91SAM9RL_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91SAM9RL_BASE_MCI,
+	.irq		= AT91SAM9RL_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9rl_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA2, 0);
-
-	/* CMD */
-	at91_set_A_periph(AT91_PIN_PA1, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_A_periph(AT91_PIN_PA0, 1);
-	if (data->wire4) {
-		at91_set_A_periph(AT91_PIN_PA3, 1);
-		at91_set_A_periph(AT91_PIN_PA4, 1);
-		at91_set_A_periph(AT91_PIN_PA5, 1);
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9rl_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1201,6 +1150,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+static struct at91_device_table __initdata at91sam9rl_device_table = {
+	.mmc[0]		= &device_mmc,
+};
+
+void __init at91sam9rl_init_devices(void)
+{
+	at91_init_devices(&at91sam9rl_device_table);
+}
 
 /* -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 28dc002..3135f91 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -294,6 +294,243 @@ void __init at91_add_device_eth(struct at91_eth_data *data)
 void __init at91_add_device_eth(struct at91_eth_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = DMA_BIT_MASK(32);
+static struct at91_mmc_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc0_device = {
+	.name		= "at91_mci",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc0_data,
+	},
+	.resource	= mmc0_resources,
+	.num_resources	= ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc1_device = {
+	.name		= "at91_mci",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc1_data,
+	},
+	.resource	= mmc1_resources,
+	.num_resources	= ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+	struct at91_dev_table_mmc *info = devices->mmc[mmc_id];
+	int slot;
+
+	BUG_ON(!info);
+	if (mmc_id == 0) {
+		init_resource_mem(&mmc0_resources[0], info->mmio_base);
+		init_resource_irq(&mmc0_resources[1], info->irq);
+	} else {
+		init_resource_mem(&mmc1_resources[0], info->mmio_base);
+		init_resource_irq(&mmc1_resources[1], info->irq);
+	}
+
+	if (!data)
+		return;
+
+	/* input/irq */
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+	if (data->wp_pin)
+		at91_set_gpio_input(data->wp_pin, 1);
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+
+	slot = !!data->slot_b;
+
+	/* CLK */
+	at91_config_pins(&info->clock_pin, 1);
+
+	/* CMD */
+	at91_config_pins(&info->slot[slot].cmd_pin, 1);
+
+	/* DAT0, maybe DAT1..DAT3 */
+	at91_config_pins(info->slot[slot].data_pins, data->wire4 ? 4 : 1);
+
+	if (info->clock_asc) {
+		if (mmc_id == 0) {
+			mmc0_data = *data;
+			at91_clock_associate(info->clock_asc,
+					     &at91_mmc0_device.dev, "mci_clk");
+			platform_device_register(&at91_mmc0_device);
+		} else {
+			mmc1_data = *data;
+			at91_clock_associate(info->clock_asc,
+					     &at91_mmc1_device.dev, "mci_clk");
+			platform_device_register(&at91_mmc1_device);
+		}
+	}
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
+ *  MMC / SD Slot for Atmel MCI Driver
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static u64 mmc0_dmamask = DMA_BIT_MASK(32);
+static struct mci_platform_data mmc0_data;
+
+static struct resource mmc0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc0_device = {
+	.name		= "atmel_mci",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &mmc0_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc0_data,
+	},
+	.resource	= mmc0_resources,
+	.num_resources	= ARRAY_SIZE(mmc0_resources),
+};
+
+static u64 mmc1_dmamask = DMA_BIT_MASK(32);
+static struct mci_platform_data mmc1_data;
+
+static struct resource mmc1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc1_device = {
+	.name		= "atmel_mci",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &mmc1_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc1_data,
+	},
+	.resource	= mmc1_resources,
+	.num_resources	= ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
+{
+	struct at91_dev_table_mmc *info = devices->mmc[mmc_id];
+	int i;
+
+	BUG_ON(!mmc_id);
+	if (mmc_id == 0) {
+		init_resource_mem(&mmc0_resources[0], info->mmio_base);
+		init_resource_irq(&mmc0_resources[1], info->irq);
+	} else {
+		init_resource_mem(&mmc1_resources[0], info->mmio_base);
+		init_resource_irq(&mmc1_resources[1], info->irq);
+	}
+
+#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
+	{
+	struct at_dma_slave	*atslave;
+	struct mci_dma_data	*alt_atslave;
+
+	alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
+	atslave = &alt_atslave->sdata;
+
+	/* DMA slave channel configuration */
+	atslave->dma_dev = &at_hdmac_device.dev;
+	atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
+	atslave->cfg = ATC_FIFOCFG_HALFFIFO
+			| ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
+	atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
+	if (mmc_id == 0)	/* MCI0 */
+		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
+			      | ATC_DST_PER(AT_DMA_ID_MCI0);
+
+	else			/* MCI1 */
+		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
+			      | ATC_DST_PER(AT_DMA_ID_MCI1);
+
+	data->dma_slave = alt_atslave;
+	}
+#endif
+
+	/* CLK */
+	at91_config_pins(&info->clock_pin, 1);
+
+	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+		if (data->slot[i].bus_width) {
+			/* input/irq */
+			if (data->slot[i].detect_pin) {
+				at91_set_gpio_input(data->slot[i].detect_pin, 1);
+				at91_set_deglitch(data->slot[i].detect_pin, 1);
+			}
+			if (data->slot[i].wp_pin)
+				at91_set_gpio_input(data->slot[i].wp_pin, 1);
+
+			/* CMD */
+			at91_config_pins(&info->slot[i].cmd_pin, 1);
+
+			/* DAT0, maybe DAT1..DAT7 */
+			at91_config_pins(info->slot[i].data_pins,
+					 info->slot[i].bus_width);
+		}
+	}
+
+	if (mmc_id == 0) {
+		mmc0_data = *data;
+		platform_device_register(&at91_mmc0_device);
+	} else {
+		mmc1_data = *data;
+		platform_device_register(&at91_mmc1_device);
+	}
+}
+#else
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
+#endif
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 9203f58..eab2f54 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -48,11 +48,26 @@ struct at91_dev_table_usb_ohci {
 	void			(*device_init)(void);
 };
 
+struct at91_mmc_pins {
+	struct at91_pin_config	cmd_pin;
+	struct at91_pin_config	data_pins[8];
+	int			bus_width;
+};
+
+struct at91_dev_table_mmc {
+	unsigned 		mmio_base;
+	int			irq;
+	const char		*clock_asc;
+	struct at91_pin_config	clock_pin;
+	struct at91_mmc_pins	slot[2];
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
 	struct at91_dev_table_basic_device	*usbh_ehci;
 	struct at91_dev_table_basic_device	*udc;
+	struct at91_dev_table_mmc		*mmc[2];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 05/23] at91: Make MMC device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (4 preceding siblings ...)
  2011-04-20  1:10 ` [PATCH 05/23] at91: Make MMC device (at91_mci) common Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 06/23] at91: Make NAND " Ryan Mallon
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual MMC code for each at91 variant with a single
implementation in devices.c. Both the AT91 MMC and Atmel MCI drivers
are converted here to use the common data in both instances.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |   79 ++--------
 arch/arm/mach-at91/at91cap9_devices.c    |  134 ++++-------------
 arch/arm/mach-at91/at91rm9200_devices.c  |   96 +++----------
 arch/arm/mach-at91/at91sam9260_devices.c |  192 +++---------------------
 arch/arm/mach-at91/at91sam9261_devices.c |   76 ++--------
 arch/arm/mach-at91/at91sam9263_devices.c |  173 ++++++----------------
 arch/arm/mach-at91/at91sam9g45_devices.c |  189 +++++-------------------
 arch/arm/mach-at91/at91sam9rl.c          |    4 +
 arch/arm/mach-at91/at91sam9rl_devices.c  |   85 +++--------
 arch/arm/mach-at91/devices.c             |  237 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   15 ++
 11 files changed, 455 insertions(+), 825 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index ad74f57..fa735f3 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -84,72 +84,22 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_MCI,
-		.end	= AT572D940HF_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_MCI,
-		.end	= AT572D940HF_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at572d940hf_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT572D940HF_BASE_MCI,
+	.irq		= AT572D940HF_ID_MCI,
+	.clock_pin	= {AT91_PIN_PC22, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 /* mmc_id 0, slot a */
+		 .cmd_pin	= {AT91_PIN_PC23, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PC24, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PC25, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PC26, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PC27, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
+	 },
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PC22, 0);
-
-	/* CMD */
-	at91_set_A_periph(AT91_PIN_PC23, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_A_periph(AT91_PIN_PC24, 1);
-	if (data->wire4) {
-		at91_set_A_periph(AT91_PIN_PC25, 1);
-		at91_set_A_periph(AT91_PIN_PC26, 1);
-		at91_set_A_periph(AT91_PIN_PC27, 1);
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at572d940hf_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -836,6 +786,7 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index c88633c..2b83683 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -192,118 +192,38 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_MCI0,
-		.end	= AT91CAP9_BASE_MCI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_MCI0,
-		.end	= AT91CAP9_ID_MCI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91cap9_mmc0_device = {
-	.name		= "at91_mci",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc0_data,
+static struct __initdata at91_dev_table_mmc device_mmc0 = {
+	.mmio_base	= AT91CAP9_BASE_MCI0,
+	.irq		= AT91CAP9_ID_MCI0,
+	.clock_asc	= "mci0_clk",
+	.clock_pin	= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc0_resources,
-	.num_resources	= ARRAY_SIZE(mmc0_resources),
 };
 
-static struct resource mmc1_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_MCI1,
-		.end	= AT91CAP9_BASE_MCI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_MCI1,
-		.end	= AT91CAP9_ID_MCI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_mmc device_mmc1 = {
+	.mmio_base	= AT91CAP9_BASE_MCI1,
+	.irq		= AT91CAP9_ID_MCI1,
+	.clock_asc	= "mci1_clk",
+	.clock_pin	= {AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA17, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA18, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA19, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA20, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91cap9_mmc1_device = {
-	.name		= "at91_mci",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc1_data,
-	},
-	.resource	= mmc1_resources,
-	.num_resources	= ARRAY_SIZE(mmc1_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	if (mmc_id == 0) {		/* MCI0 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA2, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA0, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA3, 1);
-			at91_set_A_periph(AT91_PIN_PA4, 1);
-			at91_set_A_periph(AT91_PIN_PA5, 1);
-		}
-
-		mmc0_data = *data;
-		at91_clock_associate("mci0_clk", &at91cap9_mmc0_device.dev, "mci_clk");
-		platform_device_register(&at91cap9_mmc0_device);
-	} else {			/* MCI1 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA16, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA17, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA18, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA19, 1);
-			at91_set_A_periph(AT91_PIN_PA20, 1);
-			at91_set_A_periph(AT91_PIN_PA21, 1);
-		}
-
-		mmc1_data = *data;
-		at91_clock_associate("mci1_clk", &at91cap9_mmc1_device.dev, "mci_clk");
-		platform_device_register(&at91cap9_mmc1_device);
-	}
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1179,6 +1099,8 @@ void __init at91_add_device_serial(void) {}
 static struct at91_device_table __initdata at91cap9_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
+	.mmc[0]		= &device_mmc0,
+	.mmc[1]		= &device_mmc1,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 8230d83..adcb222 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -170,85 +170,30 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_MCI,
-		.end	= AT91RM9200_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91RM9200_BASE_MCI,
+	.irq		= AT91RM9200_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA27, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA28, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA29, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PB3,  AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PB4,  AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PB5,  AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
-	[1] = {
-		.start	= AT91RM9200_ID_MCI,
-		.end	= AT91RM9200_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA8, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA9,  AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA10, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA11, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA12, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA27, 0);
-
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA8, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA9, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA10, 1);
-			at91_set_B_periph(AT91_PIN_PA11, 1);
-			at91_set_B_periph(AT91_PIN_PA12, 1);
-		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA28, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA29, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PB3, 1);
-			at91_set_B_periph(AT91_PIN_PB4, 1);
-			at91_set_B_periph(AT91_PIN_PB5, 1);
-		}
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91rm9200_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1059,6 +1004,7 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index d743335..03c548f 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -85,181 +85,30 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_MCI,
-		.end	= AT91SAM9260_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91SAM9260_BASE_MCI,
+	.irq		= AT91SAM9260_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA8, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA7, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA9,  AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA10, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA11, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	[1] = {
-		.start	= AT91SAM9260_ID_MCI,
-		.end	= AT91SAM9260_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9260_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA8, 0);
-
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA0, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA5, 1);
-			at91_set_B_periph(AT91_PIN_PA4, 1);
-			at91_set_B_periph(AT91_PIN_PA3, 1);
-		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA7, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA6, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA9, 1);
-			at91_set_A_periph(AT91_PIN_PA10, 1);
-			at91_set_A_periph(AT91_PIN_PA11, 1);
-		}
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9260_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  MMC / SD Slot for Atmel MCI Driver
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_MCI,
-		.end	= AT91SAM9260_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_MCI,
-		.end	= AT91SAM9260_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_mmc_device = {
-	.name		= "atmel_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-	unsigned int i;
-	unsigned int slot_count = 0;
-
-	if (!data)
-		return;
-
-	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
-		if (data->slot[i].bus_width) {
-			/* input/irq */
-			if (data->slot[i].detect_pin) {
-				at91_set_gpio_input(data->slot[i].detect_pin, 1);
-				at91_set_deglitch(data->slot[i].detect_pin, 1);
-			}
-			if (data->slot[i].wp_pin)
-				at91_set_gpio_input(data->slot[i].wp_pin, 1);
-
-			switch (i) {
-			case 0:
-				/* CMD */
-				at91_set_A_periph(AT91_PIN_PA7, 1);
-				/* DAT0, maybe DAT1..DAT3 */
-				at91_set_A_periph(AT91_PIN_PA6, 1);
-				if (data->slot[i].bus_width == 4) {
-					at91_set_A_periph(AT91_PIN_PA9, 1);
-					at91_set_A_periph(AT91_PIN_PA10, 1);
-					at91_set_A_periph(AT91_PIN_PA11, 1);
-				}
-				slot_count++;
-				break;
-			case 1:
-				/* CMD */
-				at91_set_B_periph(AT91_PIN_PA1, 1);
-				/* DAT0, maybe DAT1..DAT3 */
-				at91_set_B_periph(AT91_PIN_PA0, 1);
-				if (data->slot[i].bus_width == 4) {
-					at91_set_B_periph(AT91_PIN_PA5, 1);
-					at91_set_B_periph(AT91_PIN_PA4, 1);
-					at91_set_B_periph(AT91_PIN_PA3, 1);
-				}
-				slot_count++;
-				break;
-			default:
-				printk(KERN_ERR
-					"AT91: SD/MMC slot %d not available\n", i);
-				break;
-			}
-		}
-	}
-
-	if (slot_count) {
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA8, 0);
-
-		mmc_data = *data;
-		platform_device_register(&at91sam9260_mmc_device);
-	}
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1215,6 +1064,7 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index ab194c0..b6d4578 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -51,72 +51,21 @@ static struct __initdata at91_dev_table_basic_device device_udc = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_MCI,
-		.end	= AT91SAM9261_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_MCI,
-		.end	= AT91SAM9261_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91SAM9261_BASE_MCI,
+	.irq		= AT91SAM9261_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA2, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_B, 1, 0, 0},
+			  {AT91_PIN_PA6, AT91_PIN_PERIPH_B, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9261_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_B_periph(AT91_PIN_PA2, 0);
-
-	/* CMD */
-	at91_set_B_periph(AT91_PIN_PA1, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_B_periph(AT91_PIN_PA0, 1);
-	if (data->wire4) {
-		at91_set_B_periph(AT91_PIN_PA4, 1);
-		at91_set_B_periph(AT91_PIN_PA5, 1);
-		at91_set_B_periph(AT91_PIN_PA6, 1);
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9261_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -970,6 +919,7 @@ void __init at91_add_device_serial(void) {}
 static struct at91_device_table __initdata at91sam9261_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 530e4c6..5e09258 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -88,143 +88,56 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_MCI0,
-		.end	= AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_mmc device_mmc0 = {
+	.mmio_base	= AT91SAM9263_BASE_MCI0,
+	.irq		= AT91SAM9263_ID_MCI0,
+	.clock_asc	= "mci0_clk",
+	.clock_pin	= {AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	[1] = {
-		.start	= AT91SAM9263_ID_MCI0,
-		.end	= AT91SAM9263_ID_MCI0,
-		.flags	= IORESOURCE_IRQ,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA16, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA17, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA18, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA19, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA20, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9263_mmc0_device = {
-	.name		= "at91_mci",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc0_data,
+static struct __initdata at91_dev_table_mmc device_mmc1 = {
+	.mmio_base	= AT91SAM9263_BASE_MCI1,
+	.irq		= AT91SAM9263_ID_MCI1,
+	.clock_asc	= "mci1_clk",
+	.clock_pin	= {AT91_PIN_PA6, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA7, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA8, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA9, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA10, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA11, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc0_resources,
-	.num_resources	= ARRAY_SIZE(mmc0_resources),
-};
-
-static struct resource mmc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_MCI1,
-		.end	= AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_MCI1,
-		.end	= AT91SAM9263_ID_MCI1,
-		.flags	= IORESOURCE_IRQ,
+	.slot[1]	= {
+		 .cmd_pin	= {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA22, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA25, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9263_mmc1_device = {
-	.name		= "at91_mci",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc1_data,
-	},
-	.resource	= mmc1_resources,
-	.num_resources	= ARRAY_SIZE(mmc1_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	if (mmc_id == 0) {		/* MCI0 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA12, 0);
-
-		if (data->slot_b) {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA16, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA17, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA18, 1);
-				at91_set_A_periph(AT91_PIN_PA19, 1);
-				at91_set_A_periph(AT91_PIN_PA20, 1);
-			}
-		} else {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA1, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA0, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA3, 1);
-				at91_set_A_periph(AT91_PIN_PA4, 1);
-				at91_set_A_periph(AT91_PIN_PA5, 1);
-			}
-		}
-
-		mmc0_data = *data;
-		at91_clock_associate("mci0_clk", &at91sam9263_mmc0_device.dev, "mci_clk");
-		platform_device_register(&at91sam9263_mmc0_device);
-	} else {			/* MCI1 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA6, 0);
-
-		if (data->slot_b) {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA21, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA22, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA23, 1);
-				at91_set_A_periph(AT91_PIN_PA24, 1);
-				at91_set_A_periph(AT91_PIN_PA25, 1);
-			}
-		} else {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA7, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA8, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA9, 1);
-				at91_set_A_periph(AT91_PIN_PA10, 1);
-				at91_set_A_periph(AT91_PIN_PA11, 1);
-			}
-		}
-
-		mmc1_data = *data;
-		at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
-		platform_device_register(&at91sam9263_mmc1_device);
-	}
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  Compact Flash (PCMCIA or IDE)
  * -------------------------------------------------------------------- */
@@ -1307,6 +1220,8 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
+	.mmc[0]		= &device_mmc0,
+	.mmc[1]		= &device_mmc1,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 2961249..01636f0 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -228,165 +228,46 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_MCI0,
-		.end	= AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_MCI0,
-		.end	= AT91SAM9G45_ID_MCI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_mmc0_device = {
-	.name		= "atmel_mci",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc0_data,
+static struct __initdata at91_dev_table_mmc device_mmc0 = {
+	.mmio_base	= AT91SAM9G45_BASE_MCI0,
+	.irq		= AT91SAM9G45_ID_MCI0,
+	.clock_asc	= "mci0_clk",
+	.clock_pin	= {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA6, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA7, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA8, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA9, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc0_resources,
-	.num_resources	= ARRAY_SIZE(mmc0_resources),
 };
 
-static struct resource mmc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_MCI1,
-		.end	= AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_MCI1,
-		.end	= AT91SAM9G45_ID_MCI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_mmc1_device = {
-	.name		= "atmel_mci",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc1_data,
+static struct __initdata at91_dev_table_mmc device_mmc1 = {
+	.mmio_base	= AT91SAM9G45_BASE_MCI1,
+	.irq		= AT91SAM9G45_ID_MCI1,
+	.clock_asc	= "mci1_clk",
+	.clock_pin	= {AT91_PIN_PA31, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA22, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA25, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA26, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA27, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA28, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA29, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA30, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
-	.resource	= mmc1_resources,
-	.num_resources	= ARRAY_SIZE(mmc1_resources),
 };
 
-/* Consider only one slot : slot 0 */
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-
-	if (!data)
-		return;
-
-	/* Must have at least one usable slot */
-	if (!data->slot[0].bus_width)
-		return;
-
-#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
-	{
-	struct at_dma_slave	*atslave;
-	struct mci_dma_data	*alt_atslave;
-
-	alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
-	atslave = &alt_atslave->sdata;
-
-	/* DMA slave channel configuration */
-	atslave->dma_dev = &at_hdmac_device.dev;
-	atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
-	atslave->cfg = ATC_FIFOCFG_HALFFIFO
-			| ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
-	atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
-	if (mmc_id == 0)	/* MCI0 */
-		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
-			      | ATC_DST_PER(AT_DMA_ID_MCI0);
-
-	else			/* MCI1 */
-		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
-			      | ATC_DST_PER(AT_DMA_ID_MCI1);
-
-	data->dma_slave = alt_atslave;
-	}
-#endif
-
-
-	/* input/irq */
-	if (data->slot[0].detect_pin) {
-		at91_set_gpio_input(data->slot[0].detect_pin, 1);
-		at91_set_deglitch(data->slot[0].detect_pin, 1);
-	}
-	if (data->slot[0].wp_pin)
-		at91_set_gpio_input(data->slot[0].wp_pin, 1);
-
-	if (mmc_id == 0) {		/* MCI0 */
-
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA0, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
-		at91_set_A_periph(AT91_PIN_PA2, 1);
-		if (data->slot[0].bus_width == 4) {
-			at91_set_A_periph(AT91_PIN_PA3, 1);
-			at91_set_A_periph(AT91_PIN_PA4, 1);
-			at91_set_A_periph(AT91_PIN_PA5, 1);
-			if (data->slot[0].bus_width == 8) {
-				at91_set_A_periph(AT91_PIN_PA6, 1);
-				at91_set_A_periph(AT91_PIN_PA7, 1);
-				at91_set_A_periph(AT91_PIN_PA8, 1);
-				at91_set_A_periph(AT91_PIN_PA9, 1);
-			}
-		}
-
-		mmc0_data = *data;
-		at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk");
-		platform_device_register(&at91sam9g45_mmc0_device);
-
-	} else {			/* MCI1 */
-
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA31, 0);
-
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA22, 1);
-
-		/* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
-		at91_set_A_periph(AT91_PIN_PA23, 1);
-		if (data->slot[0].bus_width == 4) {
-			at91_set_A_periph(AT91_PIN_PA24, 1);
-			at91_set_A_periph(AT91_PIN_PA25, 1);
-			at91_set_A_periph(AT91_PIN_PA26, 1);
-			if (data->slot[0].bus_width == 8) {
-				at91_set_A_periph(AT91_PIN_PA27, 1);
-				at91_set_A_periph(AT91_PIN_PA28, 1);
-				at91_set_A_periph(AT91_PIN_PA29, 1);
-				at91_set_A_periph(AT91_PIN_PA30, 1);
-			}
-		}
-
-		mmc1_data = *data;
-		at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk");
-		platform_device_register(&at91sam9g45_mmc1_device);
-
-	}
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1464,6 +1345,8 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usb_ohci,
 	.usbh_ehci	= &device_usb_ehci,
+	.mmc[0]		= &device_mmc0,
+	.mmc[1]		= &device_mmc1,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 6a9d24e..9ca108a 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -24,6 +24,8 @@
 #include "generic.h"
 #include "clock.h"
 
+extern void __init at91sam9rl_init_devices(void);
+
 static struct map_desc at91sam9rl_io_desc[] __initdata = {
 	{
 		.virtual	= AT91_VA_BASE_SYS,
@@ -259,6 +261,8 @@ void __init at91sam9rl_initialize(unsigned long main_clock)
 	/* Map peripherals */
 	iotable_init(at91sam9rl_io_desc, ARRAY_SIZE(at91sam9rl_io_desc));
 
+	at91sam9rl_init_devices();
+
 	cidr = at91_sys_read(AT91_DBGU_CIDR);
 
 	switch (cidr & AT91_CIDR_SRAMSIZ) {
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 53aaa94..70c8669 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -24,7 +24,7 @@
 #include <mach/at_hdmac.h>
 
 #include "generic.h"
-
+#include "devices.h"
 
 /* --------------------------------------------------------------------
  *  HDMAC - AHB DMA Controller
@@ -170,72 +170,21 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_MCI,
-		.end	= AT91SAM9RL_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_MCI,
-		.end	= AT91SAM9RL_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_mmc device_mmc = {
+	.mmio_base	= AT91SAM9RL_BASE_MCI,
+	.irq		= AT91SAM9RL_ID_MCI,
+	.clock_pin	= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.slot[0]	= {
+		 .cmd_pin	= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 .data_pins	= {
+			  {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA3, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 1, 0, 0},
+			  {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 1, 0, 0},
+		 },
 	},
 };
 
-static struct platform_device at91sam9rl_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (data->wp_pin)
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA2, 0);
-
-	/* CMD */
-	at91_set_A_periph(AT91_PIN_PA1, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_A_periph(AT91_PIN_PA0, 1);
-	if (data->wire4) {
-		at91_set_A_periph(AT91_PIN_PA3, 1);
-		at91_set_A_periph(AT91_PIN_PA4, 1);
-		at91_set_A_periph(AT91_PIN_PA5, 1);
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9rl_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -1201,6 +1150,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+static struct at91_device_table __initdata at91sam9rl_device_table = {
+	.mmc[0]		= &device_mmc,
+};
+
+void __init at91sam9rl_init_devices(void)
+{
+	at91_init_devices(&at91sam9rl_device_table);
+}
 
 /* -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 28dc002..3135f91 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -294,6 +294,243 @@ void __init at91_add_device_eth(struct at91_eth_data *data)
 void __init at91_add_device_eth(struct at91_eth_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = DMA_BIT_MASK(32);
+static struct at91_mmc_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc0_device = {
+	.name		= "at91_mci",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc0_data,
+	},
+	.resource	= mmc0_resources,
+	.num_resources	= ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc1_device = {
+	.name		= "at91_mci",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &mmc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc1_data,
+	},
+	.resource	= mmc1_resources,
+	.num_resources	= ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+	struct at91_dev_table_mmc *info = devices->mmc[mmc_id];
+	int slot;
+
+	BUG_ON(!info);
+	if (mmc_id == 0) {
+		init_resource_mem(&mmc0_resources[0], info->mmio_base);
+		init_resource_irq(&mmc0_resources[1], info->irq);
+	} else {
+		init_resource_mem(&mmc1_resources[0], info->mmio_base);
+		init_resource_irq(&mmc1_resources[1], info->irq);
+	}
+
+	if (!data)
+		return;
+
+	/* input/irq */
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+	if (data->wp_pin)
+		at91_set_gpio_input(data->wp_pin, 1);
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+
+	slot = !!data->slot_b;
+
+	/* CLK */
+	at91_config_pins(&info->clock_pin, 1);
+
+	/* CMD */
+	at91_config_pins(&info->slot[slot].cmd_pin, 1);
+
+	/* DAT0, maybe DAT1..DAT3 */
+	at91_config_pins(info->slot[slot].data_pins, data->wire4 ? 4 : 1);
+
+	if (info->clock_asc) {
+		if (mmc_id == 0) {
+			mmc0_data = *data;
+			at91_clock_associate(info->clock_asc,
+					     &at91_mmc0_device.dev, "mci_clk");
+			platform_device_register(&at91_mmc0_device);
+		} else {
+			mmc1_data = *data;
+			at91_clock_associate(info->clock_asc,
+					     &at91_mmc1_device.dev, "mci_clk");
+			platform_device_register(&at91_mmc1_device);
+		}
+	}
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
+ *  MMC / SD Slot for Atmel MCI Driver
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static u64 mmc0_dmamask = DMA_BIT_MASK(32);
+static struct mci_platform_data mmc0_data;
+
+static struct resource mmc0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc0_device = {
+	.name		= "atmel_mci",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &mmc0_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc0_data,
+	},
+	.resource	= mmc0_resources,
+	.num_resources	= ARRAY_SIZE(mmc0_resources),
+};
+
+static u64 mmc1_dmamask = DMA_BIT_MASK(32);
+static struct mci_platform_data mmc1_data;
+
+static struct resource mmc1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_mmc1_device = {
+	.name		= "atmel_mci",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &mmc1_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &mmc1_data,
+	},
+	.resource	= mmc1_resources,
+	.num_resources	= ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
+{
+	struct at91_dev_table_mmc *info = devices->mmc[mmc_id];
+	int i;
+
+	BUG_ON(!mmc_id);
+	if (mmc_id == 0) {
+		init_resource_mem(&mmc0_resources[0], info->mmio_base);
+		init_resource_irq(&mmc0_resources[1], info->irq);
+	} else {
+		init_resource_mem(&mmc1_resources[0], info->mmio_base);
+		init_resource_irq(&mmc1_resources[1], info->irq);
+	}
+
+#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
+	{
+	struct at_dma_slave	*atslave;
+	struct mci_dma_data	*alt_atslave;
+
+	alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
+	atslave = &alt_atslave->sdata;
+
+	/* DMA slave channel configuration */
+	atslave->dma_dev = &at_hdmac_device.dev;
+	atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
+	atslave->cfg = ATC_FIFOCFG_HALFFIFO
+			| ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
+	atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
+	if (mmc_id == 0)	/* MCI0 */
+		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
+			      | ATC_DST_PER(AT_DMA_ID_MCI0);
+
+	else			/* MCI1 */
+		atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
+			      | ATC_DST_PER(AT_DMA_ID_MCI1);
+
+	data->dma_slave = alt_atslave;
+	}
+#endif
+
+	/* CLK */
+	at91_config_pins(&info->clock_pin, 1);
+
+	for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) {
+		if (data->slot[i].bus_width) {
+			/* input/irq */
+			if (data->slot[i].detect_pin) {
+				at91_set_gpio_input(data->slot[i].detect_pin, 1);
+				at91_set_deglitch(data->slot[i].detect_pin, 1);
+			}
+			if (data->slot[i].wp_pin)
+				at91_set_gpio_input(data->slot[i].wp_pin, 1);
+
+			/* CMD */
+			at91_config_pins(&info->slot[i].cmd_pin, 1);
+
+			/* DAT0, maybe DAT1..DAT7 */
+			at91_config_pins(info->slot[i].data_pins,
+					 info->slot[i].bus_width);
+		}
+	}
+
+	if (mmc_id == 0) {
+		mmc0_data = *data;
+		platform_device_register(&at91_mmc0_device);
+	} else {
+		mmc1_data = *data;
+		platform_device_register(&at91_mmc1_device);
+	}
+}
+#else
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
+#endif
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 9203f58..eab2f54 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -48,11 +48,26 @@ struct at91_dev_table_usb_ohci {
 	void			(*device_init)(void);
 };
 
+struct at91_mmc_pins {
+	struct at91_pin_config	cmd_pin;
+	struct at91_pin_config	data_pins[8];
+	int			bus_width;
+};
+
+struct at91_dev_table_mmc {
+	unsigned 		mmio_base;
+	int			irq;
+	const char		*clock_asc;
+	struct at91_pin_config	clock_pin;
+	struct at91_mmc_pins	slot[2];
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
 	struct at91_dev_table_basic_device	*usbh_ehci;
 	struct at91_dev_table_basic_device	*udc;
+	struct at91_dev_table_mmc		*mmc[2];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 06/23] at91: Make NAND device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (5 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 05/23] at91: Make MMC device common Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 07/23] at91: Make TWI " Ryan Mallon
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual NAND code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |   65 ++++--------------------
 arch/arm/mach-at91/at91cap9_devices.c    |   62 ++--------------------
 arch/arm/mach-at91/at91rm9200_devices.c  |   81 +++++++-----------------------
 arch/arm/mach-at91/at91sam9260_devices.c |   62 ++--------------------
 arch/arm/mach-at91/at91sam9261_devices.c |   63 ++++-------------------
 arch/arm/mach-at91/at91sam9263_devices.c |   62 ++--------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   62 ++--------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   66 ++----------------------
 arch/arm/mach-at91/devices.c             |   76 ++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   12 ++++
 10 files changed, 158 insertions(+), 453 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index fa735f3..b06be51 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -104,64 +104,20 @@ static struct __initdata at91_dev_table_mmc device_mmc = {
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	{
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_pin_config nand_pins[] = {
+	{AT91_PIN_PB28, AT91_PIN_PERIPH_A, 0, 0, 0},	/* A[22] */
+	{AT91_PIN_PA28, AT91_PIN_PERIPH_B, 0, 0, 0},	/* NANDOE */
+	{AT91_PIN_PA29, AT91_PIN_PERIPH_B, 0, 0, 0},	/* NANDWE */
 };
 
-static struct platform_device at572d940hf_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_MATRIX_EBICSA,
+	.enable		= AT91_MATRIX_CS3A_SMC_SMARTMEDIA,
+	.pins		= nand_pins,
+	.nr_pins	= ARRAY_SIZE(nand_pins),
 };
 
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned long csa;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	at91_set_A_periph(AT91_PIN_PB28, 0);		/* A[22] */
-	at91_set_B_periph(AT91_PIN_PA28, 0);		/* NANDOE */
-	at91_set_B_periph(AT91_PIN_PA29, 0);		/* NANDWE */
-
-	nand_data = *data;
-	platform_device_register(&at572d940hf_nand_device);
-}
-
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
@@ -787,6 +743,7 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
+	.nand		= &device_nand,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 2b83683..435cda1 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -228,64 +228,13 @@ static struct __initdata at91_dev_table_mmc device_mmc1 = {
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	[0] = {
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_BASE_SYS + AT91_ECC,
-		.end	= AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_MATRIX_EBICSA,
+	.enable		= AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA,
+	.ecc_mmio_base	= AT91_BASE_SYS + AT91_ECC,
 };
 
-static struct platform_device at91cap9_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned long csa;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	nand_data = *data;
-	platform_device_register(&at91cap9_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
@@ -1101,6 +1050,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.mmc[0]		= &device_mmc0,
 	.mmc[1]		= &device_mmc1,
+	.nand		= &device_nand,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index adcb222..0521525 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -198,70 +198,26 @@ static struct __initdata at91_dev_table_mmc device_mmc = {
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	{
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91rm9200_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned int csa;
-
-	if (!data)
-		return;
-
-	/* enable the address range of CS3 */
-	csa = at91_sys_read(AT91_EBI_CSA);
-	at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA);
-
-	/* set the bus interface characteristics */
-	at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
+static struct __initdata at91_pin_config nand_pins[] = {
+	{AT91_PIN_PC1, AT91_PIN_PERIPH_A, 0, 0, 0},	/* SMOE */
+	{AT91_PIN_PC3, AT91_PIN_PERIPH_A, 0, 0, 0},	/* SMWE */
+};
+
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_EBI_CSA,
+	.enable		= AT91_EBI_CS3A_SMC_SMARTMEDIA,
+	.flags_reg	= AT91_SMC_CSR(3),
+	.flags		= (
+		  AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
 		| AT91_SMC_NWS_(5)
 		| AT91_SMC_TDF_(1)
-		| AT91_SMC_RWSETUP_(0)	/* tDS Data Set up Time 30 - ns */
-		| AT91_SMC_RWHOLD_(1)	/* tDH Data Hold Time 20 - ns */
-	);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	at91_set_A_periph(AT91_PIN_PC1, 0);		/* SMOE */
-	at91_set_A_periph(AT91_PIN_PC3, 0);		/* SMWE */
-
-	nand_data = *data;
-	platform_device_register(&at91rm9200_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
+		| AT91_SMC_RWSETUP_(0)	 /* tDS Data Set up Time 30 - ns */
+		| AT91_SMC_RWHOLD_(1)	 /* tDH Data Hold Time 20 - ns */
+		),
+	.pins		= nand_pins,
+	.nr_pins	= ARRAY_SIZE(nand_pins),
+};
 
 /* --------------------------------------------------------------------
  *  TWI (i2c)
@@ -1005,6 +961,7 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
+	.nand		= &device_nand,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 03c548f..83aa050 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -113,64 +113,13 @@ static struct __initdata at91_dev_table_mmc device_mmc = {
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	[0] = {
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_BASE_SYS + AT91_ECC,
-		.end	= AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_MATRIX_EBICSA,
+	.enable		= AT91_MATRIX_CS3A_SMC_SMARTMEDIA,
+	.ecc_mmio_base	= AT91_BASE_SYS + AT91_ECC,
 };
 
-static struct platform_device at91sam9260_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned long csa;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	nand_data = *data;
-	platform_device_register(&at91sam9260_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
@@ -1065,6 +1014,7 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
+	.nand		= &device_nand,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index b6d4578..d3384e6 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -70,63 +70,19 @@ static struct __initdata at91_dev_table_mmc device_mmc = {
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	{
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_pin_config nand_pins[] = {
+	{AT91_PIN_PC0, AT91_PIN_PERIPH_A, 0, 0, 0},	/* NANDOE */
+	{AT91_PIN_PC1, AT91_PIN_PERIPH_A, 0, 0, 0},	/* NANDWE */
 };
 
-static struct platform_device atmel_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_MATRIX_EBICSA,
+	.enable		= AT91_MATRIX_CS3A_SMC_SMARTMEDIA,
+	.pins		= nand_pins,
+	.nr_pins	= ARRAY_SIZE(nand_pins),
 };
 
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned long csa;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	at91_set_A_periph(AT91_PIN_PC0, 0);		/* NANDOE */
-	at91_set_A_periph(AT91_PIN_PC1, 0);		/* NANDWE */
-
-	nand_data = *data;
-	platform_device_register(&atmel_nand_device);
-}
-
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
@@ -920,6 +876,7 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
+	.nand		= &device_nand,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 5e09258..f2c4987 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -248,64 +248,13 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {}
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	[0] = {
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_BASE_SYS + AT91_ECC0,
-		.end	= AT91_BASE_SYS + AT91_ECC0 + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_MATRIX_EBI0CSA,
+	.enable		= AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA,
+	.ecc_mmio_base	= AT91_BASE_SYS + AT91_ECC0,
 };
 
-static struct platform_device at91sam9263_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned long csa;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
-	at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	nand_data = *data;
-	platform_device_register(&at91sam9263_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
@@ -1222,6 +1171,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc0,
 	.mmc[1]		= &device_mmc1,
+	.nand		= &device_nand,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 01636f0..e3e4cd8 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -272,64 +272,13 @@ static struct __initdata at91_dev_table_mmc device_mmc1 = {
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	[0] = {
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_BASE_SYS + AT91_ECC,
-		.end	= AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_MATRIX_EBICSA,
+	.enable		= AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA,
+	.ecc_mmio_base	= AT91_BASE_SYS + AT91_ECC,
 };
 
-static struct platform_device at91sam9g45_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned long csa;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	nand_data = *data;
-	platform_device_register(&at91sam9g45_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
@@ -1347,6 +1296,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.usbh_ehci	= &device_usb_ehci,
 	.mmc[0]		= &device_mmc0,
 	.mmc[1]		= &device_mmc1,
+	.nand		= &device_nand,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 70c8669..e848cc0 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -189,68 +189,13 @@ static struct __initdata at91_dev_table_mmc device_mmc = {
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE	AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-	[0] = {
-		.start	= NAND_BASE,
-		.end	= NAND_BASE + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_BASE_SYS + AT91_ECC,
-		.end	= AT91_BASE_SYS + AT91_ECC + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_dev_table_nand device_nand = {
+	.chip_select	= 3,
+	.enable_reg	= AT91_MATRIX_EBICSA,
+	.enable		= AT91_MATRIX_CS3A_SMC_SMARTMEDIA,
+	.ecc_mmio_base	= AT91_BASE_SYS + AT91_ECC,
 };
 
-static struct platform_device atmel_nand_device = {
-	.name		= "atmel_nand",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &nand_data,
-	},
-	.resource	= nand_resources,
-	.num_resources	= ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-	unsigned long csa;
-
-	if (!data)
-		return;
-
-	csa = at91_sys_read(AT91_MATRIX_EBICSA);
-	at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
-
-	/* enable pin */
-	if (data->enable_pin)
-		at91_set_gpio_output(data->enable_pin, 1);
-
-	/* ready/busy pin */
-	if (data->rdy_pin)
-		at91_set_gpio_input(data->rdy_pin, 1);
-
-	/* card detect pin */
-	if (data->det_pin)
-		at91_set_gpio_input(data->det_pin, 1);
-
-	at91_set_A_periph(AT91_PIN_PB4, 0);		/* NANDOE */
-	at91_set_A_periph(AT91_PIN_PB5, 0);		/* NANDWE */
-
-	nand_data = *data;
-	platform_device_register(&atmel_nand_device);
-}
-
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
@@ -1152,6 +1097,7 @@ void __init at91_add_device_serial(void) {}
 
 static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.mmc[0]		= &device_mmc,
+	.nand		= &device_nand,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 3135f91..ea11801 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -529,6 +529,82 @@ void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
 }
 #else
 void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
+#endif 
+
+/* --------------------------------------------------------------------
+ *  NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
+static struct atmel_nand_data nand_data;
+
+static struct resource nand_resources[] = {
+	[0] = {
+		.end	= SZ_256M,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* ECC resource, not all at91 variants have this */
+		.end	= SZ_512,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91_nand_device = {
+	.name		= "atmel_nand",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &nand_data,
+	},
+	.resource	= nand_resources,
+	/* We fill in num_resources in at91_add_device_nand */
+};
+
+void __init at91_add_device_nand(struct atmel_nand_data *data)
+{
+	struct at91_dev_table_nand *info = devices->nand;
+	unsigned long csa;
+
+	BUG_ON(!info);
+	init_resource_mem(&nand_resources[0],
+			  (info->chip_select + 1) * 0x10000000);
+	if (info->ecc_mmio_base) {
+		init_resource_mem(&nand_resources[1], info->ecc_mmio_base);
+		at91_nand_device.num_resources = 2;
+	} else {
+		at91_nand_device.num_resources = 1;
+	}
+
+	if (!data)
+		return;
+
+	/* enable the address range for the chip-select */
+	csa = at91_sys_read(info->enable_reg);
+	at91_sys_write(info->enable_reg, csa | info->enable);
+
+	if (info->flags_reg && info->flags)
+		at91_sys_write(info->flags_reg, info->flags);
+
+	/* enable pin */
+	if (data->enable_pin)
+		at91_set_gpio_output(data->enable_pin, 1);
+
+	/* ready/busy pin */
+	if (data->rdy_pin)
+		at91_set_gpio_input(data->rdy_pin, 1);
+
+	/* card detect pin */
+	if (data->det_pin)
+		at91_set_gpio_input(data->det_pin, 1);
+
+	if (info->pins)
+		at91_config_pins(info->pins, info->nr_pins);
+
+	nand_data = *data;
+	platform_device_register(&at91_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
 void __init at91_init_devices(struct at91_device_table *device_table)
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index eab2f54..3e9ec54 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -62,12 +62,24 @@ struct at91_dev_table_mmc {
 	struct at91_mmc_pins	slot[2];
 };
 
+struct at91_dev_table_nand {
+	unsigned		chip_select;
+	unsigned		enable_reg;
+	unsigned		enable;
+	unsigned		ecc_mmio_base;
+	unsigned		flags_reg;
+	unsigned		flags;
+	struct at91_pin_config	*pins;
+	int			nr_pins;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
 	struct at91_dev_table_basic_device	*usbh_ehci;
 	struct at91_dev_table_basic_device	*udc;
 	struct at91_dev_table_mmc		*mmc[2];
+	struct at91_dev_table_nand		*nand;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 07/23] at91: Make TWI device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (6 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 06/23] at91: Make NAND " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 08/23] at91: Make SPI " Ryan Mallon
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual TWI code for each at91 variant with a single
implementation in devices.c

The AT91SAM9G45 has an additional argument to at91_add_device_i2c for
the bus number. We change the other variants to use this API for
consistency.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c  |  111 +++--------------------
 arch/arm/mach-at91/at91cap9_devices.c     |   76 ++---------------
 arch/arm/mach-at91/at91rm9200_devices.c   |   77 ++---------------
 arch/arm/mach-at91/at91sam9260_devices.c  |   78 ++---------------
 arch/arm/mach-at91/at91sam9261_devices.c  |   77 ++---------------
 arch/arm/mach-at91/at91sam9263_devices.c  |   77 ++---------------
 arch/arm/mach-at91/at91sam9g45_devices.c  |  136 +++--------------------------
 arch/arm/mach-at91/at91sam9rl_devices.c   |   77 ++---------------
 arch/arm/mach-at91/board-afeb-9260v1.c    |    2 +-
 arch/arm/mach-at91/board-at572d940hf_ek.c |    2 +-
 arch/arm/mach-at91/board-cap9adk.c        |    2 +-
 arch/arm/mach-at91/board-carmeva.c        |    2 +-
 arch/arm/mach-at91/board-cpu9krea.c       |    2 +-
 arch/arm/mach-at91/board-cpuat91.c        |    2 +-
 arch/arm/mach-at91/board-csb337.c         |    2 +-
 arch/arm/mach-at91/board-csb637.c         |    2 +-
 arch/arm/mach-at91/board-eb9200.c         |    2 +-
 arch/arm/mach-at91/board-ecbat91.c        |    2 +-
 arch/arm/mach-at91/board-foxg20.c         |    2 +-
 arch/arm/mach-at91/board-gsia18s.c        |    2 +-
 arch/arm/mach-at91/board-kafa.c           |    2 +-
 arch/arm/mach-at91/board-kb9202.c         |    2 +-
 arch/arm/mach-at91/board-neocore926.c     |    2 +-
 arch/arm/mach-at91/board-pcontrol-g20.c   |    2 +-
 arch/arm/mach-at91/board-picotux200.c     |    2 +-
 arch/arm/mach-at91/board-qil-a9260.c      |    2 +-
 arch/arm/mach-at91/board-rm9200dk.c       |    2 +-
 arch/arm/mach-at91/board-rm9200ek.c       |    2 +-
 arch/arm/mach-at91/board-sam9-l9260.c     |    2 +-
 arch/arm/mach-at91/board-sam9260ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9261ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9263ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9g20ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9rlek.c       |    2 +-
 arch/arm/mach-at91/board-snapper9260.c    |    2 +-
 arch/arm/mach-at91/board-stamp9g20.c      |    4 +-
 arch/arm/mach-at91/board-usb-a9260.c      |    2 +-
 arch/arm/mach-at91/board-usb-a9263.c      |    2 +-
 arch/arm/mach-at91/board-yl-9200.c        |    2 +-
 arch/arm/mach-at91/devices.c              |  122 ++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h              |    9 ++
 arch/arm/mach-at91/include/mach/board.h   |    4 -
 42 files changed, 233 insertions(+), 675 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index b06be51..f8ea398 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -122,107 +122,22 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= AT91_PIN_PC7,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PC8,
-	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
-};
-
-static struct platform_device at572d940hf_twi_device {
-	.name			= "i2c-gpio",
-	.id			= -1,
-	.dev.platform_data	= &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	at91_set_GPIO_periph(AT91_PIN_PC7, 1);		/* TWD (SDA) */
-	at91_set_multi_drive(AT91_PIN_PC7, 1);
-
-	at91_set_GPIO_periph(AT91_PIN_PA8, 1);		/* TWCK (SCL) */
-	at91_set_multi_drive(AT91_PIN_PC8, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at572d940hf_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi0_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_TWI0,
-		.end	= AT572D940HF_BASE_TWI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_TWI0,
-		.end	= AT572D940HF_ID_TWI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at572d940hf_twi0_device = {
-	.name		= "at91_i2c",
-	.id		= 0,
-	.resource	= twi0_resources,
-	.num_resources	= ARRAY_SIZE(twi0_resources),
+static struct __initdata at91_dev_table_twi device_twi0 = {
+	.mmio_base	= AT572D940HF_BASE_TWI0,
+	.irq		= AT572D940HF_ID_TWI0,
+	.sda_pin 	= {AT91_PIN_PC7, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PC8, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 2,
 };
 
-static struct resource twi1_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_TWI1,
-		.end	= AT572D940HF_BASE_TWI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_TWI1,
-		.end	= AT572D940HF_ID_TWI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at572d940hf_twi1_device = {
-	.name		= "at91_i2c",
-	.id		= 1,
-	.resource	= twi1_resources,
-	.num_resources	= ARRAY_SIZE(twi1_resources),
+static struct __initdata at91_dev_table_twi device_twi1 = {
+	.mmio_base	= AT572D940HF_BASE_TWI1,
+	.irq		= AT572D940HF_ID_TWI1,
+	.sda_pin 	= {AT91_PIN_PC7, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PC8, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 2,
 };
 
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	/* pins used for TWI0 interface */
-	at91_set_A_periph(AT91_PIN_PC7, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PC7, 1);
-
-	at91_set_A_periph(AT91_PIN_PC8, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PC8, 1);
-
-	/* pins used for TWI1 interface */
-	at91_set_A_periph(AT91_PIN_PC20, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PC20, 1);
-
-	at91_set_A_periph(AT91_PIN_PC21, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PC21, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at572d940hf_twi0_device);
-	platform_device_register(&at572d940hf_twi1_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -744,6 +659,8 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi0,
+	.twi[1]		= &device_twi1,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 435cda1..a775fcc 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -239,77 +239,14 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= AT91_PIN_PB4,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PB5,
-	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
-};
-
-static struct platform_device at91cap9_twi_device = {
-	.name			= "i2c-gpio",
-	.id			= -1,
-	.dev.platform_data	= &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	at91_set_GPIO_periph(AT91_PIN_PB4, 1);		/* TWD (SDA) */
-	at91_set_multi_drive(AT91_PIN_PB4, 1);
-
-	at91_set_GPIO_periph(AT91_PIN_PB5, 1);		/* TWCK (SCL) */
-	at91_set_multi_drive(AT91_PIN_PB5, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91cap9_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_TWI,
-		.end	= AT91CAP9_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_TWI,
-		.end	= AT91CAP9_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91cap9_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
+static struct __initdata at91_dev_table_twi device_twi = {
+	.mmio_base	= AT91CAP9_BASE_TWI,
+	.irq		= AT91CAP9_ID_TWI,
+	.sda_pin 	= {AT91_PIN_PB4, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PB5, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.udelay		= 2,
 };
 
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	/* pins used for TWI interface */
-	at91_set_B_periph(AT91_PIN_PB4, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PB4, 1);
-
-	at91_set_B_periph(AT91_PIN_PB5, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PB5, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91cap9_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -1051,6 +988,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.mmc[0]		= &device_mmc0,
 	.mmc[1]		= &device_mmc1,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 0521525..d3ef09d 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -223,78 +223,14 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= AT91_PIN_PA25,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PA26,
-	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
-};
-
-static struct platform_device at91rm9200_twi_device = {
-	.name			= "i2c-gpio",
-	.id			= -1,
-	.dev.platform_data	= &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	at91_set_GPIO_periph(AT91_PIN_PA25, 1);		/* TWD (SDA) */
-	at91_set_multi_drive(AT91_PIN_PA25, 1);
-
-	at91_set_GPIO_periph(AT91_PIN_PA26, 1);		/* TWCK (SCL) */
-	at91_set_multi_drive(AT91_PIN_PA26, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91rm9200_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_TWI,
-		.end	= AT91RM9200_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_TWI,
-		.end	= AT91RM9200_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_twi device_twi = {
+	.mmio_base	= AT91RM9200_BASE_TWI,
+	.irq		= AT91RM9200_ID_TWI,
+	.sda_pin 	= {AT91_PIN_PA25, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PA26, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 2,
 };
 
-static struct platform_device at91rm9200_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	/* pins used for TWI interface */
-	at91_set_A_periph(AT91_PIN_PA25, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PA25, 1);
-
-	at91_set_A_periph(AT91_PIN_PA26, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PA26, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91rm9200_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -962,6 +898,7 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 83aa050..ffcde0e 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -124,79 +124,14 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= AT91_PIN_PA23,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PA24,
-	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
+static struct __initdata at91_dev_table_twi device_twi = {
+	.mmio_base	= AT91SAM9260_BASE_TWI,
+	.irq		= AT91SAM9260_ID_TWI,
+	.sda_pin 	= {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 2,
 };
 
-static struct platform_device at91sam9260_twi_device = {
-	.name			= "i2c-gpio",
-	.id			= -1,
-	.dev.platform_data	= &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	at91_set_GPIO_periph(AT91_PIN_PA23, 1);		/* TWD (SDA) */
-	at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-	at91_set_GPIO_periph(AT91_PIN_PA24, 1);		/* TWCK (SCL) */
-	at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9260_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_TWI,
-		.end	= AT91SAM9260_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_TWI,
-		.end	= AT91SAM9260_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	/* pins used for TWI interface */
-	at91_set_A_periph(AT91_PIN_PA23, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-	at91_set_A_periph(AT91_PIN_PA24, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9260_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -1015,6 +950,7 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index d3384e6..dfcd763 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -87,78 +87,14 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= AT91_PIN_PA7,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PA8,
-	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
-};
-
-static struct platform_device at91sam9261_twi_device = {
-	.name			= "i2c-gpio",
-	.id			= -1,
-	.dev.platform_data	= &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	at91_set_GPIO_periph(AT91_PIN_PA7, 1);		/* TWD (SDA) */
-	at91_set_multi_drive(AT91_PIN_PA7, 1);
-
-	at91_set_GPIO_periph(AT91_PIN_PA8, 1);		/* TWCK (SCL) */
-	at91_set_multi_drive(AT91_PIN_PA8, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9261_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_TWI,
-		.end	= AT91SAM9261_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_TWI,
-		.end	= AT91SAM9261_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_twi device_twi = {
+	.mmio_base	= AT91SAM9261_BASE_TWI,
+	.irq		= AT91SAM9261_ID_TWI,
+	.sda_pin 	= {AT91_PIN_PA7, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PA8, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 2,
 };
 
-static struct platform_device at91sam9261_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	/* pins used for TWI interface */
-	at91_set_A_periph(AT91_PIN_PA7, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PA7, 1);
-
-	at91_set_A_periph(AT91_PIN_PA8, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PA8, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9261_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -877,6 +813,7 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.udc		= &device_udc,
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index f2c4987..346aa9e 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -259,78 +259,14 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= AT91_PIN_PB4,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PB5,
-	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
-};
-
-static struct platform_device at91sam9263_twi_device = {
-	.name			= "i2c-gpio",
-	.id			= -1,
-	.dev.platform_data	= &pdata,
+static struct __initdata at91_dev_table_twi device_twi = {
+	.mmio_base	= AT91SAM9263_BASE_TWI,
+	.irq		= AT91SAM9263_ID_TWI,
+	.sda_pin 	= {AT91_PIN_PB4, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PB5, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 2,
 };
 
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	at91_set_GPIO_periph(AT91_PIN_PB4, 1);		/* TWD (SDA) */
-	at91_set_multi_drive(AT91_PIN_PB4, 1);
-
-	at91_set_GPIO_periph(AT91_PIN_PB5, 1);		/* TWCK (SCL) */
-	at91_set_multi_drive(AT91_PIN_PB5, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9263_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_TWI,
-		.end	= AT91SAM9263_BASE_TWI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_TWI,
-		.end	= AT91SAM9263_ID_TWI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9263_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	/* pins used for TWI interface */
-	at91_set_A_periph(AT91_PIN_PB4, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PB4, 1);
-
-	at91_set_A_periph(AT91_PIN_PB5, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PB5, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9263_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -1172,6 +1108,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.mmc[0]		= &device_mmc0,
 	.mmc[1]		= &device_mmc1,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index e3e4cd8..a86f08e 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -283,132 +283,22 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-static struct i2c_gpio_platform_data pdata_i2c0 = {
-	.sda_pin		= AT91_PIN_PA20,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PA21,
-	.scl_is_open_drain	= 1,
-	.udelay			= 5,		/* ~100 kHz */
-};
-
-static struct platform_device at91sam9g45_twi0_device = {
-	.name			= "i2c-gpio",
-	.id			= 0,
-	.dev.platform_data	= &pdata_i2c0,
+static struct __initdata at91_dev_table_twi device_twi0 = {
+	.mmio_base	= AT91SAM9G45_BASE_TWI0,
+	.irq		= AT91SAM9G45_ID_TWI0,
+	.sda_pin 	= {AT91_PIN_PA20, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 5,
 };
 
-static struct i2c_gpio_platform_data pdata_i2c1 = {
-	.sda_pin		= AT91_PIN_PB10,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PB11,
-	.scl_is_open_drain	= 1,
-	.udelay			= 5,		/* ~100 kHz */
+static struct __initdata at91_dev_table_twi device_twi1 = {
+	.mmio_base	= AT91SAM9G45_BASE_TWI1,
+	.irq		= AT91SAM9G45_ID_TWI1,
+	.sda_pin 	= {AT91_PIN_PB20, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PB21, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 5,
 };
 
-static struct platform_device at91sam9g45_twi1_device = {
-	.name			= "i2c-gpio",
-	.id			= 1,
-	.dev.platform_data	= &pdata_i2c1,
-};
-
-void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
-{
-	i2c_register_board_info(i2c_id, devices, nr_devices);
-
-	if (i2c_id == 0) {
-		at91_set_GPIO_periph(AT91_PIN_PA20, 1);		/* TWD (SDA) */
-		at91_set_multi_drive(AT91_PIN_PA20, 1);
-
-		at91_set_GPIO_periph(AT91_PIN_PA21, 1);		/* TWCK (SCL) */
-		at91_set_multi_drive(AT91_PIN_PA21, 1);
-
-		platform_device_register(&at91sam9g45_twi0_device);
-	} else {
-		at91_set_GPIO_periph(AT91_PIN_PB10, 1);		/* TWD (SDA) */
-		at91_set_multi_drive(AT91_PIN_PB10, 1);
-
-		at91_set_GPIO_periph(AT91_PIN_PB11, 1);		/* TWCK (SCL) */
-		at91_set_multi_drive(AT91_PIN_PB11, 1);
-
-		platform_device_register(&at91sam9g45_twi1_device);
-	}
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-static struct resource twi0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_TWI0,
-		.end	= AT91SAM9G45_BASE_TWI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_TWI0,
-		.end	= AT91SAM9G45_ID_TWI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_twi0_device = {
-	.name		= "at91_i2c",
-	.id		= 0,
-	.resource	= twi0_resources,
-	.num_resources	= ARRAY_SIZE(twi0_resources),
-};
-
-static struct resource twi1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_TWI1,
-		.end	= AT91SAM9G45_BASE_TWI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_TWI1,
-		.end	= AT91SAM9G45_ID_TWI1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_twi1_device = {
-	.name		= "at91_i2c",
-	.id		= 1,
-	.resource	= twi1_resources,
-	.num_resources	= ARRAY_SIZE(twi1_resources),
-};
-
-void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
-{
-	i2c_register_board_info(i2c_id, devices, nr_devices);
-
-	/* pins used for TWI interface */
-	if (i2c_id == 0) {
-		at91_set_A_periph(AT91_PIN_PA20, 0);		/* TWD */
-		at91_set_multi_drive(AT91_PIN_PA20, 1);
-
-		at91_set_A_periph(AT91_PIN_PA21, 0);		/* TWCK */
-		at91_set_multi_drive(AT91_PIN_PA21, 1);
-
-		platform_device_register(&at91sam9g45_twi0_device);
-	} else {
-		at91_set_A_periph(AT91_PIN_PB10, 0);		/* TWD */
-		at91_set_multi_drive(AT91_PIN_PB10, 1);
-
-		at91_set_A_periph(AT91_PIN_PB11, 0);		/* TWCK */
-		at91_set_multi_drive(AT91_PIN_PB11, 1);
-
-		platform_device_register(&at91sam9g45_twi1_device);
-	}
-}
-#else
-void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -1297,6 +1187,8 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.mmc[0]		= &device_mmc0,
 	.mmc[1]		= &device_mmc1,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi0,
+	.twi[1]		= &device_twi1,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index e848cc0..dd8f8c4 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -200,78 +200,14 @@ static struct __initdata at91_dev_table_nand device_nand = {
  *  TWI (i2c)
  * -------------------------------------------------------------------- */
 
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= AT91_PIN_PA23,
-	.sda_is_open_drain	= 1,
-	.scl_pin		= AT91_PIN_PA24,
-	.scl_is_open_drain	= 1,
-	.udelay			= 2,		/* ~100 kHz */
-};
-
-static struct platform_device at91sam9rl_twi_device = {
-	.name			= "i2c-gpio",
-	.id			= -1,
-	.dev.platform_data	= &pdata,
+static struct __initdata at91_dev_table_twi device_twi = {
+	.mmio_base	= AT91SAM9RL_BASE_TWI0,
+	.irq		= AT91SAM9RL_ID_TWI0,
+	.sda_pin 	= {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.scl_pin	= {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.udelay		= 2,
 };
 
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	at91_set_GPIO_periph(AT91_PIN_PA23, 1);		/* TWD (SDA) */
-	at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-	at91_set_GPIO_periph(AT91_PIN_PA24, 1);		/* TWCK (SCL) */
-	at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9rl_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_TWI0,
-		.end	= AT91SAM9RL_BASE_TWI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_TWI0,
-		.end	= AT91SAM9RL_ID_TWI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9rl_twi_device = {
-	.name		= "at91_i2c",
-	.id		= -1,
-	.resource	= twi_resources,
-	.num_resources	= ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-	/* pins used for TWI interface */
-	at91_set_A_periph(AT91_PIN_PA23, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-	at91_set_A_periph(AT91_PIN_PA24, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-	i2c_register_board_info(0, devices, nr_devices);
-	platform_device_register(&at91sam9rl_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SPI
  * -------------------------------------------------------------------- */
@@ -1098,6 +1034,7 @@ void __init at91_add_device_serial(void) {}
 static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
+	.twi[0]		= &device_twi,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 88d08ae..c64b7d6 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -208,7 +208,7 @@ static void __init afeb9260_board_init(void)
 	/* MMC */
 	at91_add_device_mmc(0, &afeb9260_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(afeb9260_i2c_devices,
+	at91_add_device_i2c(0, afeb9260_i2c_devices,
 			ARRAY_SIZE(afeb9260_i2c_devices));
 	/* Audio */
 	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c
index c9ab05d..edbbce4 100644
--- a/arch/arm/mach-at91/board-at572d940hf_ek.c
+++ b/arch/arm/mach-at91/board-at572d940hf_ek.c
@@ -301,7 +301,7 @@ static void __init eb_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&eb_udc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* NOR */
 	eb_add_device_nor();
 	/* NAND */
diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
index 0d60378..4fe8c55 100644
--- a/arch/arm/mach-at91/board-cap9adk.c
+++ b/arch/arm/mach-at91/board-cap9adk.c
@@ -390,7 +390,7 @@ static void __init cap9adk_board_init(void)
 	/* NOR Flash */
 	cap9adk_add_device_nor();
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* LCD Controller */
 	at91_add_device_lcdc(&cap9adk_lcdc_data);
 	/* AC97 */
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index 9d007a8..b9033cb 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -149,7 +149,7 @@ static void __init carmeva_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&carmeva_udc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* SPI */
 	at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices));
 	/* Compact Flash */
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 65c6513..9a88ca0 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -361,7 +361,7 @@ static void __init cpu9krea_board_init(void)
 	/* MMC */
 	at91_add_device_mmc(0, &cpu9krea_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(cpu9krea_i2c_devices,
+	at91_add_device_i2c(0, cpu9krea_i2c_devices,
 		ARRAY_SIZE(cpu9krea_i2c_devices));
 	/* LEDs */
 	at91_gpio_leds(cpu9krea_leds, ARRAY_SIZE(cpu9krea_leds));
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index ce3525d..fbdd54b 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -168,7 +168,7 @@ static void __init cpuat91_board_init(void)
 	/* MMC */
 	at91_add_device_mmc(0, &cpuat91_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* Platform devices */
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index ff7b8c0..f611720 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -239,7 +239,7 @@ static void __init csb337_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&csb337_udc_data);
 	/* I2C */
-	at91_add_device_i2c(csb337_i2c_devices, ARRAY_SIZE(csb337_i2c_devices));
+	at91_add_device_i2c(0, csb337_i2c_devices, ARRAY_SIZE(csb337_i2c_devices));
 	/* Compact Flash */
 	at91_set_gpio_input(AT91_PIN_PB22, 1);		/* IOIS16 */
 	at91_add_device_cf(&csb337_cf_data);
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index 74d5b7e..bc26bf7 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -129,7 +129,7 @@ static void __init csb637_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&csb637_udc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* SPI */
 	at91_add_device_spi(NULL, 0);
 	/* NOR flash */
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 3705082..eed4d6c 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -109,7 +109,7 @@ static void __init eb9200_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&eb9200_udc_data);
 	/* I2C */
-	at91_add_device_i2c(eb9200_i2c_devices, ARRAY_SIZE(eb9200_i2c_devices));
+	at91_add_device_i2c(0, eb9200_i2c_devices, ARRAY_SIZE(eb9200_i2c_devices));
 	/* Compact Flash */
 	at91_add_device_cf(&eb9200_cf_data);
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index df4a07f..b730b01 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -157,7 +157,7 @@ static void __init ecb_at91board_init(void)
 	at91_add_device_usbh_ohci(&ecb_at91usbh_data);
 
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 
 	/* MMC */
 	at91_add_device_mmc(0, &ecb_at91mmc_data);
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index 6688ec2..79c54fc 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -254,7 +254,7 @@ static void __init foxg20_board_init(void)
 	/* MMC */
 	at91_add_device_mmc(0, &foxg20_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(foxg20_i2c_devices, ARRAY_SIZE(foxg20_i2c_devices));
+	at91_add_device_i2c(0, foxg20_i2c_devices, ARRAY_SIZE(foxg20_i2c_devices));
 	/* LEDs */
 	at91_gpio_leds(foxg20_leds, ARRAY_SIZE(foxg20_leds));
 	/* Push Buttons */
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index 8b1d498..e32833d 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -567,7 +567,7 @@ static void __init gsia18s_board_init(void)
 	gsia18s_leds_init();
 	gsia18s_pcf_leds_init();
 	gsia18s_add_device_buttons();
-	at91_add_device_i2c(gsia18s_i2c_devices,
+	at91_add_device_i2c(0, gsia18s_i2c_devices,
 				ARRAY_SIZE(gsia18s_i2c_devices));
 	at91_add_device_cf(&gsia18s_cf1_data);
 	at91_add_device_spi(gsia18s_spi_devices,
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index a0cac24..1edff1b 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -87,7 +87,7 @@ static void __init kafa_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&kafa_udc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* SPI */
 	at91_add_device_spi(NULL, 0);
 }
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 59eafa2..682e9f4 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -127,7 +127,7 @@ static void __init kb9202_board_init(void)
 	/* MMC */
 	at91_add_device_mmc(0, &kb9202_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* SPI */
 	at91_add_device_spi(NULL, 0);
 	/* NAND */
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index bffbbdf..f2c79fb 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -373,7 +373,7 @@ static void __init neocore926_board_init(void)
 	neocore926_add_device_nand();
 
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 
 	/* LCD Controller */
 	at91_add_device_lcdc(&neocore926_lcdc_data);
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index 4c5848d..ad9cc28 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -207,7 +207,7 @@ static void __init pcontrol_g20_board_init(void)
 	stamp9g20_board_init();
 	at91_add_device_usbh_ohci(&usbh_data);
 	at91_add_device_eth(&macb_data);
-	at91_add_device_i2c(pcontrol_g20_i2c_devices,
+	at91_add_device_i2c(0, pcontrol_g20_i2c_devices,
 		ARRAY_SIZE(pcontrol_g20_i2c_devices));
 	add_device_pcontrol();
 	at91_add_device_spi(pcontrol_g20_spi_devices,
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 419456d..2b0958b 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -113,7 +113,7 @@ static void __init picotux200_board_init(void)
 	/* USB Host */
 	at91_add_device_usbh_ohci(&picotux200_usbh_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* MMC */
 	at91_set_gpio_output(AT91_PIN_PB22, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
 	at91_add_device_mmc(0, &picotux200_mmc_data);
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index 255a984..c00b292 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -252,7 +252,7 @@ static void __init ek_board_init(void)
 	/* NAND */
 	ek_add_device_nand();
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* Ethernet */
 	at91_add_device_eth(&ek_macb_data);
 	/* MMC */
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index 3d54963..746b6ea 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -204,7 +204,7 @@ static void __init dk_board_init(void)
 	/* Compact Flash */
 	at91_add_device_cf(&dk_cf_data);
 	/* I2C */
-	at91_add_device_i2c(dk_i2c_devices, ARRAY_SIZE(dk_i2c_devices));
+	at91_add_device_i2c(0, dk_i2c_devices, ARRAY_SIZE(dk_i2c_devices));
 	/* SPI */
 	at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices));
 #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 25fe19f..5e1dca0 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -172,7 +172,7 @@ static void __init ek_board_init(void)
 	at91_add_device_udc(&ek_udc_data);
 	at91_set_multi_drive(ek_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
 	/* I2C */
-	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+	at91_add_device_i2c(0, ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* SPI */
 	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
 #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index 589e2f4..bc62008 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -207,7 +207,7 @@ static void __init ek_board_init(void)
 	/* MMC */
 	at91_add_device_mmc(0, &ek_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 }
 
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index b98e766..c8c53ac 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -344,7 +344,7 @@ static void __init ek_board_init(void)
 	/* MMC */
 	at91_add_device_mmc(0, &ek_mmc_data);
 	/* I2C */
-	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+	at91_add_device_i2c(0, ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* SSC (to AT73C213) */
 	at73c213_set_clk(&at73c213_data);
 	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index e631172..3e848ba 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -590,7 +590,7 @@ static void __init ek_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* NAND */
 	ek_add_device_nand();
 	/* DM9000 ethernet */
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index fae6ebf..5e1aac1 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -438,7 +438,7 @@ static void __init ek_board_init(void)
 	/* NAND */
 	ek_add_device_nand();
 	/* I2C */
-	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+	at91_add_device_i2c(0, ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* LCD Controller */
 	at91_add_device_lcdc(&ek_lcdc_data);
 	/* Push Buttons */
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index c25e44c..3dd5013 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -393,7 +393,7 @@ static void __init ek_board_init(void)
 	/* MMC */
 	ek_add_device_mmc();
 	/* I2C */
-	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+	at91_add_device_i2c(0, ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* LEDs */
 	ek_add_device_gpio_leds();
 	/* Push Buttons */
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 3bf3408..475b485 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -308,7 +308,7 @@ static void __init ek_board_init(void)
 	/* USB HS */
 	at91_add_device_usba(&ek_usba_udc_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* NAND */
 	ek_add_device_nand();
 	/* SPI */
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index ca14290..e93a11b 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -166,7 +166,7 @@ static void __init snapper9260_add_device_nand(void)
 
 static void __init snapper9260_board_init(void)
 {
-	at91_add_device_i2c(snapper9260_i2c_devices,
+	at91_add_device_i2c(0, snapper9260_i2c_devices,
 			    ARRAY_SIZE(snapper9260_i2c_devices));
 	at91_add_device_serial();
 	at91_add_device_usbh_ohci(&snapper9260_usbh_data);
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 1e7a73a..9b7f333 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -274,7 +274,7 @@ static void __init portuxg20_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&macb_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* SPI */
 	at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
 	/* LEDs */
@@ -291,7 +291,7 @@ static void __init stamp9g20evb_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&macb_data);
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* LEDs */
 	at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));
 }
diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c
index 9b5cbf5..8c3bbde 100644
--- a/arch/arm/mach-at91/board-usb-a9260.c
+++ b/arch/arm/mach-at91/board-usb-a9260.c
@@ -214,7 +214,7 @@ static void __init ek_board_init(void)
 	/* NAND */
 	ek_add_device_nand();
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* Ethernet */
 	at91_add_device_eth(&ek_macb_data);
 	/* Push Buttons */
diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a9263.c
index 535af00..6e9f2ef 100644
--- a/arch/arm/mach-at91/board-usb-a9263.c
+++ b/arch/arm/mach-at91/board-usb-a9263.c
@@ -232,7 +232,7 @@ static void __init ek_board_init(void)
 	/* NAND */
 	ek_add_device_nand();
 	/* I2C */
-	at91_add_device_i2c(NULL, 0);
+	at91_add_device_i2c(0, NULL, 0);
 	/* Push Buttons */
 	ek_add_device_buttons();
 	/* LEDs */
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index bd5ebfd..ef80db1 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -571,7 +571,7 @@ static void __init yl9200_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&yl9200_udc_data);
 	/* I2C */
-	at91_add_device_i2c(yl9200_i2c_devices, ARRAY_SIZE(yl9200_i2c_devices));
+	at91_add_device_i2c(0, yl9200_i2c_devices, ARRAY_SIZE(yl9200_i2c_devices));
 	/* MMC */
 	at91_add_device_mmc(0, &yl9200_mmc_data);
 	/* NAND */
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index ea11801..64e02bd 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -17,6 +17,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
+#include <linux/i2c-gpio.h>
 
 #include <mach/cpu.h>
 #include <mach/board.h>
@@ -607,6 +608,127 @@ void __init at91_add_device_nand(struct atmel_nand_data *data)
 void __init at91_add_device_nand(struct atmel_nand_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+/*
+ * Prefer the GPIO code since the TWI controller isn't robust
+ * (gets overruns and underruns under load) and can only issue
+ * repeated STARTs in one scenario (the driver doesn't yet handle them).
+ */
+
+#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
+
+static struct i2c_gpio_platform_data i2c_gpio_pdata = {
+	.sda_is_open_drain	= 1,
+	.scl_is_open_drain	= 1,
+};
+
+static struct platform_device at91_twi_device = {
+	.name			= "i2c-gpio",
+	.id			= -1,
+	.dev.platform_data	= &i2c_gpio_pdata,
+};
+
+void __init at91_add_device_i2c(short i2c_id,
+				struct i2c_board_info *i2c_devices,
+				int nr_devices)
+{
+	struct at91_dev_table_twi *info;
+
+	BUG_ON(i2c_id < 0 || i2c_id >= ARRAY_SIZE(devices->twi));
+	info = devices->twi[i2c_id];
+	BUG_ON(!info);
+
+	/* TWD (SDA) */
+	i2c_gpio_pdata.sda_pin = info->sda_pin.pin;
+	at91_set_GPIO_periph(info->sda_pin.pin, 1);
+	at91_set_multi_drive(info->sda_pin.pin, 1);
+
+	/* TWCK (SCL) */
+	i2c_gpio_pdata.scl_pin = info->scl_pin.pin;
+	at91_set_GPIO_periph(info->scl_pin.pin, 1);
+	at91_set_multi_drive(info->scl_pin.pin, 1);
+
+	i2c_register_board_info(i2c_id, i2c_devices, nr_devices);
+	platform_device_register(&at91_twi_device);
+}
+
+#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_twi0_device = {
+	.name		= "at91_i2c",
+	.id		= 0,
+	.resource	= twi0_resources,
+	.num_resources	= ARRAY_SIZE(twi0_resources),
+};
+
+static struct resource twi1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_twi1_device = {
+	.name		= "at91_i2c",
+	.id		= 1,
+	.resource	= twi1_resources,
+	.num_resources	= ARRAY_SIZE(twi1_resources),
+};
+
+void __init at91_add_device_i2c(short i2c_id,
+				struct i2c_board_info *i2c_devices,
+				int nr_devices)
+{
+	struct at91_dev_table_twi *info;
+
+	BUG_ON(i2c_id < 0 || i2c_id >= ARRAY_SIZE(devices->twi));
+	info = devices->twi[i2c_id]
+	BUG_ON(!info);
+
+	if (i2c_id == 0) {
+		init_resource_mem(&twi0_resources[0], info->mmio_base);
+		init_resource_irq(&twi0_resources[1], info->irq);
+	} else {
+		init_resource_mem(&twi1_resources[0], info->mmio_base);
+		init_resource_irq(&twi1_resources[1], info->irq);
+	}
+
+	/* TWD */
+	config_pins(&info->pin_sda, 1);
+	at91_set_multi_drive(info->pin_sda, 1);
+
+	/* TWCK */
+	config_pins(&info->pin_scl, 1);
+	at91_set_multi_drive(info->pin_scl, 1);
+
+	i2c_register_board_info(i2c_id, i2c_devices, nr_devices);
+	if (i2c_id == 0)
+		platform_device_register(&at91_twi0_device);
+	else
+		platform_device_register(&at91_twi1_device);
+}
+#else
+void __init at91_add_device_i2c(short i2c_id,
+				struct i2c_board_info *i2c_devices,
+				int nr_devices) {}
+#endif
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 3e9ec54..9b99be2 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -73,6 +73,14 @@ struct at91_dev_table_nand {
 	int			nr_pins;
 };
 
+struct at91_dev_table_twi {
+	unsigned		mmio_base;
+	int			irq;
+	struct at91_pin_config	scl_pin;
+	struct at91_pin_config	sda_pin;
+	int			udelay;		/* For i2c-gpio */
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -80,6 +88,7 @@ struct at91_device_table {
 	struct at91_dev_table_basic_device	*udc;
 	struct at91_dev_table_mmc		*mmc[2];
 	struct at91_dev_table_nand		*nand;
+	struct at91_dev_table_twi		*twi[2];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index dd0855d..94232a4 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -116,11 +116,7 @@ struct atmel_nand_data {
 extern void __init at91_add_device_nand(struct atmel_nand_data *data);
 
  /* I2C*/
-#if defined(CONFIG_ARCH_AT91SAM9G45)
 extern void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices);
-#else
-extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices);
-#endif
 
  /* SPI */
 extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
-- 
1.7.0.4

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

* [RFC PATCH 08/23] at91: Make SPI device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (7 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 07/23] at91: Make TWI " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 09/23] at91: Make TCB " Ryan Mallon
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual SPI code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |  122 +++++-------------------------
 arch/arm/mach-at91/at91cap9_devices.c    |  122 +++++-------------------------
 arch/arm/mach-at91/at91rm9200_devices.c  |   69 ++---------------
 arch/arm/mach-at91/at91sam9260_devices.c |  122 +++++-------------------------
 arch/arm/mach-at91/at91sam9261_devices.c |  122 +++++-------------------------
 arch/arm/mach-at91/at91sam9263_devices.c |  122 +++++-------------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |  122 +++++-------------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   67 ++--------------
 arch/arm/mach-at91/devices.c             |  103 +++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   11 +++
 10 files changed, 252 insertions(+), 730 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index f8ea398..5df2d13 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -142,114 +142,30 @@ static struct __initdata at91_dev_table_twi device_twi1 = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_SPI0,
-		.end	= AT572D940HF_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_SPI0,
-		.end	= AT572D940HF_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at572d940hf_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi0 = {
+	.mmio_base		= AT572D940HF_BASE_SPI0,
+	.irq			= AT572D940HF_ID_SPI0,
+	.clk_asc		= "spi0_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6,
 	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.pin_miso		= {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_SPI1,
-		.end	= AT572D940HF_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_SPI1,
-		.end	= AT572D940HF_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_spi device_spi1 = {
+	.mmio_base		= AT572D940HF_BASE_SPI1,
+	.irq			= AT572D940HF_ID_SPI1,
+	.clk_asc		= "spi1_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PC3, AT91_PIN_PC4, AT91_PIN_PC5, AT91_PIN_PC6,
 	},
+	.pin_miso		= {AT91_PIN_PC0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PC1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PC2, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct platform_device at572d940hf_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PC3, AT91_PIN_PC4, AT91_PIN_PC5, AT91_PIN_PC6 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
-		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
-		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI0_SPCK */
-
-		at91_clock_associate("spi0_clk", &at572d940hf_spi0_device.dev, "spi_clk");
-		platform_device_register(&at572d940hf_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PC0, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PC1, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PC2, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at572d940hf_spi1_device.dev, "spi_clk");
-		platform_device_register(&at572d940hf_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Timer/Counter blocks
  * -------------------------------------------------------------------- */
@@ -661,6 +577,8 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi0,
 	.twi[1]		= &device_twi1,
+	.spi[0]		= &device_spi0,
+	.spi[1]		= &device_spi1,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index a775fcc..1cc0b5b 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -251,114 +251,30 @@ static struct __initdata at91_dev_table_twi device_twi = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_SPI0,
-		.end	= AT91CAP9_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_SPI0,
-		.end	= AT91CAP9_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91cap9_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi0 = {
+	.mmio_base		= AT91CAP9_BASE_SPI0,
+	.irq			= AT91CAP9_ID_SPI0,
+	.clk_asc		= "spi0_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PD0, AT91_PIN_PD1,
 	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.pin_miso		= {AT91_PIN_PA0, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PA1, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PA2, AT91_PIN_PERIPH_B, 0, 0, 0},
 };
 
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PD0, AT91_PIN_PD1 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_SPI1,
-		.end	= AT91CAP9_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_SPI1,
-		.end	= AT91CAP9_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_spi device_spi1 = {
+	.mmio_base		= AT91CAP9_BASE_SPI1,
+	.irq			= AT91CAP9_ID_SPI1,
+	.clk_asc		= "spi1_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18,
 	},
+	.pin_miso		= {AT91_PIN_PB12, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PC13, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PC14, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct platform_device at91cap9_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_B_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
-		at91_set_B_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
-		at91_set_B_periph(AT91_PIN_PA2, 0);	/* SPI0_SPCK */
-
-		at91_clock_associate("spi0_clk", &at91cap9_spi0_device.dev, "spi_clk");
-		platform_device_register(&at91cap9_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PB12, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PB13, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PB14, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at91cap9_spi1_device.dev, "spi_clk");
-		platform_device_register(&at91cap9_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
@@ -989,6 +905,8 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.mmc[1]		= &device_mmc1,
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
+	.spi[0]		= &device_spi0,
+	.spi[1]		= &device_spi1,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index d3ef09d..a2fec48 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -235,69 +235,17 @@ static struct __initdata at91_dev_table_twi device_twi = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_SPI,
-		.end	= AT91RM9200_BASE_SPI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_SPI,
-		.end	= AT91RM9200_ID_SPI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_spi_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi = {
+	.mmio_base		= AT91RM9200_BASE_SPI,
+	.irq			= AT91RM9200_ID_SPI,
+	.standard_cs_pins	= {
+		AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6,
 	},
-	.resource	= spi_resources,
-	.num_resources	= ARRAY_SIZE(spi_resources),
+	.pin_miso		= {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-
-	at91_set_A_periph(AT91_PIN_PA0, 0);	/* MISO */
-	at91_set_A_periph(AT91_PIN_PA1, 0);	/* MOSI */
-	at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPCK */
-
-	/* Enable SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else
-			cs_pin = spi_standard_cs[devices[i].chip_select];
-
-		if (devices[i].chip_select == 0)	/* for CS0 errata */
-			at91_set_A_periph(cs_pin, 0);
-		else
-			at91_set_gpio_output(cs_pin, 1);
-
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-	platform_device_register(&at91rm9200_spi_device);
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Timer/Counter blocks
  * -------------------------------------------------------------------- */
@@ -899,6 +847,7 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
+	.spi[0]		= &device_spi,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index ffcde0e..f5d264a 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -136,114 +136,30 @@ static struct __initdata at91_dev_table_twi device_twi = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_SPI0,
-		.end	= AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_SPI0,
-		.end	= AT91SAM9260_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi0 = {
+	.mmio_base		= AT91SAM9260_BASE_SPI0,
+	.irq			= AT91SAM9260_ID_SPI0,
+	.clk_asc		= "spi0_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17,
 	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.pin_miso		= {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_SPI1,
-		.end	= AT91SAM9260_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_SPI1,
-		.end	= AT91SAM9260_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_spi device_spi1 = {
+	.mmio_base		= AT91SAM9260_BASE_SPI1,
+	.irq			= AT91SAM9260_ID_SPI1,
+	.clk_asc		= "spi1_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3,
 	},
+	.pin_miso		= {AT91_PIN_PB0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PB1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PB2, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct platform_device at91sam9260_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
-		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
-		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk");
-		platform_device_register(&at91sam9260_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PB0, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PB1, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PB2, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk");
-		platform_device_register(&at91sam9260_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Timer/Counter blocks
  * -------------------------------------------------------------------- */
@@ -951,6 +867,8 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
+	.spi[0]		= &device_spi0,
+	.spi[1]		= &device_spi1,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index dfcd763..70b1adc 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -99,114 +99,30 @@ static struct __initdata at91_dev_table_twi device_twi = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_SPI0,
-		.end	= AT91SAM9261_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_SPI0,
-		.end	= AT91SAM9261_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi0 = {
+	.mmio_base		= AT91SAM9261_BASE_SPI0,
+	.irq			= AT91SAM9261_ID_SPI0,
+	.clk_asc		= "spi0_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6,
 	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.pin_miso		= {AT91_PIN_PA0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PA1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PA2, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_SPI1,
-		.end	= AT91SAM9261_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_SPI1,
-		.end	= AT91SAM9261_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_spi device_spi1 = {
+	.mmio_base		= AT91SAM9261_BASE_SPI1,
+	.irq			= AT91SAM9261_ID_SPI1,
+	.clk_asc		= "spi1_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26,
 	},
+	.pin_miso		= {AT91_PIN_PB30, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PB31, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PB29, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct platform_device at91sam9261_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_A_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
-		at91_set_A_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
-		at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPI0_SPCK */
-
-		at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk");
-		platform_device_register(&at91sam9261_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PB30, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PB31, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PB29, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk");
-		platform_device_register(&at91sam9261_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  LCD Controller
  * -------------------------------------------------------------------- */
@@ -814,6 +730,8 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
+	.spi[0]		= &device_spi0,
+	.spi[1]		= &device_spi1,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 346aa9e..934a756 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -271,114 +271,30 @@ static struct __initdata at91_dev_table_twi device_twi = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_SPI0,
-		.end	= AT91SAM9263_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_SPI0,
-		.end	= AT91SAM9263_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9263_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi0 = {
+	.mmio_base		= AT91SAM9263_BASE_SPI0,
+	.irq			= AT91SAM9263_ID_SPI0,
+	.clk_asc		= "spi0_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11,
 	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.pin_miso		= {AT91_PIN_PA0, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PA1, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PA2, AT91_PIN_PERIPH_B, 0, 0, 0},
 };
 
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_SPI1,
-		.end	= AT91SAM9263_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_SPI1,
-		.end	= AT91SAM9263_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_spi device_spi1 = {
+	.mmio_base		= AT91SAM9263_BASE_SPI1,
+	.irq			= AT91SAM9263_ID_SPI1,
+	.clk_asc		= "spi1_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18,
 	},
+	.pin_miso		= {AT91_PIN_PB12, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PB13, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PB14, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct platform_device at91sam9263_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_B_periph(AT91_PIN_PA0, 0);	/* SPI0_MISO */
-		at91_set_B_periph(AT91_PIN_PA1, 0);	/* SPI0_MOSI */
-		at91_set_B_periph(AT91_PIN_PA2, 0);	/* SPI0_SPCK */
-
-		at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk");
-		platform_device_register(&at91sam9263_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PB12, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PB13, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PB14, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk");
-		platform_device_register(&at91sam9263_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  AC97
  * -------------------------------------------------------------------- */
@@ -1109,6 +1025,8 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.mmc[1]		= &device_mmc1,
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
+	.spi[0]		= &device_spi0,
+	.spi[1]		= &device_spi1,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index a86f08e..f9ba907 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -303,114 +303,30 @@ static struct __initdata at91_dev_table_twi device_twi1 = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_SPI0,
-		.end	= AT91SAM9G45_BASE_SPI0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_SPI0,
-		.end	= AT91SAM9G45_ID_SPI0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_spi0_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi0 = {
+	.mmio_base		= AT91SAM9G45_BASE_SPI0,
+	.irq			= AT91SAM9G45_ID_SPI0,
+	.clk_asc		= "spi0_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PB3, AT91_PIN_PB18, AT91_PIN_PB19, AT91_PIN_PD27,
 	},
-	.resource	= spi0_resources,
-	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.pin_miso		= {AT91_PIN_PB0, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PB1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PB2, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PB18, AT91_PIN_PB19, AT91_PIN_PD27 };
-
-static struct resource spi1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_SPI1,
-		.end	= AT91SAM9G45_BASE_SPI1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_SPI1,
-		.end	= AT91SAM9G45_ID_SPI1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_spi device_spi1 = {
+	.mmio_base		= AT91SAM9G45_BASE_SPI1,
+	.irq			= AT91SAM9G45_ID_SPI1,
+	.clk_asc		= "spi1_clk",
+	.standard_cs_pins	= {
+		AT91_PIN_PB17, AT91_PIN_PD28, AT91_PIN_PD18, AT91_PIN_PD19,
 	},
+	.pin_miso		= {AT91_PIN_PB14, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PB15, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PB16, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct platform_device at91sam9g45_spi1_device = {
-	.name		= "atmel_spi",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= spi1_resources,
-	.num_resources	= ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB17, AT91_PIN_PD28, AT91_PIN_PD18, AT91_PIN_PD19 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-	short enable_spi0 = 0;
-	short enable_spi1 = 0;
-
-	/* Choose SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else if (devices[i].bus_num == 0)
-			cs_pin = spi0_standard_cs[devices[i].chip_select];
-		else
-			cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-		if (devices[i].bus_num == 0)
-			enable_spi0 = 1;
-		else
-			enable_spi1 = 1;
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-
-	/* Configure SPI bus(es) */
-	if (enable_spi0) {
-		at91_set_A_periph(AT91_PIN_PB0, 0);	/* SPI0_MISO */
-		at91_set_A_periph(AT91_PIN_PB1, 0);	/* SPI0_MOSI */
-		at91_set_A_periph(AT91_PIN_PB2, 0);	/* SPI0_SPCK */
-
-		at91_clock_associate("spi0_clk", &at91sam9g45_spi0_device.dev, "spi_clk");
-		platform_device_register(&at91sam9g45_spi0_device);
-	}
-	if (enable_spi1) {
-		at91_set_A_periph(AT91_PIN_PB14, 0);	/* SPI1_MISO */
-		at91_set_A_periph(AT91_PIN_PB15, 0);	/* SPI1_MOSI */
-		at91_set_A_periph(AT91_PIN_PB16, 0);	/* SPI1_SPCK */
-
-		at91_clock_associate("spi1_clk", &at91sam9g45_spi1_device.dev, "spi_clk");
-		platform_device_register(&at91sam9g45_spi1_device);
-	}
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  AC97
  * -------------------------------------------------------------------- */
@@ -1189,6 +1105,8 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi0,
 	.twi[1]		= &device_twi1,
+	.spi[0]		= &device_spi0,
+	.spi[1]		= &device_spi1,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index dd8f8c4..5d1aba4 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -212,67 +212,17 @@ static struct __initdata at91_dev_table_twi device_twi = {
  *  SPI
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_SPI,
-		.end	= AT91SAM9RL_BASE_SPI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_SPI,
-		.end	= AT91SAM9RL_ID_SPI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9rl_spi_device = {
-	.name		= "atmel_spi",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &spi_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
+static struct __initdata at91_dev_table_spi device_spi = {
+	.mmio_base		= AT91SAM9RL_BASE_SPI,
+	.irq			= AT91SAM9RL_ID_SPI,
+	.standard_cs_pins	= {
+		AT91_PIN_PA28, AT91_PIN_PB7, AT91_PIN_PD8, AT91_PIN_PD9,
 	},
-	.resource	= spi_resources,
-	.num_resources	= ARRAY_SIZE(spi_resources),
+	.pin_miso		= {AT91_PIN_PA25, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_mosi		= {AT91_PIN_PA26, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.pin_spck		= {AT91_PIN_PA27, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static const unsigned spi_standard_cs[4] = { AT91_PIN_PA28, AT91_PIN_PB7, AT91_PIN_PD8, AT91_PIN_PD9 };
-
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-	int i;
-	unsigned long cs_pin;
-
-	at91_set_A_periph(AT91_PIN_PA25, 0);	/* MISO */
-	at91_set_A_periph(AT91_PIN_PA26, 0);	/* MOSI */
-	at91_set_A_periph(AT91_PIN_PA27, 0);	/* SPCK */
-
-	/* Enable SPI chip-selects */
-	for (i = 0; i < nr_devices; i++) {
-		if (devices[i].controller_data)
-			cs_pin = (unsigned long) devices[i].controller_data;
-		else
-			cs_pin = spi_standard_cs[devices[i].chip_select];
-
-		/* enable chip-select pin */
-		at91_set_gpio_output(cs_pin, 1);
-
-		/* pass chip-select pin to driver */
-		devices[i].controller_data = (void *) cs_pin;
-	}
-
-	spi_register_board_info(devices, nr_devices);
-	platform_device_register(&at91sam9rl_spi_device);
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  AC97
  * -------------------------------------------------------------------- */
@@ -1035,6 +985,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
+	.spi[0]		= &device_spi,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 64e02bd..0df4b06 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -729,6 +729,109 @@ void __init at91_add_device_i2c(short i2c_id,
 				int nr_devices) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+static struct resource spi0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_spi0_device = {
+	.name		= "atmel_spi",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= spi0_resources,
+	.num_resources	= ARRAY_SIZE(spi0_resources),
+};
+
+static struct resource spi1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_spi1_device = {
+	.name		= "atmel_spi",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &spi_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= spi1_resources,
+	.num_resources	= ARRAY_SIZE(spi1_resources),
+};
+
+void __init at91_add_device_spi(struct spi_board_info *spi_devices,
+				int nr_devices)
+{
+	struct at91_dev_table_spi *info;
+	int i;
+	unsigned long cs_pin;
+	short enable_spi0 = 0;
+	short enable_spi1 = 0;
+
+	/* Choose SPI chip-selects */
+	for (i = 0; i < nr_devices; i++) {
+		info = devices->spi[spi_devices[i].bus_num];
+		BUG_ON(!info);
+
+		if (spi_devices[i].controller_data)
+			cs_pin = (unsigned long)spi_devices[i].controller_data;
+		else
+			cs_pin = info->standard_cs_pins[spi_devices[i].chip_select];
+
+		/* enable chip-select pin */
+		at91_set_gpio_output(cs_pin, 1);
+
+		/* pass chip-select pin to driver */
+		spi_devices[i].controller_data = (void *)cs_pin;
+
+		at91_config_pins(&info->pin_miso, 1);
+		at91_config_pins(&info->pin_mosi, 1);
+		at91_config_pins(&info->pin_spck, 1);
+
+		if (spi_devices[i].bus_num == 0) {
+			enable_spi0 = 1;
+			if (info->clk_asc)
+				at91_clock_associate(info->clk_asc,
+						     &at91_spi0_device.dev,
+						     "spi_clk");
+		} else {
+			enable_spi1 = 1;
+			if (info->clk_asc)
+				at91_clock_associate(info->clk_asc,
+						     &at91_spi1_device.dev,
+						     "spi_clk");
+		}
+	}
+
+	spi_register_board_info(spi_devices, nr_devices);
+	if (enable_spi0)
+		platform_device_register(&at91_spi0_device);
+	if (enable_spi1)
+		platform_device_register(&at91_spi1_device);
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *spi_devices, int nr_devices) {}
+#endif
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 9b99be2..ba85523 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -81,6 +81,16 @@ struct at91_dev_table_twi {
 	int			udelay;		/* For i2c-gpio */
 };
 
+struct at91_dev_table_spi {
+	unsigned		mmio_base;
+	int			irq;
+	const char		*clk_asc;
+	int			standard_cs_pins[4];
+	struct at91_pin_config	pin_miso;
+	struct at91_pin_config	pin_mosi;
+	struct at91_pin_config	pin_spck;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -89,6 +99,7 @@ struct at91_device_table {
 	struct at91_dev_table_mmc		*mmc[2];
 	struct at91_dev_table_nand		*nand;
 	struct at91_dev_table_twi		*twi[2];
+	struct at91_dev_table_spi		*spi[2];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 09/23] at91: Make TCB device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (8 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 08/23] at91: Make SPI " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 10/23] at91: Make RTT " Ryan Mallon
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual TCB code for each at91 variant with a single
implementation in devices.c

This also fixes a bug on the AT572D940HF, where at91_add_device_tc was
never called.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |   52 +++-------------
 arch/arm/mach-at91/at91cap9_devices.c    |   38 +++---------
 arch/arm/mach-at91/at91rm9200_devices.c  |   93 ++++++----------------------
 arch/arm/mach-at91/at91sam9260_devices.c |   91 ++++++----------------------
 arch/arm/mach-at91/at91sam9261_devices.c |   52 +++-------------
 arch/arm/mach-at91/at91sam9263_devices.c |   38 +++---------
 arch/arm/mach-at91/at91sam9g45_devices.c |   64 +++++--------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   52 +++-------------
 arch/arm/mach-at91/devices.c             |   99 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   13 ++++
 10 files changed, 212 insertions(+), 380 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index 5df2d13..08b1c19 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -170,51 +170,19 @@ static struct __initdata at91_dev_table_spi device_spi1 = {
  *  Timer/Counter blocks
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_TCB,
-		.end	= AT572D940HF_BASE_TCB + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_TC0,
-		.end	= AT572D940HF_ID_TC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= AT572D940HF_ID_TC1,
-		.end	= AT572D940HF_ID_TC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= AT572D940HF_ID_TC2,
-		.end	= AT572D940HF_ID_TC2,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb_resources[] = {
+	/* this chip has a separate clock and irq for each TC channel */
+	{AT572D940HF_ID_TC0, "tc0_clk", "t0_clk"},
+	{AT572D940HF_ID_TC1, "tc1_clk", "t1_clk"},
+	{AT572D940HF_ID_TC2, "tc2_clk", "t2_clk"},
 };
 
-static struct platform_device at572d940hf_tcb_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb_resources,
-	.num_resources	= ARRAY_SIZE(tcb_resources),
+static struct __initdata at91_dev_table_tcb device_tcb = {
+	.mmio_base	= AT572D940HF_BASE_TCB,
+	.resources	= tcb_resources,
+	.nr_resources	= ARRAY_SIZE(tcb_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has a separate clock and irq for each TC channel */
-	at91_clock_associate("tc0_clk", &at572d940hf_tcb_device.dev, "t0_clk");
-	at91_clock_associate("tc1_clk", &at572d940hf_tcb_device.dev, "t1_clk");
-	at91_clock_associate("tc2_clk", &at572d940hf_tcb_device.dev, "t2_clk");
-	platform_device_register(&at572d940hf_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
@@ -579,6 +547,7 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.twi[1]		= &device_twi1,
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
+	.tcb[0]		= &device_tcb,
 };
 
 void __init at572d940hf_init_devices(void)
@@ -596,7 +565,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 1cc0b5b..575926d 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -279,39 +279,17 @@ static struct __initdata at91_dev_table_spi device_spi1 = {
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_TCB0,
-		.end	= AT91CAP9_BASE_TCB0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_TCB,
-		.end	= AT91CAP9_ID_TCB,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb_resources[] = {
+	/* this chip has one clock and irq for all three TC channels */
+	{AT91CAP9_ID_TCB, "tcb_clk", "t0_clk"},
 };
 
-static struct platform_device at91cap9_tcb_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb_resources,
-	.num_resources	= ARRAY_SIZE(tcb_resources),
+static struct __initdata at91_dev_table_tcb device_tcb = {
+	.mmio_base	= AT91CAP9_BASE_TCB0,
+	.resources	= tcb_resources,
+	.nr_resources	= ARRAY_SIZE(tcb_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has one clock and irq for all three TC channels */
-	at91_clock_associate("tcb_clk", &at91cap9_tcb_device.dev, "t0_clk");
-	platform_device_register(&at91cap9_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
@@ -907,6 +885,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.twi[0]		= &device_twi,
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
+	.tcb[0]		= &device_tcb,
 };
 
 void __init at91cap9_init_devices(void)
@@ -923,7 +902,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index a2fec48..b6ab608 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -250,86 +250,32 @@ static struct __initdata at91_dev_table_spi device_spi = {
  *  Timer/Counter blocks
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb0_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_TCB0,
-		.end	= AT91RM9200_BASE_TCB0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_TC0,
-		.end	= AT91RM9200_ID_TC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= AT91RM9200_ID_TC1,
-		.end	= AT91RM9200_ID_TC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= AT91RM9200_ID_TC2,
-		.end	= AT91RM9200_ID_TC2,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb0_resources[] = {
+	/* this chip has a separate clock and irq for each TC channel */
+	{AT91RM9200_ID_TC0, "tc0_clk", "t0_clk"},
+	{AT91RM9200_ID_TC1, "tc1_clk", "t1_clk"},
+	{AT91RM9200_ID_TC2, "tc2_clk", "t2_clk"},
 };
 
-static struct platform_device at91rm9200_tcb0_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb0_resources,
-	.num_resources	= ARRAY_SIZE(tcb0_resources),
+static struct __initdata at91_dev_table_tcb device_tcb0 = {
+	.mmio_base	= AT91RM9200_BASE_TCB0,
+	.resources	= tcb0_resources,
+	.nr_resources	= ARRAY_SIZE(tcb0_resources),
 };
 
-static struct resource tcb1_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_TCB1,
-		.end	= AT91RM9200_BASE_TCB1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_TC3,
-		.end	= AT91RM9200_ID_TC3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= AT91RM9200_ID_TC4,
-		.end	= AT91RM9200_ID_TC4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= AT91RM9200_ID_TC5,
-		.end	= AT91RM9200_ID_TC5,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb1_resources[] = {
+	/* this chip has a separate clock and irq for each TC channel */
+	{AT91RM9200_ID_TC3, "tc3_clk", "t0_clk"},
+	{AT91RM9200_ID_TC4, "tc4_clk", "t1_clk"},
+	{AT91RM9200_ID_TC5, "tc5_clk", "t2_clk"},
 };
 
-static struct platform_device at91rm9200_tcb1_device = {
-	.name		= "atmel_tcb",
-	.id		= 1,
-	.resource	= tcb1_resources,
-	.num_resources	= ARRAY_SIZE(tcb1_resources),
+static struct __initdata at91_dev_table_tcb device_tcb1 = {
+	.mmio_base	= AT91RM9200_BASE_TCB1,
+	.resources	= tcb1_resources,
+	.nr_resources	= ARRAY_SIZE(tcb1_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has a separate clock and irq for each TC channel */
-	at91_clock_associate("tc0_clk", &at91rm9200_tcb0_device.dev, "t0_clk");
-	at91_clock_associate("tc1_clk", &at91rm9200_tcb0_device.dev, "t1_clk");
-	at91_clock_associate("tc2_clk", &at91rm9200_tcb0_device.dev, "t2_clk");
-	platform_device_register(&at91rm9200_tcb0_device);
-
-	at91_clock_associate("tc3_clk", &at91rm9200_tcb1_device.dev, "t0_clk");
-	at91_clock_associate("tc4_clk", &at91rm9200_tcb1_device.dev, "t1_clk");
-	at91_clock_associate("tc5_clk", &at91rm9200_tcb1_device.dev, "t2_clk");
-	platform_device_register(&at91rm9200_tcb1_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTC
  * -------------------------------------------------------------------- */
@@ -848,6 +794,8 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
 	.spi[0]		= &device_spi,
+	.tcb[0]		= &device_tcb0,
+	.tcb[1]		= &device_tcb1,
 };
 
 void __init at91rm9200_init_devices(void)
@@ -865,7 +813,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_rtc();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index f5d264a..aeb3807 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -164,86 +164,30 @@ static struct __initdata at91_dev_table_spi device_spi1 = {
  *  Timer/Counter blocks
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_TCB0,
-		.end	= AT91SAM9260_BASE_TCB0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_TC0,
-		.end	= AT91SAM9260_ID_TC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= AT91SAM9260_ID_TC1,
-		.end	= AT91SAM9260_ID_TC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= AT91SAM9260_ID_TC2,
-		.end	= AT91SAM9260_ID_TC2,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb0_resources[] = {
+	{AT91SAM9260_ID_TC0, "tc0_clk", "t0_clk"},
+	{AT91SAM9260_ID_TC1, "tc1_clk", "t1_clk"},
+	{AT91SAM9260_ID_TC2, "tc2_clk", "t2_clk"},
 };
 
-static struct platform_device at91sam9260_tcb0_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb0_resources,
-	.num_resources	= ARRAY_SIZE(tcb0_resources),
+static struct __initdata at91_dev_table_tcb device_tcb0 = {
+	.mmio_base	= AT91SAM9260_BASE_TCB0,
+	.resources	= tcb0_resources,
+	.nr_resources	= ARRAY_SIZE(tcb0_resources),
 };
 
-static struct resource tcb1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_TCB1,
-		.end	= AT91SAM9260_BASE_TCB1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_TC3,
-		.end	= AT91SAM9260_ID_TC3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= AT91SAM9260_ID_TC4,
-		.end	= AT91SAM9260_ID_TC4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= AT91SAM9260_ID_TC5,
-		.end	= AT91SAM9260_ID_TC5,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb1_resources[] = {
+	{AT91SAM9260_ID_TC3, "tc3_clk", "t0_clk"},
+	{AT91SAM9260_ID_TC4, "tc4_clk", "t1_clk"},
+	{AT91SAM9260_ID_TC5, "tc5_clk", "t2_clk"},
 };
 
-static struct platform_device at91sam9260_tcb1_device = {
-	.name		= "atmel_tcb",
-	.id		= 1,
-	.resource	= tcb1_resources,
-	.num_resources	= ARRAY_SIZE(tcb1_resources),
+static struct __initdata at91_dev_table_tcb device_tcb1 = {
+	.mmio_base	= AT91SAM9260_BASE_TCB1,
+	.resources	= tcb1_resources,
+	.nr_resources	= ARRAY_SIZE(tcb1_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has a separate clock and irq for each TC channel */
-	at91_clock_associate("tc0_clk", &at91sam9260_tcb0_device.dev, "t0_clk");
-	at91_clock_associate("tc1_clk", &at91sam9260_tcb0_device.dev, "t1_clk");
-	at91_clock_associate("tc2_clk", &at91sam9260_tcb0_device.dev, "t2_clk");
-	platform_device_register(&at91sam9260_tcb0_device);
-
-	at91_clock_associate("tc3_clk", &at91sam9260_tcb1_device.dev, "t0_clk");
-	at91_clock_associate("tc4_clk", &at91sam9260_tcb1_device.dev, "t1_clk");
-	at91_clock_associate("tc5_clk", &at91sam9260_tcb1_device.dev, "t2_clk");
-	platform_device_register(&at91sam9260_tcb1_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
@@ -869,6 +813,8 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.twi[0]		= &device_twi,
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
+	.tcb[0]		= &device_tcb0,
+	.tcb[1]		= &device_tcb1,
 };
 
 void __init at91sam9260_init_devices(void)
@@ -885,7 +831,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 70b1adc..f5a98c5 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -227,51 +227,19 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_TCB0,
-		.end	= AT91SAM9261_BASE_TCB0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_TC0,
-		.end	= AT91SAM9261_ID_TC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= AT91SAM9261_ID_TC1,
-		.end	= AT91SAM9261_ID_TC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= AT91SAM9261_ID_TC2,
-		.end	= AT91SAM9261_ID_TC2,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb_resources[] = {
+	/* this chip has a separate clock and irq for each TC channel */
+	{AT91SAM9261_ID_TC0, "tc0_clk", "t0_clk"},
+	{AT91SAM9261_ID_TC1, "tc1_clk", "t1_clk"},
+	{AT91SAM9261_ID_TC2, "tc2_clk", "t2_clk"},
 };
 
-static struct platform_device at91sam9261_tcb_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb_resources,
-	.num_resources	= ARRAY_SIZE(tcb_resources),
+static struct __initdata at91_dev_table_tcb device_tcb = {
+	.mmio_base	= AT91SAM9261_BASE_TCB0,
+	.resources	= tcb_resources,
+	.nr_resources	= ARRAY_SIZE(tcb_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has a separate clock and irq for each TC channel */
-	at91_clock_associate("tc0_clk", &at91sam9261_tcb_device.dev, "t0_clk");
-	at91_clock_associate("tc1_clk", &at91sam9261_tcb_device.dev, "t1_clk");
-	at91_clock_associate("tc2_clk", &at91sam9261_tcb_device.dev, "t2_clk");
-	platform_device_register(&at91sam9261_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
@@ -732,6 +700,7 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.twi[0]		= &device_twi,
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
+	.tcb[0]		= &device_tcb,
 };
 
 void __init at91sam9261_init_devices(void)
@@ -749,7 +718,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 934a756..6fcdf1a 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -509,39 +509,17 @@ void __init at91_add_device_isi(void) {}
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_TCB0,
-		.end	= AT91SAM9263_BASE_TCB0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_TCB,
-		.end	= AT91SAM9263_ID_TCB,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb_resources[] = {
+	/* this chip has one clock and irq for all three TC channels */
+	{AT91SAM9263_ID_TCB, "tcb_clk", "t0_clk"},
 };
 
-static struct platform_device at91sam9263_tcb_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb_resources,
-	.num_resources	= ARRAY_SIZE(tcb_resources),
+static struct __initdata at91_dev_table_tcb device_tcb = {
+	.mmio_base	= AT91SAM9263_BASE_TCB0,
+	.resources	= tcb_resources,
+	.nr_resources	= ARRAY_SIZE(tcb_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has one clock and irq for all three TC channels */
-	at91_clock_associate("tcb_clk", &at91sam9263_tcb_device.dev, "t0_clk");
-	platform_device_register(&at91sam9263_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
@@ -1027,6 +1005,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.twi[0]		= &device_twi,
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
+	.tcb[0]		= &device_tcb,
 };
 
 void __init at91sam9263_init_devices(void)
@@ -1043,7 +1022,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index f9ba907..27f7102 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -464,61 +464,28 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-static struct resource tcb0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_TCB0,
-		.end	= AT91SAM9G45_BASE_TCB0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_TCB,
-		.end	= AT91SAM9G45_ID_TCB,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb0_resources[] = {
+	/* this chip has one clock and irq for all six TC channels */
+	{AT91SAM9G45_ID_TCB, "tcb0_clk", "t0_clk"},
 };
 
-static struct platform_device at91sam9g45_tcb0_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb0_resources,
-	.num_resources	= ARRAY_SIZE(tcb0_resources),
+static struct __initdata at91_dev_table_tcb device_tcb0 = {
+	.mmio_base	= AT91SAM9G45_BASE_TCB0,
+	.resources	= tcb0_resources,
+	.nr_resources	= ARRAY_SIZE(tcb0_resources),
 };
 
-/* TCB1 begins with TC3 */
-static struct resource tcb1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_TCB1,
-		.end	= AT91SAM9G45_BASE_TCB1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_TCB,
-		.end	= AT91SAM9G45_ID_TCB,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb1_resources[] = {
+	/* this chip has one clock and irq for all six TC channels */
+	{AT91SAM9G45_ID_TCB, "tcb1_clk", "t0_clk"},
 };
 
-static struct platform_device at91sam9g45_tcb1_device = {
-	.name		= "atmel_tcb",
-	.id		= 1,
-	.resource	= tcb1_resources,
-	.num_resources	= ARRAY_SIZE(tcb1_resources),
+static struct __initdata at91_dev_table_tcb device_tcb1 = {
+	.mmio_base	= AT91SAM9G45_BASE_TCB1,
+	.resources	= tcb1_resources,
+	.nr_resources	= ARRAY_SIZE(tcb1_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has one clock and irq for all six TC channels */
-	at91_clock_associate("tcb0_clk", &at91sam9g45_tcb0_device.dev, "t0_clk");
-	platform_device_register(&at91sam9g45_tcb0_device);
-	at91_clock_associate("tcb1_clk", &at91sam9g45_tcb1_device.dev, "t0_clk");
-	platform_device_register(&at91sam9g45_tcb1_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTC
  * -------------------------------------------------------------------- */
@@ -1107,6 +1074,8 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.twi[1]		= &device_twi1,
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
+	.tcb[0]		= &device_tcb0,
+	.tcb[1]		= &device_tcb1,
 };
 
 void __init at91sam9g45_init_devices(void)
@@ -1125,7 +1094,6 @@ static int __init at91_add_standard_devices(void)
 	at91_add_device_rtc();
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 5d1aba4..23dc097 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -351,51 +351,19 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
 
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_TCB0,
-		.end	= AT91SAM9RL_BASE_TCB0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_TC0,
-		.end	= AT91SAM9RL_ID_TC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= AT91SAM9RL_ID_TC1,
-		.end	= AT91SAM9RL_ID_TC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= AT91SAM9RL_ID_TC2,
-		.end	= AT91SAM9RL_ID_TC2,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_tcb_res tcb_resources[] = {
+	/* this chip has a separate clock and irq for each TC channel */
+	{AT91SAM9RL_ID_TC0, "tc0_clk", "t0_clk"},
+	{AT91SAM9RL_ID_TC1, "tc1_clk", "t1_clk"},
+	{AT91SAM9RL_ID_TC2, "tc2_clk", "t2_clk"},
 };
 
-static struct platform_device at91sam9rl_tcb_device = {
-	.name		= "atmel_tcb",
-	.id		= 0,
-	.resource	= tcb_resources,
-	.num_resources	= ARRAY_SIZE(tcb_resources),
+static struct __initdata at91_dev_table_tcb device_tcb = {
+	.mmio_base	= AT91SAM9RL_BASE_TCB0,
+	.resources	= tcb_resources,
+	.nr_resources	= ARRAY_SIZE(tcb_resources),
 };
 
-static void __init at91_add_device_tc(void)
-{
-	/* this chip has a separate clock and irq for each TC channel */
-	at91_clock_associate("tc0_clk", &at91sam9rl_tcb_device.dev, "t0_clk");
-	at91_clock_associate("tc1_clk", &at91sam9rl_tcb_device.dev, "t1_clk");
-	at91_clock_associate("tc2_clk", &at91sam9rl_tcb_device.dev, "t2_clk");
-	platform_device_register(&at91sam9rl_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Touchscreen
  * -------------------------------------------------------------------- */
@@ -986,6 +954,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.nand		= &device_nand,
 	.twi[0]		= &device_twi,
 	.spi[0]		= &device_spi,
+	.tcb[0]		= &device_tcb,
 };
 
 void __init at91sam9rl_init_devices(void)
@@ -1005,7 +974,6 @@ static int __init at91_add_standard_devices(void)
 	at91_add_device_rtc();
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
-	at91_add_device_tc();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 0df4b06..f7ed9aa 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -832,7 +832,106 @@ void __init at91_add_device_spi(struct spi_board_info *spi_devices,
 void __init at91_add_device_spi(struct spi_board_info *spi_devices, int nr_devices) {}
 #endif
 
+#ifdef CONFIG_ATMEL_TCLIB
+
+static struct resource tcb0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_tcb0_device = {
+	.name		= "atmel_tcb",
+	.id		= 0,
+	.resource	= tcb0_resources,
+	.num_resources	= 1,
+};
+
+static struct resource tcb1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_tcb1_device = {
+	.name		= "atmel_tcb",
+	.id		= 1,
+	.resource	= tcb1_resources,
+	.num_resources	= 1,
+};
+
+static void __init at91_add_device_tc(void)
+{
+	struct at91_dev_table_tcb *info;
+	struct at91_tcb_res *res;
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(devices->tcb); i++) {
+		info = devices->tcb[i];
+		if (!info)
+			continue;
+
+		for (j = 0; j < info->nr_resources; j++) {
+			res = &info->resources[j];
+			if (i == 0) {
+				init_resource_irq(&tcb0_resources[j + 1],
+						  res->irq);
+				at91_clock_associate(res->clock_asc,
+						     &at91_tcb0_device.dev,
+						     res->clock_name);
+			} else {
+				init_resource_irq(&tcb1_resources[j + 1],
+						  res->irq);
+				at91_clock_associate(res->clock_asc,
+						     &at91_tcb1_device.dev,
+						     res->clock_name);
+			}
+		}
+
+		if (i == 0) {
+			init_resource_mem(&tcb0_resources[0], info->mmio_base);
+			at91_tcb0_device.num_resources += info->nr_resources;
+			platform_device_register(&at91_tcb0_device);
+		} else {
+			init_resource_mem(&tcb1_resources[0], info->mmio_base);
+			at91_tcb1_device.num_resources += info->nr_resources;
+			platform_device_register(&at91_tcb1_device);
+		}
+	}
+}
+#else
+static void __init at91_add_device_tc(void) { }
+#endif
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
 }
+
+static int __init at91_add_standard_devices(void)
+{
+	at91_add_device_tc();
+	return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index ba85523..41b6f6e 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -91,6 +91,18 @@ struct at91_dev_table_spi {
 	struct at91_pin_config	pin_spck;
 };
 
+struct at91_tcb_res {
+	int			irq;
+	const char		*clock_asc;
+	const char		*clock_name;
+};
+
+struct at91_dev_table_tcb {
+	unsigned		mmio_base;
+	struct at91_tcb_res	*resources;
+	int			nr_resources;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -100,6 +112,7 @@ struct at91_device_table {
 	struct at91_dev_table_nand		*nand;
 	struct at91_dev_table_twi		*twi[2];
 	struct at91_dev_table_spi		*spi[2];
+	struct at91_dev_table_tcb		*tcb[2];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 10/23] at91: Make RTT device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (9 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 09/23] at91: Make TCB " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 11/23] at91: Make watchdog " Ryan Mallon
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual RTT code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |   23 ++------------
 arch/arm/mach-at91/at91cap9_devices.c    |   23 ++------------
 arch/arm/mach-at91/at91sam9260_devices.c |   23 ++------------
 arch/arm/mach-at91/at91sam9261_devices.c |   23 ++------------
 arch/arm/mach-at91/at91sam9263_devices.c |   40 +++--------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   23 ++------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   23 ++------------
 arch/arm/mach-at91/devices.c             |   51 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |    5 +++
 9 files changed, 80 insertions(+), 154 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index 08b1c19..2828e7e 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -187,27 +187,10 @@ static struct __initdata at91_dev_table_tcb device_tcb = {
  *  RTT
  * -------------------------------------------------------------------- */
 
-static struct resource rtt_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT,
-		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at572d940hf_rtt_device = {
-	.name		= "at91_rtt",
-	.id		= 0,
-	.resource	= rtt_resources,
-	.num_resources	= ARRAY_SIZE(rtt_resources),
+static struct __initdata at91_dev_table_rtt device_rtt = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT,
 };
 
-static void __init at91_add_device_rtt(void)
-{
-	platform_device_register(&at572d940hf_rtt_device);
-}
-
-
 /* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
@@ -548,6 +531,7 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb,
+	.rtt[0]		= &device_rtt,
 };
 
 void __init at572d940hf_init_devices(void)
@@ -563,7 +547,6 @@ void __init at572d940hf_init_devices(void)
  */
 static int __init at91_add_standard_devices(void)
 {
-	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 575926d..cf33337 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -294,27 +294,10 @@ static struct __initdata at91_dev_table_tcb device_tcb = {
  *  RTT
  * -------------------------------------------------------------------- */
 
-static struct resource rtt_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT,
-		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91cap9_rtt_device = {
-	.name		= "at91_rtt",
-	.id		= 0,
-	.resource	= rtt_resources,
-	.num_resources	= ARRAY_SIZE(rtt_resources),
+static struct __initdata at91_dev_table_rtt device_rtt = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT,
 };
 
-static void __init at91_add_device_rtt(void)
-{
-	platform_device_register(&at91cap9_rtt_device);
-}
-
-
 /* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
@@ -886,6 +869,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb,
+	.rtt[0]		= &device_rtt,
 };
 
 void __init at91cap9_init_devices(void)
@@ -900,7 +884,6 @@ void __init at91cap9_init_devices(void)
  */
 static int __init at91_add_standard_devices(void)
 {
-	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index aeb3807..fb6d939 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -192,27 +192,10 @@ static struct __initdata at91_dev_table_tcb device_tcb1 = {
  *  RTT
  * -------------------------------------------------------------------- */
 
-static struct resource rtt_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT,
-		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91sam9260_rtt_device = {
-	.name		= "at91_rtt",
-	.id		= 0,
-	.resource	= rtt_resources,
-	.num_resources	= ARRAY_SIZE(rtt_resources),
+static struct __initdata at91_dev_table_rtt device_rtt = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT,
 };
 
-static void __init at91_add_device_rtt(void)
-{
-	platform_device_register(&at91sam9260_rtt_device);
-}
-
-
 /* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
@@ -815,6 +798,7 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb0,
 	.tcb[1]		= &device_tcb1,
+	.rtt[0]		= &device_rtt,
 };
 
 void __init at91sam9260_init_devices(void)
@@ -829,7 +813,6 @@ void __init at91sam9260_init_devices(void)
  */
 static int __init at91_add_standard_devices(void)
 {
-	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index f5a98c5..da06dbb 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -244,27 +244,10 @@ static struct __initdata at91_dev_table_tcb device_tcb = {
  *  RTT
  * -------------------------------------------------------------------- */
 
-static struct resource rtt_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT,
-		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91sam9261_rtt_device = {
-	.name		= "at91_rtt",
-	.id		= 0,
-	.resource	= rtt_resources,
-	.num_resources	= ARRAY_SIZE(rtt_resources),
+static struct __initdata at91_dev_table_rtt device_rtt = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT,
 };
 
-static void __init at91_add_device_rtt(void)
-{
-	platform_device_register(&at91sam9261_rtt_device);
-}
-
-
 /* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
@@ -701,6 +684,7 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb,
+	.rtt[0]		= &device_rtt,
 };
 
 void __init at91sam9261_init_devices(void)
@@ -716,7 +700,6 @@ void __init at91sam9261_init_devices(void)
  */
 static int __init at91_add_standard_devices(void)
 {
-	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 6fcdf1a..cd55e8f 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -524,43 +524,14 @@ static struct __initdata at91_dev_table_tcb device_tcb = {
  *  RTT
  * -------------------------------------------------------------------- */
 
-static struct resource rtt0_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT0,
-		.end	= AT91_BASE_SYS + AT91_RTT0 + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91sam9263_rtt0_device = {
-	.name		= "at91_rtt",
-	.id		= 0,
-	.resource	= rtt0_resources,
-	.num_resources	= ARRAY_SIZE(rtt0_resources),
-};
-
-static struct resource rtt1_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT1,
-		.end	= AT91_BASE_SYS + AT91_RTT1 + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
+static struct __initdata at91_dev_table_rtt device_rtt0 = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT0,
 };
 
-static struct platform_device at91sam9263_rtt1_device = {
-	.name		= "at91_rtt",
-	.id		= 1,
-	.resource	= rtt1_resources,
-	.num_resources	= ARRAY_SIZE(rtt1_resources),
+static struct __initdata at91_dev_table_rtt device_rtt1 = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT1,
 };
 
-static void __init at91_add_device_rtt(void)
-{
-	platform_device_register(&at91sam9263_rtt0_device);
-	platform_device_register(&at91sam9263_rtt1_device);
-}
-
-
 /* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
@@ -1006,6 +977,8 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.spi[0]		= &device_spi0,
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb,
+	.rtt[0]		= &device_rtt0,
+	.rtt[1]		= &device_rtt1,
 };
 
 void __init at91sam9263_init_devices(void)
@@ -1020,7 +993,6 @@ void __init at91sam9263_init_devices(void)
  */
 static int __init at91_add_standard_devices(void)
 {
-	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 27f7102..53ce9eb 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -561,27 +561,10 @@ void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
  *  RTT
  * -------------------------------------------------------------------- */
 
-static struct resource rtt_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT,
-		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91sam9g45_rtt_device = {
-	.name		= "at91_rtt",
-	.id		= 0,
-	.resource	= rtt_resources,
-	.num_resources	= ARRAY_SIZE(rtt_resources),
+static struct __initdata at91_dev_table_rtt device_rtt = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT,
 };
 
-static void __init at91_add_device_rtt(void)
-{
-	platform_device_register(&at91sam9g45_rtt_device);
-}
-
-
 /* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
@@ -1076,6 +1059,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb0,
 	.tcb[1]		= &device_tcb1,
+	.rtt[0]		= &device_rtt,
 };
 
 void __init at91sam9g45_init_devices(void)
@@ -1092,7 +1076,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_hdmac();
 	at91_add_device_rtc();
-	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 23dc097..65cd887 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -439,27 +439,10 @@ static void __init at91_add_device_rtc(void) {}
  *  RTT
  * -------------------------------------------------------------------- */
 
-static struct resource rtt_resources[] = {
-	{
-		.start	= AT91_BASE_SYS + AT91_RTT,
-		.end	= AT91_BASE_SYS + AT91_RTT + SZ_16 - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device at91sam9rl_rtt_device = {
-	.name		= "at91_rtt",
-	.id		= 0,
-	.resource	= rtt_resources,
-	.num_resources	= ARRAY_SIZE(rtt_resources),
+static struct __initdata at91_dev_table_rtt device_rtt = {
+	.mmio_base	=  AT91_BASE_SYS + AT91_RTT,
 };
 
-static void __init at91_add_device_rtt(void)
-{
-	platform_device_register(&at91sam9rl_rtt_device);
-}
-
-
 /* --------------------------------------------------------------------
  *  Watchdog
  * -------------------------------------------------------------------- */
@@ -955,6 +938,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.twi[0]		= &device_twi,
 	.spi[0]		= &device_spi,
 	.tcb[0]		= &device_tcb,
+	.rtt[0]		= &device_rtt,
 };
 
 void __init at91sam9rl_init_devices(void)
@@ -972,7 +956,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_hdmac();
 	at91_add_device_rtc();
-	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index f7ed9aa..1596c20 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -923,6 +923,56 @@ static void __init at91_add_device_tc(void)
 static void __init at91_add_device_tc(void) { }
 #endif
 
+/* --------------------------------------------------------------------
+ *  RTT
+ * -------------------------------------------------------------------- */
+
+static struct resource rtt0_resources[] = {
+	{
+		.end	= SZ_16,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91_rtt0_device = {
+	.name		= "at91_rtt",
+	.id		= 0,
+	.resource	= rtt0_resources,
+	.num_resources	= ARRAY_SIZE(rtt0_resources),
+};
+
+static struct resource rtt1_resources[] = {
+	{
+		.end	= SZ_16,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91_rtt1_device = {
+	.name		= "at91_rtt",
+	.id		= 1,
+	.resource	= rtt1_resources,
+	.num_resources	= ARRAY_SIZE(rtt1_resources),
+};
+
+static void __init at91_add_device_rtt(void)
+{
+	struct at91_dev_table_rtt *info[2];
+
+	info[0] = devices->rtt[0];
+	info[1] = devices->rtt[1];
+	BUG_ON(!info[0] && !info[1]);
+
+	if (info[0]) {
+		init_resource_mem(&rtt0_resources[0], info[0]->mmio_base);
+		platform_device_register(&at91_rtt0_device);
+	}
+	if (info[1]) {
+		init_resource_mem(&rtt1_resources[0], info[1]->mmio_base);
+		platform_device_register(&at91_rtt1_device);
+	}
+}
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
@@ -931,6 +981,7 @@ void __init at91_init_devices(struct at91_device_table *device_table)
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
+	at91_add_device_rtt();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 41b6f6e..d7855ec 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -103,6 +103,10 @@ struct at91_dev_table_tcb {
 	int			nr_resources;
 };
 
+struct at91_dev_table_rtt {
+	unsigned		mmio_base;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -113,6 +117,7 @@ struct at91_device_table {
 	struct at91_dev_table_twi		*twi[2];
 	struct at91_dev_table_spi		*spi[2];
 	struct at91_dev_table_tcb		*tcb[2];
+	struct at91_dev_table_rtt		*rtt[2];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 11/23] at91: Make watchdog device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (10 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 10/23] at91: Make RTT " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20 17:10   ` H Hartley Sweeten
  2011-04-20  1:10 ` [RFC PATCH 13/23] at91: Make PWM " Ryan Mallon
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

The code for the watchdog device for each of the at91 variants is
identical. Remove it from each variant and replace them with a single
version in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c |   34 ------------------------------
 arch/arm/mach-at91/at91cap9_devices.c    |   33 -----------------------------
 arch/arm/mach-at91/at91rm9200_devices.c  |   22 -------------------
 arch/arm/mach-at91/at91sam9260_devices.c |   33 -----------------------------
 arch/arm/mach-at91/at91sam9261_devices.c |   34 ------------------------------
 arch/arm/mach-at91/at91sam9263_devices.c |   33 -----------------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   21 ------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   21 ------------------
 arch/arm/mach-at91/devices.c             |   23 ++++++++++++++++++++
 9 files changed, 23 insertions(+), 231 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index 2828e7e..20fe358 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -192,26 +192,6 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
 };
 
 /* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct platform_device at572d940hf_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at572d940hf_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
 
@@ -538,17 +518,3 @@ void __init at572d940hf_init_devices(void)
 {
 	at91_init_devices(&at572d940hf_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_watchdog();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index cf33337..3a73ac8 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -299,26 +299,6 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
 };
 
 /* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct platform_device at91cap9_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91cap9_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  PWM
  * --------------------------------------------------------------------*/
 
@@ -876,16 +856,3 @@ void __init at91cap9_init_devices(void)
 {
 	at91_init_devices(&at91cap9_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_watchdog();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index b6ab608..243054a 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -295,27 +295,6 @@ static void __init at91_add_device_rtc(void)
 static void __init at91_add_device_rtc(void) {}
 #endif
 
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE)
-static struct platform_device at91rm9200_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91rm9200_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
@@ -812,7 +791,6 @@ void __init at91rm9200_init_devices(void)
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_rtc();
-	at91_add_device_watchdog();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index fb6d939..b2b8416 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -197,26 +197,6 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
 };
 
 /* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct platform_device at91sam9260_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91sam9260_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
@@ -805,16 +785,3 @@ void __init at91sam9260_init_devices(void)
 {
 	at91_init_devices(&at91sam9260_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_watchdog();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index da06dbb..6f719d5 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -249,26 +249,6 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
 };
 
 /* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct platform_device at91sam9261_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91sam9261_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
@@ -691,17 +671,3 @@ void __init at91sam9261_init_devices(void)
 {
 	at91_init_devices(&at91sam9261_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_watchdog();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index cd55e8f..1e8e84a 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -533,26 +533,6 @@ static struct __initdata at91_dev_table_rtt device_rtt1 = {
 };
 
 /* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct platform_device at91sam9263_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91sam9263_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  PWM
  * --------------------------------------------------------------------*/
 
@@ -985,16 +965,3 @@ void __init at91sam9263_init_devices(void)
 {
 	at91_init_devices(&at91sam9263_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_watchdog();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 53ce9eb..16006d5 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -566,26 +566,6 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
 };
 
 /* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct platform_device at91sam9g45_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91sam9g45_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  PWM
  * --------------------------------------------------------------------*/
 
@@ -1076,7 +1056,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_hdmac();
 	at91_add_device_rtc();
-	at91_add_device_watchdog();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 65cd887..a6ce60c 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -444,26 +444,6 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
 };
 
 /* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct platform_device at91sam9rl_wdt_device = {
-	.name		= "at91_wdt",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-	platform_device_register(&at91sam9rl_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  PWM
  * --------------------------------------------------------------------*/
 
@@ -956,7 +936,6 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_hdmac();
 	at91_add_device_rtc();
-	at91_add_device_watchdog();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 1596c20..5d254cb 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -973,6 +973,28 @@ static void __init at91_add_device_rtt(void)
 	}
 }
 
+/* --------------------------------------------------------------------
+ *  Watchdog
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91SAM9X_WATCHDOG)        || \
+    defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE) || \
+    defined(CONFIG_AT91RM9200_WATCHDOG)       || \
+    defined(CONFIG_AT91RM9200_WATCHDOG_MODULE)
+static struct platform_device at91_wdt_device = {
+	.name		= "at91_wdt",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+static void __init at91_add_device_watchdog(void)
+{
+	platform_device_register(&at91_wdt_device);
+}
+#else
+static void __init at91_add_device_watchdog(void) {}
+#endif
+
 void __init at91_init_devices(struct at91_device_table *device_table)
 {
 	devices = device_table;
@@ -982,6 +1004,7 @@ static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
 	at91_add_device_rtt();
+	at91_add_device_watchdog();
 	return 0;
 }
 
-- 
1.7.0.4

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

* [RFC PATCH 13/23] at91: Make PWM device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (11 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 11/23] at91: Make watchdog " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 14/23] at91: Make SSC " Ryan Mallon
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual PWM code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91cap9_devices.c    |   56 +++++-------------------------
 arch/arm/mach-at91/at91sam9263_devices.c |   55 +++++------------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   55 +++++------------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   55 +++++------------------------
 arch/arm/mach-at91/devices.c             |   55 +++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |    7 ++++
 6 files changed, 98 insertions(+), 185 deletions(-)

diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 9aa7b40..d127f5b 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -302,56 +302,17 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
  *  PWM
  * --------------------------------------------------------------------*/
 
-#if defined(CONFIG_ATMEL_PWM)
-static u32 pwm_mask;
-
-static struct resource pwm_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_PWMC,
-		.end	= AT91CAP9_BASE_PWMC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_PWMC,
-		.end	= AT91CAP9_ID_PWMC,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_pwm device_pwm = {
+	.mmio_base	= AT91CAP9_BASE_PWMC,
+	.irq		= AT91CAP9_ID_PWMC,
+	.pwm_pins	= {
+		{AT91_PIN_PB19, AT91_PIN_PERIPH_A, 1, 0, 0},
+		{AT91_PIN_PB8,  AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PC29, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PA11, AT91_PIN_PERIPH_B, 1, 0, 0},
 	},
 };
 
-static struct platform_device at91cap9_pwm0_device = {
-	.name	= "atmel_pwm",
-	.id	= -1,
-	.dev	= {
-		.platform_data		= &pwm_mask,
-	},
-	.resource	= pwm_resources,
-	.num_resources	= ARRAY_SIZE(pwm_resources),
-};
-
-void __init at91_add_device_pwm(u32 mask)
-{
-	if (mask & (1 << AT91_PWM0))
-		at91_set_A_periph(AT91_PIN_PB19, 1);	/* enable PWM0 */
-
-	if (mask & (1 << AT91_PWM1))
-		at91_set_B_periph(AT91_PIN_PB8, 1);	/* enable PWM1 */
-
-	if (mask & (1 << AT91_PWM2))
-		at91_set_B_periph(AT91_PIN_PC29, 1);	/* enable PWM2 */
-
-	if (mask & (1 << AT91_PWM3))
-		at91_set_B_periph(AT91_PIN_PA11, 1);	/* enable PWM3 */
-
-	pwm_mask = mask;
-
-	platform_device_register(&at91cap9_pwm0_device);
-}
-#else
-void __init at91_add_device_pwm(u32 mask) {}
-#endif
-
-
-
 /* --------------------------------------------------------------------
  *  AC97
  * -------------------------------------------------------------------- */
@@ -679,6 +640,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.uart[0]	= &device_uart0,
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
+	.pwm		= &device_pwm,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index e5f0164..1ffd044 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -536,55 +536,17 @@ static struct __initdata at91_dev_table_rtt device_rtt1 = {
  *  PWM
  * --------------------------------------------------------------------*/
 
-#if defined(CONFIG_ATMEL_PWM)
-static u32 pwm_mask;
-
-static struct resource pwm_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_PWMC,
-		.end	= AT91SAM9263_BASE_PWMC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_PWMC,
-		.end	= AT91SAM9263_ID_PWMC,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_pwm device_pwm = {
+	.mmio_base	= AT91SAM9263_BASE_PWMC,
+	.irq		= AT91SAM9263_ID_PWMC,
+	.pwm_pins	= {
+		{AT91_PIN_PB7,  AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PB8,  AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PC29, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PB29, AT91_PIN_PERIPH_B, 1, 0, 0},
 	},
 };
 
-static struct platform_device at91sam9263_pwm0_device = {
-	.name	= "atmel_pwm",
-	.id	= -1,
-	.dev	= {
-		.platform_data		= &pwm_mask,
-	},
-	.resource	= pwm_resources,
-	.num_resources	= ARRAY_SIZE(pwm_resources),
-};
-
-void __init at91_add_device_pwm(u32 mask)
-{
-	if (mask & (1 << AT91_PWM0))
-		at91_set_B_periph(AT91_PIN_PB7, 1);	/* enable PWM0 */
-
-	if (mask & (1 << AT91_PWM1))
-		at91_set_B_periph(AT91_PIN_PB8, 1);	/* enable PWM1 */
-
-	if (mask & (1 << AT91_PWM2))
-		at91_set_B_periph(AT91_PIN_PC29, 1);	/* enable PWM2 */
-
-	if (mask & (1 << AT91_PWM3))
-		at91_set_B_periph(AT91_PIN_PB29, 1);	/* enable PWM3 */
-
-	pwm_mask = mask;
-
-	platform_device_register(&at91sam9263_pwm0_device);
-}
-#else
-void __init at91_add_device_pwm(u32 mask) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
@@ -787,6 +749,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.uart[0]	= &device_uart0,
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
+	.pwm		= &device_pwm,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index c832917..0f11c56 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -569,55 +569,17 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
  *  PWM
  * --------------------------------------------------------------------*/
 
-#if defined(CONFIG_ATMEL_PWM) || defined(CONFIG_ATMEL_PWM_MODULE)
-static u32 pwm_mask;
-
-static struct resource pwm_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_PWMC,
-		.end	= AT91SAM9G45_BASE_PWMC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_PWMC,
-		.end	= AT91SAM9G45_ID_PWMC,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_pwm device_pwm = {
+	.mmio_base	= AT91SAM9G45_BASE_PWMC,
+	.irq		= AT91SAM9G45_ID_PWMC,
+	.pwm_pins	= {
+		{AT91_PIN_PD24, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PD31, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PD26, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PD0,  AT91_PIN_PERIPH_B, 1, 0, 0},
 	},
 };
 
-static struct platform_device at91sam9g45_pwm0_device = {
-	.name	= "atmel_pwm",
-	.id	= -1,
-	.dev	= {
-		.platform_data		= &pwm_mask,
-	},
-	.resource	= pwm_resources,
-	.num_resources	= ARRAY_SIZE(pwm_resources),
-};
-
-void __init at91_add_device_pwm(u32 mask)
-{
-	if (mask & (1 << AT91_PWM0))
-		at91_set_B_periph(AT91_PIN_PD24, 1);	/* enable PWM0 */
-
-	if (mask & (1 << AT91_PWM1))
-		at91_set_B_periph(AT91_PIN_PD31, 1);	/* enable PWM1 */
-
-	if (mask & (1 << AT91_PWM2))
-		at91_set_B_periph(AT91_PIN_PD26, 1);	/* enable PWM2 */
-
-	if (mask & (1 << AT91_PWM3))
-		at91_set_B_periph(AT91_PIN_PD0, 1);	/* enable PWM3 */
-
-	pwm_mask = mask;
-
-	platform_device_register(&at91sam9g45_pwm0_device);
-}
-#else
-void __init at91_add_device_pwm(u32 mask) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
@@ -836,6 +798,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
 	.uart[3]	= &device_uart3,
+	.pwm		= &device_pwm,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index e7a1fe1..7890d55 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -447,55 +447,17 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
  *  PWM
  * --------------------------------------------------------------------*/
 
-#if defined(CONFIG_ATMEL_PWM)
-static u32 pwm_mask;
-
-static struct resource pwm_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_PWMC,
-		.end	= AT91SAM9RL_BASE_PWMC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_PWMC,
-		.end	= AT91SAM9RL_ID_PWMC,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_pwm device_pwm = {
+	.mmio_base	= AT91SAM9RL_BASE_PWMC,
+	.irq		= AT91SAM9RL_ID_PWMC,
+	.pwm_pins	= {
+		{AT91_PIN_PB8, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PB9, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PD5, AT91_PIN_PERIPH_B, 1, 0, 0},
+		{AT91_PIN_PD8, AT91_PIN_PERIPH_B, 1, 0, 0},
 	},
 };
 
-static struct platform_device at91sam9rl_pwm0_device = {
-	.name	= "atmel_pwm",
-	.id	= -1,
-	.dev	= {
-		.platform_data		= &pwm_mask,
-	},
-	.resource	= pwm_resources,
-	.num_resources	= ARRAY_SIZE(pwm_resources),
-};
-
-void __init at91_add_device_pwm(u32 mask)
-{
-	if (mask & (1 << AT91_PWM0))
-		at91_set_B_periph(AT91_PIN_PB8, 1);	/* enable PWM0 */
-
-	if (mask & (1 << AT91_PWM1))
-		at91_set_B_periph(AT91_PIN_PB9, 1);	/* enable PWM1 */
-
-	if (mask & (1 << AT91_PWM2))
-		at91_set_B_periph(AT91_PIN_PD5, 1);	/* enable PWM2 */
-
-	if (mask & (1 << AT91_PWM3))
-		at91_set_B_periph(AT91_PIN_PD8, 1);	/* enable PWM3 */
-
-	pwm_mask = mask;
-
-	platform_device_register(&at91sam9rl_pwm0_device);
-}
-#else
-void __init at91_add_device_pwm(u32 mask) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
@@ -711,6 +673,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
 	.uart[3]	= &device_uart3,
+	.pwm		= &device_pwm,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index f94b27d..a4c29ed 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1303,6 +1303,61 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  PWM
+ * --------------------------------------------------------------------*/
+
+#if defined(CONFIG_ATMEL_PWM)
+static u32 pwm_mask;
+
+static struct resource pwm_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_pwm_device = {
+	.name	= "atmel_pwm",
+	.id	= -1,
+	.dev	= {
+		.platform_data		= &pwm_mask,
+	},
+	.resource	= pwm_resources,
+	.num_resources	= ARRAY_SIZE(pwm_resources),
+};
+
+void __init at91_add_device_pwm(u32 mask)
+{
+	struct at91_dev_table_pwm *info = devices->pwm;
+
+	BUG_ON(!info);
+	init_resource_mem(&pwm_resources[0], info->mmio_base);
+	init_resource_irq(&pwm_resources[1], info->irq);
+
+	if (mask & (1 << AT91_PWM0))
+		at91_config_pins(&info->pwm_pins[0], 1); /* enable PWM0 */
+
+	if (mask & (1 << AT91_PWM1))
+		at91_config_pins(&info->pwm_pins[1], 1); /* enable PWM1 */
+
+	if (mask & (1 << AT91_PWM2))
+		at91_config_pins(&info->pwm_pins[2], 1); /* enable PWM2 */
+
+	if (mask & (1 << AT91_PWM3))
+		at91_config_pins(&info->pwm_pins[3], 1); /* enable PWM3 */
+
+	pwm_mask = mask;
+
+	platform_device_register(&at91_pwm_device);
+}
+#else
+void __init at91_add_device_pwm(u32 mask) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index c535f58..52563be 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -122,6 +122,12 @@ struct at91_dev_table_uart {
 	struct at91_pin_config	dsr_pin;
 };
 
+struct at91_dev_table_pwm {
+	unsigned		mmio_base;
+	int			irq;
+	struct at91_pin_config	pwm_pins[4];
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -135,6 +141,7 @@ struct at91_device_table {
 	struct at91_dev_table_rtt		*rtt[2];
 	struct at91_dev_table_uart		*dbgu;
 	struct at91_dev_table_uart		*uart[6];
+	struct at91_dev_table_pwm		*pwm;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 14/23] at91: Make SSC device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (12 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 13/23] at91: Make PWM " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 15/23] at91: Make AC97 " Ryan Mallon
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual SSC code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91cap9_devices.c    |  142 ++++------------------
 arch/arm/mach-at91/at91rm9200_devices.c  |  199 ++++++------------------------
 arch/arm/mach-at91/at91sam9260_devices.c |   85 ++-----------
 arch/arm/mach-at91/at91sam9261_devices.c |  199 ++++++------------------------
 arch/arm/mach-at91/at91sam9263_devices.c |  146 ++++------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |  146 ++++------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |  142 ++++------------------
 arch/arm/mach-at91/board-afeb-9260v1.c   |    2 +-
 arch/arm/mach-at91/board-sam9260ek.c     |    2 +-
 arch/arm/mach-at91/board-sam9261ek.c     |    2 +-
 arch/arm/mach-at91/board-sam9g20ek.c     |    2 +-
 arch/arm/mach-at91/board-snapper9260.c   |    4 +-
 arch/arm/mach-at91/devices.c             |  167 +++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   14 ++
 14 files changed, 371 insertions(+), 881 deletions(-)

diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index d127f5b..8fb598b 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -444,128 +444,32 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_SSC0,
-		.end	= AT91CAP9_BASE_SSC0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_SSC0,
-		.end	= AT91CAP9_ID_SSC0,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_ssc device_ssc0 = {
+	.mmio_base	= AT91CAP9_BASE_SSC0,
+	.irq		= AT91CAP9_ID_SSC0,
+	.clock_asc	= "ssc0_clk",
+	.clock_name	= "ssc",
+	.tf_pin		= {AT91_PIN_PB0, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB1, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB2, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB3, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB4, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB5, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static struct platform_device at91cap9_ssc0_device = {
-	.name	= "ssc",
-	.id	= 0,
-	.dev	= {
-		.dma_mask		= &ssc0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc0_resources,
-	.num_resources	= ARRAY_SIZE(ssc0_resources),
+static struct __initdata at91_dev_table_ssc device_ssc1 = {
+	.mmio_base	= AT91CAP9_BASE_SSC1,
+	.irq		= AT91CAP9_ID_SSC1,
+	.clock_asc	= "ssc0_clk",
+	.clock_name	= "ssc",
+	.tf_pin		= {AT91_PIN_PB6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB7,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB8,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB9,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB10, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB11, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static inline void configure_ssc0_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB0, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB1, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB2, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB3, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB4, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB5, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_SSC1,
-		.end	= AT91CAP9_BASE_SSC1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_SSC1,
-		.end	= AT91CAP9_ID_SSC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91cap9_ssc1_device = {
-	.name	= "ssc",
-	.id	= 1,
-	.dev	= {
-		.dma_mask		= &ssc1_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc1_resources,
-	.num_resources	= ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB6, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB7, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB8, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB9, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB10, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB11, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	/*
-	 * NOTE: caller is responsible for passing information matching
-	 * "pins" to whatever will be using each particular controller.
-	 */
-	switch (id) {
-	case AT91CAP9_ID_SSC0:
-		pdev = &at91cap9_ssc0_device;
-		configure_ssc0_pins(pins);
-		at91_clock_associate("ssc0_clk", &pdev->dev, "ssc");
-		break;
-	case AT91CAP9_ID_SSC1:
-		pdev = &at91cap9_ssc1_device;
-		configure_ssc1_pins(pins);
-		at91_clock_associate("ssc1_clk", &pdev->dev, "ssc");
-		break;
-	default:
-		return;
-	}
-
-	platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
@@ -641,6 +545,8 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
 	.pwm		= &device_pwm,
+	.ssc[0]		= &device_ssc0,
+	.ssc[1]		= &device_ssc1,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 8f5ffb5..a6d91f2 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -299,175 +299,45 @@ static void __init at91_add_device_rtc(void) {}
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_SSC0,
-		.end	= AT91RM9200_BASE_SSC0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_SSC0,
-		.end	= AT91RM9200_ID_SSC0,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_ssc device_ssc0 = {
+	.mmio_base	= AT91RM9200_BASE_SSC0,
+	.irq		= AT91RM9200_ID_SSC0,
+	.clock_asc	= "ssc0_clk",
+	.clock_name	= "ssc",
+	.tf_pin		= {AT91_PIN_PB0, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB1, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB2, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB3, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB4, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB5, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static struct platform_device at91rm9200_ssc0_device = {
-	.name	= "ssc",
-	.id	= 0,
-	.dev	= {
-		.dma_mask		= &ssc0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc0_resources,
-	.num_resources	= ARRAY_SIZE(ssc0_resources),
+static struct __initdata at91_dev_table_ssc device_ssc1 = {
+	.mmio_base	= AT91RM9200_BASE_SSC1,
+	.irq		= AT91RM9200_ID_SSC1,
+	.clock_asc	= "ssc2_clk",
+	.clock_name	= "ssc",
+	.tf_pin		= {AT91_PIN_PB6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB7,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB8,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB9,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB10, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB11, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static inline void configure_ssc0_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB0, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB1, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB2, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB3, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB4, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB5, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_SSC1,
-		.end	= AT91RM9200_BASE_SSC1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_SSC1,
-		.end	= AT91RM9200_ID_SSC1,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_ssc device_ssc2 = {
+	.mmio_base	= AT91RM9200_BASE_SSC2,
+	.irq		= AT91RM9200_ID_SSC2,
+	.clock_asc	= "ssc2_clk",
+	.clock_name	= "ssc",
+	.tf_pin		= {AT91_PIN_PB12, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB13, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB14, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB15, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB16, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB17, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static struct platform_device at91rm9200_ssc1_device = {
-	.name	= "ssc",
-	.id	= 1,
-	.dev	= {
-		.dma_mask		= &ssc1_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc1_resources,
-	.num_resources	= ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB6, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB7, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB8, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB9, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB10, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB11, 1);
-}
-
-static u64 ssc2_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc2_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_SSC2,
-		.end	= AT91RM9200_BASE_SSC2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_SSC2,
-		.end	= AT91RM9200_ID_SSC2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91rm9200_ssc2_device = {
-	.name	= "ssc",
-	.id	= 2,
-	.dev	= {
-		.dma_mask		= &ssc2_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc2_resources,
-	.num_resources	= ARRAY_SIZE(ssc2_resources),
-};
-
-static inline void configure_ssc2_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB12, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB13, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB14, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB15, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB16, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB17, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	/*
-	 * NOTE: caller is responsible for passing information matching
-	 * "pins" to whatever will be using each particular controller.
-	 */
-	switch (id) {
-	case AT91RM9200_ID_SSC0:
-		pdev = &at91rm9200_ssc0_device;
-		configure_ssc0_pins(pins);
-		at91_clock_associate("ssc0_clk", &pdev->dev, "ssc");
-		break;
-	case AT91RM9200_ID_SSC1:
-		pdev = &at91rm9200_ssc1_device;
-		configure_ssc1_pins(pins);
-		at91_clock_associate("ssc1_clk", &pdev->dev, "ssc");
-		break;
-	case AT91RM9200_ID_SSC2:
-		pdev = &at91rm9200_ssc2_device;
-		configure_ssc2_pins(pins);
-		at91_clock_associate("ssc2_clk", &pdev->dev, "ssc");
-		break;
-	default:
-		return;
-	}
-
-	platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
@@ -565,6 +435,9 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
 	.uart[3]	= &device_uart3,
+	.ssc[0]		= &device_ssc0,
+	.ssc[1]		= &device_ssc1,
+	.ssc[2]		= &device_ssc2,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 2a99cd8..e459ad6 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -200,81 +200,19 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_SSC,
-		.end	= AT91SAM9260_BASE_SSC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_SSC,
-		.end	= AT91SAM9260_ID_SSC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_ssc_device = {
-	.name	= "ssc",
-	.id	= 0,
-	.dev	= {
-		.dma_mask		= &ssc_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc_resources,
-	.num_resources	= ARRAY_SIZE(ssc_resources),
+static struct __initdata at91_dev_table_ssc device_ssc = {
+	.mmio_base	= AT91SAM9260_BASE_SSC,
+	.irq		= AT91SAM9260_ID_SSC,
+	.clock_asc	= "ssc_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PB17, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB16, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB18, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB19, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB20, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB21, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static inline void configure_ssc_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB17, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB16, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB18, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB19, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB20, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB21, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	/*
-	 * NOTE: caller is responsible for passing information matching
-	 * "pins" to whatever will be using each particular controller.
-	 */
-	switch (id) {
-	case AT91SAM9260_ID_SSC:
-		pdev = &at91sam9260_ssc_device;
-		configure_ssc_pins(pins);
-		at91_clock_associate("ssc_clk", &pdev->dev, "pclk");
-		break;
-	default:
-		return;
-	}
-
-	platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
@@ -512,6 +450,7 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.uart[3]	= &device_uart3,
 	.uart[4]	= &device_uart4,
 	.uart[5]	= &device_uart5,
+	.ssc[0]		= &device_ssc,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index c355c23..6efa1e8 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -252,175 +252,45 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_SSC0,
-		.end	= AT91SAM9261_BASE_SSC0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_SSC0,
-		.end	= AT91SAM9261_ID_SSC0,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_ssc device_ssc0 = {
+	.mmio_base	= AT91SAM9261_BASE_SSC0,
+	.irq		= AT91SAM9261_ID_SSC0,
+	.clock_asc	= "ssc0_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PB21, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB22, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB23, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB24, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB25, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB26, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static struct platform_device at91sam9261_ssc0_device = {
-	.name	= "ssc",
-	.id	= 0,
-	.dev	= {
-		.dma_mask		= &ssc0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc0_resources,
-	.num_resources	= ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB21, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB22, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB23, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB24, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB25, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB26, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_SSC1,
-		.end	= AT91SAM9261_BASE_SSC1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_SSC1,
-		.end	= AT91SAM9261_ID_SSC1,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_ssc device_ssc1 = {
+	.mmio_base	= AT91SAM9261_BASE_SSC1,
+	.irq		= AT91SAM9261_ID_SSC1,
+	.clock_asc	= "ssc1_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PA17, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PA18, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PA19, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PA20, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PA21, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PA22, AT91_PIN_PERIPH_B, 1, 0, 0},
 };
 
-static struct platform_device at91sam9261_ssc1_device = {
-	.name	= "ssc",
-	.id	= 1,
-	.dev	= {
-		.dma_mask		= &ssc1_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc1_resources,
-	.num_resources	= ARRAY_SIZE(ssc1_resources),
+static struct __initdata at91_dev_table_ssc device_ssc2 = {
+	.mmio_base	= AT91SAM9261_BASE_SSC2,
+	.irq		= AT91SAM9261_ID_SSC2,
+	.clock_asc	= "ssc2_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PC25, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PC26, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PC27, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PC28, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PC29, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PC30, AT91_PIN_PERIPH_B, 1, 0, 0},
 };
 
-static inline void configure_ssc1_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_B_periph(AT91_PIN_PA17, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_B_periph(AT91_PIN_PA18, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_B_periph(AT91_PIN_PA19, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_B_periph(AT91_PIN_PA20, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_B_periph(AT91_PIN_PA21, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_B_periph(AT91_PIN_PA22, 1);
-}
-
-static u64 ssc2_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_SSC2,
-		.end	= AT91SAM9261_BASE_SSC2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_SSC2,
-		.end	= AT91SAM9261_ID_SSC2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9261_ssc2_device = {
-	.name	= "ssc",
-	.id	= 2,
-	.dev	= {
-		.dma_mask		= &ssc2_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc2_resources,
-	.num_resources	= ARRAY_SIZE(ssc2_resources),
-};
-
-static inline void configure_ssc2_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_B_periph(AT91_PIN_PC25, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_B_periph(AT91_PIN_PC26, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_B_periph(AT91_PIN_PC27, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_B_periph(AT91_PIN_PC28, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_B_periph(AT91_PIN_PC29, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_B_periph(AT91_PIN_PC30, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	/*
-	 * NOTE: caller is responsible for passing information matching
-	 * "pins" to whatever will be using each particular controller.
-	 */
-	switch (id) {
-	case AT91SAM9261_ID_SSC0:
-		pdev = &at91sam9261_ssc0_device;
-		configure_ssc0_pins(pins);
-		at91_clock_associate("ssc0_clk", &pdev->dev, "pclk");
-		break;
-	case AT91SAM9261_ID_SSC1:
-		pdev = &at91sam9261_ssc1_device;
-		configure_ssc1_pins(pins);
-		at91_clock_associate("ssc1_clk", &pdev->dev, "pclk");
-		break;
-	case AT91SAM9261_ID_SSC2:
-		pdev = &at91sam9261_ssc2_device;
-		configure_ssc2_pins(pins);
-		at91_clock_associate("ssc2_clk", &pdev->dev, "pclk");
-		break;
-	default:
-		return;
-	}
-
-	platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
@@ -494,6 +364,9 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.uart[0]	= &device_uart0,
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
+	.ssc[0]		= &device_ssc0,
+	.ssc[1]		= &device_ssc1,
+	.ssc[2]		= &device_ssc2,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 1ffd044..3ff223c 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -551,128 +551,32 @@ static struct __initdata at91_dev_table_pwm device_pwm = {
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_SSC0,
-		.end	= AT91SAM9263_BASE_SSC0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_SSC0,
-		.end	= AT91SAM9263_ID_SSC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9263_ssc0_device = {
-	.name	= "ssc",
-	.id	= 0,
-	.dev	= {
-		.dma_mask		= &ssc0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc0_resources,
-	.num_resources	= ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_B_periph(AT91_PIN_PB0, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_B_periph(AT91_PIN_PB1, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_B_periph(AT91_PIN_PB2, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_B_periph(AT91_PIN_PB3, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_B_periph(AT91_PIN_PB4, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_B_periph(AT91_PIN_PB5, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_SSC1,
-		.end	= AT91SAM9263_BASE_SSC1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_SSC1,
-		.end	= AT91SAM9263_ID_SSC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9263_ssc1_device = {
-	.name	= "ssc",
-	.id	= 1,
-	.dev	= {
-		.dma_mask		= &ssc1_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc1_resources,
-	.num_resources	= ARRAY_SIZE(ssc1_resources),
+static struct __initdata at91_dev_table_ssc device_ssc0 = {
+	.mmio_base	= AT91SAM9263_BASE_SSC0,
+	.irq		= AT91SAM9263_ID_SSC0,
+	.clock_asc	= "ssc0_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PB0, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB1, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB2, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB3, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB4, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB5, AT91_PIN_PERIPH_B, 1, 0, 0},
+};
+
+static struct __initdata at91_dev_table_ssc device_ssc1 = {
+	.mmio_base	= AT91SAM9263_BASE_SSC1,
+	.irq		= AT91SAM9263_ID_SSC1,
+	.clock_asc	= "ssc1_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PB6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PB7,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PB8,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PB9,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PB10, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PB11, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static inline void configure_ssc1_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PB6, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PB7, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PB8, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PB9, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PB10, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PB11, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	/*
-	 * NOTE: caller is responsible for passing information matching
-	 * "pins" to whatever will be using each particular controller.
-	 */
-	switch (id) {
-	case AT91SAM9263_ID_SSC0:
-		pdev = &at91sam9263_ssc0_device;
-		configure_ssc0_pins(pins);
-		at91_clock_associate("ssc0_clk", &pdev->dev, "pclk");
-		break;
-	case AT91SAM9263_ID_SSC1:
-		pdev = &at91sam9263_ssc1_device;
-		configure_ssc1_pins(pins);
-		at91_clock_associate("ssc1_clk", &pdev->dev, "pclk");
-		break;
-	default:
-		return;
-	}
-
-	platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
@@ -750,6 +654,8 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.uart[1]	= &device_uart1,
 	.uart[2]	= &device_uart2,
 	.pwm		= &device_pwm,
+	.ssc[0]		= &device_ssc0,
+	.ssc[1]		= &device_ssc1,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 0f11c56..fcfb1ca 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -584,128 +584,32 @@ static struct __initdata at91_dev_table_pwm device_pwm = {
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_SSC0,
-		.end	= AT91SAM9G45_BASE_SSC0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_SSC0,
-		.end	= AT91SAM9G45_ID_SSC0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_ssc0_device = {
-	.name	= "ssc",
-	.id	= 0,
-	.dev	= {
-		.dma_mask		= &ssc0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc0_resources,
-	.num_resources	= ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PD1, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PD0, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PD2, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PD3, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PD4, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PD5, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_SSC1,
-		.end	= AT91SAM9G45_BASE_SSC1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_SSC1,
-		.end	= AT91SAM9G45_ID_SSC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_ssc1_device = {
-	.name	= "ssc",
-	.id	= 1,
-	.dev	= {
-		.dma_mask		= &ssc1_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc1_resources,
-	.num_resources	= ARRAY_SIZE(ssc1_resources),
+static struct __initdata at91_dev_table_ssc device_ssc0 = {
+	.mmio_base	= AT91SAM9G45_BASE_SSC0,
+	.irq		= AT91SAM9G45_ID_SSC0,
+	.clock_asc	= "ssc0_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PD1, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PD0, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PD2, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PD3, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PD4, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PD5, AT91_PIN_PERIPH_A, 1, 0, 0},
+};
+
+static struct __initdata at91_dev_table_ssc device_ssc1 = {
+	.mmio_base	= AT91SAM9G45_BASE_SSC1,
+	.irq		= AT91SAM9G45_ID_SSC1,
+	.clock_asc	= "ssc1_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PD14, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PD12, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PD10, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PD11, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PD13, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PD15, AT91_PIN_PERIPH_A, 1, 0, 0},
 };
 
-static inline void configure_ssc1_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PD14, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PD12, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PD10, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PD11, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_A_periph(AT91_PIN_PD13, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_A_periph(AT91_PIN_PD15, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	/*
-	 * NOTE: caller is responsible for passing information matching
-	 * "pins" to whatever will be using each particular controller.
-	 */
-	switch (id) {
-	case AT91SAM9G45_ID_SSC0:
-		pdev = &at91sam9g45_ssc0_device;
-		configure_ssc0_pins(pins);
-		at91_clock_associate("ssc0_clk", &pdev->dev, "pclk");
-		break;
-	case AT91SAM9G45_ID_SSC1:
-		pdev = &at91sam9g45_ssc1_device;
-		configure_ssc1_pins(pins);
-		at91_clock_associate("ssc1_clk", &pdev->dev, "pclk");
-		break;
-	default:
-		return;
-	}
-
-	platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
@@ -799,6 +703,8 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.uart[2]	= &device_uart2,
 	.uart[3]	= &device_uart3,
 	.pwm		= &device_pwm,
+	.ssc[0]		= &device_ssc0,
+	.ssc[1]		= &device_ssc1,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 7890d55..606d790 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -462,128 +462,32 @@ static struct __initdata at91_dev_table_pwm device_pwm = {
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_SSC0,
-		.end	= AT91SAM9RL_BASE_SSC0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_SSC0,
-		.end	= AT91SAM9RL_ID_SSC0,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_dev_table_ssc device_ssc0 = {
+	.mmio_base	= AT91SAM9RL_BASE_SSC0,
+	.irq		= AT91SAM9RL_ID_SSC0,
+	.clock_asc	= "ssc0_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PC0,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PC1,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PA15, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PA16, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PA10, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PA22, AT91_PIN_PERIPH_B, 1, 0, 0},
 };
 
-static struct platform_device at91sam9rl_ssc0_device = {
-	.name	= "ssc",
-	.id	= 0,
-	.dev	= {
-		.dma_mask		= &ssc0_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc0_resources,
-	.num_resources	= ARRAY_SIZE(ssc0_resources),
+static struct __initdata at91_dev_table_ssc device_ssc1 = {
+	.mmio_base	= AT91SAM9RL_BASE_SSC1,
+	.irq		= AT91SAM9RL_ID_SSC1,
+	.clock_asc	= "ssc1_clk",
+	.clock_name	= "pclk",
+	.tf_pin		= {AT91_PIN_PA29, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.tk_pin		= {AT91_PIN_PA30, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.td_pin		= {AT91_PIN_PA13, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rd_pin		= {AT91_PIN_PA14, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rk_pin		= {AT91_PIN_PA9,  AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rf_pin		= {AT91_PIN_PA8,  AT91_PIN_PERIPH_B, 1, 0, 0},
 };
 
-static inline void configure_ssc0_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_A_periph(AT91_PIN_PC0, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_A_periph(AT91_PIN_PC1, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_A_periph(AT91_PIN_PA15, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_A_periph(AT91_PIN_PA16, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_B_periph(AT91_PIN_PA10, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_B_periph(AT91_PIN_PA22, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_SSC1,
-		.end	= AT91SAM9RL_BASE_SSC1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_SSC1,
-		.end	= AT91SAM9RL_ID_SSC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9rl_ssc1_device = {
-	.name	= "ssc",
-	.id	= 1,
-	.dev	= {
-		.dma_mask		= &ssc1_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.resource	= ssc1_resources,
-	.num_resources	= ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-	if (pins & ATMEL_SSC_TF)
-		at91_set_B_periph(AT91_PIN_PA29, 1);
-	if (pins & ATMEL_SSC_TK)
-		at91_set_B_periph(AT91_PIN_PA30, 1);
-	if (pins & ATMEL_SSC_TD)
-		at91_set_B_periph(AT91_PIN_PA13, 1);
-	if (pins & ATMEL_SSC_RD)
-		at91_set_B_periph(AT91_PIN_PA14, 1);
-	if (pins & ATMEL_SSC_RK)
-		at91_set_B_periph(AT91_PIN_PA9, 1);
-	if (pins & ATMEL_SSC_RF)
-		at91_set_B_periph(AT91_PIN_PA8, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	/*
-	 * NOTE: caller is responsible for passing information matching
-	 * "pins" to whatever will be using each particular controller.
-	 */
-	switch (id) {
-	case AT91SAM9RL_ID_SSC0:
-		pdev = &at91sam9rl_ssc0_device;
-		configure_ssc0_pins(pins);
-		at91_clock_associate("ssc0_clk", &pdev->dev, "pclk");
-		break;
-	case AT91SAM9RL_ID_SSC1:
-		pdev = &at91sam9rl_ssc1_device;
-		configure_ssc1_pins(pins);
-		at91_clock_associate("ssc1_clk", &pdev->dev, "pclk");
-		break;
-	default:
-		return;
-	}
-
-	platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
@@ -674,6 +578,8 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.uart[2]	= &device_uart2,
 	.uart[3]	= &device_uart3,
 	.pwm		= &device_pwm,
+	.ssc[0]		= &device_ssc0,
+	.ssc[1]		= &device_ssc1,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 4c382c3..7b9e7f0 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -211,7 +211,7 @@ static void __init afeb9260_board_init(void)
 	at91_add_device_i2c(0, afeb9260_i2c_devices,
 			ARRAY_SIZE(afeb9260_i2c_devices));
 	/* Audio */
-	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+	at91_add_device_ssc(0, ATMEL_SSC_TX);
 	/* IDE */
 	at91_add_device_cf(&afeb9260_cf_data);
 }
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index e9926e5..88f3238 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -347,7 +347,7 @@ static void __init ek_board_init(void)
 	at91_add_device_i2c(0, ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* SSC (to AT73C213) */
 	at73c213_set_clk(&at73c213_data);
-	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+	at91_add_device_ssc(0, ATMEL_SSC_TX);
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 	/* Push Buttons */
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 3e848ba..1139b69 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -604,7 +604,7 @@ static void __init ek_board_init(void)
 	ek_add_device_ts();
 	/* SSC (to AT73C213) */
 	at73c213_set_clk(&at73c213_data);
-	at91_add_device_ssc(AT91SAM9261_ID_SSC1, ATMEL_SSC_TX);
+	at91_add_device_ssc(1, ATMEL_SSC_TX);
 #else
 	/* MMC */
 	at91_add_device_mmc(0, &ek_mmc_data);
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index d228b5f..edcb674 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -401,7 +401,7 @@ static void __init ek_board_init(void)
 	/* PCK0 provides MCLK to the WM8731 */
 	at91_set_B_periph(AT91_PIN_PC1, 0);
 	/* SSC (for WM8731) */
-	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+	at91_add_device_ssc(0, ATMEL_SSC_TX);
 }
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 4521b66..bc4e710 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -172,8 +172,8 @@ static void __init snapper9260_board_init(void)
 	at91_add_device_usbh_ohci(&snapper9260_usbh_data);
 	at91_add_device_udc(&snapper9260_udc_data);
 	at91_add_device_eth(&snapper9260_macb_data);
-	at91_add_device_ssc(AT91SAM9260_ID_SSC, (ATMEL_SSC_TF | ATMEL_SSC_TK |
-						 ATMEL_SSC_TD | ATMEL_SSC_RD));
+	at91_add_device_ssc(0, (ATMEL_SSC_TF | ATMEL_SSC_TK |
+				ATMEL_SSC_TD | ATMEL_SSC_RD));
 	snapper9260_add_device_nand();
 }
 
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index a4c29ed..2cab70b 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1358,6 +1358,173 @@ void __init at91_add_device_pwm(u32 mask)
 void __init at91_add_device_pwm(u32 mask) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  SSC -- Synchronous Serial Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
+static u64 ssc0_dmamask = DMA_BIT_MASK(32);
+
+static struct resource ssc0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_ssc0_device = {
+	.name	= "ssc",
+	.id	= 0,
+	.dev	= {
+		.dma_mask		= &ssc0_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= ssc0_resources,
+	.num_resources	= ARRAY_SIZE(ssc0_resources),
+};
+
+static u64 ssc1_dmamask = DMA_BIT_MASK(32);
+
+static struct resource ssc1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_ssc1_device = {
+	.name	= "ssc",
+	.id	= 1,
+	.dev	= {
+		.dma_mask		= &ssc1_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= ssc1_resources,
+	.num_resources	= ARRAY_SIZE(ssc1_resources),
+};
+
+static u64 ssc2_dmamask = DMA_BIT_MASK(32);
+
+static struct resource ssc2_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_ssc2_device = {
+	.name	= "ssc",
+	.id	= 2,
+	.dev	= {
+		.dma_mask		= &ssc2_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= ssc2_resources,
+	.num_resources	= ARRAY_SIZE(ssc2_resources),
+};
+
+static u64 ssc3_dmamask = DMA_BIT_MASK(32);
+
+static struct resource ssc3_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_ssc3_device = {
+	.name	= "ssc",
+	.id	= 3,
+	.dev	= {
+		.dma_mask		= &ssc3_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.resource	= ssc3_resources,
+	.num_resources	= ARRAY_SIZE(ssc3_resources),
+};
+
+static inline void configure_ssc(struct at91_dev_table_ssc *ssc,
+				 struct resource *res, struct device *dev,
+				 unsigned pins)
+{
+	init_resource_mem(&res[0], ssc->mmio_base);
+	init_resource_irq(&res[1], ssc->irq);
+	if (ssc->clock_asc)
+		at91_clock_associate(ssc->clock_asc, dev, "pclk");
+
+	if (pins & ATMEL_SSC_TF)
+		at91_config_pins(&ssc->tf_pin, 1);
+	if (pins & ATMEL_SSC_TK)
+		at91_config_pins(&ssc->tk_pin, 1);
+	if (pins & ATMEL_SSC_TD)
+		at91_config_pins(&ssc->td_pin, 1);
+	if (pins & ATMEL_SSC_RD)
+		at91_config_pins(&ssc->rd_pin, 1);
+	if (pins & ATMEL_SSC_RK)
+		at91_config_pins(&ssc->rk_pin, 1);
+	if (pins & ATMEL_SSC_RF)
+		at91_config_pins(&ssc->rf_pin, 1);
+}
+
+/*
+ * SSC controllers are accessed through library code, instead of any
+ * kind of all-singing/all-dancing driver.  For example one could be
+ * used by a particular I2S audio codec's driver, while another one
+ * on the same system might be used by a custom data capture driver.
+ */
+void __init at91_add_device_ssc(unsigned id, unsigned pins)
+{
+	struct at91_dev_table_ssc *info;
+	struct platform_device *pdev;
+	struct resource *res;
+
+	BUG_ON(id < 0 || id >= ARRAY_SIZE(devices->ssc) || !devices->ssc[id]);
+	info = devices->ssc[id];
+
+	/*
+	 * NOTE: caller is responsible for passing information matching
+	 * "pins" to whatever will be using each particular controller.
+	 */
+	switch (id) {
+	case 0:
+		pdev = &at91_ssc0_device;
+		res  = ssc0_resources;
+		break;
+	case 1:
+		pdev = &at91_ssc1_device;
+		res  = ssc1_resources;
+		break;
+	case 2:
+		pdev = &at91_ssc2_device;
+		res  = ssc2_resources;
+		break;
+	case 3:
+		pdev = &at91_ssc3_device;
+		res  = ssc3_resources;
+		break;
+	default:
+		return;
+	}
+
+	configure_ssc(info, res, &pdev->dev, pins);
+	platform_device_register(pdev);
+}
+#else
+void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 52563be..177fc3d 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -128,6 +128,19 @@ struct at91_dev_table_pwm {
 	struct at91_pin_config	pwm_pins[4];
 };
 
+struct at91_dev_table_ssc {
+	unsigned		mmio_base;
+	int			irq;
+	const char		*clock_asc;
+	const char		*clock_name;
+	struct at91_pin_config	tf_pin;
+	struct at91_pin_config	tk_pin;
+	struct at91_pin_config	td_pin;
+	struct at91_pin_config	rf_pin;
+	struct at91_pin_config	rd_pin;
+	struct at91_pin_config	rk_pin;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -142,6 +155,7 @@ struct at91_device_table {
 	struct at91_dev_table_uart		*dbgu;
 	struct at91_dev_table_uart		*uart[6];
 	struct at91_dev_table_pwm		*pwm;
+	struct at91_dev_table_ssc		*ssc[4];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 15/23] at91: Make AC97 device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (13 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 14/23] at91: Make SSC " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 16/23] at91: Make LCD controller " Ryan Mallon
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual AC97 code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91cap9_devices.c    |   57 +++++-------------------------
 arch/arm/mach-at91/at91sam9263_devices.c |   56 +++++------------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   57 +++++-------------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   57 +++++-------------------------
 arch/arm/mach-at91/devices.c             |   54 ++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |    7 ++++
 6 files changed, 97 insertions(+), 191 deletions(-)

diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 8fb598b..ae8e118 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -317,57 +317,17 @@ static struct __initdata at91_dev_table_pwm device_pwm = {
  *  AC97
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
-static u64 ac97_dmamask = DMA_BIT_MASK(32);
-static struct ac97c_platform_data ac97_data;
-
-static struct resource ac97_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_AC97C,
-		.end	= AT91CAP9_BASE_AC97C + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_AC97C,
-		.end	= AT91CAP9_ID_AC97C,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91cap9_ac97_device = {
-	.name		= "atmel_ac97c",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &ac97_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &ac97_data,
+static struct __initdata at91_dev_table_ac97 device_ac97 = {
+	.mmio_base	= AT91CAP9_BASE_AC97C,
+	.irq		= AT91CAP9_ID_AC97C,
+	.pins		= {
+		{AT91_PIN_PA6, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97FS */
+		{AT91_PIN_PA7, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97CK */
+		{AT91_PIN_PA8, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97TX */
+		{AT91_PIN_PA9, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97RX */
 	},
-	.resource	= ac97_resources,
-	.num_resources	= ARRAY_SIZE(ac97_resources),
 };
 
-void __init at91_add_device_ac97(struct ac97c_platform_data *data)
-{
-	if (!data)
-		return;
-
-	at91_set_A_periph(AT91_PIN_PA6, 0);	/* AC97FS */
-	at91_set_A_periph(AT91_PIN_PA7, 0);	/* AC97CK */
-	at91_set_A_periph(AT91_PIN_PA8, 0);	/* AC97TX */
-	at91_set_A_periph(AT91_PIN_PA9, 0);	/* AC97RX */
-
-	/* reset */
-	if (data->reset_pin)
-		at91_set_gpio_output(data->reset_pin, 0);
-
-	ac97_data = *data;
-	platform_device_register(&at91cap9_ac97_device);
-}
-#else
-void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  LCD Controller
  * -------------------------------------------------------------------- */
@@ -547,6 +507,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.pwm		= &device_pwm,
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
+	.ac97		= &device_ac97,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 3ff223c..6155a9f 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -299,56 +299,17 @@ static struct __initdata at91_dev_table_spi device_spi1 = {
  *  AC97
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
-static u64 ac97_dmamask = DMA_BIT_MASK(32);
-static struct ac97c_platform_data ac97_data;
-
-static struct resource ac97_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_AC97C,
-		.end	= AT91SAM9263_BASE_AC97C + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_AC97C,
-		.end	= AT91SAM9263_ID_AC97C,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9263_ac97_device = {
-	.name		= "atmel_ac97c",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &ac97_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &ac97_data,
+static struct __initdata at91_dev_table_ac97 device_ac97 = {
+	.mmio_base	= AT91SAM9263_BASE_AC97C,
+	.irq		= AT91SAM9263_ID_AC97C,
+	.pins		= {
+		{AT91_PIN_PB0, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97FS */
+		{AT91_PIN_PB1, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97CK */
+		{AT91_PIN_PB2, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97TX */
+		{AT91_PIN_PB3, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97RX */
 	},
-	.resource	= ac97_resources,
-	.num_resources	= ARRAY_SIZE(ac97_resources),
 };
 
-void __init at91_add_device_ac97(struct ac97c_platform_data *data)
-{
-	if (!data)
-		return;
-
-	at91_set_A_periph(AT91_PIN_PB0, 0);	/* AC97FS */
-	at91_set_A_periph(AT91_PIN_PB1, 0);	/* AC97CK */
-	at91_set_A_periph(AT91_PIN_PB2, 0);	/* AC97TX */
-	at91_set_A_periph(AT91_PIN_PB3, 0);	/* AC97RX */
-
-	/* reset */
-	if (data->reset_pin)
-		at91_set_gpio_output(data->reset_pin, 0);
-
-	ac97_data = *data;
-	platform_device_register(&at91sam9263_ac97_device);
-}
-#else
-void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  CAN Controller
  * -------------------------------------------------------------------- */
@@ -656,6 +617,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.pwm		= &device_pwm,
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
+	.ac97		= &device_ac97,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index fcfb1ca..3f71e45 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -331,57 +331,17 @@ static struct __initdata at91_dev_table_spi device_spi1 = {
  *  AC97
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
-static u64 ac97_dmamask = DMA_BIT_MASK(32);
-static struct ac97c_platform_data ac97_data;
-
-static struct resource ac97_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_AC97C,
-		.end	= AT91SAM9G45_BASE_AC97C + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_AC97C,
-		.end	= AT91SAM9G45_ID_AC97C,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9g45_ac97_device = {
-	.name		= "atmel_ac97c",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &ac97_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &ac97_data,
+static struct __initdata at91_dev_table_ac97 device_ac97 = {
+	.mmio_base	= AT91SAM9G45_BASE_AC97C,
+	.irq		= AT91SAM9G45_ID_AC97C,
+	.pins		= {
+		{AT91_PIN_PD8, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97FS */
+		{AT91_PIN_PD9, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97CK */
+		{AT91_PIN_PD7, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97TX */
+		{AT91_PIN_PD6, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97RX */
 	},
-	.resource	= ac97_resources,
-	.num_resources	= ARRAY_SIZE(ac97_resources),
 };
 
-void __init at91_add_device_ac97(struct ac97c_platform_data *data)
-{
-	if (!data)
-		return;
-
-	at91_set_A_periph(AT91_PIN_PD8, 0);	/* AC97FS */
-	at91_set_A_periph(AT91_PIN_PD9, 0);	/* AC97CK */
-	at91_set_A_periph(AT91_PIN_PD7, 0);	/* AC97TX */
-	at91_set_A_periph(AT91_PIN_PD6, 0);	/* AC97RX */
-
-	/* reset */
-	if (data->reset_pin)
-		at91_set_gpio_output(data->reset_pin, 0);
-
-	ac97_data = *data;
-	platform_device_register(&at91sam9g45_ac97_device);
-}
-#else
-void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  LCD Controller
  * -------------------------------------------------------------------- */
@@ -705,6 +665,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.pwm		= &device_pwm,
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
+	.ac97		= &device_ac97,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 606d790..3b6010b 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -227,57 +227,17 @@ static struct __initdata at91_dev_table_spi device_spi = {
  *  AC97
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
-static u64 ac97_dmamask = DMA_BIT_MASK(32);
-static struct ac97c_platform_data ac97_data;
-
-static struct resource ac97_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_AC97C,
-		.end	= AT91SAM9RL_BASE_AC97C + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_AC97C,
-		.end	= AT91SAM9RL_ID_AC97C,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9rl_ac97_device = {
-	.name		= "atmel_ac97c",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &ac97_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &ac97_data,
+static struct __initdata at91_dev_table_ac97 device_ac97 = {
+	.mmio_base	= AT91SAM9RL_BASE_AC97C,
+	.irq		= AT91SAM9RL_ID_AC97C,
+	.pins		= {
+		{AT91_PIN_PD1, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97FS */
+		{AT91_PIN_PD2, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97CK */
+		{AT91_PIN_PD3, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97TX */
+		{AT91_PIN_PD4, AT91_PIN_PERIPH_A, 0, 0, 0},	/* AC97RX */
 	},
-	.resource	= ac97_resources,
-	.num_resources	= ARRAY_SIZE(ac97_resources),
 };
 
-void __init at91_add_device_ac97(struct ac97c_platform_data *data)
-{
-	if (!data)
-		return;
-
-	at91_set_A_periph(AT91_PIN_PD1, 0);	/* AC97FS */
-	at91_set_A_periph(AT91_PIN_PD2, 0);	/* AC97CK */
-	at91_set_A_periph(AT91_PIN_PD3, 0);	/* AC97TX */
-	at91_set_A_periph(AT91_PIN_PD4, 0);	/* AC97RX */
-
-	/* reset */
-	if (data->reset_pin)
-		at91_set_gpio_output(data->reset_pin, 0);
-
-	ac97_data = *data;
-	platform_device_register(&at91sam9rl_ac97_device);
-}
-#else
-void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  LCD Controller
  * -------------------------------------------------------------------- */
@@ -580,6 +540,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.pwm		= &device_pwm,
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
+	.ac97		= &device_ac97,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 2cab70b..86f0640 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1525,6 +1525,60 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins)
 void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  AC97
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
+static u64 ac97_dmamask = DMA_BIT_MASK(32);
+static struct ac97c_platform_data ac97_data;
+
+static struct resource ac97_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_ac97_device = {
+	.name		= "atmel_ac97c",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &ac97_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &ac97_data,
+	},
+	.resource	= ac97_resources,
+	.num_resources	= ARRAY_SIZE(ac97_resources),
+};
+
+void __init at91_add_device_ac97(struct ac97c_platform_data *data)
+{
+	struct at91_dev_table_ac97 *info = devices->ac97;
+
+	BUG_ON(!info);
+	init_resource_mem(&ac97_resources[0], info->mmio_base);
+	init_resource_irq(&ac97_resources[0], info->irq);
+
+	if (!data)
+		return;
+
+	at91_config_pins(info->pins, ARRAY_SIZE(info->pins));
+
+	/* reset */
+	if (data->reset_pin)
+		at91_set_gpio_output(data->reset_pin, 0);
+
+	ac97_data = *data;
+	platform_device_register(&at91sam9g45_ac97_device);
+}
+#else
+void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 177fc3d..3d6ca83 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -141,6 +141,12 @@ struct at91_dev_table_ssc {
 	struct at91_pin_config	rk_pin;
 };
 
+struct at91_dev_table_ac97 {
+	unsigned		mmio_base;
+	int			irq;
+	struct at91_pin_config	pins[4];	/* FS, CK, TX, RX */
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -156,6 +162,7 @@ struct at91_device_table {
 	struct at91_dev_table_uart		*uart[6];
 	struct at91_dev_table_pwm		*pwm;
 	struct at91_dev_table_ssc		*ssc[4];
+	struct at91_dev_table_ac97		*ac97;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 16/23] at91: Make LCD controller device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (14 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 15/23] at91: Make AC97 " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 17/23] at91: Make touchscreen " Ryan Mallon
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual LCD controller device code for each at91 variant with a
single implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91cap9_devices.c    |   96 ++++++++--------------
 arch/arm/mach-at91/at91sam9261_devices.c |  133 ++++++++++--------------------
 arch/arm/mach-at91/at91sam9263_devices.c |   94 +++++++--------------
 arch/arm/mach-at91/at91sam9g45_devices.c |  111 +++++++++----------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   89 ++++++--------------
 arch/arm/mach-at91/devices.c             |   75 +++++++++++++++++
 arch/arm/mach-at91/devices.h             |   11 +++
 7 files changed, 261 insertions(+), 348 deletions(-)

diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index ae8e118..6724011 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -332,73 +332,44 @@ static struct __initdata at91_dev_table_ac97 device_ac97 = {
  *  LCD Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
-
-static struct resource lcdc_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_LCDC_BASE,
-		.end	= AT91CAP9_LCDC_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_LCDC,
-		.end	= AT91CAP9_ID_LCDC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &lcdc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &lcdc_data,
-	},
-	.resource	= lcdc_resources,
-	.num_resources	= ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+static void __init at91cap9_lcdc_init(void)
 {
-	if (!data)
-		return;
-
 	if (cpu_is_at91cap9_revB())
 		irq_set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH);
-
-	at91_set_A_periph(AT91_PIN_PC1, 0);	/* LCDHSYNC */
-	at91_set_A_periph(AT91_PIN_PC2, 0);	/* LCDDOTCK */
-	at91_set_A_periph(AT91_PIN_PC3, 0);	/* LCDDEN */
-	at91_set_B_periph(AT91_PIN_PB9, 0);	/* LCDCC */
-	at91_set_A_periph(AT91_PIN_PC6, 0);	/* LCDD2 */
-	at91_set_A_periph(AT91_PIN_PC7, 0);	/* LCDD3 */
-	at91_set_A_periph(AT91_PIN_PC8, 0);	/* LCDD4 */
-	at91_set_A_periph(AT91_PIN_PC9, 0);	/* LCDD5 */
-	at91_set_A_periph(AT91_PIN_PC10, 0);	/* LCDD6 */
-	at91_set_A_periph(AT91_PIN_PC11, 0);	/* LCDD7 */
-	at91_set_A_periph(AT91_PIN_PC14, 0);	/* LCDD10 */
-	at91_set_A_periph(AT91_PIN_PC15, 0);	/* LCDD11 */
-	at91_set_A_periph(AT91_PIN_PC16, 0);	/* LCDD12 */
-	at91_set_A_periph(AT91_PIN_PC17, 0);	/* LCDD13 */
-	at91_set_A_periph(AT91_PIN_PC18, 0);	/* LCDD14 */
-	at91_set_A_periph(AT91_PIN_PC19, 0);	/* LCDD15 */
-	at91_set_A_periph(AT91_PIN_PC22, 0);	/* LCDD18 */
-	at91_set_A_periph(AT91_PIN_PC23, 0);	/* LCDD19 */
-	at91_set_A_periph(AT91_PIN_PC24, 0);	/* LCDD20 */
-	at91_set_A_periph(AT91_PIN_PC25, 0);	/* LCDD21 */
-	at91_set_A_periph(AT91_PIN_PC26, 0);	/* LCDD22 */
-	at91_set_A_periph(AT91_PIN_PC27, 0);	/* LCDD23 */
-
-	lcdc_data = *data;
-	platform_device_register(&at91_lcdc_device);
 }
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
-#endif
 
+static struct __initdata at91_pin_config lcdc_pins[] = {
+	{AT91_PIN_PC1,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDHSYNC */
+	{AT91_PIN_PC2,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDOTCK */
+	{AT91_PIN_PC3,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDEN */
+	{AT91_PIN_PB9,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDCC */
+	{AT91_PIN_PC6,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD2 */
+	{AT91_PIN_PC7,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD3 */
+	{AT91_PIN_PC8,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD4 */
+	{AT91_PIN_PC9,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD5 */
+	{AT91_PIN_PC10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD6 */
+	{AT91_PIN_PC11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD7 */
+	{AT91_PIN_PC14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD10 */
+	{AT91_PIN_PC15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD11 */
+	{AT91_PIN_PC16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD12 */
+	{AT91_PIN_PC17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD13 */
+	{AT91_PIN_PC18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD14 */
+	{AT91_PIN_PC19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD15 */
+	{AT91_PIN_PC22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD18 */
+	{AT91_PIN_PC23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD19 */
+	{AT91_PIN_PC24, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD20 */
+	{AT91_PIN_PC25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD21 */
+	{AT91_PIN_PC26, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD22 */
+	{AT91_PIN_PC27, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD23 */
+};
+
+static struct at91_dev_table_lcdc __initdata device_lcdc = {
+	.mmio_base	= AT91CAP9_LCDC_BASE,
+	.irq		= AT91CAP9_ID_LCDC,
+	.device_init	= at91cap9_lcdc_init,
+	.pins		= lcdc_pins,
+	.nr_pins	= ARRAY_SIZE(lcdc_pins),
+};
 
 /* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
@@ -508,6 +479,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
+	.lcdc		= &device_lcdc,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 6efa1e8..97fb389 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -127,101 +127,53 @@ static struct __initdata at91_dev_table_spi device_spi1 = {
  *  LCD Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
-
-static struct resource lcdc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_LCDC_BASE,
-		.end	= AT91SAM9261_LCDC_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_LCDC,
-		.end	= AT91SAM9261_ID_LCDC,
-		.flags	= IORESOURCE_IRQ,
-	},
-#if defined(CONFIG_FB_INTSRAM)
-	[2] = {
-		.start	= AT91SAM9261_SRAM_BASE,
-		.end	= AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-#endif
-};
-
-static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &lcdc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &lcdc_data,
-	},
-	.resource	= lcdc_resources,
-	.num_resources	= ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
-{
-	if (!data) {
-		return;
-	}
-
+static struct __initdata at91_pin_config lcdc_pins[] = {
 #if defined(CONFIG_FB_ATMEL_STN)
-	at91_set_A_periph(AT91_PIN_PB0, 0);     /* LCDVSYNC */
-	at91_set_A_periph(AT91_PIN_PB1, 0);     /* LCDHSYNC */
-	at91_set_A_periph(AT91_PIN_PB2, 0);     /* LCDDOTCK */
-	at91_set_A_periph(AT91_PIN_PB3, 0);     /* LCDDEN */
-	at91_set_A_periph(AT91_PIN_PB4, 0);     /* LCDCC */
-	at91_set_A_periph(AT91_PIN_PB5, 0);     /* LCDD0 */
-	at91_set_A_periph(AT91_PIN_PB6, 0);     /* LCDD1 */
-	at91_set_A_periph(AT91_PIN_PB7, 0);     /* LCDD2 */
-	at91_set_A_periph(AT91_PIN_PB8, 0);     /* LCDD3 */
+	{AT91_PIN_PB0,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDVSYNC */
+	{AT91_PIN_PB1,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDHSYNC */
+	{AT91_PIN_PB2,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDDOTCK */
+	{AT91_PIN_PB3,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDDEN */
+	{AT91_PIN_PB4,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDCC */
+	{AT91_PIN_PB5,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDD0 */
+	{AT91_PIN_PB6,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDD1 */
+	{AT91_PIN_PB7,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDD2 */
+	{AT91_PIN_PB8,  AT91_PIN_PERIPH_A, 0, 0, 0},     /* LCDD3 */
 #else
-	at91_set_A_periph(AT91_PIN_PB1, 0);	/* LCDHSYNC */
-	at91_set_A_periph(AT91_PIN_PB2, 0);	/* LCDDOTCK */
-	at91_set_A_periph(AT91_PIN_PB3, 0);	/* LCDDEN */
-	at91_set_A_periph(AT91_PIN_PB4, 0);	/* LCDCC */
-	at91_set_A_periph(AT91_PIN_PB7, 0);	/* LCDD2 */
-	at91_set_A_periph(AT91_PIN_PB8, 0);	/* LCDD3 */
-	at91_set_A_periph(AT91_PIN_PB9, 0);	/* LCDD4 */
-	at91_set_A_periph(AT91_PIN_PB10, 0);	/* LCDD5 */
-	at91_set_A_periph(AT91_PIN_PB11, 0);	/* LCDD6 */
-	at91_set_A_periph(AT91_PIN_PB12, 0);	/* LCDD7 */
-	at91_set_A_periph(AT91_PIN_PB15, 0);	/* LCDD10 */
-	at91_set_A_periph(AT91_PIN_PB16, 0);	/* LCDD11 */
-	at91_set_A_periph(AT91_PIN_PB17, 0);	/* LCDD12 */
-	at91_set_A_periph(AT91_PIN_PB18, 0);	/* LCDD13 */
-	at91_set_A_periph(AT91_PIN_PB19, 0);	/* LCDD14 */
-	at91_set_A_periph(AT91_PIN_PB20, 0);	/* LCDD15 */
-	at91_set_B_periph(AT91_PIN_PB23, 0);	/* LCDD18 */
-	at91_set_B_periph(AT91_PIN_PB24, 0);	/* LCDD19 */
-	at91_set_B_periph(AT91_PIN_PB25, 0);	/* LCDD20 */
-	at91_set_B_periph(AT91_PIN_PB26, 0);	/* LCDD21 */
-	at91_set_B_periph(AT91_PIN_PB27, 0);	/* LCDD22 */
-	at91_set_B_periph(AT91_PIN_PB28, 0);	/* LCDD23 */
+	{AT91_PIN_PB1,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDHSYNC */
+	{AT91_PIN_PB2,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDOTCK */
+	{AT91_PIN_PB3,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDEN */
+	{AT91_PIN_PB4,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDCC */
+	{AT91_PIN_PB7,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD2 */
+	{AT91_PIN_PB8,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD3 */
+	{AT91_PIN_PB9,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD4 */
+	{AT91_PIN_PB10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD5 */
+	{AT91_PIN_PB11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD6 */
+	{AT91_PIN_PB12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD7 */
+	{AT91_PIN_PB15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD10 */
+	{AT91_PIN_PB16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD11 */
+	{AT91_PIN_PB17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD12 */
+	{AT91_PIN_PB18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD13 */
+	{AT91_PIN_PB19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD14 */
+	{AT91_PIN_PB20, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD15 */
+	{AT91_PIN_PB23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD18 */
+	{AT91_PIN_PB24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD19 */
+	{AT91_PIN_PB25, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD20 */
+	{AT91_PIN_PB26, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD21 */
+	{AT91_PIN_PB27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD22 */
+	{AT91_PIN_PB28, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD23 */
 #endif
+};
 
-	if (ARRAY_SIZE(lcdc_resources) > 2) {
-		void __iomem *fb;
-		struct resource *fb_res = &lcdc_resources[2];
-		size_t fb_len = fb_res->end - fb_res->start + 1;
-
-		fb = ioremap(fb_res->start, fb_len);
-		if (fb) {
-			memset(fb, 0, fb_len);
-			iounmap(fb);
-		}
-	}
-	lcdc_data = *data;
-	platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+static struct __initdata at91_dev_table_lcdc device_lcdc = {
+	.mmio_base	= AT91SAM9261_LCDC_BASE,
+	.irq		= AT91SAM9261_ID_LCDC,
+#if defined(CONFIG_FB_INTSRAM)
+	.sram_base	= AT91SAM9261_SRAM_BASE,
+	.sram_size	= AT91SAM9261_SRAM_SIZE,
 #endif
-
+	.pins		= lcdc_pins,
+	.nr_pins	= ARRAY_SIZE(lcdc_pins),
+};
 
 /* --------------------------------------------------------------------
  *  Timer/Counter block
@@ -367,6 +319,7 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
 	.ssc[2]		= &device_ssc2,
+	.lcdc		= &device_lcdc,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 6155a9f..f8c6f9c 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -351,71 +351,38 @@ void __init at91_add_device_can(struct at91_can_data *data) {}
  *  LCD Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
-
-static struct resource lcdc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_LCDC_BASE,
-		.end	= AT91SAM9263_LCDC_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_LCDC,
-		.end	= AT91SAM9263_ID_LCDC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config lcdc_pins[] = {
+	{AT91_PIN_PC1,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDHSYNC */
+	{AT91_PIN_PC2,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDOTCK */
+	{AT91_PIN_PC3,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDEN */
+	{AT91_PIN_PB9,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDCC */
+	{AT91_PIN_PC6,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD2 */
+	{AT91_PIN_PC7,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD3 */
+	{AT91_PIN_PC8,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD4 */
+	{AT91_PIN_PC9,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD5 */
+	{AT91_PIN_PC10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD6 */
+	{AT91_PIN_PC11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD7 */
+	{AT91_PIN_PC14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD10 */
+	{AT91_PIN_PC15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD11 */
+	{AT91_PIN_PC16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD12 */
+	{AT91_PIN_PC12, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD13 */
+	{AT91_PIN_PC18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD14 */
+	{AT91_PIN_PC19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD15 */
+	{AT91_PIN_PC22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD18 */
+	{AT91_PIN_PC23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD19 */
+	{AT91_PIN_PC24, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD20 */
+	{AT91_PIN_PC17, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD21 */
+	{AT91_PIN_PC26, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD22 */
+	{AT91_PIN_PC27, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD23 */
+};
+
+static struct __initdata at91_dev_table_lcdc device_lcdc = {
+	.mmio_base	= AT91SAM9263_LCDC_BASE,
+	.irq		= AT91SAM9263_ID_LCDC,
+	.pins		= lcdc_pins,
+	.nr_pins	= ARRAY_SIZE(lcdc_pins),
 };
 
-static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &lcdc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &lcdc_data,
-	},
-	.resource	= lcdc_resources,
-	.num_resources	= ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
-{
-	if (!data)
-		return;
-
-	at91_set_A_periph(AT91_PIN_PC1, 0);	/* LCDHSYNC */
-	at91_set_A_periph(AT91_PIN_PC2, 0);	/* LCDDOTCK */
-	at91_set_A_periph(AT91_PIN_PC3, 0);	/* LCDDEN */
-	at91_set_B_periph(AT91_PIN_PB9, 0);	/* LCDCC */
-	at91_set_A_periph(AT91_PIN_PC6, 0);	/* LCDD2 */
-	at91_set_A_periph(AT91_PIN_PC7, 0);	/* LCDD3 */
-	at91_set_A_periph(AT91_PIN_PC8, 0);	/* LCDD4 */
-	at91_set_A_periph(AT91_PIN_PC9, 0);	/* LCDD5 */
-	at91_set_A_periph(AT91_PIN_PC10, 0);	/* LCDD6 */
-	at91_set_A_periph(AT91_PIN_PC11, 0);	/* LCDD7 */
-	at91_set_A_periph(AT91_PIN_PC14, 0);	/* LCDD10 */
-	at91_set_A_periph(AT91_PIN_PC15, 0);	/* LCDD11 */
-	at91_set_A_periph(AT91_PIN_PC16, 0);	/* LCDD12 */
-	at91_set_B_periph(AT91_PIN_PC12, 0);	/* LCDD13 */
-	at91_set_A_periph(AT91_PIN_PC18, 0);	/* LCDD14 */
-	at91_set_A_periph(AT91_PIN_PC19, 0);	/* LCDD15 */
-	at91_set_A_periph(AT91_PIN_PC22, 0);	/* LCDD18 */
-	at91_set_A_periph(AT91_PIN_PC23, 0);	/* LCDD19 */
-	at91_set_A_periph(AT91_PIN_PC24, 0);	/* LCDD20 */
-	at91_set_B_periph(AT91_PIN_PC17, 0);	/* LCDD21 */
-	at91_set_A_periph(AT91_PIN_PC26, 0);	/* LCDD22 */
-	at91_set_A_periph(AT91_PIN_PC27, 0);	/* LCDD23 */
-
-	lcdc_data = *data;
-	platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Image Sensor Interface
  * -------------------------------------------------------------------- */
@@ -618,6 +585,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
+	.lcdc		= &device_lcdc,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 3f71e45..0f7cc97 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -346,80 +346,46 @@ static struct __initdata at91_dev_table_ac97 device_ac97 = {
  *  LCD Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
-
-static struct resource lcdc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_LCDC_BASE,
-		.end	= AT91SAM9G45_LCDC_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_LCDC,
-		.end	= AT91SAM9G45_ID_LCDC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config lcdc_pins[] = {
+	{AT91_PIN_PE0,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDPWR */
+	{AT91_PIN_PE2,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDCC */
+	{AT91_PIN_PE3,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDVSYNC */
+	{AT91_PIN_PE4,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDHSYNC */
+	{AT91_PIN_PE5,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDOTCK */
+	{AT91_PIN_PE6,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDEN */
+	{AT91_PIN_PE7,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD0 */
+	{AT91_PIN_PE8,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD1 */
+	{AT91_PIN_PE9,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD2 */
+	{AT91_PIN_PE10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD3 */
+	{AT91_PIN_PE11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD4 */
+	{AT91_PIN_PE12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD5 */
+	{AT91_PIN_PE13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD6 */
+	{AT91_PIN_PE14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD7 */
+	{AT91_PIN_PE15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD8 */
+	{AT91_PIN_PE16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD9 */
+	{AT91_PIN_PE17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD10 */
+	{AT91_PIN_PE18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD11 */
+	{AT91_PIN_PE19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD12 */
+	{AT91_PIN_PE20, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD13 */
+	{AT91_PIN_PE21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD14 */
+	{AT91_PIN_PE22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD15 */
+	{AT91_PIN_PE23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD16 */
+	{AT91_PIN_PE24, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD17 */
+	{AT91_PIN_PE25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD18 */
+	{AT91_PIN_PE26, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD19 */
+	{AT91_PIN_PE27, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD20 */
+	{AT91_PIN_PE28, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD21 */
+	{AT91_PIN_PE29, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD22 */
+	{AT91_PIN_PE30, AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDD23 */
+};
+
+static struct __initdata at91_dev_table_lcdc device_lcdc = {
+	.mmio_base	= AT91SAM9G45_LCDC_BASE,
+	.irq		= AT91SAM9G45_ID_LCDC,
+	.pins		= lcdc_pins,
+	.nr_pins	= ARRAY_SIZE(lcdc_pins),
 };
 
-static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &lcdc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &lcdc_data,
-	},
-	.resource	= lcdc_resources,
-	.num_resources	= ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
-{
-	if (!data)
-		return;
-
-	at91_set_A_periph(AT91_PIN_PE0, 0);	/* LCDDPWR */
-
-	at91_set_A_periph(AT91_PIN_PE2, 0);	/* LCDCC */
-	at91_set_A_periph(AT91_PIN_PE3, 0);	/* LCDVSYNC */
-	at91_set_A_periph(AT91_PIN_PE4, 0);	/* LCDHSYNC */
-	at91_set_A_periph(AT91_PIN_PE5, 0);	/* LCDDOTCK */
-	at91_set_A_periph(AT91_PIN_PE6, 0);	/* LCDDEN */
-	at91_set_A_periph(AT91_PIN_PE7, 0);	/* LCDD0 */
-	at91_set_A_periph(AT91_PIN_PE8, 0);	/* LCDD1 */
-	at91_set_A_periph(AT91_PIN_PE9, 0);	/* LCDD2 */
-	at91_set_A_periph(AT91_PIN_PE10, 0);	/* LCDD3 */
-	at91_set_A_periph(AT91_PIN_PE11, 0);	/* LCDD4 */
-	at91_set_A_periph(AT91_PIN_PE12, 0);	/* LCDD5 */
-	at91_set_A_periph(AT91_PIN_PE13, 0);	/* LCDD6 */
-	at91_set_A_periph(AT91_PIN_PE14, 0);	/* LCDD7 */
-	at91_set_A_periph(AT91_PIN_PE15, 0);	/* LCDD8 */
-	at91_set_A_periph(AT91_PIN_PE16, 0);	/* LCDD9 */
-	at91_set_A_periph(AT91_PIN_PE17, 0);	/* LCDD10 */
-	at91_set_A_periph(AT91_PIN_PE18, 0);	/* LCDD11 */
-	at91_set_A_periph(AT91_PIN_PE19, 0);	/* LCDD12 */
-	at91_set_A_periph(AT91_PIN_PE20, 0);	/* LCDD13 */
-	at91_set_A_periph(AT91_PIN_PE21, 0);	/* LCDD14 */
-	at91_set_A_periph(AT91_PIN_PE22, 0);	/* LCDD15 */
-	at91_set_A_periph(AT91_PIN_PE23, 0);	/* LCDD16 */
-	at91_set_A_periph(AT91_PIN_PE24, 0);	/* LCDD17 */
-	at91_set_A_periph(AT91_PIN_PE25, 0);	/* LCDD18 */
-	at91_set_A_periph(AT91_PIN_PE26, 0);	/* LCDD19 */
-	at91_set_A_periph(AT91_PIN_PE27, 0);	/* LCDD20 */
-	at91_set_A_periph(AT91_PIN_PE28, 0);	/* LCDD21 */
-	at91_set_A_periph(AT91_PIN_PE29, 0);	/* LCDD22 */
-	at91_set_A_periph(AT91_PIN_PE30, 0);	/* LCDD23 */
-
-	lcdc_data = *data;
-	platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
@@ -666,6 +632,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
+	.lcdc		= &device_lcdc,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 3b6010b..927cbd7 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -242,71 +242,37 @@ static struct __initdata at91_dev_table_ac97 device_ac97 = {
  *  LCD Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
-
-static struct resource lcdc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_LCDC_BASE,
-		.end	= AT91SAM9RL_LCDC_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_LCDC,
-		.end	= AT91SAM9RL_ID_LCDC,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct __initdata at91_pin_config lcdc_pins[] = {
+	{AT91_PIN_PC1,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDPWR */
+	{AT91_PIN_PC5,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDHSYNC */
+	{AT91_PIN_PC6,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDOTCK */
+	{AT91_PIN_PC7,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDDEN */
+	{AT91_PIN_PC3,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* LCDCC */
+	{AT91_PIN_PC9,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD3 */
+	{AT91_PIN_PC10, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD4 */
+	{AT91_PIN_PC11, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD5 */
+	{AT91_PIN_PC12, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD6 */
+	{AT91_PIN_PC13, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD7 */
+	{AT91_PIN_PC15, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD11 */
+	{AT91_PIN_PC16, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD12 */
+	{AT91_PIN_PC17, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD13 */
+	{AT91_PIN_PC18, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD14 */
+	{AT91_PIN_PC19, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD15 */
+	{AT91_PIN_PC20, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD18 */
+	{AT91_PIN_PC21, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD19 */
+	{AT91_PIN_PC22, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD20 */
+	{AT91_PIN_PC23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD21 */
+	{AT91_PIN_PC24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD22 */
+	{AT91_PIN_PC25, AT91_PIN_PERIPH_B, 0, 0, 0},	/* LCDD23 */
 };
 
-static struct platform_device at91_lcdc_device = {
-	.name		= "atmel_lcdfb",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &lcdc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &lcdc_data,
-	},
-	.resource	= lcdc_resources,
-	.num_resources	= ARRAY_SIZE(lcdc_resources),
+static struct __initdata at91_dev_table_lcdc device_lcdc = {
+	.mmio_base	= AT91SAM9RL_LCDC_BASE,
+	.irq		= AT91SAM9RL_ID_LCDC,
+	.pins		= lcdc_pins,
+	.nr_pins	= ARRAY_SIZE(lcdc_pins),
 };
 
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
-{
-	if (!data) {
-		return;
-	}
-
-	at91_set_B_periph(AT91_PIN_PC1, 0);	/* LCDPWR */
-	at91_set_A_periph(AT91_PIN_PC5, 0);	/* LCDHSYNC */
-	at91_set_A_periph(AT91_PIN_PC6, 0);	/* LCDDOTCK */
-	at91_set_A_periph(AT91_PIN_PC7, 0);	/* LCDDEN */
-	at91_set_A_periph(AT91_PIN_PC3, 0);	/* LCDCC */
-	at91_set_B_periph(AT91_PIN_PC9, 0);	/* LCDD3 */
-	at91_set_B_periph(AT91_PIN_PC10, 0);	/* LCDD4 */
-	at91_set_B_periph(AT91_PIN_PC11, 0);	/* LCDD5 */
-	at91_set_B_periph(AT91_PIN_PC12, 0);	/* LCDD6 */
-	at91_set_B_periph(AT91_PIN_PC13, 0);	/* LCDD7 */
-	at91_set_B_periph(AT91_PIN_PC15, 0);	/* LCDD11 */
-	at91_set_B_periph(AT91_PIN_PC16, 0);	/* LCDD12 */
-	at91_set_B_periph(AT91_PIN_PC17, 0);	/* LCDD13 */
-	at91_set_B_periph(AT91_PIN_PC18, 0);	/* LCDD14 */
-	at91_set_B_periph(AT91_PIN_PC19, 0);	/* LCDD15 */
-	at91_set_B_periph(AT91_PIN_PC20, 0);	/* LCDD18 */
-	at91_set_B_periph(AT91_PIN_PC21, 0);	/* LCDD19 */
-	at91_set_B_periph(AT91_PIN_PC22, 0);	/* LCDD20 */
-	at91_set_B_periph(AT91_PIN_PC23, 0);	/* LCDD21 */
-	at91_set_B_periph(AT91_PIN_PC24, 0);	/* LCDD22 */
-	at91_set_B_periph(AT91_PIN_PC25, 0);	/* LCDD23 */
-
-	lcdc_data = *data;
-	platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
@@ -541,6 +507,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
+	.lcdc		= &device_lcdc,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 86f0640..ad32529 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1579,6 +1579,81 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
 void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  LCD Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static u64 lcdc_dmamask = DMA_BIT_MASK(32);
+static struct atmel_lcdfb_info lcdc_data;
+
+static struct resource lcdc_resources[] = {
+	[0] = {
+		.end	= SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+#if defined(CONFIG_FB_INTSRAM)
+	[2] = {
+		.flags	= IORESOURCE_MEM,
+	},
+#endif
+};
+
+static struct platform_device at91_lcdc_device = {
+	.name		= "atmel_lcdfb",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &lcdc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &lcdc_data,
+	},
+	.resource	= lcdc_resources,
+	.num_resources	= ARRAY_SIZE(lcdc_resources),
+};
+
+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+{
+	struct at91_dev_table_lcdc *info = devices->lcdc;
+
+	BUG_ON(!info);
+	init_resource_mem(&lcdc_resources[0], info->mmio_base);
+	init_resource_irq(&lcdc_resources[1], info->irq);
+
+	if (info->device_init)
+		info->device_init();
+
+#if defined(CONFIG_FB_INTSRAM)
+	if (info->sram_base) {
+		void __iomem *fb;
+		struct resource *fb_res = &lcdc_resources[2];
+		size_t fb_len;
+
+		lcdc_resources[2].size = info->sram_size;
+		init_resource_mem(&lcdc_resources[2], info->sram_base);
+
+		fb_len = fb_res->end - fb_res->start + 1;
+		fb = ioremap(fb_res->start, fb_len);
+		if (fb) {
+			memset(fb, 0, fb_len);
+			iounmap(fb);
+		}
+	}
+#endif
+
+	if (!data)
+		return;
+
+	at91_config_pins(info->pins, info->nr_pins);
+	lcdc_data = *data;
+	platform_device_register(&at91_lcdc_device);
+}
+#else
+void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 3d6ca83..65a036c 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -147,6 +147,16 @@ struct at91_dev_table_ac97 {
 	struct at91_pin_config	pins[4];	/* FS, CK, TX, RX */
 };
 
+struct at91_dev_table_lcdc {
+	unsigned		mmio_base;
+	int			irq;
+	unsigned		sram_base;	/* Only on AT91SAM9261 */
+	unsigned		sram_size;
+	void			(*device_init)(void);
+	struct at91_pin_config	*pins;
+	int			nr_pins;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -163,6 +173,7 @@ struct at91_device_table {
 	struct at91_dev_table_pwm		*pwm;
 	struct at91_dev_table_ssc		*ssc[4];
 	struct at91_dev_table_ac97		*ac97;
+	struct at91_dev_table_lcdc		*lcdc;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 17/23] at91: Make touchscreen device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (15 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 16/23] at91: Make LCD controller " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 18/23] at91: Make HDMAC " Ryan Mallon
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual touchscreen code for each at91 variant with a
single implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91sam9g45_devices.c |   53 +++++------------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   53 +++++------------------------
 arch/arm/mach-at91/devices.c             |   49 +++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |    7 ++++
 4 files changed, 74 insertions(+), 88 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 0f7cc97..38d5d45 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -436,53 +436,17 @@ static void __init at91_add_device_rtc(void) {}
  *  Touchscreen
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
-static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
-static struct at91_tsadcc_data tsadcc_data;
-
-static struct resource tsadcc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_TSC,
-		.end	= AT91SAM9G45_BASE_TSC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_TSC,
-		.end	= AT91SAM9G45_ID_TSC,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device at91sam9g45_tsadcc_device = {
-	.name		= "atmel_tsadcc",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &tsadcc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &tsadcc_data,
+static struct __initdata at91_dev_table_tsadcc device_tsadcc = {
+	.mmio_base	= AT91SAM9G45_BASE_TSC,
+	.irq		= AT91SAM9G45_ID_TSC,
+	.pins		= {
+		{AT91_PIN_PD20, AT91_PIN_GPIO, 0, GPIOF_DIR_IN, 0}, /* AD0_XR */
+		{AT91_PIN_PD21, AT91_PIN_GPIO, 0, GPIOF_DIR_IN, 0}, /* AD0_XL */
+		{AT91_PIN_PD22, AT91_PIN_GPIO, 0, GPIOF_DIR_IN, 0}, /* AD0_YT */
+		{AT91_PIN_PD23, AT91_PIN_GPIO, 0, GPIOF_DIR_IN, 0}, /* AD0_TB */
 	},
-	.resource	= tsadcc_resources,
-	.num_resources	= ARRAY_SIZE(tsadcc_resources),
 };
 
-void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
-{
-	if (!data)
-		return;
-
-	at91_set_gpio_input(AT91_PIN_PD20, 0);	/* AD0_XR */
-	at91_set_gpio_input(AT91_PIN_PD21, 0);	/* AD1_XL */
-	at91_set_gpio_input(AT91_PIN_PD22, 0);	/* AD2_YT */
-	at91_set_gpio_input(AT91_PIN_PD23, 0);	/* AD3_TB */
-
-	tsadcc_data = *data;
-	platform_device_register(&at91sam9g45_tsadcc_device);
-}
-#else
-void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
@@ -633,6 +597,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
+	.tsadcc		= &device_tsadcc,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 927cbd7..92d7aa3 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -294,53 +294,17 @@ static struct __initdata at91_dev_table_tcb device_tcb = {
  *  Touchscreen
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
-static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
-static struct at91_tsadcc_data tsadcc_data;
-
-static struct resource tsadcc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_TSC,
-		.end	= AT91SAM9RL_BASE_TSC + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_TSC,
-		.end	= AT91SAM9RL_ID_TSC,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device at91sam9rl_tsadcc_device = {
-	.name		= "atmel_tsadcc",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &tsadcc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &tsadcc_data,
+static struct __initdata at91_dev_table_tsadcc device_tsadcc = {
+	.mmio_base	= AT91SAM9RL_BASE_TSC,
+	.irq		= AT91SAM9RL_ID_TSC,
+	.pins		= {
+		{AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0}, /* AD0_XR */
+		{AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0}, /* AD0_XL */
+		{AT91_PIN_PA19, AT91_PIN_PERIPH_A, 0, 0, 0}, /* AD0_YT */
+		{AT91_PIN_PA20, AT91_PIN_PERIPH_A, 0, 0, 0}, /* AD0_TB */
 	},
-	.resource	= tsadcc_resources,
-	.num_resources	= ARRAY_SIZE(tsadcc_resources),
 };
 
-void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
-{
-	if (!data)
-		return;
-
-	at91_set_A_periph(AT91_PIN_PA17, 0);	/* AD0_XR */
-	at91_set_A_periph(AT91_PIN_PA18, 0);	/* AD1_XL */
-	at91_set_A_periph(AT91_PIN_PA19, 0);	/* AD2_YT */
-	at91_set_A_periph(AT91_PIN_PA20, 0);	/* AD3_TB */
-
-	tsadcc_data = *data;
-	platform_device_register(&at91sam9rl_tsadcc_device);
-}
-#else
-void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  RTC
  * -------------------------------------------------------------------- */
@@ -508,6 +472,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
+	.tsadcc		= &device_tsadcc,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index ad32529..b5244b1 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1654,6 +1654,55 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
 void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  Touchscreen
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
+static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
+static struct at91_tsadcc_data tsadcc_data;
+
+static struct resource tsadcc_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device at91_tsadcc_device = {
+	.name		= "atmel_tsadcc",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &tsadcc_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &tsadcc_data,
+	},
+	.resource	= tsadcc_resources,
+	.num_resources	= ARRAY_SIZE(tsadcc_resources),
+};
+
+void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
+{
+	struct at91_dev_table_tsadcc *info = devices->tsadcc;
+
+	BUG_ON(!info);
+	init_resource_mem(&tsadcc_resources[0], info->mmio_base);
+	init_resource_irq(&tsadcc_resources[1], info->irq);
+
+	if (!data)
+		return;
+
+	at91_config_pins(info->pins, ARRAY_SIZE(info->pins));
+	tsadcc_data = *data;
+	platform_device_register(&at91sam9g45_tsadcc_device);
+}
+#else
+void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 65a036c..4b68228 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -157,6 +157,12 @@ struct at91_dev_table_lcdc {
 	int			nr_pins;
 };
 
+struct at91_dev_table_tsadcc {
+	unsigned		mmio_base;
+	int			irq;
+	struct at91_pin_config	pins[4];	/* XR, XL, YT, TB */
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -174,6 +180,7 @@ struct at91_device_table {
 	struct at91_dev_table_ssc		*ssc[4];
 	struct at91_dev_table_ac97		*ac97;
 	struct at91_dev_table_lcdc		*lcdc;
+	struct at91_dev_table_tsadcc		*tsadcc;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 18/23] at91: Make HDMAC device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (16 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 17/23] at91: Make touchscreen " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 19/23] at91: Make RTC " Ryan Mallon
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual HDMAC code for each at91 variant with a single
implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91sam9g45_devices.c |   46 +++--------------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   43 ++-------------------------
 arch/arm/mach-at91/devices.c             |   46 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |    8 +++++
 4 files changed, 63 insertions(+), 80 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 38d5d45..421d941 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -36,49 +36,13 @@
  *  HDMAC - AHB DMA Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
-static u64 hdmac_dmamask = DMA_BIT_MASK(32);
-
-static struct at_dma_platform_data atdma_pdata = {
+static struct __initdata at91_dev_table_hdmac device_hdmac = {
+	.mmio_base	= AT91_BASE_SYS + AT91_DMA,
+	.irq		= AT91SAM9G45_ID_DMA,
 	.nr_channels	= 8,
+	.have_slave	= 1,
 };
 
-static struct resource hdmac_resources[] = {
-	[0] = {
-		.start	= AT91_BASE_SYS + AT91_DMA,
-		.end	= AT91_BASE_SYS + AT91_DMA + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_DMA,
-		.end	= AT91SAM9G45_ID_DMA,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at_hdmac_device = {
-	.name		= "at_hdmac",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &hdmac_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &atdma_pdata,
-	},
-	.resource	= hdmac_resources,
-	.num_resources	= ARRAY_SIZE(hdmac_resources),
-};
-
-void __init at91_add_device_hdmac(void)
-{
-	dma_cap_set(DMA_MEMCPY, atdma_pdata.cap_mask);
-	dma_cap_set(DMA_SLAVE, atdma_pdata.cap_mask);
-	platform_device_register(&at_hdmac_device);
-}
-#else
-void __init at91_add_device_hdmac(void) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  USB Host (OHCI)
  * -------------------------------------------------------------------- */
@@ -598,6 +562,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
 	.tsadcc		= &device_tsadcc,
+	.hdmac		= &device_hdmac,
 };
 
 void __init at91sam9g45_init_devices(void)
@@ -612,7 +577,6 @@ void __init at91sam9g45_init_devices(void)
  */
 static int __init at91_add_standard_devices(void)
 {
-	at91_add_device_hdmac();
 	at91_add_device_rtc();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 92d7aa3..975ef10 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -30,47 +30,12 @@
  *  HDMAC - AHB DMA Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
-static u64 hdmac_dmamask = DMA_BIT_MASK(32);
-
-static struct at_dma_platform_data atdma_pdata = {
+static struct __initdata at91_dev_table_hdmac device_hdmac = {
+	.mmio_base	= AT91_BASE_SYS + AT91_DMA,
+	.irq		= AT91SAM9RL_ID_DMA,
 	.nr_channels	= 2,
 };
 
-static struct resource hdmac_resources[] = {
-	[0] = {
-		.start	= AT91_BASE_SYS + AT91_DMA,
-		.end	= AT91_BASE_SYS + AT91_DMA + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= AT91SAM9RL_ID_DMA,
-		.end	= AT91SAM9RL_ID_DMA,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at_hdmac_device = {
-	.name		= "at_hdmac",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &hdmac_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &atdma_pdata,
-	},
-	.resource	= hdmac_resources,
-	.num_resources	= ARRAY_SIZE(hdmac_resources),
-};
-
-void __init at91_add_device_hdmac(void)
-{
-	dma_cap_set(DMA_MEMCPY, atdma_pdata.cap_mask);
-	platform_device_register(&at_hdmac_device);
-}
-#else
-void __init at91_add_device_hdmac(void) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
@@ -473,6 +438,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
 	.tsadcc		= &device_tsadcc,
+	.hdmac		= &device_hdmac,
 };
 
 void __init at91sam9rl_init_devices(void)
@@ -488,7 +454,6 @@ void __init at91sam9rl_init_devices(void)
  */
 static int __init at91_add_standard_devices(void)
 {
-	at91_add_device_hdmac();
 	at91_add_device_rtc();
 	return 0;
 }
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index b5244b1..30c531b 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1703,11 +1703,57 @@ void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
 void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
 #endif
 
+#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
+static u64 hdmac_dmamask = DMA_BIT_MASK(32);
+
+static struct at_dma_platform_data atdma_pdata;
+
+static struct resource hdmac_resources[] = {
+	[0] = {
+		.end	= SZ_512,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at_hdmac_device = {
+	.name		= "at_hdmac",
+	.id		= -1,
+	.dev		= {
+				.dma_mask		= &hdmac_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &atdma_pdata,
+	},
+	.resource	= hdmac_resources,
+	.num_resources	= ARRAY_SIZE(hdmac_resources),
+};
+
+void __init at91_add_device_hdmac(void)
+{
+	struct at91_dev_table_hdmac *info = devices->hdmac;
+
+	BUG_ON(!info);
+	init_resource_mem(&hdmac_resources[0], info->mmio_base);
+	init_resource_irq(&hdmac_resources[1], info->irq);
+
+	atdma_pdata.nr_channels = info->nr_channels;
+	dma_cap_set(DMA_MEMCPY, atdma_pdata.cap_mask);
+	if (info->have_slave)
+		dma_cap_set(DMA_SLAVE, atdma_pdata.cap_mask);
+	platform_device_register(&at_hdmac_device);
+}
+#else
+void __init at91_add_device_hdmac(void) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
+	at91_add_device_hdmac();
 	return 0;
 }
 
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 4b68228..417c959 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -163,6 +163,13 @@ struct at91_dev_table_tsadcc {
 	struct at91_pin_config	pins[4];	/* XR, XL, YT, TB */
 };
 
+struct at91_dev_table_hdmac {
+	unsigned		mmio_base;
+	int			irq;
+	int			nr_channels;
+	int			have_slave;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -181,6 +188,7 @@ struct at91_device_table {
 	struct at91_dev_table_ac97		*ac97;
 	struct at91_dev_table_lcdc		*lcdc;
 	struct at91_dev_table_tsadcc		*tsadcc;
+	struct at91_dev_table_hdmac		*hdmac;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 19/23] at91: Make RTC device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (17 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 18/23] at91: Make HDMAC " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 20/23] at91: Make high speed USB gadget " Ryan Mallon
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

The RTC device code for the AT91RM9200, AT91SAM9G45 and AT91SAM9RL are
all exactly the same. Remove the individual implementations and
replace them with a single version in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91rm9200_devices.c  |   33 -----------------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   33 -----------------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |   34 ------------------------------
 arch/arm/mach-at91/devices.c             |   20 +++++++++++++++++
 4 files changed, 20 insertions(+), 100 deletions(-)

diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index a6d91f2..fb53848 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -277,25 +277,6 @@ static struct __initdata at91_dev_table_tcb device_tcb1 = {
 };
 
 /* --------------------------------------------------------------------
- *  RTC
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
-static struct platform_device at91rm9200_rtc_device = {
-	.name		= "at91_rtc",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_rtc(void)
-{
-	platform_device_register(&at91rm9200_rtc_device);
-}
-#else
-static void __init at91_add_device_rtc(void) {}
-#endif
-
-/* --------------------------------------------------------------------
  *  SSC -- Synchronous Serial Controller
  * -------------------------------------------------------------------- */
 
@@ -444,17 +425,3 @@ void __init at91rm9200_init_devices(void)
 {
 	at91_init_devices(&at91rm9200_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_rtc();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 421d941..3c05a6f 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -377,26 +377,6 @@ static struct __initdata at91_dev_table_tcb device_tcb1 = {
 };
 
 /* --------------------------------------------------------------------
- *  RTC
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
-static struct platform_device at91sam9g45_rtc_device = {
-	.name		= "at91_rtc",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_rtc(void)
-{
-	platform_device_register(&at91sam9g45_rtc_device);
-}
-#else
-static void __init at91_add_device_rtc(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  Touchscreen
  * -------------------------------------------------------------------- */
 
@@ -569,16 +549,3 @@ void __init at91sam9g45_init_devices(void)
 {
 	at91_init_devices(&at91sam9g45_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_rtc();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 975ef10..fe73270 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -271,26 +271,6 @@ static struct __initdata at91_dev_table_tsadcc device_tsadcc = {
 };
 
 /* --------------------------------------------------------------------
- *  RTC
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
-static struct platform_device at91sam9rl_rtc_device = {
-	.name		= "at91_rtc",
-	.id		= -1,
-	.num_resources	= 0,
-};
-
-static void __init at91_add_device_rtc(void)
-{
-	platform_device_register(&at91sam9rl_rtc_device);
-}
-#else
-static void __init at91_add_device_rtc(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
 
@@ -445,17 +425,3 @@ void __init at91sam9rl_init_devices(void)
 {
 	at91_init_devices(&at91sam9rl_device_table);
 }
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-	at91_add_device_rtc();
-	return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 30c531b..40c305d 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1748,12 +1748,32 @@ void __init at91_add_device_hdmac(void)
 void __init at91_add_device_hdmac(void) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
+static struct platform_device at91_rtc_device = {
+	.name		= "at91_rtc",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+static void __init at91_add_device_rtc(void)
+{
+	platform_device_register(&at91_rtc_device);
+}
+#else
+static void __init at91_add_device_rtc(void) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
 	at91_add_device_rtt();
 	at91_add_device_watchdog();
 	at91_add_device_hdmac();
+	at91_add_device_rtc();
 	return 0;
 }
 
-- 
1.7.0.4

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

* [RFC PATCH 20/23] at91: Make high speed USB gadget device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (18 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 19/23] at91: Make RTC " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 21/23] at91: Make compact flash " Ryan Mallon
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual high-speed UDC code for each at91 variant with
a single implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91cap9_devices.c    |  114 ++++++------------------------
 arch/arm/mach-at91/at91sam9g45_devices.c |   94 ++++---------------------
 arch/arm/mach-at91/at91sam9rl_devices.c  |  100 ++++----------------------
 arch/arm/mach-at91/devices.c             |   79 +++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   20 +++++
 5 files changed, 150 insertions(+), 257 deletions(-)

diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 6724011..551f067 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -51,105 +51,36 @@ static struct at91_dev_table_usb_ohci __initdata device_usbh_ohci = {
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
-
-static struct resource usba_udc_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_UDPHS_FIFO,
-		.end	= AT91CAP9_UDPHS_FIFO + SZ_512K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_BASE_UDPHS,
-		.end	= AT91CAP9_BASE_UDPHS + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= AT91CAP9_ID_UDPHS,
-		.end	= AT91CAP9_ID_UDPHS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-#define EP(nam, idx, maxpkt, maxbk, dma, isoc)			\
-	[idx] = {						\
-		.name		= nam,				\
-		.index		= idx,				\
-		.fifo_size	= maxpkt,			\
-		.nr_banks	= maxbk,			\
-		.can_dma	= dma,				\
-		.can_isoc	= isoc,				\
-	}
-
-static struct usba_ep_data usba_udc_ep[] = {
-	EP("ep0", 0,   64, 1, 0, 0),
-	EP("ep1", 1, 1024, 3, 1, 1),
-	EP("ep2", 2, 1024, 3, 1, 1),
-	EP("ep3", 3, 1024, 2, 1, 1),
-	EP("ep4", 4, 1024, 2, 1, 1),
-	EP("ep5", 5, 1024, 2, 1, 0),
-	EP("ep6", 6, 1024, 2, 1, 0),
-	EP("ep7", 7, 1024, 2, 0, 0),
-};
-
-#undef EP
-
-/*
- * pdata doesn't have room for any endpoints, so we need to
- * append room for the ones we need right after it.
- */
-static struct {
-	struct usba_platform_data pdata;
-	struct usba_ep_data ep[8];
-} usba_udc_data;
-
-static struct platform_device at91_usba_udc_device = {
-	.name		= "atmel_usba_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &usba_udc_data.pdata,
-	},
-	.resource	= usba_udc_resources,
-	.num_resources	= ARRAY_SIZE(usba_udc_resources),
-};
-
-void __init at91_add_device_usba(struct usba_platform_data *data)
+static void at91cap9_usba_init(void)
 {
 	if (cpu_is_at91cap9_revB()) {
 		irq_set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
 		at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS |
-						  AT91_MATRIX_UDPHS_BYPASS_LOCK);
-	}
-	else
+			       AT91_MATRIX_UDPHS_BYPASS_LOCK);
+	} else {
 		at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS);
-
-	/*
-	 * Invalid pins are 0 on AT91, but the usba driver is shared
-	 * with AVR32, which use negative values instead. Once/if
-	 * gpio_is_valid() is ported to AT91, revisit this code.
-	 */
-	usba_udc_data.pdata.vbus_pin = -EINVAL;
-	usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
-	memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));;
-
-	if (data && data->vbus_pin > 0) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-		usba_udc_data.pdata.vbus_pin = data->vbus_pin;
 	}
-
-	/* Pullup pin is handled internally by USB device peripheral */
-
-	/* Clocks */
-	at91_clock_associate("utmi_clk", &at91_usba_udc_device.dev, "hclk");
-	at91_clock_associate("udphs_clk", &at91_usba_udc_device.dev, "pclk");
-
-	platform_device_register(&at91_usba_udc_device);
 }
-#else
-void __init at91_add_device_usba(struct usba_platform_data *data) {}
-#endif
 
+static struct usba_ep_data usba_udc_ep[] = {
+	AT91_UDC_HS_EP("ep0", 0,   64, 1, 0, 0),
+	AT91_UDC_HS_EP("ep1", 1, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep2", 2, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep3", 3, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep4", 4, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep5", 5, 1024, 2, 1, 0),
+	AT91_UDC_HS_EP("ep6", 6, 1024, 2, 1, 0),
+	AT91_UDC_HS_EP("ep7", 7, 1024, 2, 0, 0),
+};
+
+static struct at91_dev_table_udc_hs __initdata device_udc_hs = {
+	.fifo_base	= AT91CAP9_UDPHS_FIFO,
+	.mmio_base	= AT91CAP9_BASE_UDPHS,
+	.irq		= AT91CAP9_ID_UDPHS,
+	.device_init	= at91cap9_usba_init,
+	.endpoints	= usba_udc_ep,
+	.nr_endpoints	= ARRAY_SIZE(usba_udc_ep),
+};
 
 /* --------------------------------------------------------------------
  *  Ethernet
@@ -480,6 +411,7 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
+	.udc_hs		= &device_udc_hs,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 3c05a6f..4f6c8e9 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -66,91 +66,24 @@ static struct __initdata at91_dev_table_basic_device device_usb_ehci = {
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
-static struct resource usba_udc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_UDPHS_FIFO,
-		.end	= AT91SAM9G45_UDPHS_FIFO + SZ_512K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_BASE_UDPHS,
-		.end	= AT91SAM9G45_BASE_UDPHS + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= AT91SAM9G45_ID_UDPHS,
-		.end	= AT91SAM9G45_ID_UDPHS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-#define EP(nam, idx, maxpkt, maxbk, dma, isoc)			\
-	[idx] = {						\
-		.name		= nam,				\
-		.index		= idx,				\
-		.fifo_size	= maxpkt,			\
-		.nr_banks	= maxbk,			\
-		.can_dma	= dma,				\
-		.can_isoc	= isoc,				\
-	}
-
 static struct usba_ep_data usba_udc_ep[] __initdata = {
-	EP("ep0", 0, 64, 1, 0, 0),
-	EP("ep1", 1, 1024, 2, 1, 1),
-	EP("ep2", 2, 1024, 2, 1, 1),
-	EP("ep3", 3, 1024, 3, 1, 0),
-	EP("ep4", 4, 1024, 3, 1, 0),
-	EP("ep5", 5, 1024, 3, 1, 1),
-	EP("ep6", 6, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep0", 0, 64, 1, 0, 0),
+	AT91_UDC_HS_EP("ep1", 1, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep2", 2, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep3", 3, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep4", 4, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep5", 5, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep6", 6, 1024, 3, 1, 1),
 };
 
-#undef EP
-
-/*
- * pdata doesn't have room for any endpoints, so we need to
- * append room for the ones we need right after it.
- */
-static struct {
-	struct usba_platform_data pdata;
-	struct usba_ep_data ep[7];
-} usba_udc_data;
-
-static struct platform_device at91_usba_udc_device = {
-	.name		= "atmel_usba_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &usba_udc_data.pdata,
-	},
-	.resource	= usba_udc_resources,
-	.num_resources	= ARRAY_SIZE(usba_udc_resources),
+static struct at91_dev_table_udc_hs __initdata device_udc_hs = {
+	.fifo_base	= AT91SAM9G45_UDPHS_FIFO,
+	.mmio_base	= AT91SAM9G45_BASE_UDPHS,
+	.irq		= AT91SAM9G45_ID_UDPHS,
+	.endpoints	= usba_udc_ep,
+	.nr_endpoints	= ARRAY_SIZE(usba_udc_ep),
 };
 
-void __init at91_add_device_usba(struct usba_platform_data *data)
-{
-	usba_udc_data.pdata.vbus_pin = -EINVAL;
-	usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
-	memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));;
-
-	if (data && data->vbus_pin > 0) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-		usba_udc_data.pdata.vbus_pin = data->vbus_pin;
-	}
-
-	/* Pullup pin is handled internally by USB device peripheral */
-
-	/* Clocks */
-	at91_clock_associate("utmi_clk", &at91_usba_udc_device.dev, "hclk");
-	at91_clock_associate("udphs_clk", &at91_usba_udc_device.dev, "pclk");
-
-	platform_device_register(&at91_usba_udc_device);
-}
-#else
-void __init at91_add_device_usba(struct usba_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  Ethernet
  * -------------------------------------------------------------------- */
@@ -543,6 +476,7 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.lcdc		= &device_lcdc,
 	.tsadcc		= &device_tsadcc,
 	.hdmac		= &device_hdmac,
+	.udc_hs		= &device_udc_hs,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index fe73270..7518958 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -40,97 +40,24 @@ static struct __initdata at91_dev_table_hdmac device_hdmac = {
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
-
-static struct resource usba_udc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_UDPHS_FIFO,
-		.end	= AT91SAM9RL_UDPHS_FIFO + SZ_512K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_BASE_UDPHS,
-		.end	= AT91SAM9RL_BASE_UDPHS + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start	= AT91SAM9RL_ID_UDPHS,
-		.end	= AT91SAM9RL_ID_UDPHS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-#define EP(nam, idx, maxpkt, maxbk, dma, isoc)			\
-	[idx] = {						\
-		.name		= nam,				\
-		.index		= idx,				\
-		.fifo_size	= maxpkt,			\
-		.nr_banks	= maxbk,			\
-		.can_dma	= dma,				\
-		.can_isoc	= isoc,				\
-	}
-
 static struct usba_ep_data usba_udc_ep[] __initdata = {
-	EP("ep0", 0, 64, 1, 0, 0),
-	EP("ep1", 1, 1024, 2, 1, 1),
-	EP("ep2", 2, 1024, 2, 1, 1),
-	EP("ep3", 3, 1024, 3, 1, 0),
-	EP("ep4", 4, 1024, 3, 1, 0),
-	EP("ep5", 5, 1024, 3, 1, 1),
-	EP("ep6", 6, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep0", 0, 64, 1, 0, 0),
+	AT91_UDC_HS_EP("ep1", 1, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep2", 2, 1024, 2, 1, 1),
+	AT91_UDC_HS_EP("ep3", 3, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep4", 4, 1024, 3, 1, 0),
+	AT91_UDC_HS_EP("ep5", 5, 1024, 3, 1, 1),
+	AT91_UDC_HS_EP("ep6", 6, 1024, 3, 1, 1),
 };
 
-#undef EP
-
-/*
- * pdata doesn't have room for any endpoints, so we need to
- * append room for the ones we need right after it.
- */
-static struct {
-	struct usba_platform_data pdata;
-	struct usba_ep_data ep[7];
-} usba_udc_data;
-
-static struct platform_device at91_usba_udc_device = {
-	.name		= "atmel_usba_udc",
-	.id		= -1,
-	.dev		= {
-				.platform_data	= &usba_udc_data.pdata,
-	},
-	.resource	= usba_udc_resources,
-	.num_resources	= ARRAY_SIZE(usba_udc_resources),
+static struct at91_dev_table_udc_hs __initdata device_udc_hs = {
+	.fifo_base	= AT91SAM9RL_UDPHS_FIFO,
+	.mmio_base	= AT91SAM9RL_BASE_UDPHS,
+	.irq		= AT91SAM9RL_ID_UDPHS,
+	.endpoints	= usba_udc_ep,
+	.nr_endpoints	= ARRAY_SIZE(usba_udc_ep),
 };
 
-void __init at91_add_device_usba(struct usba_platform_data *data)
-{
-	/*
-	 * Invalid pins are 0 on AT91, but the usba driver is shared
-	 * with AVR32, which use negative values instead. Once/if
-	 * gpio_is_valid() is ported to AT91, revisit this code.
-	 */
-	usba_udc_data.pdata.vbus_pin = -EINVAL;
-	usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
-	memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));;
-
-	if (data && data->vbus_pin > 0) {
-		at91_set_gpio_input(data->vbus_pin, 0);
-		at91_set_deglitch(data->vbus_pin, 1);
-		usba_udc_data.pdata.vbus_pin = data->vbus_pin;
-	}
-
-	/* Pullup pin is handled internally by USB device peripheral */
-
-	/* Clocks */
-	at91_clock_associate("utmi_clk", &at91_usba_udc_device.dev, "hclk");
-	at91_clock_associate("udphs_clk", &at91_usba_udc_device.dev, "pclk");
-
-	platform_device_register(&at91_usba_udc_device);
-}
-#else
-void __init at91_add_device_usba(struct usba_platform_data *data) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  MMC / SD
  * -------------------------------------------------------------------- */
@@ -419,6 +346,7 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.lcdc		= &device_lcdc,
 	.tsadcc		= &device_tsadcc,
 	.hdmac		= &device_hdmac,
+	.udc_hs		= &device_udc_hs,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 40c305d..30e676d 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1767,6 +1767,85 @@ static void __init at91_add_device_rtc(void)
 static void __init at91_add_device_rtc(void) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  USB HS Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+static struct resource usba_udc_resources[] = {
+	[0] = {
+		.end	= SZ_512K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.end	= SZ_1K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[2] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/*
+ * pdata doesn't have room for any endpoints, so we need to
+ * append room for the ones we need right after it.
+ */
+static struct {
+	struct usba_platform_data pdata;
+	struct usba_ep_data ep[8];
+} usba_udc_data;
+
+static struct platform_device at91_usba_udc_device = {
+	.name		= "atmel_usba_udc",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &usba_udc_data.pdata,
+	},
+	.resource	= usba_udc_resources,
+	.num_resources	= ARRAY_SIZE(usba_udc_resources),
+};
+
+void __init at91_add_device_usba(struct usba_platform_data *data)
+{
+	struct at91_dev_table_udc_hs *info = devices->udc_hs;
+
+	BUG_ON(!info);
+	init_resource_mem(&usba_udc_resources[0], info->fifo_base);
+	init_resource_mem(&usba_udc_resources[1], info->mmio_base);
+	init_resource_irq(&usba_udc_resources[2], info->irq);
+
+	/* Custom platform initialisation */
+	if (info->device_init)
+		info->device_init();
+
+	/*
+	 * Invalid pins are 0 on AT91, but the usba driver is shared
+	 * with AVR32, which use negative values instead. Once/if
+	 * gpio_is_valid() is ported to AT91, revisit this code.
+	 */
+	usba_udc_data.pdata.vbus_pin = -EINVAL;
+	usba_udc_data.pdata.num_ep = info->nr_endpoints;
+	memcpy(usba_udc_data.ep, info->endpoints,
+	       info->nr_endpoints * sizeof(struct usba_ep_data));
+
+	if (data && data->vbus_pin > 0) {
+		at91_set_gpio_input(data->vbus_pin, 0);
+		at91_set_deglitch(data->vbus_pin, 1);
+		usba_udc_data.pdata.vbus_pin = data->vbus_pin;
+	}
+
+	/* Pullup pin is handled internally by USB device peripheral */
+
+	/* Clocks */
+	at91_clock_associate("utmi_clk", &at91_usba_udc_device.dev, "hclk");
+	at91_clock_associate("udphs_clk", &at91_usba_udc_device.dev, "pclk");
+
+	platform_device_register(&at91_usba_udc_device);
+}
+#else
+void __init at91_add_device_usba(struct usba_platform_data *data) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 417c959..a1374fa 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -170,6 +170,25 @@ struct at91_dev_table_hdmac {
 	int			have_slave;
 };
 
+#define AT91_UDC_HS_EP(nam, idx, maxpkt, maxbk, dma, isoc)	\
+	[idx] = {						\
+		.name		= nam,				\
+		.index		= idx,				\
+		.fifo_size	= maxpkt,			\
+		.nr_banks	= maxbk,			\
+		.can_dma	= dma,				\
+		.can_isoc	= isoc,				\
+	}
+
+struct at91_dev_table_udc_hs {
+	unsigned		fifo_base;
+	unsigned		mmio_base;
+	int			irq;
+	void			(*device_init)(void);
+	struct usba_ep_data	*endpoints;
+	int			nr_endpoints;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -189,6 +208,7 @@ struct at91_device_table {
 	struct at91_dev_table_lcdc		*lcdc;
 	struct at91_dev_table_tsadcc		*tsadcc;
 	struct at91_dev_table_hdmac		*hdmac;
+	struct at91_dev_table_udc_hs		*udc_hs;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 21/23] at91: Make compact flash device common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (19 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 20/23] at91: Make high speed USB gadget " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 22/23] at91: Move at91sam9263 CAN device to common devices Ryan Mallon
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual compact flash device code for each at91 variant with
a single implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91rm9200_devices.c  |   74 ++++++--------------
 arch/arm/mach-at91/at91sam9260_devices.c |  114 +++++++-----------------------
 arch/arm/mach-at91/at91sam9263_devices.c |  102 +++++++--------------------
 arch/arm/mach-at91/devices.c             |  105 +++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |   14 ++++
 5 files changed, 193 insertions(+), 216 deletions(-)

diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index fb53848..feb8de8 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -84,38 +84,12 @@ static struct __initdata at91_dev_table_ethernet device_eth = {
  *  Compact Flash / PCMCIA
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
-static struct at91_cf_data cf_data;
-
-#define CF_BASE		AT91_CHIPSELECT_4
-
-static struct resource cf_resources[] = {
-	[0] = {
-		.start	= CF_BASE,
-		/* ties up CS4, CS5 and CS6 */
-		.end	= CF_BASE + (0x30000000 - 1),
-		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
-	},
-};
-
-static struct platform_device at91rm9200_cf_device = {
-	.name		= "at91_cf",
-	.id		= -1,
-	.dev		= {
-				.platform_data		= &cf_data,
-	},
-	.resource	= cf_resources,
-	.num_resources	= ARRAY_SIZE(cf_resources),
-};
-
-void __init at91_add_device_cf(struct at91_cf_data *data)
+static int __init at91rm9200_cf_init(struct at91_cf_data *data, int *slot)
 {
 	unsigned int csa;
 
-	if (!data)
-		return;
-
 	data->chipselect = 4;		/* can only use EBI ChipSelect 4 */
+	*slot = 0;			/* only one CF slot */
 
 	/* CF takes over CS4, CS5, CS6 */
 	csa = at91_sys_read(AT91_EBI_CSA);
@@ -136,35 +110,30 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
 				| AT91_SMC_RWHOLD_(4)	/* hold time */
 	);
 
-	/* input/irq */
-	if (data->irq_pin) {
-		at91_set_gpio_input(data->irq_pin, 1);
-		at91_set_deglitch(data->irq_pin, 1);
-	}
-	at91_set_gpio_input(data->det_pin, 1);
-	at91_set_deglitch(data->det_pin, 1);
-
-	/* outputs, initially off */
-	if (data->vcc_pin)
-		at91_set_gpio_output(data->vcc_pin, 0);
-	at91_set_gpio_output(data->rst_pin, 0);
+	return 0;
+}
 
+static struct at91_pin_config __initdata cf_pins[] = {
 	/* force poweron defaults for these pins ... */
-	at91_set_A_periph(AT91_PIN_PC9, 0);	/* A25/CFRNW */
-	at91_set_A_periph(AT91_PIN_PC10, 0);	/* NCS4/CFCS */
-	at91_set_A_periph(AT91_PIN_PC11, 0);	/* NCS5/CFCE1 */
-	at91_set_A_periph(AT91_PIN_PC12, 0);	/* NCS6/CFCE2 */
+	{AT91_PIN_PC9,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* A25/CFRNW */
+	{AT91_PIN_PC10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* NCS4/CFCS */
+	{AT91_PIN_PC11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* NCS5/CFCE1 */
+	{AT91_PIN_PC12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* NCS6/CFCE2 */
 
 	/* nWAIT is _not_ a default setting */
-	at91_set_A_periph(AT91_PIN_PC6, 1);	/* nWAIT */
-
-	cf_data = *data;
-	platform_device_register(&at91rm9200_cf_device);
-}
-#else
-void __init at91_add_device_cf(struct at91_cf_data *data) {}
-#endif
+	{AT91_PIN_PC6,  AT91_PIN_PERIPH_A, 1, 0, 0},	/* nWAIT */
+};
 
+static struct at91_dev_table_cf __initdata device_cf = {
+	.slot[0]	= {
+		/* ties up CS4, CS5 and CS6 */
+		.mmio_base	= AT91_CHIPSELECT_4,
+		.mmio_size	= 0x30000000,
+	},
+	.device_init	= at91rm9200_cf_init,
+	.pins		= cf_pins,
+	.nr_pins	= ARRAY_SIZE(cf_pins),
+};
 
 /* --------------------------------------------------------------------
  *  MMC / SD
@@ -419,6 +388,7 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.ssc[0]		= &device_ssc0,
 	.ssc[1]		= &device_ssc1,
 	.ssc[2]		= &device_ssc2,
+	.cf		= &device_cf,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index e459ad6..bf3c921 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -318,56 +318,10 @@ static struct __initdata at91_dev_table_uart device_uart5 = {
  *  CF/IDE
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE) || \
-	defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
-	defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
-
-static struct at91_cf_data cf0_data;
-
-static struct resource cf0_resources[] = {
-	[0] = {
-		.start	= AT91_CHIPSELECT_4,
-		.end	= AT91_CHIPSELECT_4 + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device cf0_device = {
-	.id		= 0,
-	.dev		= {
-				.platform_data	= &cf0_data,
-	},
-	.resource	= cf0_resources,
-	.num_resources	= ARRAY_SIZE(cf0_resources),
-};
-
-static struct at91_cf_data cf1_data;
-
-static struct resource cf1_resources[] = {
-	[0] = {
-		.start	= AT91_CHIPSELECT_5,
-		.end	= AT91_CHIPSELECT_5 + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM,
-	}
-};
-
-static struct platform_device cf1_device = {
-	.id		= 1,
-	.dev		= {
-				.platform_data	= &cf1_data,
-	},
-	.resource	= cf1_resources,
-	.num_resources	= ARRAY_SIZE(cf1_resources),
-};
-
-void __init at91_add_device_cf(struct at91_cf_data *data)
+static int __init at91sam9260_cf_init(struct at91_cf_data *data, int *slot)
 {
-	struct platform_device *pdev;
 	unsigned long csa;
 
-	if (!data)
-		return;
-
 	csa = at91_sys_read(AT91_MATRIX_EBICSA);
 
 	switch (data->chipselect) {
@@ -375,61 +329,44 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
 		at91_set_multi_drive(AT91_PIN_PC8, 0);
 		at91_set_A_periph(AT91_PIN_PC8, 0);
 		csa |= AT91_MATRIX_CS4A_SMC_CF1;
-		cf0_data = *data;
-		pdev = &cf0_device;
+		*slot = 0;
 		break;
 	case 5:
 		at91_set_multi_drive(AT91_PIN_PC9, 0);
 		at91_set_A_periph(AT91_PIN_PC9, 0);
 		csa |= AT91_MATRIX_CS5A_SMC_CF2;
-		cf1_data = *data;
-		pdev = &cf1_device;
+		*slot = 1;
 		break;
 	default:
 		printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n",
 		       data->chipselect);
-		return;
+		return -EINVAL;
 	}
 
 	at91_sys_write(AT91_MATRIX_EBICSA, csa);
-
-	if (data->rst_pin) {
-		at91_set_multi_drive(data->rst_pin, 0);
-		at91_set_gpio_output(data->rst_pin, 1);
-	}
-
-	if (data->irq_pin) {
-		at91_set_gpio_input(data->irq_pin, 0);
-		at91_set_deglitch(data->irq_pin, 1);
-	}
-
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 0);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-
-	at91_set_B_periph(AT91_PIN_PC6, 0);     /* CFCE1 */
-	at91_set_B_periph(AT91_PIN_PC7, 0);     /* CFCE2 */
-	at91_set_A_periph(AT91_PIN_PC10, 0);    /* CFRNW */
-	at91_set_A_periph(AT91_PIN_PC15, 1);    /* NWAIT */
-
-	if (data->flags & AT91_CF_TRUE_IDE)
-#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE)
-		pdev->name = "pata_at91";
-#elif defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
-		pdev->name = "at91_ide";
-#else
-#warning "board requires AT91_CF_TRUE_IDE: enable either at91_ide or pata_at91"
-#endif
-	else
-		pdev->name = "at91_cf";
-
-	platform_device_register(pdev);
+	return 0;
 }
 
-#else
-void __init at91_add_device_cf(struct at91_cf_data * data) {}
-#endif
+static struct at91_pin_config __initdata cf_pins[] = {
+	{AT91_PIN_PC6,  AT91_PIN_PERIPH_B, 0, 0, 0}, /* CFCE1 */
+	{AT91_PIN_PC7,  AT91_PIN_PERIPH_B, 0, 0, 0}, /* CFCE2 */
+	{AT91_PIN_PC10, AT91_PIN_PERIPH_A, 0, 0, 0}, /* CFRNW */
+	{AT91_PIN_PC15, AT91_PIN_PERIPH_A, 1, 0, 0}, /* NWAIT */
+};
+
+static struct at91_dev_table_cf __initdata device_cf = {
+	.slot[0]	= {
+		.mmio_base	= AT91_CHIPSELECT_4,
+		.mmio_size	= SZ_256M,
+	},
+	.slot[1] 	= {
+		.mmio_base	= AT91_CHIPSELECT_5,
+		.mmio_size	= SZ_256M,
+	},
+	.device_init	= at91sam9260_cf_init,
+	.pins		= cf_pins,
+	.nr_pins	= ARRAY_SIZE(cf_pins),
+};
 
 static struct at91_device_table __initdata at91sam9260_device_table = {
 	.ethernet	= &device_eth,
@@ -451,6 +388,7 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.uart[4]	= &device_uart4,
 	.uart[5]	= &device_uart5,
 	.ssc[0]		= &device_ssc,
+	.cf		= &device_cf,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index f8c6f9c..7f2e99f 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -142,54 +142,9 @@ static struct __initdata at91_dev_table_mmc device_mmc1 = {
  *  Compact Flash (PCMCIA or IDE)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) || \
-    defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
-
-static struct at91_cf_data cf0_data;
-
-static struct resource cf0_resources[] = {
-	[0] = {
-		.start	= AT91_CHIPSELECT_4,
-		.end	= AT91_CHIPSELECT_4 + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
-	}
-};
-
-static struct platform_device cf0_device = {
-	.id		= 0,
-	.dev		= {
-				.platform_data	= &cf0_data,
-	},
-	.resource	= cf0_resources,
-	.num_resources	= ARRAY_SIZE(cf0_resources),
-};
-
-static struct at91_cf_data cf1_data;
-
-static struct resource cf1_resources[] = {
-	[0] = {
-		.start	= AT91_CHIPSELECT_5,
-		.end	= AT91_CHIPSELECT_5 + SZ_256M - 1,
-		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
-	}
-};
-
-static struct platform_device cf1_device = {
-	.id		= 1,
-	.dev		= {
-				.platform_data	= &cf1_data,
-	},
-	.resource	= cf1_resources,
-	.num_resources	= ARRAY_SIZE(cf1_resources),
-};
-
-void __init at91_add_device_cf(struct at91_cf_data *data)
+static int __init at91sam9263_cf_init(struct at91_cf_data *data, int *slot)
 {
 	unsigned long ebi0_csa;
-	struct platform_device *pdev;
-
-	if (!data)
-		return;
 
 	/*
 	 * assign CS4 or CS5 to SMC with Compact Flash logic support,
@@ -201,48 +156,42 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
 	case 4:
 		at91_set_A_periph(AT91_PIN_PD6, 0);  /* EBI0_NCS4/CFCS0 */
 		ebi0_csa |= AT91_MATRIX_EBI0_CS4A_SMC_CF1;
-		cf0_data = *data;
-		pdev = &cf0_device;
+		*slot = 0;
 		break;
 	case 5:
 		at91_set_A_periph(AT91_PIN_PD7, 0);  /* EBI0_NCS5/CFCS1 */
 		ebi0_csa |= AT91_MATRIX_EBI0_CS5A_SMC_CF2;
-		cf1_data = *data;
-		pdev = &cf1_device;
+		*slot = 1;
 		break;
 	default:
 		printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n",
 		       data->chipselect);
-		return;
+		return -EINVAL;
 	}
 	at91_sys_write(AT91_MATRIX_EBI0CSA, ebi0_csa);
+	return 0;
+}
 
-	if (data->det_pin) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-
-	if (data->irq_pin) {
-		at91_set_gpio_input(data->irq_pin, 1);
-		at91_set_deglitch(data->irq_pin, 1);
-	}
-
-	if (data->vcc_pin)
-		/* initially off */
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* enable EBI controlled pins */
-	at91_set_A_periph(AT91_PIN_PD5, 1);  /* NWAIT */
-	at91_set_A_periph(AT91_PIN_PD8, 0);  /* CFCE1 */
-	at91_set_A_periph(AT91_PIN_PD9, 0);  /* CFCE2 */
-	at91_set_A_periph(AT91_PIN_PD14, 0); /* CFNRW */
+static struct at91_pin_config __initdata cf_pins[] = {
+	{AT91_PIN_PD5,  AT91_PIN_PERIPH_A, 1, 0, 0}, /* NWAIT */
+	{AT91_PIN_PD8,  AT91_PIN_PERIPH_A, 0, 0, 0}, /* CFCE1 */
+	{AT91_PIN_PD9,  AT91_PIN_PERIPH_A, 0, 0, 0}, /* CFCE2 */
+	{AT91_PIN_PD14, AT91_PIN_PERIPH_A, 0, 0, 0}, /* CFNRW */
+};
 
-	pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "at91_ide" : "at91_cf";
-	platform_device_register(pdev);
-}
-#else
-void __init at91_add_device_cf(struct at91_cf_data *data) {}
-#endif
+static struct at91_dev_table_cf __initdata device_cf = {
+	.slot[0]	= {
+		.mmio_base	= AT91_CHIPSELECT_4,
+		.mmio_size	= SZ_256M,
+	},
+	.slot[1] 	= {
+		.mmio_base	= AT91_CHIPSELECT_5,
+		.mmio_size	= SZ_256M,
+	},
+	.device_init	= at91sam9263_cf_init,
+	.pins		= cf_pins,
+	.nr_pins	= ARRAY_SIZE(cf_pins),
+};
 
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
@@ -586,6 +535,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ssc[1]		= &device_ssc1,
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
+	.cf		= &device_cf,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 30e676d..054b64d 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1846,6 +1846,111 @@ void __init at91_add_device_usba(struct usba_platform_data *data)
 void __init at91_add_device_usba(struct usba_platform_data *data) {}
 #endif
 
+
+/* --------------------------------------------------------------------
+ *  Compact Flash (PCMCIA or IDE)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) || \
+    defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
+
+static struct at91_cf_data cf0_data;
+
+static struct resource cf0_resources[] = {
+	[0] = {
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+	}
+};
+
+static struct platform_device cf0_device = {
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &cf0_data,
+	},
+	.resource	= cf0_resources,
+	.num_resources	= ARRAY_SIZE(cf0_resources),
+};
+
+static struct at91_cf_data cf1_data;
+
+static struct resource cf1_resources[] = {
+	[0] = {
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+	}
+};
+
+static struct platform_device cf1_device = {
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &cf1_data,
+	},
+	.resource	= cf1_resources,
+	.num_resources	= ARRAY_SIZE(cf1_resources),
+};
+
+void __init at91_add_device_cf(struct at91_cf_data *data)
+{
+	struct at91_dev_table_cf *info = devices->cf;
+	struct platform_device *pdev;
+	int err, slot;
+
+	BUG_ON(!info);
+	if (!data)
+		return;
+
+	/* Platform specific device initialisation */
+	if (info->device_init) {
+		err = info->device_init(data, &slot);
+		if (err)
+			return;
+	}
+
+	cf0_resources[0].end = info->slot[slot].mmio_size;
+	init_resource_mem(&cf0_resources[0], info->slot[slot].mmio_base);
+
+	if (slot == 0) {
+		pdev = &cf0_device;
+		cf0_data = *data;
+	} else {
+		pdev = &cf1_device;
+		cf1_data = *data;
+	}
+
+	if (data->det_pin) {
+		at91_set_gpio_input(data->det_pin, 1);
+		at91_set_deglitch(data->det_pin, 1);
+	}
+
+	if (data->irq_pin) {
+		at91_set_gpio_input(data->irq_pin, 1);
+		at91_set_deglitch(data->irq_pin, 1);
+	}
+
+	/* outputs, initially off */
+	if (data->vcc_pin)
+		at91_set_gpio_output(data->vcc_pin, 0);
+	if (data->rst_pin)
+		at91_set_gpio_output(data->rst_pin, 0);
+
+	at91_config_pins(info->pins, info->nr_pins);
+
+	if (data->flags & AT91_CF_TRUE_IDE)
+#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE)
+		pdev->name = "pata_at91";
+#elif defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
+		pdev->name = "at91_ide";
+#else
+#warning "board requires AT91_CF_TRUE_IDE: enable either at91_ide or pata_at91"
+#endif
+	else
+		pdev->name = "at91_cf";
+
+	platform_device_register(pdev);
+}
+#else
+void __init at91_add_device_cf(struct at91_cf_data *data) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index a1374fa..74f1b9a 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -189,6 +189,19 @@ struct at91_dev_table_udc_hs {
 	int			nr_endpoints;
 };
 
+struct at91_cf_slot {
+	unsigned		mmio_base;
+	unsigned		mmio_size;
+};
+
+struct at91_dev_table_cf {
+	struct at91_cf_slot	slot[2];
+	int			(*device_init)(struct at91_cf_data *data,
+					       int *slot);
+	struct at91_pin_config	*pins;
+	int			nr_pins;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -209,6 +222,7 @@ struct at91_device_table {
 	struct at91_dev_table_tsadcc		*tsadcc;
 	struct at91_dev_table_hdmac		*hdmac;
 	struct at91_dev_table_udc_hs		*udc_hs;
+	struct at91_dev_table_cf		*cf;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 22/23] at91: Move at91sam9263 CAN device to common devices
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (20 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 21/23] at91: Make compact flash " Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:10 ` [RFC PATCH 23/23] at91: Remove mAgic and ISI device code Ryan Mallon
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

The CAN device is only used on the AT91SAM9263. Move it to the common
devices.c file to be consistent with other devices.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at91sam9263_devices.c |   37 +++++-----------------------
 arch/arm/mach-at91/devices.c             |   38 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/devices.h             |    7 +++++
 3 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 7f2e99f..5212480 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -263,39 +263,15 @@ static struct __initdata at91_dev_table_ac97 device_ac97 = {
  *  CAN Controller
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
-static struct resource can_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_CAN,
-		.end	= AT91SAM9263_BASE_CAN + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_CAN,
-		.end	= AT91SAM9263_ID_CAN,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_can device_can = {
+	.mmio_base	= AT91SAM9263_BASE_CAN,
+	.irq		= AT91SAM9263_ID_CAN,
+	.pins		= {
+		{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* CANTX */
+		{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* CANRX */
 	},
 };
 
-static struct platform_device at91sam9263_can_device = {
-	.name		= "at91_can",
-	.id		= -1,
-	.resource	= can_resources,
-	.num_resources	= ARRAY_SIZE(can_resources),
-};
-
-void __init at91_add_device_can(struct at91_can_data *data)
-{
-	at91_set_A_periph(AT91_PIN_PA13, 0);	/* CANTX */
-	at91_set_A_periph(AT91_PIN_PA14, 0);	/* CANRX */
-	at91sam9263_can_device.dev.platform_data = data;
-
-	platform_device_register(&at91sam9263_can_device);
-}
-#else
-void __init at91_add_device_can(struct at91_can_data *data) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  LCD Controller
  * -------------------------------------------------------------------- */
@@ -536,6 +512,7 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ac97		= &device_ac97,
 	.lcdc		= &device_lcdc,
 	.cf		= &device_cf,
+	.can		= &device_can,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 054b64d..fe16fd2 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -1951,6 +1951,44 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
 void __init at91_add_device_cf(struct at91_cf_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  CAN Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
+static struct resource can_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_can_device = {
+	.name		= "at91_can",
+	.id		= -1,
+	.resource	= can_resources,
+	.num_resources	= ARRAY_SIZE(can_resources),
+};
+
+void __init at91_add_device_can(struct at91_can_data *data)
+{
+	struct at91_dev_table_can *info = devices->can;
+
+	BUG_ON(!info);
+	init_resource_mem(&can_resources[0], info->mmio_base);
+	init_resource_irq(&can_resources[1], info->irq);
+
+	at91_config_pins(info->pins, ARRAY_SIZE(info->pins));
+	at91_can_device.dev.platform_data = data;
+	platform_device_register(&at91sam9263_can_device);
+}
+#else
+void __init at91_add_device_can(struct at91_can_data *data) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index 74f1b9a..846f36f 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -202,6 +202,12 @@ struct at91_dev_table_cf {
 	int			nr_pins;
 };
 
+struct at91_dev_table_can {
+	unsigned		mmio_base;
+	int			irq;
+	struct at91_pin_config	pins[2];	/* TX, RX */
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -223,6 +229,7 @@ struct at91_device_table {
 	struct at91_dev_table_hdmac		*hdmac;
 	struct at91_dev_table_udc_hs		*udc_hs;
 	struct at91_dev_table_cf		*cf;
+	struct at91_dev_table_can		*can;
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
-- 
1.7.0.4

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

* [RFC PATCH 23/23] at91: Remove mAgic and ISI device code
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (21 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 22/23] at91: Move at91sam9263 CAN device to common devices Ryan Mallon
@ 2011-04-20  1:10 ` Ryan Mallon
  2011-04-20  1:11 ` [RFC PATCH 12/23] at91: Make UART devices common Ryan Mallon
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:10 UTC (permalink / raw)
  To: linux-arm-kernel

The AT572D940HF mAgic device and the AT91SAM9263 ISI device do not
have drivers yet and therefore the platform code in arch/arm/mach-at91
is unused and can be removed.

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c  |   73 -----------------------------
 arch/arm/mach-at91/at91sam9263_devices.c  |   50 --------------------
 arch/arm/mach-at91/board-at572d940hf_ek.c |    2 -
 arch/arm/mach-at91/include/mach/board.h   |    6 --
 4 files changed, 0 insertions(+), 131 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index e002ef2..ffe2c0d 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -250,79 +250,6 @@ static struct __initdata at91_dev_table_uart device_uart2 = {
 	.cts_pin	= {AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-/* --------------------------------------------------------------------
- *  mAgic
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_MAGICV
-static struct resource mAgic_resources[] = {
-	{
-		.start = AT91_MAGIC_PM_BASE,
-		.end   = AT91_MAGIC_PM_BASE + AT91_MAGIC_PM_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = AT91_MAGIC_DM_I_BASE,
-		.end   = AT91_MAGIC_DM_I_BASE + AT91_MAGIC_DM_I_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = AT91_MAGIC_DM_F_BASE,
-		.end   = AT91_MAGIC_DM_F_BASE + AT91_MAGIC_DM_F_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = AT91_MAGIC_DM_DB_BASE,
-		.end   = AT91_MAGIC_DM_DB_BASE + AT91_MAGIC_DM_DB_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = AT91_MAGIC_REGS_BASE,
-		.end   = AT91_MAGIC_REGS_BASE + AT91_MAGIC_REGS_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = AT91_MAGIC_EXTPAGE_BASE,
-		.end   = AT91_MAGIC_EXTPAGE_BASE + AT91_MAGIC_EXTPAGE_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start  = AT572D940HF_ID_MSIRQ0,
-		.end    = AT572D940HF_ID_MSIRQ0,
-		.flags  = IORESOURCE_IRQ,
-	},
-	{
-		.start  = AT572D940HF_ID_MHALT,
-		.end    = AT572D940HF_ID_MHALT,
-		.flags  = IORESOURCE_IRQ,
-	},
-	{
-		.start  = AT572D940HF_ID_MEXC,
-		.end    = AT572D940HF_ID_MEXC,
-		.flags  = IORESOURCE_IRQ,
-	},
-	{
-		.start  = AT572D940HF_ID_MEDMA,
-		.end    = AT572D940HF_ID_MEDMA,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device mAgic_device = {
-	.name           = "mAgic",
-	.id             = -1,
-	.num_resources  = ARRAY_SIZE(mAgic_resources),
-	.resource       = mAgic_resources,
-};
-
-void __init at91_add_device_mAgic(void)
-{
-	platform_device_register(&mAgic_device);
-}
-#else
-void __init at91_add_device_mAgic(void) {}
-#endif
-
 static struct at91_device_table __initdata at572d940hf_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 5212480..3108029 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -309,56 +309,6 @@ static struct __initdata at91_dev_table_lcdc device_lcdc = {
 };
 
 /* --------------------------------------------------------------------
- *  Image Sensor Interface
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_VIDEO_AT91_ISI) || defined(CONFIG_VIDEO_AT91_ISI_MODULE)
-
-struct resource isi_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_ISI,
-		.end	= AT91SAM9263_BASE_ISI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_ISI,
-		.end	= AT91SAM9263_ID_ISI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9263_isi_device = {
-	.name		= "at91_isi",
-	.id		= -1,
-	.resource	= isi_resources,
-	.num_resources	= ARRAY_SIZE(isi_resources),
-};
-
-void __init at91_add_device_isi(void)
-{
-	at91_set_A_periph(AT91_PIN_PE0, 0);	/* ISI_D0 */
-	at91_set_A_periph(AT91_PIN_PE1, 0);	/* ISI_D1 */
-	at91_set_A_periph(AT91_PIN_PE2, 0);	/* ISI_D2 */
-	at91_set_A_periph(AT91_PIN_PE3, 0);	/* ISI_D3 */
-	at91_set_A_periph(AT91_PIN_PE4, 0);	/* ISI_D4 */
-	at91_set_A_periph(AT91_PIN_PE5, 0);	/* ISI_D5 */
-	at91_set_A_periph(AT91_PIN_PE6, 0);	/* ISI_D6 */
-	at91_set_A_periph(AT91_PIN_PE7, 0);	/* ISI_D7 */
-	at91_set_A_periph(AT91_PIN_PE8, 0);	/* ISI_PCK */
-	at91_set_A_periph(AT91_PIN_PE9, 0);	/* ISI_HSYNC */
-	at91_set_A_periph(AT91_PIN_PE10, 0);	/* ISI_VSYNC */
-	at91_set_B_periph(AT91_PIN_PE11, 0);	/* ISI_MCK (PCK3) */
-	at91_set_B_periph(AT91_PIN_PE12, 0);	/* ISI_PD8 */
-	at91_set_B_periph(AT91_PIN_PE13, 0);	/* ISI_PD9 */
-	at91_set_B_periph(AT91_PIN_PE14, 0);	/* ISI_PD10 */
-	at91_set_B_periph(AT91_PIN_PE15, 0);	/* ISI_PD11 */
-}
-#else
-void __init at91_add_device_isi(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
  *  Timer/Counter block
  * -------------------------------------------------------------------- */
 
diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c
index d768cdb..5ee7f6a 100644
--- a/arch/arm/mach-at91/board-at572d940hf_ek.c
+++ b/arch/arm/mach-at91/board-at572d940hf_ek.c
@@ -312,8 +312,6 @@ static void __init eb_board_init(void)
 	at91_add_device_mmc(0, &eb_mmc_data);
 	/* Ethernet */
 	at91_add_device_eth(&eb_eth_data);
-	/* mAgic */
-	at91_add_device_mAgic();
 }
 
 MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 851c6c2..cee6419 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -186,9 +186,6 @@ extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
  /* AC97 */
 extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
 
- /* ISI */
-extern void __init at91_add_device_isi(void);
-
  /* Touchscreen Controller */
 struct at91_tsadcc_data {
 	unsigned int    adc_clock;
@@ -208,9 +205,6 @@ extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
 extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
 
- /* AT572D940HF DSP */
-extern void __init at91_add_device_mAgic(void);
-
 /* FIXME: this needs a better location, but gets stuff building again */
 extern int at91_suspend_entering_slow_clock(void);
 
-- 
1.7.0.4

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

* [RFC PATCH 12/23] at91: Make UART devices common
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (22 preceding siblings ...)
  2011-04-20  1:10 ` [RFC PATCH 23/23] at91: Remove mAgic and ISI device code Ryan Mallon
@ 2011-04-20  1:11 ` Ryan Mallon
  2011-04-20  3:47 ` [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Jean-Christophe PLAGNIOL-VILLARD
  2011-04-20 17:14 ` H Hartley Sweeten
  25 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:11 UTC (permalink / raw)
  To: linux-arm-kernel

Replace the individual UART, including debug UART, code for each at91
vairiant with a single implementation in devices.c

Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
---
 arch/arm/mach-at91/at572d940hf_devices.c  |  267 +++--------------
 arch/arm/mach-at91/at91cap9_devices.c     |  285 ++++---------------
 arch/arm/mach-at91/at91rm9200_devices.c   |  358 +++++------------------
 arch/arm/mach-at91/at91sam9260_devices.c  |  449 ++++++-----------------------
 arch/arm/mach-at91/at91sam9261_devices.c  |  273 ++++--------------
 arch/arm/mach-at91/at91sam9263_devices.c  |  286 ++++---------------
 arch/arm/mach-at91/at91sam9g45_devices.c  |  348 +++++------------------
 arch/arm/mach-at91/at91sam9rl_devices.c   |  360 +++++------------------
 arch/arm/mach-at91/board-1arm.c           |    4 +-
 arch/arm/mach-at91/board-afeb-9260v1.c    |    4 +-
 arch/arm/mach-at91/board-at572d940hf_ek.c |    6 +-
 arch/arm/mach-at91/board-carmeva.c        |    2 +-
 arch/arm/mach-at91/board-cpu9krea.c       |   12 +-
 arch/arm/mach-at91/board-cpuat91.c        |    8 +-
 arch/arm/mach-at91/board-eb9200.c         |    4 +-
 arch/arm/mach-at91/board-ecbat91.c        |    2 +-
 arch/arm/mach-at91/board-foxg20.c         |   12 +-
 arch/arm/mach-at91/board-gsia18s.c        |   10 +-
 arch/arm/mach-at91/board-kafa.c           |    2 +-
 arch/arm/mach-at91/board-kb9202.c         |    6 +-
 arch/arm/mach-at91/board-neocore926.c     |    2 +-
 arch/arm/mach-at91/board-pcontrol-g20.c   |    6 +-
 arch/arm/mach-at91/board-picotux200.c     |    2 +-
 arch/arm/mach-at91/board-qil-a9260.c      |    6 +-
 arch/arm/mach-at91/board-rm9200dk.c       |    2 +-
 arch/arm/mach-at91/board-rm9200ek.c       |    2 +-
 arch/arm/mach-at91/board-sam9-l9260.c     |    4 +-
 arch/arm/mach-at91/board-sam9260ek.c      |    4 +-
 arch/arm/mach-at91/board-sam9263ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9g20ek.c      |    4 +-
 arch/arm/mach-at91/board-sam9m10g45ek.c   |    2 +-
 arch/arm/mach-at91/board-sam9rlek.c       |    2 +-
 arch/arm/mach-at91/board-snapper9260.c    |    6 +-
 arch/arm/mach-at91/board-stamp9g20.c      |   12 +-
 arch/arm/mach-at91/board-yl-9200.c        |    6 +-
 arch/arm/mach-at91/devices.c              |  303 +++++++++++++++++++
 arch/arm/mach-at91/devices.h              |   17 ++
 arch/arm/mach-at91/include/mach/board.h   |   10 +
 38 files changed, 922 insertions(+), 2168 deletions(-)

diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
index 20fe358..e002ef2 100644
--- a/arch/arm/mach-at91/at572d940hf_devices.c
+++ b/arch/arm/mach-at91/at572d940hf_devices.c
@@ -195,238 +195,61 @@ static struct __initdata at91_dev_table_rtt device_rtt = {
  *  UART
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at572d940hf_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PC31, 1);		/* DTXD */
-	at91_set_A_periph(AT91_PIN_PC30, 0);		/* DRXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_US0,
-		.end	= AT572D940HF_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_US0,
-		.end	= AT572D940HF_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
+	.tx_pin		= {AT91_PIN_PC31, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC30, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at572d940hf_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT572D940HF_BASE_US0,
+	.irq		= AT572D940HF_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
+	.tx_pin		= {AT91_PIN_PA8,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA7,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA10, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA9,  AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA8, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PA7, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PA10, 0);	/* RTS0 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PA9, 0);	/* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_US1,
-		.end	= AT572D940HF_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_US1,
-		.end	= AT572D940HF_ID_US1,
-		.flags	= IORESOURCE_IRQ,
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT572D940HF_BASE_US1,
+	.irq		= AT572D940HF_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
+	.tx_pin		= {AT91_PIN_PC10, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC9,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA11, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at572d940hf_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT572D940HF_BASE_US2,
+	.irq		= AT572D940HF_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
+	.tx_pin		= {AT91_PIN_PC15, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC14,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PC10, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PC9 , 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PC12, 0);	/* RTS1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PC11, 0);	/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT572D940HF_BASE_US2,
-		.end	= AT572D940HF_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT572D940HF_ID_US2,
-		.end	= AT572D940HF_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at572d940hf_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PC15, 1);		/* TXD2 */
-	at91_set_A_periph(AT91_PIN_PC14, 0);		/* RXD2 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PC17, 0);	/* RTS2 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PC16, 0);	/* CTS2 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at572d940hf_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT572D940HF_ID_US0:
-			pdev = &at572d940hf_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT572D940HF_ID_US1:
-			pdev = &at572d940hf_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT572D940HF_ID_US2:
-			pdev = &at572d940hf_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
 /* --------------------------------------------------------------------
  *  mAgic
  * -------------------------------------------------------------------- */
@@ -512,6 +335,10 @@ static struct at91_device_table __initdata at572d940hf_device_table = {
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb,
 	.rtt[0]		= &device_rtt,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
 };
 
 void __init at572d940hf_init_devices(void)
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 3a73ac8..9aa7b40 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -609,236 +609,61 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
  *  UART
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91cap9_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PC30, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PC31, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_US0,
-		.end	= AT91CAP9_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_US0,
-		.end	= AT91CAP9_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+	},
+	.tx_pin		= {AT91_PIN_PC31, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC30, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT91CAP9_BASE_US0,
+	.irq		= AT91CAP9_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PA22, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA25, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT91CAP9_BASE_US1,
+	.irq		= AT91CAP9_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PD0, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PD1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PD7, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PD8, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT91CAP9_BASE_US2,
+	.irq		= AT91CAP9_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PD2, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PD3, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PD5, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PD6, AT91_PIN_PERIPH_B, 0, 0, 0},
 };
 
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91cap9_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA22, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PA23, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PA24, 0);	/* RTS0 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PA25, 0);	/* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_US1,
-		.end	= AT91CAP9_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_US1,
-		.end	= AT91CAP9_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91cap9_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PD0, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PD1, 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PD7, 0);	/* RTS1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PD8, 0);	/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91CAP9_BASE_US2,
-		.end	= AT91CAP9_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91CAP9_ID_US2,
-		.end	= AT91CAP9_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91cap9_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PD2, 1);		/* TXD2 */
-	at91_set_A_periph(AT91_PIN_PD3, 0);		/* RXD2 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PD5, 0);	/* RTS2 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PD6, 0);	/* CTS2 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at91cap9_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT91CAP9_ID_US0:
-			pdev = &at91cap9_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT91CAP9_ID_US1:
-			pdev = &at91cap9_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT91CAP9_ID_US2:
-			pdev = &at91cap9_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
 static struct at91_device_table __initdata at91cap9_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
@@ -850,6 +675,10 @@ static struct at91_device_table __initdata at91cap9_device_table = {
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb,
 	.rtt[0]		= &device_rtt,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
 };
 
 void __init at91cap9_init_devices(void)
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 243054a..8f5ffb5 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -472,299 +472,84 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
  *  UART
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
+	.tx_pin		= {AT91_PIN_PC31, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC30, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PA30, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PA31, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US0,
-		.end	= AT91RM9200_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_US0,
-		.end	= AT91RM9200_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT91RM9200_BASE_US0,
+	.irq		= AT91RM9200_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA17, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PA18, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PA20, 0);	/* CTS0 */
-
-	if (pins & ATMEL_UART_RTS) {
-		/*
-		 * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
-		 *  We need to drive the pin manually.  Default is off (RTS is active low).
-		 */
-		at91_set_gpio_output(AT91_PIN_PA21, 1);
-	}
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US1,
-		.end	= AT91RM9200_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_US1,
-		.end	= AT91RM9200_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB20, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PB21, 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RI)
-		at91_set_A_periph(AT91_PIN_PB18, 0);	/* RI1 */
-	if (pins & ATMEL_UART_DTR)
-		at91_set_A_periph(AT91_PIN_PB19, 0);	/* DTR1 */
-	if (pins & ATMEL_UART_DCD)
-		at91_set_A_periph(AT91_PIN_PB23, 0);	/* DCD1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PB24, 0);	/* CTS1 */
-	if (pins & ATMEL_UART_DSR)
-		at91_set_A_periph(AT91_PIN_PB25, 0);	/* DSR1 */
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PB26, 0);	/* RTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US2,
-		.end	= AT91RM9200_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91RM9200_ID_US2,
-		.end	= AT91RM9200_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA22, 0);		/* RXD2 */
-	at91_set_A_periph(AT91_PIN_PA23, 1);		/* TXD2 */
-
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PA30, 0);	/* CTS2 */
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PA31, 0);	/* RTS2 */
-}
-
-static struct resource uart3_resources[] = {
-	[0] = {
-		.start	= AT91RM9200_BASE_US3,
-		.end	= AT91RM9200_BASE_US3 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+	.tx_pin		= {AT91_PIN_PA17, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA20, AT91_PIN_PERIPH_A, 0, 0, 0},
+	/*
+	 * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
+	 * We need to drive the pin manually.  Default is off (RTS is active
+	 * low).
+	 */	
+	.cts_pin	= {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 1, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT91RM9200_BASE_US1,
+	.irq		= AT91RM9200_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	[1] = {
-		.start	= AT91RM9200_ID_US3,
-		.end	= AT91RM9200_ID_US3,
-		.flags	= IORESOURCE_IRQ,
+	.tx_pin		= {AT91_PIN_PA20, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PB26, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA24, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.ri_pin		= {AT91_PIN_PB18, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.dtr_pin	= {AT91_PIN_PB19, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.dcd_pin	= {AT91_PIN_PB23, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.dsr_pin	= {AT91_PIN_PB25, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT91RM9200_BASE_US2,
+	.irq		= AT91RM9200_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-};
-
-static struct atmel_uart_data uart3_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart3_device = {
-	.name		= "atmel_usart",
-	.id		= 4,
-	.dev		= {
-				.dma_mask		= &uart3_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart3_data,
+	.tx_pin		= {AT91_PIN_PA23, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA22, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PB31, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA30, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart3 = {
+	.mmio_base	= AT91RM9200_BASE_US3,
+	.irq		= AT91RM9200_ID_US3,
+	.clock_asc	= "usart3_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	.resource	= uart3_resources,
-	.num_resources	= ARRAY_SIZE(uart3_resources),
+	.tx_pin		= {AT91_PIN_PA5, AT91_PIN_PERIPH_B, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA6, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PB1, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PB0, AT91_PIN_PERIPH_B, 0, 0, 0},
 };
 
-static inline void configure_usart3_pins(unsigned pins)
-{
-	at91_set_B_periph(AT91_PIN_PA5, 1);		/* TXD3 */
-	at91_set_B_periph(AT91_PIN_PA6, 0);		/* RXD3 */
-
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PB1, 0);	/* CTS3 */
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PB0, 0);	/* RTS3 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at91rm9200_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT91RM9200_ID_US0:
-			pdev = &at91rm9200_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT91RM9200_ID_US1:
-			pdev = &at91rm9200_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT91RM9200_ID_US2:
-			pdev = &at91rm9200_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		case AT91RM9200_ID_US3:
-			pdev = &at91rm9200_uart3_device;
-			configure_usart3_pins(pins);
-			at91_clock_associate("usart3_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-#else
-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
 static struct at91_device_table __initdata at91rm9200_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
@@ -775,6 +560,11 @@ static struct at91_device_table __initdata at91rm9200_device_table = {
 	.spi[0]		= &device_spi,
 	.tcb[0]		= &device_tcb0,
 	.tcb[1]		= &device_tcb1,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
+	.uart[3]	= &device_uart3,
 };
 
 void __init at91rm9200_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index b2b8416..2a99cd8 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -278,378 +278,104 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 /* --------------------------------------------------------------------
  *  UART
  * -------------------------------------------------------------------- */
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
 
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
+	.tx_pin		= {AT91_PIN_PB15, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB14, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB14, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PB15, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US0,
-		.end	= AT91SAM9260_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT91SAM9260_BASE_US0,
+	.irq		= AT91SAM9260_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US0,
-		.end	= AT91SAM9260_ID_US0,
-		.flags	= IORESOURCE_IRQ,
+	.tx_pin		= {AT91_PIN_PB4,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB5,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PB26, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PB27, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.dtr_pin	= {AT91_PIN_PB24, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.dsr_pin	= {AT91_PIN_PB22, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.dcd_pin	= {AT91_PIN_PB23, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.ri_pin		= {AT91_PIN_PB25, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT91SAM9260_BASE_US1,
+	.irq		= AT91SAM9260_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
+	.tx_pin		= {AT91_PIN_PB6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB7,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PB28, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PB29, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT91SAM9260_BASE_US2,
+	.irq		= AT91SAM9260_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB4, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PB5, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PB26, 0);	/* RTS0 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PB27, 0);	/* CTS0 */
-	if (pins & ATMEL_UART_DTR)
-		at91_set_A_periph(AT91_PIN_PB24, 0);	/* DTR0 */
-	if (pins & ATMEL_UART_DSR)
-		at91_set_A_periph(AT91_PIN_PB22, 0);	/* DSR0 */
-	if (pins & ATMEL_UART_DCD)
-		at91_set_A_periph(AT91_PIN_PB23, 0);	/* DCD0 */
-	if (pins & ATMEL_UART_RI)
-		at91_set_A_periph(AT91_PIN_PB25, 0);	/* RI0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US1,
-		.end	= AT91SAM9260_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+	.tx_pin		= {AT91_PIN_PB8, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB9, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA4, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA5, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart3 = {
+	.mmio_base	= AT91SAM9260_BASE_US3,
+	.irq		= AT91SAM9260_ID_US3,
+	.clock_asc	= "usart3_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US1,
-		.end	= AT91SAM9260_ID_US1,
-		.flags	= IORESOURCE_IRQ,
+	.tx_pin		= {AT91_PIN_PB10, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB11, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PC8,  AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PC10, AT91_PIN_PERIPH_B, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart4 = {
+	.mmio_base	= AT91SAM9260_BASE_US4,
+	.irq		= AT91SAM9260_ID_US4,
+	.clock_asc	= "usart4_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
+	.tx_pin		= {AT91_PIN_PA31, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA30, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB6, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PB7, 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PB28, 0);	/* RTS1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PB29, 0);	/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US2,
-		.end	= AT91SAM9260_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US2,
-		.end	= AT91SAM9260_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
+static struct __initdata at91_dev_table_uart device_uart5 = {
+	.mmio_base	= AT91SAM9260_BASE_US5,
+	.irq		= AT91SAM9260_ID_US5,
+	.clock_asc	= "usart5_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
+	.tx_pin		= {AT91_PIN_PB12, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB13, AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB8, 1);		/* TXD2 */
-	at91_set_A_periph(AT91_PIN_PB9, 0);		/* RXD2 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PA4, 0);	/* RTS2 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PA5, 0);	/* CTS2 */
-}
-
-static struct resource uart3_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US3,
-		.end	= AT91SAM9260_BASE_US3 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US3,
-		.end	= AT91SAM9260_ID_US3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart3_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart3_device = {
-	.name		= "atmel_usart",
-	.id		= 4,
-	.dev		= {
-				.dma_mask		= &uart3_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart3_data,
-	},
-	.resource	= uart3_resources,
-	.num_resources	= ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB10, 1);		/* TXD3 */
-	at91_set_A_periph(AT91_PIN_PB11, 0);		/* RXD3 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PC8, 0);	/* RTS3 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PC10, 0);	/* CTS3 */
-}
-
-static struct resource uart4_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US4,
-		.end	= AT91SAM9260_BASE_US4 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US4,
-		.end	= AT91SAM9260_ID_US4,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart4_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart4_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart4_device = {
-	.name		= "atmel_usart",
-	.id		= 5,
-	.dev		= {
-				.dma_mask		= &uart4_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart4_data,
-	},
-	.resource	= uart4_resources,
-	.num_resources	= ARRAY_SIZE(uart4_resources),
-};
-
-static inline void configure_usart4_pins(void)
-{
-	at91_set_B_periph(AT91_PIN_PA31, 1);		/* TXD4 */
-	at91_set_B_periph(AT91_PIN_PA30, 0);		/* RXD4 */
-}
-
-static struct resource uart5_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_US5,
-		.end	= AT91SAM9260_BASE_US5 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9260_ID_US5,
-		.end	= AT91SAM9260_ID_US5,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart5_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart5_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart5_device = {
-	.name		= "atmel_usart",
-	.id		= 6,
-	.dev		= {
-				.dma_mask		= &uart5_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart5_data,
-	},
-	.resource	= uart5_resources,
-	.num_resources	= ARRAY_SIZE(uart5_resources),
-};
-
-static inline void configure_usart5_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB12, 1);		/* TXD5 */
-	at91_set_A_periph(AT91_PIN_PB13, 0);		/* RXD5 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at91sam9260_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT91SAM9260_ID_US0:
-			pdev = &at91sam9260_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9260_ID_US1:
-			pdev = &at91sam9260_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9260_ID_US2:
-			pdev = &at91sam9260_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9260_ID_US3:
-			pdev = &at91sam9260_uart3_device;
-			configure_usart3_pins(pins);
-			at91_clock_associate("usart3_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9260_ID_US4:
-			pdev = &at91sam9260_uart4_device;
-			configure_usart4_pins();
-			at91_clock_associate("usart4_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9260_ID_US5:
-			pdev = &at91sam9260_uart5_device;
-			configure_usart5_pins();
-			at91_clock_associate("usart5_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
 /* --------------------------------------------------------------------
  *  CF/IDE
  * -------------------------------------------------------------------- */
@@ -779,6 +505,13 @@ static struct at91_device_table __initdata at91sam9260_device_table = {
 	.tcb[0]		= &device_tcb0,
 	.tcb[1]		= &device_tcb1,
 	.rtt[0]		= &device_rtt,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
+	.uart[3]	= &device_uart3,
+	.uart[4]	= &device_uart4,
+	.uart[5]	= &device_uart5,
 };
 
 void __init at91sam9260_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 6f719d5..c355c23 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -425,236 +425,61 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
  *  UART
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PA9, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PA10, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_US0,
-		.end	= AT91SAM9261_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_US0,
-		.end	= AT91SAM9261_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PC8, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PC9, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PC10, 0);	/* RTS0 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PC11, 0);	/* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_US1,
-		.end	= AT91SAM9261_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9261_ID_US1,
-		.end	= AT91SAM9261_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
+	.tx_pin		= {AT91_PIN_PA10, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA9,  AT91_PIN_PERIPH_A, 0, 0, 0},
 };
 
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PC12, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PC13, 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PA12, 0);	/* RTS1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PA13, 0);	/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9261_BASE_US2,
-		.end	= AT91SAM9261_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT91SAM9261_BASE_US0,
+	.irq		= AT91SAM9261_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	[1] = {
-		.start	= AT91SAM9261_ID_US2,
-		.end	= AT91SAM9261_ID_US2,
-		.flags	= IORESOURCE_IRQ,
+	.tx_pin		= {AT91_PIN_PC8,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC9,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PC10, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PC11, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT91SAM9261_BASE_US1,
+	.irq		= AT91SAM9261_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
+	.tx_pin		= {AT91_PIN_PC12, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC13, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA12, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA13, AT91_PIN_PERIPH_B, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT91SAM9261_BASE_US2,
+	.irq		= AT91SAM9261_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
 	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
+	.tx_pin		= {AT91_PIN_PC14, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC15, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA15, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA16, AT91_PIN_PERIPH_B, 0, 0, 0},
 };
 
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PC15, 0);		/* RXD2 */
-	at91_set_A_periph(AT91_PIN_PC14, 1);		/* TXD2 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PA15, 0);	/* RTS2*/
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PA16, 0);	/* CTS2 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at91sam9261_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT91SAM9261_ID_US0:
-			pdev = &at91sam9261_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9261_ID_US1:
-			pdev = &at91sam9261_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9261_ID_US2:
-			pdev = &at91sam9261_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
 static struct at91_device_table __initdata at91sam9261_device_table = {
 	.usbh_ohci	= &device_usbh_ohci,
 	.udc		= &device_udc,
@@ -665,6 +490,10 @@ static struct at91_device_table __initdata at91sam9261_device_table = {
 	.spi[1]		= &device_spi1,
 	.tcb[0]		= &device_tcb,
 	.rtt[0]		= &device_rtt,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
 };
 
 void __init at91sam9261_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 1e8e84a..e5f0164 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -715,237 +715,61 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
  *  UART
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SERIAL_ATMEL)
-
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PC30, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PC31, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_US0,
-		.end	= AT91SAM9263_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_US0,
-		.end	= AT91SAM9263_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA26, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PA27, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PA28, 0);	/* RTS0 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PA29, 0);	/* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_US1,
-		.end	= AT91SAM9263_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_US1,
-		.end	= AT91SAM9263_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+	},
+	.tx_pin		= {AT91_PIN_PC31, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PC30, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT91SAM9263_BASE_US0,
+	.irq		= AT91SAM9263_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PA26, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA27, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA28, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA29, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT91SAM9263_BASE_US1,
+	.irq		= AT91SAM9263_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PD0, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PD1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PD7, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PD8, AT91_PIN_PERIPH_B, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT91SAM9263_BASE_US2,
+	.irq		= AT91SAM9263_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PD2, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PD3, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PD5, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PD6, AT91_PIN_PERIPH_B, 0, 0, 0},
 };
 
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PD0, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PD1, 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PD7, 0);	/* RTS1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PD8, 0);	/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9263_BASE_US2,
-		.end	= AT91SAM9263_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9263_ID_US2,
-		.end	= AT91SAM9263_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PD2, 1);		/* TXD2 */
-	at91_set_A_periph(AT91_PIN_PD3, 0);		/* RXD2 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PD5, 0);	/* RTS2 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PD6, 0);	/* CTS2 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at91sam9263_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT91SAM9263_ID_US0:
-			pdev = &at91sam9263_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9263_ID_US1:
-			pdev = &at91sam9263_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9263_ID_US2:
-			pdev = &at91sam9263_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
 static struct at91_device_table __initdata at91sam9263_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usbh_ohci,
@@ -959,6 +783,10 @@ static struct at91_device_table __initdata at91sam9263_device_table = {
 	.tcb[0]		= &device_tcb,
 	.rtt[0]		= &device_rtt0,
 	.rtt[1]		= &device_rtt1,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
 };
 
 void __init at91sam9263_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 16006d5..c832917 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -748,284 +748,75 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
  *  UART
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PB12, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PB13, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_US0,
-		.end	= AT91SAM9G45_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_US0,
-		.end	= AT91SAM9G45_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB19, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PB18, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PB17, 0);	/* RTS0 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PB15, 0);	/* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_US1,
-		.end	= AT91SAM9G45_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_US1,
-		.end	= AT91SAM9G45_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB4, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PB5, 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PD16, 0);	/* RTS1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PD17, 0);	/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_US2,
-		.end	= AT91SAM9G45_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_US2,
-		.end	= AT91SAM9G45_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+	},
+	.tx_pin		= {AT91_PIN_PB13, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB12, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT91SAM9G45_BASE_US0,
+	.irq		= AT91SAM9G45_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PA19, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PB17, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PB15, AT91_PIN_PERIPH_B, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT91SAM9G45_BASE_US1,
+	.irq		= AT91SAM9G45_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PB4,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB5,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PD16, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PD17, AT91_PIN_PERIPH_B, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT91SAM9G45_BASE_US2,
+	.irq		= AT91SAM9G45_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PB6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB7,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PC9,  AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PC11, AT91_PIN_PERIPH_B, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart3 = {
+	.mmio_base	= AT91SAM9G45_BASE_US3,
+	.irq		= AT91SAM9G45_ID_US3,
+	.clock_asc	= "usart3_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PB8,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB9,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA23, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA24, AT91_PIN_PERIPH_B, 0, 0, 0},
 };
 
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB6, 1);		/* TXD2 */
-	at91_set_A_periph(AT91_PIN_PB7, 0);		/* RXD2 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PC9, 0);	/* RTS2 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PC11, 0);	/* CTS2 */
-}
-
-static struct resource uart3_resources[] = {
-	[0] = {
-		.start	= AT91SAM9G45_BASE_US3,
-		.end	= AT91SAM9G45_BASE_US3 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9G45_ID_US3,
-		.end	= AT91SAM9G45_ID_US3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart3_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart3_device = {
-	.name		= "atmel_usart",
-	.id		= 4,
-	.dev		= {
-				.dma_mask		= &uart3_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart3_data,
-	},
-	.resource	= uart3_resources,
-	.num_resources	= ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB8, 1);		/* TXD3 */
-	at91_set_A_periph(AT91_PIN_PB9, 0);		/* RXD3 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PA23, 0);	/* RTS3 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PA24, 0);	/* CTS3 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at91sam9g45_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT91SAM9G45_ID_US0:
-			pdev = &at91sam9g45_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9G45_ID_US1:
-			pdev = &at91sam9g45_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9G45_ID_US2:
-			pdev = &at91sam9g45_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9G45_ID_US3:
-			pdev = &at91sam9g45_uart3_device;
-			configure_usart3_pins(pins);
-			at91_clock_associate("usart3_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
 static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.ethernet	= &device_eth,
 	.usbh_ohci	= &device_usb_ohci,
@@ -1040,6 +831,11 @@ static struct at91_device_table __initdata at91sam9g45_device_table = {
 	.tcb[0]		= &device_tcb0,
 	.tcb[1]		= &device_tcb1,
 	.rtt[0]		= &device_rtt,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
+	.uart[3]	= &device_uart3,
 };
 
 void __init at91sam9g45_init_devices(void)
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index a6ce60c..e7a1fe1 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -626,292 +626,79 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
  *  UART
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-	[0] = {
-		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
-		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91_ID_SYS,
-		.end	= AT91_ID_SYS,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data dbgu_data = {
-	.use_dma_tx	= 0,
-	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
-	.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_dbgu_device = {
-	.name		= "atmel_usart",
-	.id		= 0,
-	.dev		= {
-				.dma_mask		= &dbgu_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &dbgu_data,
-	},
-	.resource	= dbgu_resources,
-	.num_resources	= ARRAY_SIZE(dbgu_resources),
+static struct __initdata at91_dev_table_uart device_dbgu = {
+	.mmio_base	= AT91_VA_BASE_SYS + AT91_DBGU,
+	.irq		= AT91_ID_SYS,
+	.clock_asc	= "mck",
+	.uart_data	= {
+		.use_dma_tx	= 0,
+		.use_dma_rx	= 0,
+		.regs		= (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+	},
+	.tx_pin		= {AT91_PIN_PA22, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA21, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart0 = {
+	.mmio_base	= AT91SAM9RL_BASE_US0,
+	.irq		= AT91SAM9RL_ID_US0,
+	.clock_asc	= "usart0_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PA6,  AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA7,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA9,  AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA10, AT91_PIN_PERIPH_A, 0, 0, 0},	
+	.dsr_pin	= {AT91_PIN_PD14, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.dtr_pin	= {AT91_PIN_PD15, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.dcd_pin	= {AT91_PIN_PD16, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.ri_pin		= {AT91_PIN_PD17, AT91_PIN_PERIPH_A, 0, 0, 0},
+};
+
+static struct __initdata at91_dev_table_uart device_uart1 = {
+	.mmio_base	= AT91SAM9RL_BASE_US1,
+	.irq		= AT91SAM9RL_ID_US1,
+	.clock_asc	= "usart1_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PA11, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA18, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA19, AT91_PIN_PERIPH_B, 0, 0, 0},	
+};
+
+static struct __initdata at91_dev_table_uart device_uart2 = {
+	.mmio_base	= AT91SAM9RL_BASE_US2,
+	.irq		= AT91SAM9RL_ID_US2,
+	.clock_asc	= "usart2_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PA13, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PA29, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PA30, AT91_PIN_PERIPH_A, 0, 0, 0},	
+};
+
+static struct __initdata at91_dev_table_uart device_uart3 = {
+	.mmio_base	= AT91SAM9RL_BASE_US3,
+	.irq		= AT91SAM9RL_ID_US3,
+	.clock_asc	= "usart3_clk",
+	.uart_data	= {
+		.use_dma_tx	= 1,
+		.use_dma_rx	= 1,
+	},
+	.tx_pin		= {AT91_PIN_PB0, AT91_PIN_PERIPH_A, 1, 0, 0},
+	.rx_pin		= {AT91_PIN_PB1, AT91_PIN_PERIPH_A, 0, 0, 0},
+	.rts_pin	= {AT91_PIN_PD4, AT91_PIN_PERIPH_B, 0, 0, 0},
+	.cts_pin	= {AT91_PIN_PD3, AT91_PIN_PERIPH_B, 0, 0, 0},	
 };
 
-static inline void configure_dbgu_pins(void)
-{
-	at91_set_A_periph(AT91_PIN_PA21, 0);		/* DRXD */
-	at91_set_A_periph(AT91_PIN_PA22, 1);		/* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_US0,
-		.end	= AT91SAM9RL_BASE_US0 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_US0,
-		.end	= AT91SAM9RL_ID_US0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart0_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart0_device = {
-	.name		= "atmel_usart",
-	.id		= 1,
-	.dev		= {
-				.dma_mask		= &uart0_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart0_data,
-	},
-	.resource	= uart0_resources,
-	.num_resources	= ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA6, 1);		/* TXD0 */
-	at91_set_A_periph(AT91_PIN_PA7, 0);		/* RXD0 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PA9, 0);	/* RTS0 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PA10, 0);	/* CTS0 */
-	if (pins & ATMEL_UART_DSR)
-		at91_set_A_periph(AT91_PIN_PD14, 0);	/* DSR0 */
-	if (pins & ATMEL_UART_DTR)
-		at91_set_A_periph(AT91_PIN_PD15, 0);	/* DTR0 */
-	if (pins & ATMEL_UART_DCD)
-		at91_set_A_periph(AT91_PIN_PD16, 0);	/* DCD0 */
-	if (pins & ATMEL_UART_RI)
-		at91_set_A_periph(AT91_PIN_PD17, 0);	/* RI0 */
-}
-
-static struct resource uart1_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_US1,
-		.end	= AT91SAM9RL_BASE_US1 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_US1,
-		.end	= AT91SAM9RL_ID_US1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart1_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart1_device = {
-	.name		= "atmel_usart",
-	.id		= 2,
-	.dev		= {
-				.dma_mask		= &uart1_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart1_data,
-	},
-	.resource	= uart1_resources,
-	.num_resources	= ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA11, 1);		/* TXD1 */
-	at91_set_A_periph(AT91_PIN_PA12, 0);		/* RXD1 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PA18, 0);	/* RTS1 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PA19, 0);	/* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_US2,
-		.end	= AT91SAM9RL_BASE_US2 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_US2,
-		.end	= AT91SAM9RL_ID_US2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart2_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart2_device = {
-	.name		= "atmel_usart",
-	.id		= 3,
-	.dev		= {
-				.dma_mask		= &uart2_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart2_data,
-	},
-	.resource	= uart2_resources,
-	.num_resources	= ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PA13, 1);		/* TXD2 */
-	at91_set_A_periph(AT91_PIN_PA14, 0);		/* RXD2 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_A_periph(AT91_PIN_PA29, 0);	/* RTS2 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_A_periph(AT91_PIN_PA30, 0);	/* CTS2 */
-}
-
-static struct resource uart3_resources[] = {
-	[0] = {
-		.start	= AT91SAM9RL_BASE_US3,
-		.end	= AT91SAM9RL_BASE_US3 + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= AT91SAM9RL_ID_US3,
-		.end	= AT91SAM9RL_ID_US3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct atmel_uart_data uart3_data = {
-	.use_dma_tx	= 1,
-	.use_dma_rx	= 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart3_device = {
-	.name		= "atmel_usart",
-	.id		= 4,
-	.dev		= {
-				.dma_mask		= &uart3_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &uart3_data,
-	},
-	.resource	= uart3_resources,
-	.num_resources	= ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(unsigned pins)
-{
-	at91_set_A_periph(AT91_PIN_PB0, 1);		/* TXD3 */
-	at91_set_A_periph(AT91_PIN_PB1, 0);		/* RXD3 */
-
-	if (pins & ATMEL_UART_RTS)
-		at91_set_B_periph(AT91_PIN_PD4, 0);	/* RTS3 */
-	if (pins & ATMEL_UART_CTS)
-		at91_set_B_periph(AT91_PIN_PD3, 0);	/* CTS3 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];	/* the UARTs to use */
-struct platform_device *atmel_default_console_device;	/* the serial console device */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-	struct platform_device *pdev;
-
-	switch (id) {
-		case 0:		/* DBGU */
-			pdev = &at91sam9rl_dbgu_device;
-			configure_dbgu_pins();
-			at91_clock_associate("mck", &pdev->dev, "usart");
-			break;
-		case AT91SAM9RL_ID_US0:
-			pdev = &at91sam9rl_uart0_device;
-			configure_usart0_pins(pins);
-			at91_clock_associate("usart0_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9RL_ID_US1:
-			pdev = &at91sam9rl_uart1_device;
-			configure_usart1_pins(pins);
-			at91_clock_associate("usart1_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9RL_ID_US2:
-			pdev = &at91sam9rl_uart2_device;
-			configure_usart2_pins(pins);
-			at91_clock_associate("usart2_clk", &pdev->dev, "usart");
-			break;
-		case AT91SAM9RL_ID_US3:
-			pdev = &at91sam9rl_uart3_device;
-			configure_usart3_pins(pins);
-			at91_clock_associate("usart3_clk", &pdev->dev, "usart");
-			break;
-		default:
-			return;
-	}
-	pdev->id = portnr;		/* update to mapped ID */
-
-	if (portnr < ATMEL_MAX_UART)
-		at91_uarts[portnr] = pdev;
-}
-
-void __init at91_set_serial_console(unsigned portnr)
-{
-	if (portnr < ATMEL_MAX_UART)
-		atmel_default_console_device = at91_uarts[portnr];
-}
-
-void __init at91_add_device_serial(void)
-{
-	int i;
-
-	for (i = 0; i < ATMEL_MAX_UART; i++) {
-		if (at91_uarts[i])
-			platform_device_register(at91_uarts[i]);
-	}
-
-	if (!atmel_default_console_device)
-		printk(KERN_INFO "AT91: No default serial console defined.\n");
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_set_serial_console(unsigned portnr) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
 static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.mmc[0]		= &device_mmc,
 	.nand		= &device_nand,
@@ -919,6 +706,11 @@ static struct at91_device_table __initdata at91sam9rl_device_table = {
 	.spi[0]		= &device_spi,
 	.tcb[0]		= &device_tcb,
 	.rtt[0]		= &device_rtt,
+	.dbgu		= &device_dbgu,
+	.uart[0]	= &device_uart0,
+	.uart[1]	= &device_uart1,
+	.uart[2]	= &device_uart2,
+	.uart[3]	= &device_uart3,
 };
 
 void __init at91sam9rl_init_devices(void)
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 244e8bb..4d9e036 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -48,10 +48,10 @@ static void __init onearm_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* USART1 on ttyS2 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index c64b7d6..4c382c3 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -57,13 +57,13 @@ static void __init afeb9260_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1,
+	at91_register_uart(AT91_ID_US0, 1,
 			     ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR
 			   | ATMEL_UART_DCD | ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2,
+	at91_register_uart(AT91_ID_US1, 2,
 			ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
diff --git a/arch/arm/mach-at91/board-at572d940hf_ek.c b/arch/arm/mach-at91/board-at572d940hf_ek.c
index edbbce4..d768cdb 100644
--- a/arch/arm/mach-at91/board-at572d940hf_ek.c
+++ b/arch/arm/mach-at91/board-at572d940hf_ek.c
@@ -55,13 +55,13 @@ static void __init eb_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx & Tx only) */
-	at91_register_uart(AT572D940HF_ID_US0, 1, 0);
+	at91_register_uart(AT91_ID_US0, 1, 0);
 
 	/* USART1 on ttyS2. (Rx & Tx only) */
-	at91_register_uart(AT572D940HF_ID_US1, 2, 0);
+	at91_register_uart(AT91_ID_US1, 2, 0);
 
 	/* USART2 on ttyS3. (Tx & Rx only */
-	at91_register_uart(AT572D940HF_ID_US2, 3, 0);
+	at91_register_uart(AT91_ID_US2, 3, 0);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index b9033cb..336dfd5 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -49,7 +49,7 @@ static void __init carmeva_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 9a88ca0..dd79122 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -56,26 +56,26 @@ static void __init cpu9krea_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS |
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS |
 		ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
 		ATMEL_UART_DCD | ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS |
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS |
 		ATMEL_UART_RTS);
 
 	/* USART2 on ttyS3. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS |
+	at91_register_uart(AT91_ID_US2, 3, ATMEL_UART_CTS |
 		ATMEL_UART_RTS);
 
 	/* USART3 on ttyS4. (Rx, Tx) */
-	at91_register_uart(AT91SAM9260_ID_US3, 4, 0);
+	at91_register_uart(AT91_ID_US3, 4, 0);
 
 	/* USART4 on ttyS5. (Rx, Tx) */
-	at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+	at91_register_uart(AT91_ID_US4, 5, 0);
 
 	/* USART5 on ttyS6. (Rx, Tx) */
-	at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
+	at91_register_uart(AT91_ID_US5, 6, 0);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index fbdd54b..ddf6b32 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -59,19 +59,19 @@ static void __init cpuat91_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS |
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS |
 		ATMEL_UART_RTS);
 
 	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS |
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS |
 		ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
 		ATMEL_UART_DCD | ATMEL_UART_RI);
 
 	/* USART2 on ttyS3 (Rx, Tx) */
-	at91_register_uart(AT91RM9200_ID_US2, 3, 0);
+	at91_register_uart(AT91_ID_US2, 3, 0);
 
 	/* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS |
+	at91_register_uart(AT91_ID_US3, 4, ATMEL_UART_CTS |
 		ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index eed4d6c..26e002b 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -49,12 +49,12 @@ static void __init eb9200_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			| ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			| ATMEL_UART_RI);
 
 	/* USART2 on ttyS2. (Rx, Tx) - IRDA */
-	at91_register_uart(AT91RM9200_ID_US2, 2, 0);
+	at91_register_uart(AT91_ID_US2, 2, 0);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index b730b01..d4c1985 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -54,7 +54,7 @@ static void __init ecb_at91map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx & Tx only) */
-	at91_register_uart(AT91RM9200_ID_US0, 1, 0);
+	at91_register_uart(AT91_ID_US0, 1, 0);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index 79c54fc..f0a021c 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -66,7 +66,7 @@ static void __init foxg20_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1,
+	at91_register_uart(AT91_ID_US0, 1,
 				ATMEL_UART_CTS
 				| ATMEL_UART_RTS
 				| ATMEL_UART_DTR
@@ -75,23 +75,23 @@ static void __init foxg20_map_io(void)
 				| ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2,
+	at91_register_uart(AT91_ID_US1, 2,
 		ATMEL_UART_CTS
 		| ATMEL_UART_RTS);
 
 	/* USART2 on ttyS3. (Rx & Tx only) */
-	at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
+	at91_register_uart(AT91_ID_US2, 3, 0);
 
 	/* USART3 on ttyS4. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US3, 4,
+	at91_register_uart(AT91_ID_US3, 4,
 		ATMEL_UART_CTS
 		| ATMEL_UART_RTS);
 
 	/* USART4 on ttyS5. (Rx & Tx only) */
-	at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+	at91_register_uart(AT91_ID_US4, 5, 0);
 
 	/* USART5 on ttyS6. (Rx & Tx only) */
-	at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
+	at91_register_uart(AT91_ID_US5, 6, 0);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index e32833d..6f04b3a 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -46,7 +46,7 @@ static void __init gsia18s_map_io(void)
 	 * USART0 on ttyS1 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI).
 	 * Used for Internal Analog Modem.
 	 */
-	at91_register_uart(AT91SAM9260_ID_US0, 1,
+	at91_register_uart(AT91_ID_US0, 1,
 				ATMEL_UART_CTS | ATMEL_UART_RTS |
 				ATMEL_UART_DTR | ATMEL_UART_DSR |
 				ATMEL_UART_DCD | ATMEL_UART_RI);
@@ -54,25 +54,25 @@ static void __init gsia18s_map_io(void)
 	 * USART1 on ttyS2 (Rx, Tx, CTS, RTS).
 	 * Used for GPS or WiFi or Data stream.
 	 */
-	at91_register_uart(AT91SAM9260_ID_US1, 2,
+	at91_register_uart(AT91_ID_US1, 2,
 				ATMEL_UART_CTS | ATMEL_UART_RTS);
 	/*
 	 * USART2 on ttyS3 (Rx, Tx, CTS, RTS).
 	 * Used for External Modem.
 	 */
-	at91_register_uart(AT91SAM9260_ID_US2, 3,
+	at91_register_uart(AT91_ID_US2, 3,
 				ATMEL_UART_CTS | ATMEL_UART_RTS);
 	/*
 	 * USART3 on ttyS4 (Rx, Tx, RTS).
 	 * Used for RS-485.
 	 */
-	at91_register_uart(AT91SAM9260_ID_US3, 4, ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US3, 4, ATMEL_UART_RTS);
 
 	/*
 	 * USART4 on ttyS5 (Rx, Tx).
 	 * Used for TRX433 Radio Module.
 	 */
-	at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+	at91_register_uart(AT91_ID_US4, 5, 0);
 }
 
 static void __init init_irq(void)
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index 1edff1b..02d2550 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -51,7 +51,7 @@ static void __init kafa_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 682e9f4..2b68edc 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -54,13 +54,13 @@ static void __init kb9202_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1 (Rx & Tx only) */
-	at91_register_uart(AT91RM9200_ID_US0, 1, 0);
+	at91_register_uart(AT91_ID_US0, 1, 0);
 
 	/* USART1 on ttyS2 (Rx & Tx only) - IRDA (optional) */
-	at91_register_uart(AT91RM9200_ID_US1, 2, 0);
+	at91_register_uart(AT91_ID_US1, 2, 0);
 
 	/* USART3 on ttyS3 (Rx, Tx, CTS, RTS) - RS485 (optional) */
-	at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index f2c79fb..e2e4988 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -60,7 +60,7 @@ static void __init neocore926_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index ad9cc28..7896b73 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -42,15 +42,15 @@ static void __init pcontrol_g20_map_io(void)
 	stamp9g20_map_io();
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS
 						| ATMEL_UART_RTS);
 
 	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485  X5 */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS
 						| ATMEL_UART_RTS);
 
 	/* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
-	at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
+	at91_register_uart(AT91_ID_US4, 3, 0);
 }
 
 
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 2b0958b..60f4456 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -52,7 +52,7 @@ static void __init picotux200_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			  | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			  | ATMEL_UART_RI);
 
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index c00b292..8cec22b 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -57,15 +57,15 @@ static void __init ek_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS1 (ie, USART0) */
 	at91_set_serial_console(1);
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index 746b6ea..92917fe 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -57,7 +57,7 @@ static void __init dk_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 5e1dca0..063c17d 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -57,7 +57,7 @@ static void __init ek_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index bc62008..a8e359f 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -56,12 +56,12 @@ static void __init ek_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index c8c53ac..e9926e5 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -58,12 +58,12 @@ static void __init ek_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 5e1aac1..62d3521 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -61,7 +61,7 @@ static void __init ek_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 3dd5013..d228b5f 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -69,12 +69,12 @@ static void __init ek_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			   | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			   | ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 6c999db..82ec1ed 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -56,7 +56,7 @@ static void __init ek_map_io(void)
 
 	/* USART0 not connected on the -EK board */
 	/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-	at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 475b485..9514b9a 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -47,7 +47,7 @@ static void __init ek_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index e93a11b..4521b66 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -48,11 +48,11 @@ static void __init snapper9260_map_io(void)
 	at91_register_uart(0, 0, 0);
 	at91_set_serial_console(0);
 
-	at91_register_uart(AT91SAM9260_ID_US0, 1,
+	at91_register_uart(AT91_ID_US0, 1,
 			   ATMEL_UART_CTS | ATMEL_UART_RTS);
-	at91_register_uart(AT91SAM9260_ID_US1, 2,
+	at91_register_uart(AT91_ID_US1, 2,
 			   ATMEL_UART_CTS | ATMEL_UART_RTS);
-	at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
+	at91_register_uart(AT91_ID_US2, 3, 0);
 }
 
 static void __init snapper9260_init_irq(void)
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 9b7f333..2b332c4 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -49,7 +49,7 @@ static void __init stamp9g20evb_map_io(void)
 	stamp9g20_map_io();
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 						| ATMEL_UART_DTR | ATMEL_UART_DSR
 						| ATMEL_UART_DCD | ATMEL_UART_RI);
 }
@@ -59,21 +59,21 @@ static void __init portuxg20_map_io(void)
 	stamp9g20_map_io();
 
 	/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 						| ATMEL_UART_DTR | ATMEL_UART_DSR
 						| ATMEL_UART_DCD | ATMEL_UART_RI);
 
 	/* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
-	at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
 
 	/* USART4 on ttyS5. (Rx, Tx only) */
-	at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
+	at91_register_uart(AT91_ID_US4, 5, 0);
 
 	/* USART5 on ttyS6. (Rx, Tx only) */
-	at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
+	at91_register_uart(AT91_ID_US5, 6, 0);
 }
 
 static void __init init_irq(void)
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index ef80db1..de79e28 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -61,15 +61,15 @@ static void __init yl9200_map_io(void)
 	at91_register_uart(0, 0, 0);
 
 	/* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-	at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+	at91_register_uart(AT91_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
 			| ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
 			| ATMEL_UART_RI);
 
 	/* USART0 on ttyS2. (Rx & Tx only to JP3) */
-	at91_register_uart(AT91RM9200_ID_US0, 2, 0);
+	at91_register_uart(AT91_ID_US0, 2, 0);
 
 	/* USART3 on ttyS3. (Rx, Tx, RTS - RS485 interface) */
-	at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_RTS);
+	at91_register_uart(AT91_ID_US3, 3, ATMEL_UART_RTS);
 
 	/* set serial console to ttyS0 (ie, DBGU) */
 	at91_set_serial_console(0);
diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 5d254cb..f94b27d 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c
@@ -23,6 +23,7 @@
 #include <mach/board.h>
 
 #include "devices.h"
+#include "generic.h"
 
 static __initdata struct at91_device_table *devices;
 
@@ -1000,6 +1001,308 @@ void __init at91_init_devices(struct at91_device_table *device_table)
 	devices = device_table;
 }
 
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+static struct resource dbgu_resources[] = {
+	[0] = {
+		.end	= SZ_512,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data dbgu_data;
+static u64 dbgu_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device at91_dbgu_device = {
+	.name		= "atmel_usart",
+	.id		= 0,
+	.dev		= {
+				.dma_mask		= &dbgu_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &dbgu_data,
+	},
+	.resource	= dbgu_resources,
+	.num_resources	= ARRAY_SIZE(dbgu_resources),
+};
+
+static struct resource uart0_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart0_data;
+static u64 uart0_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device at91_uart0_device = {
+	.name		= "atmel_usart",
+	.id		= 1,
+	.dev		= {
+				.dma_mask		= &uart0_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &uart0_data,
+	},
+	.resource	= uart0_resources,
+	.num_resources	= ARRAY_SIZE(uart0_resources),
+};
+
+static struct resource uart1_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart1_data;
+static u64 uart1_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device at91_uart1_device = {
+	.name		= "atmel_usart",
+	.id		= 2,
+	.dev		= {
+				.dma_mask		= &uart1_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &uart1_data,
+	},
+	.resource	= uart1_resources,
+	.num_resources	= ARRAY_SIZE(uart1_resources),
+};
+
+static struct resource uart2_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart2_data;
+static u64 uart2_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device at91_uart2_device = {
+	.name		= "atmel_usart",
+	.id		= 3,
+	.dev		= {
+				.dma_mask		= &uart2_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &uart2_data,
+	},
+	.resource	= uart2_resources,
+	.num_resources	= ARRAY_SIZE(uart2_resources),
+};
+
+static struct resource uart3_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart3_data;
+static u64 uart3_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device at91_uart3_device = {
+	.name		= "atmel_usart",
+	.id		= 4,
+	.dev		= {
+				.dma_mask		= &uart3_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &uart3_data,
+	},
+	.resource	= uart3_resources,
+	.num_resources	= ARRAY_SIZE(uart3_resources),
+};
+
+static struct resource uart4_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart4_data;
+static u64 uart4_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device at91_uart4_device = {
+	.name		= "atmel_usart",
+	.id		= 5,
+	.dev		= {
+				.dma_mask		= &uart4_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &uart4_data,
+	},
+	.resource	= uart4_resources,
+	.num_resources	= ARRAY_SIZE(uart4_resources),
+};
+
+static struct resource uart5_resources[] = {
+	[0] = {
+		.end	= SZ_16K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct atmel_uart_data uart5_data;
+static u64 uart5_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device at91_uart5_device = {
+	.name		= "atmel_usart",
+	.id		= 6,
+	.dev		= {
+				.dma_mask		= &uart5_dmamask,
+				.coherent_dma_mask	= DMA_BIT_MASK(32),
+				.platform_data		= &uart5_data,
+	},
+	.resource	= uart5_resources,
+	.num_resources	= ARRAY_SIZE(uart5_resources),
+};
+
+/* the UARTs to use */
+static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];
+/* the serial console device */
+struct platform_device *atmel_default_console_device;
+
+static void __init configure_uart(struct atmel_uart_data *uart_data,
+				  struct resource *uart_res,
+				  struct at91_dev_table_uart *uart,
+				  unsigned pins)
+{
+	init_resource_mem(&uart_res[0], uart->mmio_base);
+	init_resource_irq(&uart_res[1], uart->irq);
+	memcpy(uart_data, &uart->uart_data, sizeof(struct atmel_uart_data));
+
+	at91_config_pins(&uart->tx_pin, 1);
+	at91_config_pins(&uart->rx_pin, 1);
+	
+	if (pins & ATMEL_UART_RTS)
+		at91_config_pins(&uart->rts_pin, 1);
+	if (pins & ATMEL_UART_CTS)
+		at91_config_pins(&uart->cts_pin, 1);
+	if (pins & ATMEL_UART_RI)
+		at91_config_pins(&uart->ri_pin, 1);
+	if (pins & ATMEL_UART_DTR)
+		at91_config_pins(&uart->dtr_pin, 1);
+	if (pins & ATMEL_UART_DCD)
+		at91_config_pins(&uart->dcd_pin, 1);
+	if (pins & ATMEL_UART_DSR)
+		at91_config_pins(&uart->dsr_pin, 1);
+}
+
+void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
+{
+	struct platform_device *pdev;
+	struct at91_dev_table_uart *uart;
+	struct atmel_uart_data *uart_data;
+	struct resource *uart_res;
+	
+	BUG_ON(id < 0 || id > ARRAY_SIZE(devices->uart));
+	if (id == 0)
+		uart = devices->dbgu;
+	else
+		uart = devices->uart[id - 1];
+	BUG_ON(!uart);
+	
+	switch (id) {
+	case 0:		/* DBGU */
+		pdev 	  = &at91_dbgu_device;
+		uart_data = &dbgu_data;
+		uart_res  = dbgu_resources;
+		break;
+	case AT91_ID_US0:
+		pdev 	  = &at91_uart0_device;
+		uart_data = &uart0_data;
+		uart_res  = uart0_resources;
+		break;
+	case AT91_ID_US1:
+		pdev 	  = &at91_uart1_device;
+		uart_data = &uart1_data;
+		uart_res  = uart1_resources;
+		break;
+	case AT91_ID_US2:
+		pdev 	  = &at91_uart2_device;
+		uart_data = &uart2_data;
+		uart_res  = uart2_resources;
+		break;
+	case AT91_ID_US3:
+		pdev 	  = &at91_uart3_device;
+		uart_data = &uart3_data;
+		uart_res  = uart3_resources;
+		break;
+	case AT91_ID_US4:
+		pdev 	  = &at91_uart4_device;
+		uart_data = &uart4_data;
+		uart_res  = uart4_resources;
+		break;
+	case AT91_ID_US5:
+		pdev 	  = &at91_uart5_device;
+		uart_data = &uart5_data;
+		uart_res  = uart5_resources;
+		break;
+	default:
+		return;
+	}
+	
+	configure_uart(uart_data, uart_res, uart, pins);
+	if (uart->clock_asc)
+		at91_clock_associate(uart->clock_asc, &pdev->dev, "usart");
+	pdev->id = portnr;		/* update to mapped ID */
+	
+	if (portnr < ATMEL_MAX_UART)
+		at91_uarts[portnr] = pdev;
+
+	printk(KERN_ERR "%s - uart id %d, portnr = %d, pdev = %p\n",
+	       __func__, id, portnr, at91_uarts[portnr]);
+}
+
+void __init at91_set_serial_console(unsigned portnr)
+{
+	if (portnr < ATMEL_MAX_UART)
+		atmel_default_console_device = at91_uarts[portnr];
+}
+
+void __init at91_add_device_serial(void)
+{
+	int i;
+
+	for (i = 0; i < ATMEL_MAX_UART; i++) {
+		if (at91_uarts[i])
+			platform_device_register(at91_uarts[i]);
+	}
+
+	if (!atmel_default_console_device)
+		printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+#else
+void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
+void __init at91_set_serial_console(unsigned portnr) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
 static int __init at91_add_standard_devices(void)
 {
 	at91_add_device_tc();
diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
index d7855ec..c535f58 100644
--- a/arch/arm/mach-at91/devices.h
+++ b/arch/arm/mach-at91/devices.h
@@ -107,6 +107,21 @@ struct at91_dev_table_rtt {
 	unsigned		mmio_base;
 };
 
+struct at91_dev_table_uart {
+	unsigned		mmio_base;
+	int			irq;
+	struct atmel_uart_data	uart_data;
+	const char		*clock_asc;
+	struct at91_pin_config	tx_pin;
+	struct at91_pin_config	rx_pin;
+	struct at91_pin_config	rts_pin;
+	struct at91_pin_config	cts_pin;
+	struct at91_pin_config	ri_pin;
+	struct at91_pin_config	dtr_pin;
+	struct at91_pin_config	dcd_pin;
+	struct at91_pin_config	dsr_pin;
+};
+
 struct at91_device_table {
 	struct at91_dev_table_ethernet		*ethernet;
 	struct at91_dev_table_usb_ohci		*usbh_ohci;
@@ -118,6 +133,8 @@ struct at91_device_table {
 	struct at91_dev_table_spi		*spi[2];
 	struct at91_dev_table_tcb		*tcb[2];
 	struct at91_dev_table_rtt		*rtt[2];
+	struct at91_dev_table_uart		*dbgu;
+	struct at91_dev_table_uart		*uart[6];
 };
 
 extern void __init at91_init_devices(struct at91_device_table *device_table);
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 94232a4..851c6c2 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -122,6 +122,16 @@ extern void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devi
 extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
 
  /* Serial */
+enum {
+	AT91_ID_DBGU = 0,
+	AT91_ID_US0,
+	AT91_ID_US1,
+	AT91_ID_US2,
+	AT91_ID_US3,
+	AT91_ID_US4,
+	AT91_ID_US5,
+};
+
 #define ATMEL_UART_CTS	0x01
 #define ATMEL_UART_RTS	0x02
 #define ATMEL_UART_DSR	0x04
-- 
1.7.0.4

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

* [PATCH 05/23] at91: Make MMC device (at91_mci) common
  2011-04-20  1:10 ` [PATCH 05/23] at91: Make MMC device (at91_mci) common Ryan Mallon
@ 2011-04-20  1:12   ` Ryan Mallon
  0 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  1:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/20/2011 01:10 PM, Ryan Mallon wrote:
> Replace the individual MMC code for each at91 variant with a single
> implementation in devices.c
> 
> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>

Oops, please ignore this patch. It got left over after a commit message
rewording.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  1:10 ` [RFC PATCH 02/23] at91: Make Ethernet device common Ryan Mallon
@ 2011-04-20  2:10   ` H Hartley Sweeten
  2011-04-20  2:33     ` Ryan Mallon
  2011-04-20  8:36   ` Uwe Kleine-König
  1 sibling, 1 reply; 41+ messages in thread
From: H Hartley Sweeten @ 2011-04-20  2:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, April 19, 2011 6:10 PM, Ryan Mallon wrote:
>
> Replace the individual Ethernet device code for each at91 variant with
> a single implementation in devices.
>
> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>

Nice.

A couple comments below.

[snip]

> diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
> index 0fc20a2..12af1d5 100644
> --- a/arch/arm/mach-at91/at572d940hf_devices.c
> +++ b/arch/arm/mach-at91/at572d940hf_devices.c
> @@ -35,6 +35,7 @@
>  
>  #include "generic.h"
>  #include "sam9_smc.h"
> +#include "devices.h"
>  
>  
>  /* --------------------------------------------------------------------
> @@ -138,68 +139,26 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
>   *  Ethernet
>   * -------------------------------------------------------------------- */
>  
> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> -static u64 eth_dmamask = DMA_BIT_MASK(32);
> -static struct at91_eth_data eth_data;
> -
> -static struct resource eth_resources[] = {
> -	[0] = {
> -		.start	= AT572D940HF_BASE_EMAC,
> -		.end	= AT572D940HF_BASE_EMAC + SZ_16K - 1,
> -		.flags	= IORESOURCE_MEM,
> -	},
> -	[1] = {
> -		.start	= AT572D940HF_ID_EMAC,
> -		.end	= AT572D940HF_ID_EMAC,
> -		.flags	= IORESOURCE_IRQ,
> -	},

[snip]

> +static struct __initdata at91_dev_table_ethernet device_eth = {
> +	.mmio_base	= AT91SAM9260_BASE_EMAC,
> +	.irq		= AT91SAM9260_ID_EMAC,

AT572D940HF_BASE_EMAC and AT572D940HF_ID_EMAC?

> +	.rmii_pins	= eth_rmii_pins,
> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
>  };
> 
> -void __init at91_add_device_eth(struct at91_eth_data *data)
> -{
> -	if (!data)
> -		return;
> -
> -	if (data->phy_irq_pin) {
> -		at91_set_gpio_input(data->phy_irq_pin, 0);
> -		at91_set_deglitch(data->phy_irq_pin, 1);
> -	}
> -
> -	/* Only RMII is supported */
> -	data->is_rmii = 1;

How is this set for this platfrom?

[snip]

diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 59fc483..3c0959f 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -1044,7 +1044,6 @@ void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
 #endif
 
-

Nit. Unrelated whitespace change.

[snip]

diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
index 653e0a9..07fefc8 100644
--- a/arch/arm/mach-at91/devices.c
+++ b/arch/arm/mach-at91/devices.c

[snip]

> +static struct platform_device at91_eth_device = {
> +	.name		= "macb",
> +	.id		= -1,
> +	.dev		= {
> +				.dma_mask		= &eth_dmamask,
> +				.coherent_dma_mask	= DMA_BIT_MASK(32),
> +				.platform_data		= &eth_data,

Nit.  Excessive whitespace.

[snip]

> +#else
> +void __init at91_add_device_eth(struct at91_eth_data *data) {}

inline maybe?

> +#endif

Regards,
Hartley

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  2:10   ` H Hartley Sweeten
@ 2011-04-20  2:33     ` Ryan Mallon
  2011-04-20 18:23       ` H Hartley Sweeten
  0 siblings, 1 reply; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  2:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/20/2011 02:10 PM, H Hartley Sweeten wrote:
> On Tuesday, April 19, 2011 6:10 PM, Ryan Mallon wrote:
>>
>> Replace the individual Ethernet device code for each at91 variant with
>> a single implementation in devices.
>>
>> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
> 
> Nice.
> 
> A couple comments below.
> 
> [snip]
> 
>> diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
>> index 0fc20a2..12af1d5 100644
>> --- a/arch/arm/mach-at91/at572d940hf_devices.c
>> +++ b/arch/arm/mach-at91/at572d940hf_devices.c
>> @@ -35,6 +35,7 @@
>>  
>>  #include "generic.h"
>>  #include "sam9_smc.h"
>> +#include "devices.h"
>>  
>>  
>>  /* --------------------------------------------------------------------
>> @@ -138,68 +139,26 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
>>   *  Ethernet
>>   * -------------------------------------------------------------------- */
>>  
>> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
>> -static u64 eth_dmamask = DMA_BIT_MASK(32);
>> -static struct at91_eth_data eth_data;
>> -
>> -static struct resource eth_resources[] = {
>> -	[0] = {
>> -		.start	= AT572D940HF_BASE_EMAC,
>> -		.end	= AT572D940HF_BASE_EMAC + SZ_16K - 1,
>> -		.flags	= IORESOURCE_MEM,
>> -	},
>> -	[1] = {
>> -		.start	= AT572D940HF_ID_EMAC,
>> -		.end	= AT572D940HF_ID_EMAC,
>> -		.flags	= IORESOURCE_IRQ,
>> -	},
> 
> [snip]
> 
>> +static struct __initdata at91_dev_table_ethernet device_eth = {
>> +	.mmio_base	= AT91SAM9260_BASE_EMAC,
>> +	.irq		= AT91SAM9260_ID_EMAC,
> 
> AT572D940HF_BASE_EMAC and AT572D940HF_ID_EMAC?

Crap. It's somehow ended up in patch 4 instead. Will fix, thanks.

> 
>> +	.rmii_pins	= eth_rmii_pins,
>> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
>>  };
>>
>> -void __init at91_add_device_eth(struct at91_eth_data *data)
>> -{
>> -	if (!data)
>> -		return;
>> -
>> -	if (data->phy_irq_pin) {
>> -		at91_set_gpio_input(data->phy_irq_pin, 0);
>> -		at91_set_deglitch(data->phy_irq_pin, 1);
>> -	}
>> -
>> -	/* Only RMII is supported */
>> -	data->is_rmii = 1;
> 
> How is this set for this platfrom?

By having mii_pins set to NULL. The devices.c code now does:

	if (!data->is_rmii && info->mii_pins)
		...
> 
> [snip]
> 
> diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
> index 59fc483..3c0959f 100644
> --- a/arch/arm/mach-at91/at91sam9261_devices.c
> +++ b/arch/arm/mach-at91/at91sam9261_devices.c
> @@ -1044,7 +1044,6 @@ void __init at91_set_serial_console(unsigned portnr) {}
>  void __init at91_add_device_serial(void) {}
>  #endif
>  
> -
> 
> Nit. Unrelated whitespace change.

Thanks, will clean this up.

> 
> [snip]
> 
> diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
> index 653e0a9..07fefc8 100644
> --- a/arch/arm/mach-at91/devices.c
> +++ b/arch/arm/mach-at91/devices.c
> 
> [snip]
> 
>> +static struct platform_device at91_eth_device = {
>> +	.name		= "macb",
>> +	.id		= -1,
>> +	.dev		= {
>> +				.dma_mask		= &eth_dmamask,
>> +				.coherent_dma_mask	= DMA_BIT_MASK(32),
>> +				.platform_data		= &eth_data,
> 
> Nit.  Excessive whitespace.

This is cut and pasted from one of the *_devices.c files so the change
is minimal.

> 
> [snip]
> 
>> +#else
>> +void __init at91_add_device_eth(struct at91_eth_data *data) {}
> 
> inline maybe?

No. This is also cut and pasted from the *_devices.c files so the change
is minimal. The compiler should out-right remove this anyway so it
shouldn't need to be inline.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (23 preceding siblings ...)
  2011-04-20  1:11 ` [RFC PATCH 12/23] at91: Make UART devices common Ryan Mallon
@ 2011-04-20  3:47 ` Jean-Christophe PLAGNIOL-VILLARD
  2011-04-20  3:58   ` Ryan Mallon
  2011-04-20 17:14 ` H Hartley Sweeten
  25 siblings, 1 reply; 41+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2011-04-20  3:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

	I work olso on the same ideayou send first good

	will take a look on it this week-end and test it
Best Regards,
J.
On 13:10 Wed 20 Apr     , Ryan Mallon wrote:
> Each AT91 variant (AT91RM9200, AT91SAM9260, etc) currently has its own
> devices file, which includes the MMIO address, interrupt
> configuration, GPIO setup, etc for each device. This results in a large
> amount of duplicated code.
> 
> This patch set introduces a framework for adding shared devices for the
> AT91 platform and replaces the multiple device setup implementations for
> each device with single implementations in the new framework. This has
> a net reduction of nearly 5000 lines of code.
> 
> Each of the arch/arm/mach-at91/*_devices.c files becomes a collection of
> structures (with some initialisation callbacks where necessary) with a
> table of devices which are present on the particular AT91 variant. All
> structures/functions are marked as __init/__initdata so there is little
> additional memory overhead. This also means that the #ifdefs around each
> device can be removed from the *_devices.c files (but remain in the new
> common devices.c file) without overhead.
> 
> I have build tested the patch series for all of the  AT91 variants 
> and devices, and have boot tested it on the AT91SAM9260 (Snapper 9260
> board) and tested basic device functionality.
> 
> Ryan Mallon (23):
>   at91: Add common devices framework
>   at91: Make Ethernet device common
>   at91: Make USB OHCI/EHCI devices common
>   at91: Make UDC device common
>   at91: Make MMC device common
>   at91: Make NAND device common
>   at91: Make TWI device common
>   at91: Make SPI device common
>   at91: Make TCB device common
>   at91: Make RTT device common
>   at91: Make watchdog device common
>   at91: Make UART devices common
>   at91: Make PWM device common
>   at91: Make SSC device common
>   at91: Make AC97 device common
>   at91: Make LCD controller device common
>   at91: Make touchscreen device common
>   at91: Make HDMAC device common
>   at91: Make RTC device common
>   at91: Make high speed USB gadget device common
>   at91: Make compact flash device common
>   at91: Move at91sam9263 CAN device to common devices
>   at91: Remove mAgic and ISI device code
> 
>  arch/arm/mach-at91/Makefile               |    2 +-
>  arch/arm/mach-at91/at572d940hf.c          |    4 +
>  arch/arm/mach-at91/at572d940hf_devices.c  | 1022 +++-------------
>  arch/arm/mach-at91/at91cap9.c             |    4 +
>  arch/arm/mach-at91/at91cap9_devices.c     | 1411 ++++----------------
>  arch/arm/mach-at91/at91rm9200.c           |    4 +
>  arch/arm/mach-at91/at91rm9200_devices.c   | 1321 ++++---------------
>  arch/arm/mach-at91/at91sam9260.c          |    4 +
>  arch/arm/mach-at91/at91sam9260_devices.c  | 1471 ++++-----------------
>  arch/arm/mach-at91/at91sam9261.c          |    4 +
>  arch/arm/mach-at91/at91sam9261_devices.c  | 1172 ++++--------------
>  arch/arm/mach-at91/at91sam9263.c          |    4 +
>  arch/arm/mach-at91/at91sam9263_devices.c  | 1589 +++++------------------
>  arch/arm/mach-at91/at91sam9g45.c          |    4 +
>  arch/arm/mach-at91/at91sam9g45_devices.c  | 1779 +++++---------------------
>  arch/arm/mach-at91/at91sam9rl.c           |    4 +
>  arch/arm/mach-at91/at91sam9rl_devices.c   | 1332 ++++----------------
>  arch/arm/mach-at91/board-1arm.c           |    6 +-
>  arch/arm/mach-at91/board-afeb-9260v1.c    |   10 +-
>  arch/arm/mach-at91/board-at572d940hf_ek.c |   12 +-
>  arch/arm/mach-at91/board-cam60.c          |    2 +-
>  arch/arm/mach-at91/board-cap9adk.c        |    4 +-
>  arch/arm/mach-at91/board-carmeva.c        |    6 +-
>  arch/arm/mach-at91/board-cpu9krea.c       |   16 +-
>  arch/arm/mach-at91/board-cpuat91.c        |   12 +-
>  arch/arm/mach-at91/board-csb337.c         |    4 +-
>  arch/arm/mach-at91/board-csb637.c         |    4 +-
>  arch/arm/mach-at91/board-eb9200.c         |    8 +-
>  arch/arm/mach-at91/board-ecbat91.c        |    6 +-
>  arch/arm/mach-at91/board-eco920.c         |    2 +-
>  arch/arm/mach-at91/board-flexibity.c      |    2 +-
>  arch/arm/mach-at91/board-foxg20.c         |   16 +-
>  arch/arm/mach-at91/board-gsia18s.c        |   14 +-
>  arch/arm/mach-at91/board-kafa.c           |    6 +-
>  arch/arm/mach-at91/board-kb9202.c         |   10 +-
>  arch/arm/mach-at91/board-neocore926.c     |    6 +-
>  arch/arm/mach-at91/board-pcontrol-g20.c   |   10 +-
>  arch/arm/mach-at91/board-picotux200.c     |    6 +-
>  arch/arm/mach-at91/board-qil-a9260.c      |   10 +-
>  arch/arm/mach-at91/board-rm9200dk.c       |    6 +-
>  arch/arm/mach-at91/board-rm9200ek.c       |    6 +-
>  arch/arm/mach-at91/board-sam9-l9260.c     |    8 +-
>  arch/arm/mach-at91/board-sam9260ek.c      |   10 +-
>  arch/arm/mach-at91/board-sam9261ek.c      |    6 +-
>  arch/arm/mach-at91/board-sam9263ek.c      |    6 +-
>  arch/arm/mach-at91/board-sam9g20ek.c      |   10 +-
>  arch/arm/mach-at91/board-sam9m10g45ek.c   |    2 +-
>  arch/arm/mach-at91/board-sam9rlek.c       |    4 +-
>  arch/arm/mach-at91/board-snapper9260.c    |   14 +-
>  arch/arm/mach-at91/board-stamp9g20.c      |   20 +-
>  arch/arm/mach-at91/board-usb-a9260.c      |    4 +-
>  arch/arm/mach-at91/board-usb-a9263.c      |    4 +-
>  arch/arm/mach-at91/board-yl-9200.c        |   10 +-
>  arch/arm/mach-at91/devices.c              | 2002 +++++++++++++++++++++++++++++
>  arch/arm/mach-at91/devices.h              |  237 ++++
>  arch/arm/mach-at91/include/mach/board.h   |   21 +-
>  56 files changed, 4483 insertions(+), 9190 deletions(-)
>  create mode 100644 arch/arm/mach-at91/devices.c
>  create mode 100644 arch/arm/mach-at91/devices.h

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

* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
  2011-04-20  3:47 ` [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Jean-Christophe PLAGNIOL-VILLARD
@ 2011-04-20  3:58   ` Ryan Mallon
  2011-04-20  4:03     ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20  3:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/20/2011 03:47 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> Hi,
> 
> 	I work olso on the same ideayou send first good
> 
> 	will take a look on it this week-end and test it

Thanks, that would be really helpful.

Hartley pointed out that there are a couple of mistakes in the patch
series (some bits get applied in the wrong patch, which I will fix), but
if you apply the whole series it should work correctly.

Thanks,
~Ryan

> Best Regards,
> J.
> On 13:10 Wed 20 Apr     , Ryan Mallon wrote:
>> Each AT91 variant (AT91RM9200, AT91SAM9260, etc) currently has its own
>> devices file, which includes the MMIO address, interrupt
>> configuration, GPIO setup, etc for each device. This results in a large
>> amount of duplicated code.
>>
>> This patch set introduces a framework for adding shared devices for the
>> AT91 platform and replaces the multiple device setup implementations for
>> each device with single implementations in the new framework. This has
>> a net reduction of nearly 5000 lines of code.
>>
>> Each of the arch/arm/mach-at91/*_devices.c files becomes a collection of
>> structures (with some initialisation callbacks where necessary) with a
>> table of devices which are present on the particular AT91 variant. All
>> structures/functions are marked as __init/__initdata so there is little
>> additional memory overhead. This also means that the #ifdefs around each
>> device can be removed from the *_devices.c files (but remain in the new
>> common devices.c file) without overhead.
>>
>> I have build tested the patch series for all of the  AT91 variants 
>> and devices, and have boot tested it on the AT91SAM9260 (Snapper 9260
>> board) and tested basic device functionality.
>>
>> Ryan Mallon (23):
>>   at91: Add common devices framework
>>   at91: Make Ethernet device common
>>   at91: Make USB OHCI/EHCI devices common
>>   at91: Make UDC device common
>>   at91: Make MMC device common
>>   at91: Make NAND device common
>>   at91: Make TWI device common
>>   at91: Make SPI device common
>>   at91: Make TCB device common
>>   at91: Make RTT device common
>>   at91: Make watchdog device common
>>   at91: Make UART devices common
>>   at91: Make PWM device common
>>   at91: Make SSC device common
>>   at91: Make AC97 device common
>>   at91: Make LCD controller device common
>>   at91: Make touchscreen device common
>>   at91: Make HDMAC device common
>>   at91: Make RTC device common
>>   at91: Make high speed USB gadget device common
>>   at91: Make compact flash device common
>>   at91: Move at91sam9263 CAN device to common devices
>>   at91: Remove mAgic and ISI device code
>>
>>  arch/arm/mach-at91/Makefile               |    2 +-
>>  arch/arm/mach-at91/at572d940hf.c          |    4 +
>>  arch/arm/mach-at91/at572d940hf_devices.c  | 1022 +++-------------
>>  arch/arm/mach-at91/at91cap9.c             |    4 +
>>  arch/arm/mach-at91/at91cap9_devices.c     | 1411 ++++----------------
>>  arch/arm/mach-at91/at91rm9200.c           |    4 +
>>  arch/arm/mach-at91/at91rm9200_devices.c   | 1321 ++++---------------
>>  arch/arm/mach-at91/at91sam9260.c          |    4 +
>>  arch/arm/mach-at91/at91sam9260_devices.c  | 1471 ++++-----------------
>>  arch/arm/mach-at91/at91sam9261.c          |    4 +
>>  arch/arm/mach-at91/at91sam9261_devices.c  | 1172 ++++--------------
>>  arch/arm/mach-at91/at91sam9263.c          |    4 +
>>  arch/arm/mach-at91/at91sam9263_devices.c  | 1589 +++++------------------
>>  arch/arm/mach-at91/at91sam9g45.c          |    4 +
>>  arch/arm/mach-at91/at91sam9g45_devices.c  | 1779 +++++---------------------
>>  arch/arm/mach-at91/at91sam9rl.c           |    4 +
>>  arch/arm/mach-at91/at91sam9rl_devices.c   | 1332 ++++----------------
>>  arch/arm/mach-at91/board-1arm.c           |    6 +-
>>  arch/arm/mach-at91/board-afeb-9260v1.c    |   10 +-
>>  arch/arm/mach-at91/board-at572d940hf_ek.c |   12 +-
>>  arch/arm/mach-at91/board-cam60.c          |    2 +-
>>  arch/arm/mach-at91/board-cap9adk.c        |    4 +-
>>  arch/arm/mach-at91/board-carmeva.c        |    6 +-
>>  arch/arm/mach-at91/board-cpu9krea.c       |   16 +-
>>  arch/arm/mach-at91/board-cpuat91.c        |   12 +-
>>  arch/arm/mach-at91/board-csb337.c         |    4 +-
>>  arch/arm/mach-at91/board-csb637.c         |    4 +-
>>  arch/arm/mach-at91/board-eb9200.c         |    8 +-
>>  arch/arm/mach-at91/board-ecbat91.c        |    6 +-
>>  arch/arm/mach-at91/board-eco920.c         |    2 +-
>>  arch/arm/mach-at91/board-flexibity.c      |    2 +-
>>  arch/arm/mach-at91/board-foxg20.c         |   16 +-
>>  arch/arm/mach-at91/board-gsia18s.c        |   14 +-
>>  arch/arm/mach-at91/board-kafa.c           |    6 +-
>>  arch/arm/mach-at91/board-kb9202.c         |   10 +-
>>  arch/arm/mach-at91/board-neocore926.c     |    6 +-
>>  arch/arm/mach-at91/board-pcontrol-g20.c   |   10 +-
>>  arch/arm/mach-at91/board-picotux200.c     |    6 +-
>>  arch/arm/mach-at91/board-qil-a9260.c      |   10 +-
>>  arch/arm/mach-at91/board-rm9200dk.c       |    6 +-
>>  arch/arm/mach-at91/board-rm9200ek.c       |    6 +-
>>  arch/arm/mach-at91/board-sam9-l9260.c     |    8 +-
>>  arch/arm/mach-at91/board-sam9260ek.c      |   10 +-
>>  arch/arm/mach-at91/board-sam9261ek.c      |    6 +-
>>  arch/arm/mach-at91/board-sam9263ek.c      |    6 +-
>>  arch/arm/mach-at91/board-sam9g20ek.c      |   10 +-
>>  arch/arm/mach-at91/board-sam9m10g45ek.c   |    2 +-
>>  arch/arm/mach-at91/board-sam9rlek.c       |    4 +-
>>  arch/arm/mach-at91/board-snapper9260.c    |   14 +-
>>  arch/arm/mach-at91/board-stamp9g20.c      |   20 +-
>>  arch/arm/mach-at91/board-usb-a9260.c      |    4 +-
>>  arch/arm/mach-at91/board-usb-a9263.c      |    4 +-
>>  arch/arm/mach-at91/board-yl-9200.c        |   10 +-
>>  arch/arm/mach-at91/devices.c              | 2002 +++++++++++++++++++++++++++++
>>  arch/arm/mach-at91/devices.h              |  237 ++++
>>  arch/arm/mach-at91/include/mach/board.h   |   21 +-
>>  56 files changed, 4483 insertions(+), 9190 deletions(-)
>>  create mode 100644 arch/arm/mach-at91/devices.c
>>  create mode 100644 arch/arm/mach-at91/devices.h


-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
  2011-04-20  3:58   ` Ryan Mallon
@ 2011-04-20  4:03     ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 41+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2011-04-20  4:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 15:58 Wed 20 Apr     , Ryan Mallon wrote:
> On 04/20/2011 03:47 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > Hi,
> > 
> > 	I work olso on the same ideayou send first good
> > 
> > 	will take a look on it this week-end and test it
> 
> Thanks, that would be really helpful.
> 
> Hartley pointed out that there are a couple of mistakes in the patch
> series (some bits get applied in the wrong patch, which I will fix), but
> if you apply the whole series it should work correctly.
I see some issue already I will fix them

I work for some time on a huge upadte on the clock that I update and resend
I'll rebase your patch against it and against the at91-l2 branch of the at91
tree

And send other update too this week-end

Best Regards,
J.

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  1:10 ` [RFC PATCH 02/23] at91: Make Ethernet device common Ryan Mallon
  2011-04-20  2:10   ` H Hartley Sweeten
@ 2011-04-20  8:36   ` Uwe Kleine-König
  2011-04-20 10:34     ` Jean-Christophe PLAGNIOL-VILLARD
                       ` (2 more replies)
  1 sibling, 3 replies; 41+ messages in thread
From: Uwe Kleine-König @ 2011-04-20  8:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Ryan,

On Wed, Apr 20, 2011 at 01:10:05PM +1200, Ryan Mallon wrote:
> Replace the individual Ethernet device code for each at91 variant with
> a single implementation in devices.
> 
> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
> ---
>  arch/arm/mach-at91/at572d940hf.c         |    4 +
>  arch/arm/mach-at91/at572d940hf_devices.c |   83 +++++++----------------
>  arch/arm/mach-at91/at91cap9.c            |    4 +
>  arch/arm/mach-at91/at91cap9_devices.c    |  103 ++++++++++------------------
>  arch/arm/mach-at91/at91rm9200.c          |    4 +
>  arch/arm/mach-at91/at91rm9200_devices.c  |  103 ++++++++++------------------
>  arch/arm/mach-at91/at91sam9260.c         |    4 +
>  arch/arm/mach-at91/at91sam9260_devices.c |  104 +++++++++++------------------
>  arch/arm/mach-at91/at91sam9261_devices.c |    1 -
>  arch/arm/mach-at91/at91sam9263.c         |    4 +
>  arch/arm/mach-at91/at91sam9263_devices.c |  102 ++++++++++------------------
>  arch/arm/mach-at91/at91sam9g45.c         |    4 +
>  arch/arm/mach-at91/at91sam9g45_devices.c |  108 +++++++++++-------------------
>  arch/arm/mach-at91/devices.c             |   61 +++++++++++++++++
>  arch/arm/mach-at91/devices.h             |   10 +++
>  15 files changed, 309 insertions(+), 390 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/at572d940hf.c b/arch/arm/mach-at91/at572d940hf.c
> index a6b9c68..48c1ec2 100644
> --- a/arch/arm/mach-at91/at572d940hf.c
> +++ b/arch/arm/mach-at91/at572d940hf.c
> @@ -34,6 +34,8 @@
>  #include "generic.h"
>  #include "clock.h"
>  
> +extern void at572d940hf_init_devices(void);
> +
>  static struct map_desc at572d940hf_io_desc[] __initdata = {
>  	{
>  		.virtual	= AT91_VA_BASE_SYS,
> @@ -307,6 +309,8 @@ void __init at572d940hf_initialize(unsigned long main_clock)
>  	/* Map peripherals */
>  	iotable_init(at572d940hf_io_desc, ARRAY_SIZE(at572d940hf_io_desc));
>  
> +	at572d940hf_init_devices();
> +
>  	at91_arch_reset = at572d940hf_reset;
>  	at91_extern_irq = (1 << AT572D940HF_ID_IRQ0) | (1 << AT572D940HF_ID_IRQ1)
>  			| (1 << AT572D940HF_ID_IRQ2);
> diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
> index 0fc20a2..12af1d5 100644
> --- a/arch/arm/mach-at91/at572d940hf_devices.c
> +++ b/arch/arm/mach-at91/at572d940hf_devices.c
> @@ -35,6 +35,7 @@
>  
>  #include "generic.h"
>  #include "sam9_smc.h"
> +#include "devices.h"
>  
>  
>  /* --------------------------------------------------------------------
> @@ -138,68 +139,26 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
>   *  Ethernet
>   * -------------------------------------------------------------------- */
>  
> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> -static u64 eth_dmamask = DMA_BIT_MASK(32);
> -static struct at91_eth_data eth_data;
> -
> -static struct resource eth_resources[] = {
> -	[0] = {
> -		.start	= AT572D940HF_BASE_EMAC,
> -		.end	= AT572D940HF_BASE_EMAC + SZ_16K - 1,
> -		.flags	= IORESOURCE_MEM,
> -	},
> -	[1] = {
> -		.start	= AT572D940HF_ID_EMAC,
> -		.end	= AT572D940HF_ID_EMAC,
> -		.flags	= IORESOURCE_IRQ,
> -	},
> +static struct __initdata at91_pin_config eth_rmii_pins[] = {
> +	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
> +	{AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
> +	{AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
> +	{AT91_PIN_PA19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
> +	{AT91_PIN_PA20, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
> +	{AT91_PIN_PA23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
> +	{AT91_PIN_PA21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
> +	{AT91_PIN_PA22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
> +	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
> +	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
>  };
>  
> -static struct platform_device at572d940hf_eth_device = {
> -	.name		= "macb",
> -	.id		= -1,
> -	.dev		= {
> -			.dma_mask		= &eth_dmamask,
> -			.coherent_dma_mask	= DMA_BIT_MASK(32),
> -			.platform_data		= &eth_data,
> -	},
> -	.resource	= eth_resources,
> -	.num_resources	= ARRAY_SIZE(eth_resources),
> +static struct __initdata at91_dev_table_ethernet device_eth = {
> +	.mmio_base	= AT91SAM9260_BASE_EMAC,
> +	.irq		= AT91SAM9260_ID_EMAC,
> +	.rmii_pins	= eth_rmii_pins,
> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
>  };
>  
> -void __init at91_add_device_eth(struct at91_eth_data *data)
> -{
> -	if (!data)
> -		return;
> -
> -	if (data->phy_irq_pin) {
> -		at91_set_gpio_input(data->phy_irq_pin, 0);
> -		at91_set_deglitch(data->phy_irq_pin, 1);
> -	}
> -
> -	/* Only RMII is supported */
> -	data->is_rmii = 1;
> -
> -	/* Pins used for RMII */
> -	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ETXCK_EREFCK */
> -	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ERXDV */
> -	at91_set_A_periph(AT91_PIN_PA18, 0);	/* ERX0 */
> -	at91_set_A_periph(AT91_PIN_PA19, 0);	/* ERX1 */
> -	at91_set_A_periph(AT91_PIN_PA20, 0);	/* ERXER */
> -	at91_set_A_periph(AT91_PIN_PA23, 0);	/* ETXEN */
> -	at91_set_A_periph(AT91_PIN_PA21, 0);	/* ETX0 */
> -	at91_set_A_periph(AT91_PIN_PA22, 0);	/* ETX1 */
> -	at91_set_A_periph(AT91_PIN_PA13, 0);	/* EMDIO */
> -	at91_set_A_periph(AT91_PIN_PA14, 0);	/* EMDC */
> -
> -	eth_data = *data;
> -	platform_device_register(&at572d940hf_eth_device);
> -}
> -#else
> -void __init at91_add_device_eth(struct at91_eth_data *data) {}
> -#endif
> -
> -
>  /* --------------------------------------------------------------------
>   *  MMC / SD
>   * -------------------------------------------------------------------- */
> @@ -952,6 +911,14 @@ void __init at91_add_device_mAgic(void)
>  void __init at91_add_device_mAgic(void) {}
>  #endif
>  
> +static struct at91_device_table __initdata at572d940hf_device_table = {
> +	.ethernet	= &device_eth,
> +};
> +
> +void __init at572d940hf_init_devices(void)
> +{
> +	at91_init_devices(&at572d940hf_device_table);
> +}
>  
>  /* -------------------------------------------------------------------- */
>  
> diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
> index 7337617..6413530 100644
> --- a/arch/arm/mach-at91/at91cap9.c
> +++ b/arch/arm/mach-at91/at91cap9.c
> @@ -28,6 +28,8 @@
>  #include "generic.h"
>  #include "clock.h"
>  
> +extern void at91cap9_init_devices(void);
> +
>  static struct map_desc at91cap9_io_desc[] __initdata = {
>  	{
>  		.virtual	= AT91_VA_BASE_SYS,
> @@ -308,6 +310,8 @@ void __init at91cap9_initialize(unsigned long main_clock)
>  	/* Map peripherals */
>  	iotable_init(at91cap9_io_desc, ARRAY_SIZE(at91cap9_io_desc));
>  
> +	at91cap9_init_devices();
> +
>  	at91_arch_reset = at91cap9_reset;
>  	pm_power_off = at91cap9_poweroff;
>  	at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
> diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
> index 9ffbf3a..183f320 100644
> --- a/arch/arm/mach-at91/at91cap9_devices.c
> +++ b/arch/arm/mach-at91/at91cap9_devices.c
> @@ -29,7 +29,7 @@
>  #include <mach/at91sam9_smc.h>
>  
>  #include "generic.h"
> -
> +#include "devices.h"
>  
>  /* --------------------------------------------------------------------
>   *  USB Host
> @@ -196,75 +196,38 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
>   *  Ethernet
>   * -------------------------------------------------------------------- */
>  
> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> -static u64 eth_dmamask = DMA_BIT_MASK(32);
> -static struct at91_eth_data eth_data;
> -
> -static struct resource eth_resources[] = {
> -	[0] = {
> -		.start	= AT91CAP9_BASE_EMAC,
> -		.end	= AT91CAP9_BASE_EMAC + SZ_16K - 1,
> -		.flags	= IORESOURCE_MEM,
> -	},
> -	[1] = {
> -		.start	= AT91CAP9_ID_EMAC,
> -		.end	= AT91CAP9_ID_EMAC,
> -		.flags	= IORESOURCE_IRQ,
> -	},
> +static struct __initdata at91_pin_config eth_rmii_pins[] = {
> +	{AT91_PIN_PB21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
> +	{AT91_PIN_PB22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
> +	{AT91_PIN_PB25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
> +	{AT91_PIN_PB26, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
> +	{AT91_PIN_PB27, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
> +	{AT91_PIN_PB28, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
> +	{AT91_PIN_PB23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
> +	{AT91_PIN_PB24, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
> +	{AT91_PIN_PB30, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
> +	{AT91_PIN_PB29, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
>  };
>  
> -static struct platform_device at91cap9_eth_device = {
> -	.name		= "macb",
> -	.id		= -1,
> -	.dev		= {
> -				.dma_mask		= &eth_dmamask,
> -				.coherent_dma_mask	= DMA_BIT_MASK(32),
> -				.platform_data		= &eth_data,
> -	},
> -	.resource	= eth_resources,
> -	.num_resources	= ARRAY_SIZE(eth_resources),
> +static struct __initdata at91_pin_config eth_mii_pins[] = {
> +	{AT91_PIN_PC25, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECRS */
> +	{AT91_PIN_PC26, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
> +	{AT91_PIN_PC22, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
> +	{AT91_PIN_PC23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
> +	{AT91_PIN_PC27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
> +	{AT91_PIN_PC20, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
> +	{AT91_PIN_PC21, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
> +	{AT91_PIN_PC24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
>  };
>  
> -void __init at91_add_device_eth(struct at91_eth_data *data)
> -{
> -	if (!data)
> -		return;
> -
> -	if (data->phy_irq_pin) {
> -		at91_set_gpio_input(data->phy_irq_pin, 0);
> -		at91_set_deglitch(data->phy_irq_pin, 1);
> -	}
> -
> -	/* Pins used for MII and RMII */
> -	at91_set_A_periph(AT91_PIN_PB21, 0);	/* ETXCK_EREFCK */
> -	at91_set_A_periph(AT91_PIN_PB22, 0);	/* ERXDV */
> -	at91_set_A_periph(AT91_PIN_PB25, 0);	/* ERX0 */
> -	at91_set_A_periph(AT91_PIN_PB26, 0);	/* ERX1 */
> -	at91_set_A_periph(AT91_PIN_PB27, 0);	/* ERXER */
> -	at91_set_A_periph(AT91_PIN_PB28, 0);	/* ETXEN */
> -	at91_set_A_periph(AT91_PIN_PB23, 0);	/* ETX0 */
> -	at91_set_A_periph(AT91_PIN_PB24, 0);	/* ETX1 */
> -	at91_set_A_periph(AT91_PIN_PB30, 0);	/* EMDIO */
> -	at91_set_A_periph(AT91_PIN_PB29, 0);	/* EMDC */
> -
> -	if (!data->is_rmii) {
> -		at91_set_B_periph(AT91_PIN_PC25, 0);	/* ECRS */
> -		at91_set_B_periph(AT91_PIN_PC26, 0);	/* ECOL */
> -		at91_set_B_periph(AT91_PIN_PC22, 0);	/* ERX2 */
> -		at91_set_B_periph(AT91_PIN_PC23, 0);	/* ERX3 */
> -		at91_set_B_periph(AT91_PIN_PC27, 0);	/* ERXCK */
> -		at91_set_B_periph(AT91_PIN_PC20, 0);	/* ETX2 */
> -		at91_set_B_periph(AT91_PIN_PC21, 0);	/* ETX3 */
> -		at91_set_B_periph(AT91_PIN_PC24, 0);	/* ETXER */
> -	}
> -
> -	eth_data = *data;
> -	platform_device_register(&at91cap9_eth_device);
> -}
> -#else
> -void __init at91_add_device_eth(struct at91_eth_data *data) {}
> -#endif
> -
> +static struct __initdata at91_dev_table_ethernet device_eth = {
> +	.mmio_base	= AT91CAP9_BASE_EMAC,
> +	.irq		= AT91CAP9_ID_EMAC,
> +	.rmii_pins	= eth_rmii_pins,
> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
> +	.mii_pins	= eth_mii_pins,
> +	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
> +};
>  
>  /* --------------------------------------------------------------------
>   *  MMC / SD
> @@ -1254,6 +1217,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
>  void __init at91_add_device_serial(void) {}
>  #endif
>  
> +static struct at91_device_table __initdata at91cap9_device_table = {
> +	.ethernet	= &device_eth,
> +};
> +
> +void __init at91cap9_init_devices(void)
> +{
> +	at91_init_devices(&at91cap9_device_table);
> +}
>  
>  /* -------------------------------------------------------------------- */
>  /*
> diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
> index 2e9ecad..dea90df 100644
> --- a/arch/arm/mach-at91/at91rm9200.c
> +++ b/arch/arm/mach-at91/at91rm9200.c
> @@ -22,6 +22,8 @@
>  #include "generic.h"
>  #include "clock.h"
>  
> +extern void at91rm9200_init_devices(void);
> +
>  static struct map_desc at91rm9200_io_desc[] __initdata = {
>  	{
>  		.virtual	= AT91_VA_BASE_SYS,
> @@ -275,6 +277,8 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks
>  	/* Map peripherals */
>  	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
>  
> +	at91rm9200_init_devices();
> +
>  	at91_arch_reset = at91rm9200_reset;
>  	at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
>  			| (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
> diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
> index 7b53922..1b93312 100644
> --- a/arch/arm/mach-at91/at91rm9200_devices.c
> +++ b/arch/arm/mach-at91/at91rm9200_devices.c
> @@ -23,7 +23,7 @@
>  #include <mach/at91rm9200_mc.h>
>  
>  #include "generic.h"
> -
> +#include "devices.h"
>  
>  /* --------------------------------------------------------------------
>   *  USB Host
> @@ -125,75 +125,38 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
>   *  Ethernet
>   * -------------------------------------------------------------------- */
>  
> -#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
> -static u64 eth_dmamask = DMA_BIT_MASK(32);
> -static struct at91_eth_data eth_data;
> -
> -static struct resource eth_resources[] = {
> -	[0] = {
> -		.start	= AT91_VA_BASE_EMAC,
> -		.end	= AT91_VA_BASE_EMAC + SZ_16K - 1,
> -		.flags	= IORESOURCE_MEM,
> -	},
> -	[1] = {
> -		.start	= AT91RM9200_ID_EMAC,
> -		.end	= AT91RM9200_ID_EMAC,
> -		.flags	= IORESOURCE_IRQ,
> -	},
> +static struct __initdata at91_pin_config eth_rmii_pins[] = {
> +	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
> +	{AT91_PIN_PA15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
> +	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
> +	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
> +	{AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
> +	{AT91_PIN_PA11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ECRS_ECRSDV */
> +	{AT91_PIN_PA10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
> +	{AT91_PIN_PA9,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
> +	{AT91_PIN_PA8,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
> +	{AT91_PIN_PA7,  AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
>  };
>  
> -static struct platform_device at91rm9200_eth_device = {
> -	.name		= "at91_ether",
> -	.id		= -1,
> -	.dev		= {
> -				.dma_mask		= &eth_dmamask,
> -				.coherent_dma_mask	= DMA_BIT_MASK(32),
> -				.platform_data		= &eth_data,
> -	},
> -	.resource	= eth_resources,
> -	.num_resources	= ARRAY_SIZE(eth_resources),
> +static struct __initdata at91_pin_config eth_mii_pins[] = {
> +	{AT91_PIN_PB19, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
> +	{AT91_PIN_PB18, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
> +	{AT91_PIN_PB17, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXDV */
> +	{AT91_PIN_PB16, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
> +	{AT91_PIN_PB15, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
> +	{AT91_PIN_PB14, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
> +	{AT91_PIN_PB13, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
> +	{AT91_PIN_PB12, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
>  };
>  
> -void __init at91_add_device_eth(struct at91_eth_data *data)
> -{
> -	if (!data)
> -		return;
> -
> -	if (data->phy_irq_pin) {
> -		at91_set_gpio_input(data->phy_irq_pin, 0);
> -		at91_set_deglitch(data->phy_irq_pin, 1);
> -	}
> -
> -	/* Pins used for MII and RMII */
> -	at91_set_A_periph(AT91_PIN_PA16, 0);	/* EMDIO */
> -	at91_set_A_periph(AT91_PIN_PA15, 0);	/* EMDC */
> -	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERXER */
> -	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ERX1 */
> -	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ERX0 */
> -	at91_set_A_periph(AT91_PIN_PA11, 0);	/* ECRS_ECRSDV */
> -	at91_set_A_periph(AT91_PIN_PA10, 0);	/* ETX1 */
> -	at91_set_A_periph(AT91_PIN_PA9, 0);	/* ETX0 */
> -	at91_set_A_periph(AT91_PIN_PA8, 0);	/* ETXEN */
> -	at91_set_A_periph(AT91_PIN_PA7, 0);	/* ETXCK_EREFCK */
> -
> -	if (!data->is_rmii) {
> -		at91_set_B_periph(AT91_PIN_PB19, 0);	/* ERXCK */
> -		at91_set_B_periph(AT91_PIN_PB18, 0);	/* ECOL */
> -		at91_set_B_periph(AT91_PIN_PB17, 0);	/* ERXDV */
> -		at91_set_B_periph(AT91_PIN_PB16, 0);	/* ERX3 */
> -		at91_set_B_periph(AT91_PIN_PB15, 0);	/* ERX2 */
> -		at91_set_B_periph(AT91_PIN_PB14, 0);	/* ETXER */
> -		at91_set_B_periph(AT91_PIN_PB13, 0);	/* ETX3 */
> -		at91_set_B_periph(AT91_PIN_PB12, 0);	/* ETX2 */
> -	}
> -
> -	eth_data = *data;
> -	platform_device_register(&at91rm9200_eth_device);
> -}
> -#else
> -void __init at91_add_device_eth(struct at91_eth_data *data) {}
> -#endif
> -
> +static struct __initdata at91_dev_table_ethernet device_eth = {
> +	.mmio_base	= AT91_VA_BASE_EMAC,
> +	.irq		= AT91RM9200_ID_EMAC,
> +	.rmii_pins	= eth_rmii_pins,
> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
> +	.mii_pins	= eth_mii_pins,
> +	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
> +};
>  
>  /* --------------------------------------------------------------------
>   *  Compact Flash / PCMCIA
> @@ -1170,6 +1133,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
>  void __init at91_add_device_serial(void) {}
>  #endif
>  
> +static struct at91_device_table __initdata at91rm9200_device_table = {
> +	.ethernet	= &device_eth,
> +};
> +
> +void __init at91rm9200_init_devices(void)
> +{
> +	at91_init_devices(&at91rm9200_device_table);
> +}
>  
>  /* -------------------------------------------------------------------- */
>  
> diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
> index 195208b..7445f48 100644
> --- a/arch/arm/mach-at91/at91sam9260.c
> +++ b/arch/arm/mach-at91/at91sam9260.c
> @@ -25,6 +25,8 @@
>  #include "generic.h"
>  #include "clock.h"
>  
> +extern void at91sam9260_init_devices(void);
> +
>  static struct map_desc at91sam9260_io_desc[] __initdata = {
>  	{
>  		.virtual	= AT91_VA_BASE_SYS,
> @@ -315,6 +317,8 @@ void __init at91sam9260_initialize(unsigned long main_clock)
>  	/* Map peripherals */
>  	iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
>  
> +	at91sam9260_init_devices();
> +
>  	if (cpu_is_at91sam9xe())
>  		at91sam9xe_initialize();
>  	else if (cpu_is_at91sam9g20())
> diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
> index 07eb7b0..b4f00ea 100644
> --- a/arch/arm/mach-at91/at91sam9260_devices.c
> +++ b/arch/arm/mach-at91/at91sam9260_devices.c
> @@ -24,7 +24,7 @@
>  #include <mach/at91sam9_smc.h>
>  
>  #include "generic.h"
> -
> +#include "devices.h"
>  
>  /* --------------------------------------------------------------------
>   *  USB Host
> @@ -126,75 +126,38 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
>   *  Ethernet
>   * -------------------------------------------------------------------- */
>  
> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> -static u64 eth_dmamask = DMA_BIT_MASK(32);
> -static struct at91_eth_data eth_data;
> -
> -static struct resource eth_resources[] = {
> -	[0] = {
> -		.start	= AT91SAM9260_BASE_EMAC,
> -		.end	= AT91SAM9260_BASE_EMAC + SZ_16K - 1,
> -		.flags	= IORESOURCE_MEM,
> -	},
> -	[1] = {
> -		.start	= AT91SAM9260_ID_EMAC,
> -		.end	= AT91SAM9260_ID_EMAC,
> -		.flags	= IORESOURCE_IRQ,
> -	},
> +static struct __initdata at91_pin_config eth_rmii_pins[] = {
> +	{AT91_PIN_PA19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
> +	{AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
> +	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
> +	{AT91_PIN_PA15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
> +	{AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
> +	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
> +	{AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
> +	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
> +	{AT91_PIN_PA21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
> +	{AT91_PIN_PA20, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
>  };
>  
> -static struct platform_device at91sam9260_eth_device = {
> -	.name		= "macb",
> -	.id		= -1,
> -	.dev		= {
> -				.dma_mask		= &eth_dmamask,
> -				.coherent_dma_mask	= DMA_BIT_MASK(32),
> -				.platform_data		= &eth_data,
> -	},
> -	.resource	= eth_resources,
> -	.num_resources	= ARRAY_SIZE(eth_resources),
> +static struct __initdata at91_pin_config eth_mii_pins[] = {
> +	{AT91_PIN_PA28, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECRS */
> +	{AT91_PIN_PA29, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
> +	{AT91_PIN_PA25, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
> +	{AT91_PIN_PA26, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
> +	{AT91_PIN_PA27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
> +	{AT91_PIN_PA23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
> +	{AT91_PIN_PA24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
> +	{AT91_PIN_PA22, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
>  };
>  
> -void __init at91_add_device_eth(struct at91_eth_data *data)
> -{
> -	if (!data)
> -		return;
> -
> -	if (data->phy_irq_pin) {
> -		at91_set_gpio_input(data->phy_irq_pin, 0);
> -		at91_set_deglitch(data->phy_irq_pin, 1);
> -	}
> -
> -	/* Pins used for MII and RMII */
> -	at91_set_A_periph(AT91_PIN_PA19, 0);	/* ETXCK_EREFCK */
> -	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ERXDV */
> -	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ERX0 */
> -	at91_set_A_periph(AT91_PIN_PA15, 0);	/* ERX1 */
> -	at91_set_A_periph(AT91_PIN_PA18, 0);	/* ERXER */
> -	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ETXEN */
> -	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ETX0 */
> -	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ETX1 */
> -	at91_set_A_periph(AT91_PIN_PA21, 0);	/* EMDIO */
> -	at91_set_A_periph(AT91_PIN_PA20, 0);	/* EMDC */
> -
> -	if (!data->is_rmii) {
> -		at91_set_B_periph(AT91_PIN_PA28, 0);	/* ECRS */
> -		at91_set_B_periph(AT91_PIN_PA29, 0);	/* ECOL */
> -		at91_set_B_periph(AT91_PIN_PA25, 0);	/* ERX2 */
> -		at91_set_B_periph(AT91_PIN_PA26, 0);	/* ERX3 */
> -		at91_set_B_periph(AT91_PIN_PA27, 0);	/* ERXCK */
> -		at91_set_B_periph(AT91_PIN_PA23, 0);	/* ETX2 */
> -		at91_set_B_periph(AT91_PIN_PA24, 0);	/* ETX3 */
> -		at91_set_B_periph(AT91_PIN_PA22, 0);	/* ETXER */
> -	}
> -
> -	eth_data = *data;
> -	platform_device_register(&at91sam9260_eth_device);
> -}
> -#else
> -void __init at91_add_device_eth(struct at91_eth_data *data) {}
> -#endif
> -
> +static struct __initdata at91_dev_table_ethernet device_eth = {
> +	.mmio_base	= AT91SAM9260_BASE_EMAC,
> +	.irq		= AT91SAM9260_ID_EMAC,
> +	.rmii_pins	= eth_rmii_pins,
> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
> +	.mii_pins	= eth_mii_pins,
> +	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
> +};
>  
>  /* --------------------------------------------------------------------
>   *  MMC / SD
> @@ -1326,6 +1289,15 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
>  void __init at91_add_device_cf(struct at91_cf_data * data) {}
>  #endif
>  
> +static struct at91_device_table __initdata at91sam9260_device_table = {
> +	.ethernet	= &device_eth,
> +};
> +
> +void __init at91sam9260_init_devices(void)
> +{
> +	at91_init_devices(&at91sam9260_device_table);
> +}
> +
>  /* -------------------------------------------------------------------- */
>  /*
>   * These devices are always present and don't need any board-specific
> diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
> index 59fc483..3c0959f 100644
> --- a/arch/arm/mach-at91/at91sam9261_devices.c
> +++ b/arch/arm/mach-at91/at91sam9261_devices.c
> @@ -1044,7 +1044,6 @@ void __init at91_set_serial_console(unsigned portnr) {}
>  void __init at91_add_device_serial(void) {}
>  #endif
>  
> -
>  /* -------------------------------------------------------------------- */
>  
>  /*
> diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
> index 249f900..739fc1f 100644
> --- a/arch/arm/mach-at91/at91sam9263.c
> +++ b/arch/arm/mach-at91/at91sam9263.c
> @@ -24,6 +24,8 @@
>  #include "generic.h"
>  #include "clock.h"
>  
> +extern void at91sam9263_init_devices(void);
> +
>  static struct map_desc at91sam9263_io_desc[] __initdata = {
>  	{
>  		.virtual	= AT91_VA_BASE_SYS,
> @@ -284,6 +286,8 @@ void __init at91sam9263_initialize(unsigned long main_clock)
>  	/* Map peripherals */
>  	iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
>  
> +	at91sam9263_init_devices();
> +
>  	at91_arch_reset = at91sam9_alt_reset;
>  	pm_power_off = at91sam9263_poweroff;
>  	at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
> diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
> index fb5c23a..9ff2573 100644
> --- a/arch/arm/mach-at91/at91sam9263_devices.c
> +++ b/arch/arm/mach-at91/at91sam9263_devices.c
> @@ -26,6 +26,7 @@
>  #include <mach/at91sam9_smc.h>
>  
>  #include "generic.h"
> +#include "devices.h"
>  
>  
>  /* --------------------------------------------------------------------
> @@ -136,75 +137,38 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
>   *  Ethernet
>   * -------------------------------------------------------------------- */
>  
> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> -static u64 eth_dmamask = DMA_BIT_MASK(32);
> -static struct at91_eth_data eth_data;
> -
> -static struct resource eth_resources[] = {
> -	[0] = {
> -		.start	= AT91SAM9263_BASE_EMAC,
> -		.end	= AT91SAM9263_BASE_EMAC + SZ_16K - 1,
> -		.flags	= IORESOURCE_MEM,
> -	},
> -	[1] = {
> -		.start	= AT91SAM9263_ID_EMAC,
> -		.end	= AT91SAM9263_ID_EMAC,
> -		.flags	= IORESOURCE_IRQ,
> -	},
> +static struct __initdata at91_pin_config eth_rmii_pins[] = {
> +	{AT91_PIN_PE21, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
> +	{AT91_PIN_PC25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
> +	{AT91_PIN_PE25, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
> +	{AT91_PIN_PE26, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
> +	{AT91_PIN_PE27, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
> +	{AT91_PIN_PE28, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
> +	{AT91_PIN_PE23, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
> +	{AT91_PIN_PE24, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
> +	{AT91_PIN_PE30, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
> +	{AT91_PIN_PE29, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
>  };
>  
> -static struct platform_device at91sam9263_eth_device = {
> -	.name		= "macb",
> -	.id		= -1,
> -	.dev		= {
> -				.dma_mask		= &eth_dmamask,
> -				.coherent_dma_mask	= DMA_BIT_MASK(32),
> -				.platform_data		= &eth_data,
> -	},
> -	.resource	= eth_resources,
> -	.num_resources	= ARRAY_SIZE(eth_resources),
> +static struct __initdata at91_pin_config eth_mii_pins[] = {
> +	{AT91_PIN_PE22, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ECRS */
> +	{AT91_PIN_PC26, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
> +	{AT91_PIN_PC22, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
> +	{AT91_PIN_PC23, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
> +	{AT91_PIN_PC27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
> +	{AT91_PIN_PC20, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
> +	{AT91_PIN_PC21, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
> +	{AT91_PIN_PC24, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
>  };
>  
> -void __init at91_add_device_eth(struct at91_eth_data *data)
> -{
> -	if (!data)
> -		return;
> -
> -	if (data->phy_irq_pin) {
> -		at91_set_gpio_input(data->phy_irq_pin, 0);
> -		at91_set_deglitch(data->phy_irq_pin, 1);
> -	}
> -
> -	/* Pins used for MII and RMII */
> -	at91_set_A_periph(AT91_PIN_PE21, 0);	/* ETXCK_EREFCK */
> -	at91_set_B_periph(AT91_PIN_PC25, 0);	/* ERXDV */
> -	at91_set_A_periph(AT91_PIN_PE25, 0);	/* ERX0 */
> -	at91_set_A_periph(AT91_PIN_PE26, 0);	/* ERX1 */
> -	at91_set_A_periph(AT91_PIN_PE27, 0);	/* ERXER */
> -	at91_set_A_periph(AT91_PIN_PE28, 0);	/* ETXEN */
> -	at91_set_A_periph(AT91_PIN_PE23, 0);	/* ETX0 */
> -	at91_set_A_periph(AT91_PIN_PE24, 0);	/* ETX1 */
> -	at91_set_A_periph(AT91_PIN_PE30, 0);	/* EMDIO */
> -	at91_set_A_periph(AT91_PIN_PE29, 0);	/* EMDC */
> -
> -	if (!data->is_rmii) {
> -		at91_set_A_periph(AT91_PIN_PE22, 0);	/* ECRS */
> -		at91_set_B_periph(AT91_PIN_PC26, 0);	/* ECOL */
> -		at91_set_B_periph(AT91_PIN_PC22, 0);	/* ERX2 */
> -		at91_set_B_periph(AT91_PIN_PC23, 0);	/* ERX3 */
> -		at91_set_B_periph(AT91_PIN_PC27, 0);	/* ERXCK */
> -		at91_set_B_periph(AT91_PIN_PC20, 0);	/* ETX2 */
> -		at91_set_B_periph(AT91_PIN_PC21, 0);	/* ETX3 */
> -		at91_set_B_periph(AT91_PIN_PC24, 0);	/* ETXER */
> -	}
> -
> -	eth_data = *data;
> -	platform_device_register(&at91sam9263_eth_device);
> -}
> -#else
> -void __init at91_add_device_eth(struct at91_eth_data *data) {}
> -#endif
> -
> +static struct __initdata at91_dev_table_ethernet device_eth = {
> +	.mmio_base	= AT91SAM9263_BASE_EMAC,
> +	.irq		= AT91SAM9263_ID_EMAC,
> +	.rmii_pins	= eth_rmii_pins,
> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
> +	.mii_pins	= eth_mii_pins,
> +	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
> +};
>  
>  /* --------------------------------------------------------------------
>   *  MMC / SD
> @@ -1425,6 +1389,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
>  void __init at91_add_device_serial(void) {}
>  #endif
>  
> +static struct at91_device_table __initdata at91sam9263_device_table = {
> +	.ethernet	= &device_eth,
> +};
> +
> +void __init at91sam9263_init_devices(void)
> +{
> +	at91_init_devices(&at91sam9263_device_table);
> +}
>  
>  /* -------------------------------------------------------------------- */
>  /*
> diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
> index c67b47f..357e5d7 100644
> --- a/arch/arm/mach-at91/at91sam9g45.c
> +++ b/arch/arm/mach-at91/at91sam9g45.c
> @@ -25,6 +25,8 @@
>  #include "generic.h"
>  #include "clock.h"
>  
> +extern void at91sam9g45_init_devices(void);
> +
>  static struct map_desc at91sam9g45_io_desc[] __initdata = {
>  	{
>  		.virtual	= AT91_VA_BASE_SYS,
> @@ -311,6 +313,8 @@ void __init at91sam9g45_initialize(unsigned long main_clock)
>  	/* Map peripherals */
>  	iotable_init(at91sam9g45_io_desc, ARRAY_SIZE(at91sam9g45_io_desc));
>  
> +	at91sam9g45_init_devices();
> +
>  	at91_arch_reset = at91sam9g45_reset;
>  	pm_power_off = at91sam9g45_poweroff;
>  	at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0);
> diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
> index 1e8f275..76e95f8 100644
> --- a/arch/arm/mach-at91/at91sam9g45_devices.c
> +++ b/arch/arm/mach-at91/at91sam9g45_devices.c
> @@ -29,6 +29,7 @@
>  #include <mach/atmel-mci.h>
>  
>  #include "generic.h"
> +#include "devices.h"
>  
>  
>  /* --------------------------------------------------------------------
> @@ -281,76 +282,39 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
>   *  Ethernet
>   * -------------------------------------------------------------------- */
>  
> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> -static u64 eth_dmamask = DMA_BIT_MASK(32);
> -static struct at91_eth_data eth_data;
> -
> -static struct resource eth_resources[] = {
> -	[0] = {
> -		.start	= AT91SAM9G45_BASE_EMAC,
> -		.end	= AT91SAM9G45_BASE_EMAC + SZ_16K - 1,
> -		.flags	= IORESOURCE_MEM,
> -	},
> -	[1] = {
> -		.start	= AT91SAM9G45_ID_EMAC,
> -		.end	= AT91SAM9G45_ID_EMAC,
> -		.flags	= IORESOURCE_IRQ,
> -	},
> +static struct __initdata at91_pin_config eth_rmii_pins[] = {
> +	{AT91_PIN_PA17, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXCK_EREFCK */
> +	{AT91_PIN_PA15, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXDV */
> +	{AT91_PIN_PA12, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX0 */
> +	{AT91_PIN_PA13, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERX1 */
> +	{AT91_PIN_PA16, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ERXER */
> +	{AT91_PIN_PA14, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETXEN */
> +	{AT91_PIN_PA10, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX0 */
> +	{AT91_PIN_PA11, AT91_PIN_PERIPH_A, 0, 0, 0},	/* ETX1 */
> +	{AT91_PIN_PA19, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDIO */
> +	{AT91_PIN_PA18, AT91_PIN_PERIPH_A, 0, 0, 0},	/* EMDC */
> +};
> +
> +static struct __initdata at91_pin_config eth_mii_pins[] = {
> +	{AT91_PIN_PA29, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECRS */
> +	{AT91_PIN_PA30, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ECOL */
> +	{AT91_PIN_PA8,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX2 */
> +	{AT91_PIN_PA9,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERX3 */
> +	{AT91_PIN_PA28, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ERXCK */
> +	{AT91_PIN_PA6,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX2 */
> +	{AT91_PIN_PA7,  AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETX3 */
> +	{AT91_PIN_PA27, AT91_PIN_PERIPH_B, 0, 0, 0},	/* ETXER */
> +};
> +
> +static struct __initdata at91_dev_table_ethernet device_eth = {
> +	.mmio_base	= AT91SAM9G45_BASE_EMAC,
> +	.irq		= AT91SAM9G45_ID_EMAC,
> +	.rmii_pins	= eth_rmii_pins,
> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
> +	.mii_pins	= eth_mii_pins,
> +	.nr_mii_pins	= ARRAY_SIZE(eth_mii_pins),
>  };
>  
> -static struct platform_device at91sam9g45_eth_device = {
> -	.name		= "macb",
> -	.id		= -1,
> -	.dev		= {
> -				.dma_mask		= &eth_dmamask,
> -				.coherent_dma_mask	= DMA_BIT_MASK(32),
> -				.platform_data		= &eth_data,
> -	},
> -	.resource	= eth_resources,
> -	.num_resources	= ARRAY_SIZE(eth_resources),
> -};
> -
> -void __init at91_add_device_eth(struct at91_eth_data *data)
> -{
> -	if (!data)
> -		return;
> -
> -	if (data->phy_irq_pin) {
> -		at91_set_gpio_input(data->phy_irq_pin, 0);
> -		at91_set_deglitch(data->phy_irq_pin, 1);
> -	}
> -
> -	/* Pins used for MII and RMII */
> -	at91_set_A_periph(AT91_PIN_PA17, 0);	/* ETXCK_EREFCK */
> -	at91_set_A_periph(AT91_PIN_PA15, 0);	/* ERXDV */
> -	at91_set_A_periph(AT91_PIN_PA12, 0);	/* ERX0 */
> -	at91_set_A_periph(AT91_PIN_PA13, 0);	/* ERX1 */
> -	at91_set_A_periph(AT91_PIN_PA16, 0);	/* ERXER */
> -	at91_set_A_periph(AT91_PIN_PA14, 0);	/* ETXEN */
> -	at91_set_A_periph(AT91_PIN_PA10, 0);	/* ETX0 */
> -	at91_set_A_periph(AT91_PIN_PA11, 0);	/* ETX1 */
> -	at91_set_A_periph(AT91_PIN_PA19, 0);	/* EMDIO */
> -	at91_set_A_periph(AT91_PIN_PA18, 0);	/* EMDC */
> -
> -	if (!data->is_rmii) {
> -		at91_set_B_periph(AT91_PIN_PA29, 0);	/* ECRS */
> -		at91_set_B_periph(AT91_PIN_PA30, 0);	/* ECOL */
> -		at91_set_B_periph(AT91_PIN_PA8,  0);	/* ERX2 */
> -		at91_set_B_periph(AT91_PIN_PA9,  0);	/* ERX3 */
> -		at91_set_B_periph(AT91_PIN_PA28, 0);	/* ERXCK */
> -		at91_set_B_periph(AT91_PIN_PA6,  0);	/* ETX2 */
> -		at91_set_B_periph(AT91_PIN_PA7,  0);	/* ETX3 */
> -		at91_set_B_periph(AT91_PIN_PA27, 0);	/* ETXER */
> -	}
> -
> -	eth_data = *data;
> -	platform_device_register(&at91sam9g45_eth_device);
> -}
> -#else
> -void __init at91_add_device_eth(struct at91_eth_data *data) {}
> -#endif
> -
> -
>  /* --------------------------------------------------------------------
>   *  MMC / SD
>   * -------------------------------------------------------------------- */
> @@ -1587,6 +1551,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
>  void __init at91_add_device_serial(void) {}
>  #endif
>  
> +static struct at91_device_table __initdata at91sam9g45_device_table = {
The more correct position for __initdata is just before the =, see
include/linux/init.h.

> +	.ethernet	= &device_eth,
> +};
> +
> +void __init at91sam9g45_init_devices(void)
> +{
> +	at91_init_devices(&at91sam9g45_device_table);
> +}
>  
>  /* -------------------------------------------------------------------- */
>  /*
> diff --git a/arch/arm/mach-at91/devices.c b/arch/arm/mach-at91/devices.c
> index 653e0a9..07fefc8 100644
> --- a/arch/arm/mach-at91/devices.c
> +++ b/arch/arm/mach-at91/devices.c
> @@ -14,8 +14,11 @@
>   */
>  
>  #include <linux/platform_device.h>
> +#include <linux/dma-mapping.h>
>  #include <linux/gpio.h>
>  
> +#include <mach/board.h>
> +
>  #include "devices.h"
>  
>  static __initdata struct at91_device_table *devices;
> @@ -64,6 +67,64 @@ static inline void __init init_resource_irq(struct resource *res, int irq)
>  	}
>  }
>  
> +/* --------------------------------------------------------------------
> + *  Ethernet
> + * -------------------------------------------------------------------- */
> +
> +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> +static u64 eth_dmamask = DMA_BIT_MASK(32);
> +static struct at91_eth_data eth_data;
> +
> +static struct resource eth_resources[] = {
> +	[0] = {
> +		.end	= SZ_16K,
> +		.flags	= IORESOURCE_MEM,
> +	},
> +	[1] = {
> +		.flags	= IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct platform_device at91_eth_device = {
> +	.name		= "macb",
> +	.id		= -1,
> +	.dev		= {
> +				.dma_mask		= &eth_dmamask,
> +				.coherent_dma_mask	= DMA_BIT_MASK(32),
> +				.platform_data		= &eth_data,
> +	},
> +	.resource	= eth_resources,
> +	.num_resources	= ARRAY_SIZE(eth_resources),
> +};
> +
> +void __init at91_add_device_eth(struct at91_eth_data *data)
> +{
> +	struct at91_dev_table_ethernet *info = devices->ethernet;
> +
> +	BUG_ON(!info);
> +	init_resource_mem(&eth_resources[0], info->mmio_base);
> +	init_resource_irq(&eth_resources[1], info->irq);
> +
> +	if (!data)
> +		return;
> +
> +	if (data->phy_irq_pin) {
> +		at91_set_gpio_input(data->phy_irq_pin, 0);
> +		at91_set_deglitch(data->phy_irq_pin, 1);
> +	}
> +
> +	/* Pins used for MII and RMII */
> +	at91_config_pins(info->rmii_pins, info->nr_rmii_pins);
> +	if (!data->is_rmii && info->mii_pins)
> +		at91_config_pins(info->mii_pins, info->nr_mii_pins);
> +
> +	eth_data = *data;
> +	platform_device_register(&at91_eth_device);
> +}
> +#else
> +void __init at91_add_device_eth(struct at91_eth_data *data) {}
> +#endif
> +
>  void __init at91_init_devices(struct at91_device_table *device_table)
>  {
>  	devices = device_table;
> diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
> index 738f736..7bed3e7 100644
> --- a/arch/arm/mach-at91/devices.h
> +++ b/arch/arm/mach-at91/devices.h
> @@ -28,7 +28,17 @@ struct at91_pin_config {
>  	int value;
>  };
>  
> +struct at91_dev_table_ethernet {
> +	unsigned 		mmio_base;
> +	int 			irq;
> +	struct at91_pin_config	*rmii_pins;
> +	int 			nr_rmii_pins;
> +	struct at91_pin_config	*mii_pins;
> +	int 			nr_mii_pins;
> +};
> +
>  struct at91_device_table {
> +	struct at91_dev_table_ethernet		*ethernet;
>  };
I wonder if it's a good idea to collect all data in a single cross-SoC
table. Consider a new SoC that has a new type of device, then you need
to expand this struct for only a single user. Moreover expanding this
struct will result in merge conflicts when >1 patch touches it.
If I understand your approach correctly you will have a single per-SoC
function that initialises all devices, right? If so, how do you handle
machines that don't have ethernet or that don't have handshake lines for
an UART?

For mxc I used dedicated functions instead of a generic struct. (This
isn't optimal also, because there is still a single header file, but
when the functions are moved near the drivers I think that would be
fine.) See arch/arm/plat-mxc/include/mach/devices-common.h,
arch/arm/mach-imx/devices-imx27.h (et al) and
arch/arm/plat-mxc/devices/* for the details.

Maybe this helps to consolidate cross-platform device registration.

Best regards,
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  8:36   ` Uwe Kleine-König
@ 2011-04-20 10:34     ` Jean-Christophe PLAGNIOL-VILLARD
  2011-04-20 11:07     ` Ryan Mallon
  2011-04-20 20:41     ` Ryan Mallon
  2 siblings, 0 replies; 41+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2011-04-20 10:34 UTC (permalink / raw)
  To: linux-arm-kernel

> > + * -------------------------------------------------------------------- */
> > +
> > +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
> > +static u64 eth_dmamask = DMA_BIT_MASK(32);
> > +static struct at91_eth_data eth_data;
> > +
> > +static struct resource eth_resources[] = {
> > +	[0] = {
> > +		.end	= SZ_16K,
> > +		.flags	= IORESOURCE_MEM,
> > +	},
> > +	[1] = {
> > +		.flags	= IORESOURCE_IRQ,
> > +	},
> > +};
> > +
> > +static struct platform_device at91_eth_device = {
> > +	.name		= "macb",
> > +	.id		= -1,
> > +	.dev		= {
> > +				.dma_mask		= &eth_dmamask,
> > +				.coherent_dma_mask	= DMA_BIT_MASK(32),
> > +				.platform_data		= &eth_data,
> > +	},
> > +	.resource	= eth_resources,
> > +	.num_resources	= ARRAY_SIZE(eth_resources),
> > +};
> > +
> > +void __init at91_add_device_eth(struct at91_eth_data *data)
> > +{
> > +	struct at91_dev_table_ethernet *info = devices->ethernet;
> > +
> > +	BUG_ON(!info);
> > +	init_resource_mem(&eth_resources[0], info->mmio_base);
> > +	init_resource_irq(&eth_resources[1], info->irq);
> > +
> > +	if (!data)
> > +		return;
> > +
> > +	if (data->phy_irq_pin) {
> > +		at91_set_gpio_input(data->phy_irq_pin, 0);
> > +		at91_set_deglitch(data->phy_irq_pin, 1);
> > +	}
> > +
> > +	/* Pins used for MII and RMII */
> > +	at91_config_pins(info->rmii_pins, info->nr_rmii_pins);
> > +	if (!data->is_rmii && info->mii_pins)
> > +		at91_config_pins(info->mii_pins, info->nr_mii_pins);
> > +
> > +	eth_data = *data;
> > +	platform_device_register(&at91_eth_device);
> > +}
> > +#else
> > +void __init at91_add_device_eth(struct at91_eth_data *data) {}
> > +#endif
> > +
> >  void __init at91_init_devices(struct at91_device_table *device_table)
> >  {
> >  	devices = device_table;
> > diff --git a/arch/arm/mach-at91/devices.h b/arch/arm/mach-at91/devices.h
> > index 738f736..7bed3e7 100644
> > --- a/arch/arm/mach-at91/devices.h
> > +++ b/arch/arm/mach-at91/devices.h
> > @@ -28,7 +28,17 @@ struct at91_pin_config {
> >  	int value;
> >  };
> >  
> > +struct at91_dev_table_ethernet {
> > +	unsigned 		mmio_base;
> > +	int 			irq;
> > +	struct at91_pin_config	*rmii_pins;
> > +	int 			nr_rmii_pins;
> > +	struct at91_pin_config	*mii_pins;
> > +	int 			nr_mii_pins;
> > +};
> > +
> >  struct at91_device_table {
> > +	struct at91_dev_table_ethernet		*ethernet;
> >  };
> I wonder if it's a good idea to collect all data in a single cross-SoC
> table. Consider a new SoC that has a new type of device, then you need
> to expand this struct for only a single user. Moreover expanding this
> struct will result in merge conflicts when >1 patch touches it.
> If I understand your approach correctly you will have a single per-SoC
> function that initialises all devices, right? If so, how do you handle
> machines that don't have ethernet or that don't have handshake lines for
> an UART?
> 
> For mxc I used dedicated functions instead of a generic struct. (This
> isn't optimal also, because there is still a single header file, but
> when the functions are moved near the drivers I think that would be
> fine.) See arch/arm/plat-mxc/include/mach/devices-common.h,
> arch/arm/mach-imx/devices-imx27.h (et al) and
> arch/arm/plat-mxc/devices/* for the details.
> 
> Maybe this helps to consolidate cross-platform device registration.
I've start to work olso on the function level as you do Uwe I'll take a look
this week-end to make merge both of them

but in my mind I like the idea to have pull of available ressources and the
you register the one your are interested in

as I plan to add the multi soc the idea of a structure is good so you have
generic ressource registration function for all IP available on AT91 and then
each soc declare it

Maybe we could use early devices for this or a dedicated framework so the soc
declare his capabilitues

Best Regards,
J.

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  8:36   ` Uwe Kleine-König
  2011-04-20 10:34     ` Jean-Christophe PLAGNIOL-VILLARD
@ 2011-04-20 11:07     ` Ryan Mallon
  2011-04-20 20:41     ` Ryan Mallon
  2 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20 11:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 20/04/11 20:36, Uwe Kleine-K?nig wrote:
> Hello Ryan,
> 
> On Wed, Apr 20, 2011 at 01:10:05PM +1200, Ryan Mallon wrote:
>> Replace the individual Ethernet device code for each at91 variant with
>> a single implementation in devices.
>>
>> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
>>

<snip>

>> +struct at91_dev_table_ethernet {
>> +	unsigned 		mmio_base;
>> +	int 			irq;
>> +	struct at91_pin_config	*rmii_pins;
>> +	int 			nr_rmii_pins;
>> +	struct at91_pin_config	*mii_pins;
>> +	int 			nr_mii_pins;
>> +};
>> +
>>  struct at91_device_table {
>> +	struct at91_dev_table_ethernet		*ethernet;
>>  };
> I wonder if it's a good idea to collect all data in a single cross-SoC
> table.

The thinking behind using a single large table is that it reduces the
amount of data which needs to be exported, and makes it easy to see
which devices each SoC has. The device table is initdata so it doesn't
stay in memory permanently.

> Consider a new SoC that has a new type of device, then you need
> to expand this struct for only a single user. Moreover expanding this
> struct will result in merge conflicts when >1 patch touches it.

True, but the common code has to live somewhere. You may still get merge
conflicts when more than one SoC adds a new device to the common
devices.c. I don't think that needing to expand the device table struct
is necessarily a bad thing.

> If I understand your approach correctly you will have a single per-SoC
> function that initialises all devices, right? If so, how do you handle
> machines that don't have ethernet or that don't have handshake lines for
> an UART?

Not quite. All of the device structures in the *_devices.c files are
just descriptions of the devices, and are marked initdata so they are
freed later on. Actual initialisation of the device data is handled by
individual functions (e.g. at91_add_device_ethernet) which uses the
device descriptor structure to initialise the device.

I should possibly note in the changelog that this patch does not really
introduce a functional change (boards still initialise devices the same
way as before), it just changes how the initialisation data is stored to
make it easier to consolidate the common parts.

> For mxc I used dedicated functions instead of a generic struct. (This
> isn't optimal also, because there is still a single header file, but
> when the functions are moved near the drivers I think that would be
> fine.) See arch/arm/plat-mxc/include/mach/devices-common.h,
> arch/arm/mach-imx/devices-imx27.h (et al) and
> arch/arm/plat-mxc/devices/* for the details.

Our approaches are actually similar. The functions in the at91 case are
in devices.c (in my patch series), with the data structures passed to
the functions (via the device table) being in the *_devices.c files.

~Ryan

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

* [RFC PATCH 11/23] at91: Make watchdog device common
  2011-04-20  1:10 ` [RFC PATCH 11/23] at91: Make watchdog " Ryan Mallon
@ 2011-04-20 17:10   ` H Hartley Sweeten
  0 siblings, 0 replies; 41+ messages in thread
From: H Hartley Sweeten @ 2011-04-20 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, April 19, 2011 6:10 PM, Ryan Mallon wrote:
>
> The code for the watchdog device for each of the at91 variants is
> identical. Remove it from each variant and replace them with a single
> version in devices.c
>
> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>
> ---

[snip]

> diff --git a/arch/arm/mach-at91/at572d940hf_devices.c b/arch/arm/mach-at91/at572d940hf_devices.c
> index 2828e7e..20fe358 100644
> --- a/arch/arm/mach-at91/at572d940hf_devices.c
> +++ b/arch/arm/mach-at91/at572d940hf_devices.c

[snip]
 
> @@ -538,17 +518,3 @@ void __init at572d940hf_init_devices(void)
>  {
>  	at91_init_devices(&at572d940hf_device_table);
>  }
> -
> -/* -------------------------------------------------------------------- */
> -
> -/*
> - * These devices are always present and don't need any board-specific
> - * setup.
> - */
> -static int __init at91_add_standard_devices(void)
> -{
> -	at91_add_device_watchdog();
> -	return 0;
> -}
> -
> -arch_initcall(at91_add_standard_devices);

Ryan,

I would suggest leaving the various at91_add_standard_devices functions in until
all the other patches are applied.  Add one more patch to the series to finally
rip them out after all the conversions are complete.

Regards,
Hartley

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

* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
  2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
                   ` (24 preceding siblings ...)
  2011-04-20  3:47 ` [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Jean-Christophe PLAGNIOL-VILLARD
@ 2011-04-20 17:14 ` H Hartley Sweeten
  2011-04-20 21:07   ` Ryan Mallon
  25 siblings, 1 reply; 41+ messages in thread
From: H Hartley Sweeten @ 2011-04-20 17:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, April 19, 2011 6:10 PM, Ryan Mallon wrote:
>
> Each AT91 variant (AT91RM9200, AT91SAM9260, etc) currently has its own
> devices file, which includes the MMIO address, interrupt
> configuration, GPIO setup, etc for each device. This results in a large
> amount of duplicated code.
>
> This patch set introduces a framework for adding shared devices for the
> AT91 platform and replaces the multiple device setup implementations for
> each device with single implementations in the new framework. This has
> a net reduction of nearly 5000 lines of code.
>
> Each of the arch/arm/mach-at91/*_devices.c files becomes a collection of
> structures (with some initialisation callbacks where necessary) with a
> table of devices which are present on the particular AT91 variant. All
> structures/functions are marked as __init/__initdata so there is little
> additional memory overhead. This also means that the #ifdefs around each
> device can be removed from the *_devices.c files (but remain in the new
> common devices.c file) without overhead.
>
> I have build tested the patch series for all of the  AT91 variants 
> and devices, and have boot tested it on the AT91SAM9260 (Snapper 9260
> board) and tested basic device functionality.
>
> Ryan Mallon (23):
>   at91: Add common devices framework
>   at91: Make Ethernet device common
>   at91: Make USB OHCI/EHCI devices common
>   at91: Make UDC device common
>   at91: Make MMC device common
>   at91: Make NAND device common
>   at91: Make TWI device common
>   at91: Make SPI device common
>   at91: Make TCB device common
>   at91: Make RTT device common
>   at91: Make watchdog device common
>   at91: Make UART devices common

This patch (12/23) appears to be missing.

Regards,
Hartley

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  2:33     ` Ryan Mallon
@ 2011-04-20 18:23       ` H Hartley Sweeten
  0 siblings, 0 replies; 41+ messages in thread
From: H Hartley Sweeten @ 2011-04-20 18:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, April 19, 2011 7:33 PM, Ryan Mallon wrote:
>>> -#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
>>> -static u64 eth_dmamask = DMA_BIT_MASK(32);
>>> -static struct at91_eth_data eth_data;
>>> -
>>> -static struct resource eth_resources[] = {
>>> -	[0] = {
>>> -		.start	= AT572D940HF_BASE_EMAC,
>>> -		.end	= AT572D940HF_BASE_EMAC + SZ_16K - 1,
>>> -		.flags	= IORESOURCE_MEM,
>>> -	},
>>> -	[1] = {
>>> -		.start	= AT572D940HF_ID_EMAC,
>>> -		.end	= AT572D940HF_ID_EMAC,
>>> -		.flags	= IORESOURCE_IRQ,
>>> -	},
>> 
>> [snip]
>> 
>>> +static struct __initdata at91_dev_table_ethernet device_eth = {
>>> +	.mmio_base	= AT91SAM9260_BASE_EMAC,
>>> +	.irq		= AT91SAM9260_ID_EMAC,
>> 
>> AT572D940HF_BASE_EMAC and AT572D940HF_ID_EMAC?
>
> Crap. It's somehow ended up in patch 4 instead. Will fix, thanks.

OK.

>>> +	.rmii_pins	= eth_rmii_pins,
>>> +	.nr_rmii_pins	= ARRAY_SIZE(eth_rmii_pins),
>>>  };
>>>
>>> -void __init at91_add_device_eth(struct at91_eth_data *data)
>>> -{
>>> -	if (!data)
>>> -		return;
>>> -
>>> -	if (data->phy_irq_pin) {
>>> -		at91_set_gpio_input(data->phy_irq_pin, 0);
>>> -		at91_set_deglitch(data->phy_irq_pin, 1);
>>> -	}
>>> -
>>> -	/* Only RMII is supported */
>>> -	data->is_rmii = 1;
>> 
>> How is this set for this platfrom?
>
> By having mii_pins set to NULL. The devices.c code now does:
>
>	if (!data->is_rmii && info->mii_pins)
>		...

Ah, see that now. OK.

>>> diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
>>> index 59fc483..3c0959f 100644
>>> --- a/arch/arm/mach-at91/at91sam9261_devices.c
>>> +++ b/arch/arm/mach-at91/at91sam9261_devices.c
>>> @@ -1044,7 +1044,6 @@ void __init at91_set_serial_console(unsigned portnr) {}
>>>  void __init at91_add_device_serial(void) {}
>>>  #endif
>>>  
>>> -
>>> 
>> Nit. Unrelated whitespace change.
>
> Thanks, will clean this up.

OK.

>>> +static struct platform_device at91_eth_device = {
>>> +	.name		= "macb",
>>> +	.id		= -1,
>>> +	.dev		= {
>>> +				.dma_mask		= &eth_dmamask,
>>> +				.coherent_dma_mask	= DMA_BIT_MASK(32),
>>> +				.platform_data		= &eth_data,
>> 
>> Nit.  Excessive whitespace.
>
> This is cut and pasted from one of the *_devices.c files so the change
> is minimal.

It's just a bit ugly... ;-)

>>> +#else
>>> +void __init at91_add_device_eth(struct at91_eth_data *data) {}
>> 
>> inline maybe?
>
> No. This is also cut and pasted from the *_devices.c files so the change
> is minimal. The compiler should out-right remove this anyway so it
> shouldn't need to be inline.

It appears the inline format is more widely used than the __init format.  Granted
this is a bit gross but:

$ git grep 'inline' | grep ') {}' | wc -l
577
$ git grep 'inline' | grep ') { }' | wc -l
451
$ git grep '__init' | grep ') {}' | wc -l
109
$ git grep '__init' | grep ') { }' | wc -l
20

For that matter mach-at91 has most of the __init formats:

$ git grep 'inline' arch/arm/mach-at91 | grep ') {}' | wc -l
0
$ git grep 'inline' arch/arm/mach-at91 | grep ') { }' | wc -l
0
$ git grep '__init' arch/arm/mach-at91 | grep ') {}' | wc -l
87
$ git grep '__init' arch/arm/mach-at91 | grep ') { }' | wc -l
0

But, as you wish... ;-)

Regards,
Hartley

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

* [RFC PATCH 02/23] at91: Make Ethernet device common
  2011-04-20  8:36   ` Uwe Kleine-König
  2011-04-20 10:34     ` Jean-Christophe PLAGNIOL-VILLARD
  2011-04-20 11:07     ` Ryan Mallon
@ 2011-04-20 20:41     ` Ryan Mallon
  2 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20 20:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/20/2011 08:36 PM, Uwe Kleine-K?nig wrote:
> Hello Ryan,
> 
> On Wed, Apr 20, 2011 at 01:10:05PM +1200, Ryan Mallon wrote:
>> Replace the individual Ethernet device code for each at91 variant with
>> a single implementation in devices.
>>
>> Signed-off-by: Ryan Mallon <ryan@bluewatersys.com>

<snip>

>> -
>>  /* --------------------------------------------------------------------
>>   *  MMC / SD
>>   * -------------------------------------------------------------------- */
>> @@ -1587,6 +1551,14 @@ void __init at91_set_serial_console(unsigned portnr) {}
>>  void __init at91_add_device_serial(void) {}
>>  #endif
>>  
>> +static struct at91_device_table __initdata at91sam9g45_device_table = {
> The more correct position for __initdata is just before the =, see
> include/linux/init.h.

Okay, thanks. I will go through and fix this up. I'm also wondering if
all the data structures should be const?

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
  2011-04-20 17:14 ` H Hartley Sweeten
@ 2011-04-20 21:07   ` Ryan Mallon
  2011-04-21  0:56     ` Detlef Vollmann
  0 siblings, 1 reply; 41+ messages in thread
From: Ryan Mallon @ 2011-04-20 21:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/21/2011 05:14 AM, H Hartley Sweeten wrote:
> On Tuesday, April 19, 2011 6:10 PM, Ryan Mallon wrote:
>> Each AT91 variant (AT91RM9200, AT91SAM9260, etc) currently has its own
>> devices file, which includes the MMIO address, interrupt
>> configuration, GPIO setup, etc for each device. This results in a large
>> amount of duplicated code.
>>
>> This patch set introduces a framework for adding shared devices for the
>> AT91 platform and replaces the multiple device setup implementations for
>> each device with single implementations in the new framework. This has
>> a net reduction of nearly 5000 lines of code.
>>
>> Each of the arch/arm/mach-at91/*_devices.c files becomes a collection of
>> structures (with some initialisation callbacks where necessary) with a
>> table of devices which are present on the particular AT91 variant. All
>> structures/functions are marked as __init/__initdata so there is little
>> additional memory overhead. This also means that the #ifdefs around each
>> device can be removed from the *_devices.c files (but remain in the new
>> common devices.c file) without overhead.
>>
>> I have build tested the patch series for all of the  AT91 variants 
>> and devices, and have boot tested it on the AT91SAM9260 (Snapper 9260
>> board) and tested basic device functionality.
>>
>> Ryan Mallon (23):
>>   at91: Add common devices framework
>>   at91: Make Ethernet device common
>>   at91: Make USB OHCI/EHCI devices common
>>   at91: Make UDC device common
>>   at91: Make MMC device common
>>   at91: Make NAND device common
>>   at91: Make TWI device common
>>   at91: Make SPI device common
>>   at91: Make TCB device common
>>   at91: Make RTT device common
>>   at91: Make watchdog device common
>>   at91: Make UART devices common
> This patch (12/23) appears to be missing.
>

I got a message saying that it is being held for moderator approval
because it was over the size limit. The diffstat for it is below in the
meantime.

~Ryan

arch/arm/mach-at91/at572d940hf_devices.c  |  267 +++--------------
 arch/arm/mach-at91/at91cap9_devices.c     |  285 ++++---------------
 arch/arm/mach-at91/at91rm9200_devices.c   |  358 +++++------------------
 arch/arm/mach-at91/at91sam9260_devices.c  |  449 ++++++-----------------------
 arch/arm/mach-at91/at91sam9261_devices.c  |  273 ++++--------------
 arch/arm/mach-at91/at91sam9263_devices.c  |  286 ++++---------------
 arch/arm/mach-at91/at91sam9g45_devices.c  |  348 +++++------------------
 arch/arm/mach-at91/at91sam9rl_devices.c   |  360 +++++------------------
 arch/arm/mach-at91/board-1arm.c           |    4 +-
 arch/arm/mach-at91/board-afeb-9260v1.c    |    4 +-
 arch/arm/mach-at91/board-at572d940hf_ek.c |    6 +-
 arch/arm/mach-at91/board-carmeva.c        |    2 +-
 arch/arm/mach-at91/board-cpu9krea.c       |   12 +-
 arch/arm/mach-at91/board-cpuat91.c        |    8 +-
 arch/arm/mach-at91/board-eb9200.c         |    4 +-
 arch/arm/mach-at91/board-ecbat91.c        |    2 +-
 arch/arm/mach-at91/board-foxg20.c         |   12 +-
 arch/arm/mach-at91/board-gsia18s.c        |   10 +-
 arch/arm/mach-at91/board-kafa.c           |    2 +-
 arch/arm/mach-at91/board-kb9202.c         |    6 +-
 arch/arm/mach-at91/board-neocore926.c     |    2 +-
 arch/arm/mach-at91/board-pcontrol-g20.c   |    6 +-
 arch/arm/mach-at91/board-picotux200.c     |    2 +-
 arch/arm/mach-at91/board-qil-a9260.c      |    6 +-
 arch/arm/mach-at91/board-rm9200dk.c       |    2 +-
 arch/arm/mach-at91/board-rm9200ek.c       |    2 +-
 arch/arm/mach-at91/board-sam9-l9260.c     |    4 +-
 arch/arm/mach-at91/board-sam9260ek.c      |    4 +-
 arch/arm/mach-at91/board-sam9263ek.c      |    2 +-
 arch/arm/mach-at91/board-sam9g20ek.c      |    4 +-
 arch/arm/mach-at91/board-sam9m10g45ek.c   |    2 +-
 arch/arm/mach-at91/board-sam9rlek.c       |    2 +-
 arch/arm/mach-at91/board-snapper9260.c    |    6 +-
 arch/arm/mach-at91/board-stamp9g20.c      |   12 +-
 arch/arm/mach-at91/board-yl-9200.c        |    6 +-
 arch/arm/mach-at91/devices.c              |  303 +++++++++++++++++++
 arch/arm/mach-at91/devices.h              |   17 ++
 arch/arm/mach-at91/include/mach/board.h   |   10 +
 38 files changed, 922 insertions(+), 2168 deletions(-)

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751 
Fax:   +64 3 3779135			  USA 1800 261 2934

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

* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
  2011-04-20 21:07   ` Ryan Mallon
@ 2011-04-21  0:56     ` Detlef Vollmann
  2011-04-21  1:04       ` Ryan Mallon
  0 siblings, 1 reply; 41+ messages in thread
From: Detlef Vollmann @ 2011-04-21  0:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/20/11 23:07, Ryan Mallon wrote:
> On 04/21/2011 05:14 AM, H Hartley Sweeten wrote:
>> On Tuesday, April 19, 2011 6:10 PM, Ryan Mallon wrote:
>>>    at91: Make UART devices common
>> This patch (12/23) appears to be missing.
>>
>
> I got a message saying that it is being held for moderator approval
> because it was over the size limit. The diffstat for it is below in the
> meantime.
Is there a chance you can resend it, cc-ing the interested parties
(including me), just in case the moderator doesn't look at it
before the Easter weekend?
We had to apply some patches to the UART setup of at91sam9260_devices.c
and at91sam9g45_devices.c, and I'd like to check over the Easter
holidays that we can apply a similar patch to your new setup.

   Detlef

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

* [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code
  2011-04-21  0:56     ` Detlef Vollmann
@ 2011-04-21  1:04       ` Ryan Mallon
  0 siblings, 0 replies; 41+ messages in thread
From: Ryan Mallon @ 2011-04-21  1:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/21/2011 12:56 PM, Detlef Vollmann wrote:
> On 04/20/11 23:07, Ryan Mallon wrote:
>> On 04/21/2011 05:14 AM, H Hartley Sweeten wrote:
>>> On Tuesday, April 19, 2011 6:10 PM, Ryan Mallon wrote:
>>>>    at91: Make UART devices common
>>> This patch (12/23) appears to be missing.
>>>
>>
>> I got a message saying that it is being held for moderator approval
>> because it was over the size limit. The diffstat for it is below in the
>> meantime.
> Is there a chance you can resend it, cc-ing the interested parties
> (including me), just in case the moderator doesn't look at it
> before the Easter weekend?
> We had to apply some patches to the UART setup of at91sam9260_devices.c
> and at91sam9g45_devices.c, and I'd like to check over the Easter
> holidays that we can apply a similar patch to your new setup.

I've got a few fixes to apply already. I will try and get a second set
posted out by the end of today and include you on the Cc list. Thanks
for offering to test.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

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

end of thread, other threads:[~2011-04-21  1:04 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-20  1:10 [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 01/23] at91: Add common devices framework Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 02/23] at91: Make Ethernet device common Ryan Mallon
2011-04-20  2:10   ` H Hartley Sweeten
2011-04-20  2:33     ` Ryan Mallon
2011-04-20 18:23       ` H Hartley Sweeten
2011-04-20  8:36   ` Uwe Kleine-König
2011-04-20 10:34     ` Jean-Christophe PLAGNIOL-VILLARD
2011-04-20 11:07     ` Ryan Mallon
2011-04-20 20:41     ` Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 03/23] at91: Make USB OHCI/EHCI devices common Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 04/23] at91: Make UDC device common Ryan Mallon
2011-04-20  1:10 ` [PATCH 05/23] at91: Make MMC device (at91_mci) common Ryan Mallon
2011-04-20  1:12   ` Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 05/23] at91: Make MMC device common Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 06/23] at91: Make NAND " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 07/23] at91: Make TWI " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 08/23] at91: Make SPI " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 09/23] at91: Make TCB " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 10/23] at91: Make RTT " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 11/23] at91: Make watchdog " Ryan Mallon
2011-04-20 17:10   ` H Hartley Sweeten
2011-04-20  1:10 ` [RFC PATCH 13/23] at91: Make PWM " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 14/23] at91: Make SSC " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 15/23] at91: Make AC97 " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 16/23] at91: Make LCD controller " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 17/23] at91: Make touchscreen " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 18/23] at91: Make HDMAC " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 19/23] at91: Make RTC " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 20/23] at91: Make high speed USB gadget " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 21/23] at91: Make compact flash " Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 22/23] at91: Move at91sam9263 CAN device to common devices Ryan Mallon
2011-04-20  1:10 ` [RFC PATCH 23/23] at91: Remove mAgic and ISI device code Ryan Mallon
2011-04-20  1:11 ` [RFC PATCH 12/23] at91: Make UART devices common Ryan Mallon
2011-04-20  3:47 ` [RFC PATCH 00/23] at91: Replace duplicate device initialisation code with common code Jean-Christophe PLAGNIOL-VILLARD
2011-04-20  3:58   ` Ryan Mallon
2011-04-20  4:03     ` Jean-Christophe PLAGNIOL-VILLARD
2011-04-20 17:14 ` H Hartley Sweeten
2011-04-20 21:07   ` Ryan Mallon
2011-04-21  0:56     ` Detlef Vollmann
2011-04-21  1:04       ` Ryan Mallon

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.