--- a/arch/arm/mach-ixp4xx/avila-setup.c +++ b/arch/arm/mach-ixp4xx/avila-setup.c @@ -14,10 +14,18 @@ #include #include #include +#include +#include +#include #include #include #include #include +#ifdef CONFIG_SENSORS_EEPROM +# include +# include +#endif + #include #include @@ -29,6 +37,13 @@ #include #include +struct avila_board_info { + unsigned char *model; + void (* setup)(void); +}; + +static struct avila_board_info *avila_info __initdata; + static struct flash_platform_data avila_flash_data = { .map_name = "cfi_probe", .width = 2, @@ -163,10 +178,160 @@ &avila_uart }; +static void __init avila_gw23xx_setup(void) +{ + platform_device_register(&avila_npeb_device); + platform_device_register(&avila_npec_device); +} + +#ifdef CONFIG_SENSORS_EEPROM +static void __init avila_gw2342_setup(void) +{ + platform_device_register(&avila_npeb_device); + platform_device_register(&avila_npec_device); +} + +static void __init avila_gw2345_setup(void) +{ + avila_npeb_data.phy = IXP4XX_ETH_PHY_MAX_ADDR; + avila_npeb_data.phy_mask = 0x1e; /* ports 1-4 of the KS8995 switch */ + platform_device_register(&avila_npeb_device); + + avila_npec_data.phy = 5; /* port 5 of the KS8995 switch */ + platform_device_register(&avila_npec_device); +} + +static void __init avila_gw2347_setup(void) +{ + platform_device_register(&avila_npeb_device); +} + +static void __init avila_gw2348_setup(void) +{ + platform_device_register(&avila_npeb_device); + platform_device_register(&avila_npec_device); +} + +static void __init avila_gw2353_setup(void) +{ + platform_device_register(&avila_npeb_device); +} + +static void __init avila_gw2355_setup(void) +{ + avila_npeb_data.phy = IXP4XX_ETH_PHY_MAX_ADDR; + avila_npeb_data.phy_mask = 0x1e; /* ports 1-4 of the KS8995 switch */ + platform_device_register(&avila_npeb_device); + + avila_npec_data.phy = 16; + platform_device_register(&avila_npec_device); +} + +static void __init avila_gw2357_setup(void) +{ + platform_device_register(&avila_npeb_device); +} + +static struct avila_board_info avila_boards[] __initdata = { + { + .model = "GW2342", + .setup = avila_gw2342_setup, + }, { + .model = "GW2345", + .setup = avila_gw2345_setup, + }, { + .model = "GW2347", + .setup = avila_gw2347_setup, + }, { + .model = "GW2348", + .setup = avila_gw2348_setup, + }, { + .model = "GW2353", + .setup = avila_gw2353_setup, + }, { + .model = "GW2355", + .setup = avila_gw2355_setup, + }, { + .model = "GW2357", + .setup = avila_gw2357_setup, + } +}; + +static struct avila_board_info * __init avila_find_board_info(char *model) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(avila_boards); i++) { + struct avila_board_info *info = &avila_boards[i]; + if (strncmp(info->model, model, strlen(info->model)) == 0) + return info; + } + + return NULL; +} + +struct avila_eeprom_header { + unsigned char mac0[ETH_ALEN]; + unsigned char mac1[ETH_ALEN]; + unsigned char res0[4]; + unsigned char magic[2]; + unsigned char config[14]; + unsigned char model[16]; +}; + +static int __init avila_eeprom_notify(struct notifier_block *self, + unsigned long event, void *t) +{ + struct eeprom_data *ee = t; + struct avila_eeprom_header hdr; + + if (avila_info) + return NOTIFY_DONE; + + /* The eeprom is at address 0x51 */ + if (event != EEPROM_REGISTER || ee->client.addr != 0x51) + return NOTIFY_DONE; + + ee->attr->read(&ee->client.dev.kobj, ee->attr, (char *)&hdr, + 0, sizeof(hdr)); + + if (hdr.magic[0] != 'G' || hdr.magic[1] != 'W') + return NOTIFY_DONE; + + memcpy(&avila_npeb_data.hwaddr, hdr.mac0, ETH_ALEN); + memcpy(&avila_npec_data.hwaddr, hdr.mac1, ETH_ALEN); + + avila_info = avila_find_board_info(hdr.model); + + return NOTIFY_OK; +} + +static struct notifier_block avila_eeprom_notifier __initdata = { + .notifier_call = avila_eeprom_notify +}; + +static void __init avila_register_eeprom_notifier(void) +{ + register_eeprom_notifier(&avila_eeprom_notifier); +} + +static void __init avila_unregister_eeprom_notifier(void) +{ + unregister_eeprom_notifier(&avila_eeprom_notifier); +} +#else /* CONFIG_SENSORS_EEPROM */ +static inline void avila_register_eeprom_notifier(void) {}; +static inline void avila_unregister_eeprom_notifier(void) {}; +#endif /* CONFIG_SENSORS_EEPROM */ + static void __init avila_init(void) { ixp4xx_sys_init(); + /* + * These devices are present on all Avila models and don't need any + * model specific setup. + */ avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); avila_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; @@ -184,9 +349,28 @@ platform_device_register(&avila_pata); - platform_device_register(avila_npeb_device); - platform_device_register(avila_npec_device); + avila_register_eeprom_notifier(); +} + +static int __init avila_model_setup(void) +{ + if (!machine_is_avila()) + return 0; + + if (avila_info) { + printk(KERN_DEBUG "Running on Gateworks Avila %s\n", + avila_info->model); + avila_info->setup(); + } else { + printk(KERN_INFO "Unknown/missing Avila model number" + " -- defaults will be used\n"); + avila_gw23xx_setup(); + } + + avila_unregister_eeprom_notifier(); + return 0; } +late_initcall(avila_model_setup); MACHINE_START(AVILA, "Gateworks Avila Network Platform") /* Maintainer: Deepak Saxena */