[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 = ð_dmamask,
> - .coherent_dma_mask = DMA_BIT_MASK(32),
> - .platform_data = ð_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 = ð_dmamask,
> - .coherent_dma_mask = DMA_BIT_MASK(32),
> - .platform_data = ð_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 = ð_dmamask,
> - .coherent_dma_mask = DMA_BIT_MASK(32),
> - .platform_data = ð_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 = ð_dmamask,
> - .coherent_dma_mask = DMA_BIT_MASK(32),
> - .platform_data = ð_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 = ð_dmamask,
> - .coherent_dma_mask = DMA_BIT_MASK(32),
> - .platform_data = ð_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 = ð_dmamask,
> - .coherent_dma_mask = DMA_BIT_MASK(32),
> - .platform_data = ð_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 = ð_dmamask,
> + .coherent_dma_mask = DMA_BIT_MASK(32),
> + .platform_data = ð_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(ð_resources[0], info->mmio_base);
> + init_resource_irq(ð_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