[ARM] DNS323: Read MAC address from flash
authorMatt Palmer <mpalmer@hezmatt.org>
Sat, 18 Oct 2008 21:15:09 +0000 (08:15 +1100)
committerNicolas Pitre <nico@cam.org>
Thu, 11 Dec 2008 21:36:59 +0000 (16:36 -0500)
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>
arch/arm/mach-orion5x/dns323-setup.c

index 3e66098..4053bd3 100644 (file)
@@ -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)