[RFC PATCH 02/23] at91: Make Ethernet device common

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Wed Apr 20 04:36:36 EDT 2011


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 at 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/  |



More information about the linux-arm-kernel mailing list