diff options
author | Matt Palmer <mpalmer@hezmatt.org> | 2008-10-19 08:15:09 +1100 |
---|---|---|
committer | Nicolas Pitre <nico@cam.org> | 2008-12-11 16:36:59 -0500 |
commit | a93f44c1751ef1afddd4b76058fb3a2f55fe774c (patch) | |
tree | 0e4c0508e5b94e2932ac766eb55fd97433e326a1 /arch/arm/mach-orion5x | |
parent | fb6f552930e52699c8ac452c5a79ec3e97e6fc73 (diff) |
[ARM] DNS323: Read MAC address from flash
Based on similar code from the tsx09 series of machines, just rips the MAC
address out of flash and stuffs it into the NIC. Tested on a DNS323 rev B1.
It's possible (though unlikely) that an A1 will have the MAC in a different
location in flash.
Signed-off-by: Matt Palmer <mpalmer@hezmatt.org>
Diffstat (limited to 'arch/arm/mach-orion5x')
-rw-r--r-- | arch/arm/mach-orion5x/dns323-setup.c | 111 |
1 files changed, 95 insertions, 16 deletions
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 3e66098340a..4053bd35476 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -75,14 +75,6 @@ static int __init dns323_pci_init(void) subsys_initcall(dns323_pci_init); /**************************************************************************** - * Ethernet - */ - -static struct mv643xx_eth_platform_data dns323_eth_data = { - .phy_addr = MV643XX_ETH_PHY_ADDR(8), -}; - -/**************************************************************************** * 8MiB NOR flash (Spansion S29GL064M90TFIR4) * * Layout as used by D-Link: @@ -143,6 +135,90 @@ static struct platform_device dns323_nor_flash = { }; /**************************************************************************** + * Ethernet + */ + +static struct mv643xx_eth_platform_data dns323_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these + * functions be kept somewhere? + */ +static int __init dns323_parse_hex_nibble(char n) +{ + if (n >= '0' && n <= '9') + return n - '0'; + + if (n >= 'A' && n <= 'F') + return n - 'A' + 10; + + if (n >= 'a' && n <= 'f') + return n - 'a' + 10; + + return -1; +} + +static int __init dns323_parse_hex_byte(const char *b) +{ + int hi; + int lo; + + hi = dns323_parse_hex_nibble(b[0]); + lo = dns323_parse_hex_nibble(b[1]); + + if (hi < 0 || lo < 0) + return -1; + + return (hi << 4) | lo; +} + +static int __init dns323_read_mac_addr(void) +{ + u_int8_t addr[6]; + int i; + char *mac_page; + + /* MAC address is stored as a regular ol' string in /dev/mtdblock4 + * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80). + */ + mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024); + if (!mac_page) + return -ENOMEM; + + /* Sanity check the string we're looking at */ + for (i = 0; i < 5; i++) { + if (*(mac_page + (i * 3) + 2) != ':') { + goto error_fail; + } + } + + for (i = 0; i < 6; i++) { + int byte; + + byte = dns323_parse_hex_byte(mac_page + (i * 3)); + if (byte < 0) { + goto error_fail; + } + + addr[i] = byte; + } + + iounmap(mac_page); + printk("DNS323: Found ethernet MAC address: "); + for (i = 0; i < 6; i++) + printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n"); + + memcpy(dns323_eth_data.mac_addr, addr, 6); + + return 0; + +error_fail: + iounmap(mac_page); + return -EINVAL; +} + +/**************************************************************************** * GPIO LEDs (simple - doesn't use hardware blinking support) */ @@ -267,14 +343,6 @@ static void __init dns323_init(void) orion5x_mpp_conf(dns323_mpp_modes); writel(0, MPP_DEV_CTRL); /* DEV_D[31:16] */ - /* - * Configure peripherals. - */ - orion5x_ehci0_init(); - orion5x_eth_init(&dns323_eth_data); - orion5x_i2c_init(); - orion5x_uart0_init(); - /* setup flash mapping * CS3 holds a 8 MB Spansion S29GL064M90TFIR4 */ @@ -288,6 +356,17 @@ static void __init dns323_init(void) i2c_register_board_info(0, dns323_i2c_devices, ARRAY_SIZE(dns323_i2c_devices)); + /* + * Configure peripherals. + */ + if (dns323_read_mac_addr() < 0) + printk("DNS323: Failed to read MAC address\n"); + + orion5x_ehci0_init(); + orion5x_eth_init(&dns323_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + /* register dns323 specific power-off method */ if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 || gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0) |