
With the newly introduced hooks, we can now set the MAC address at the lowest level properly. The user is still free to override it via a u-boot environment variable.
Signed-off-by: Olliver Schinagl oliver@schinagl.nl --- arch/arm/include/asm/arch-sunxi/sys_proto.h | 8 +++ board/sunxi/board.c | 103 +++++++++++++++++++--------- 2 files changed, 80 insertions(+), 31 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/sys_proto.h b/arch/arm/include/asm/arch-sunxi/sys_proto.h index a373319..5b24b86 100644 --- a/arch/arm/include/asm/arch-sunxi/sys_proto.h +++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h @@ -30,4 +30,12 @@ void eth_init_board(void); static inline void eth_init_board(void) {} #endif
+#if CONFIG_SUNXI_EMAC +int sunxi_board_read_rom_hwaddr(unsigned char *enetaddr); +#endif + +#if defined(CONFIG_SUNXI_GMAC) || defined(CONFIG_ETH_DESIGNWARE) +int dw_board_read_rom_hwaddr(unsigned char *enetaddr); +#endif + #endif diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 5365638..9b56a89 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -21,6 +21,7 @@ #include <asm/arch/gpio.h> #include <asm/arch/mmc.h> #include <asm/arch/spl.h> +#include <asm/arch/sys_proto.h> #include <asm/arch/usb_phy.h> #ifndef CONFIG_ARM64 #include <asm/armv7.h> @@ -584,6 +585,76 @@ void get_board_serial(struct tag_serialnr *serialnr) } #endif
+static void _sunxi_gen_sid_hwaddr(unsigned char *enetaddr, uint8_t cnt) +{ + uint8_t mac_addr[ARP_HLEN] = { 0x00 }; + unsigned int sid[4]; + int ret; + + ret = sunxi_get_sid(sid); + if (ret == 0 && sid[0] != 0) { + /* + * The single words 1 - 3 of the SID have quite a few bits + * which are the same on many models, so we take a crc32 + * of all 3 words, to get a more unique value. + * + * Note we only do this on newer SoCs as we cannot change + * the algorithm on older SoCs since those have been using + * fixed mac-addresses based on only using word 3 for a + * long time and changing a fixed mac-address with an + * u-boot update is not good. + */ +#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \ + !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \ + !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33) + sid[3] = crc32(0, (unsigned char *)&sid[1], 12); +#endif + + /* Ensure the NIC specific bytes of the mac are not all 0 */ + if ((sid[3] & 0xffffff) == 0) + sid[3] |= 0x800000; + + /* Non OUI / registered MAC address */ + mac_addr[0] = (cnt << 4) | 0x02; + mac_addr[1] = (sid[0] >> 0) & 0xff; + mac_addr[2] = (sid[3] >> 24) & 0xff; + mac_addr[3] = (sid[3] >> 16) & 0xff; + mac_addr[4] = (sid[3] >> 8) & 0xff; + mac_addr[5] = (sid[3] >> 0) & 0xff; + } + + memcpy(enetaddr, mac_addr, ARP_HLEN); +} + +static int sunxi_read_rom_hwaddr(unsigned char *enetaddr) +{ + static unsigned int cnt; + + _sunxi_gen_sid_hwaddr(enetaddr, cnt); + + /* First call, first stored MAC address, increase for next call */ + cnt++; + + if (is_zero_ethaddr(enetaddr)) + return -ENOSYS; + + printf("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", + enetaddr[0], enetaddr[1], enetaddr[2], + enetaddr[3], enetaddr[4], enetaddr[5]); + + return 0; +} + +int sunxi_board_read_rom_hwaddr(unsigned char *enetaddr) +{ + return sunxi_read_rom_hwaddr(enetaddr); +} + +int dw_board_read_rom_hwaddr(unsigned char *enetaddr) +{ + return sunxi_read_rom_hwaddr(enetaddr); +} + /* * Check the SPL header for the "sunxi" variant. If found: parse values * that might have been passed by the loader ("fel" utility), and update @@ -625,9 +696,7 @@ static void setup_environment(const void *fdt) { char serial_string[17] = { 0 }; unsigned int sid[4]; - uint8_t mac_addr[6]; - char ethaddr[16]; - int i, ret; + int ret;
ret = sunxi_get_sid(sid); if (ret == 0 && sid[0] != 0) { @@ -648,34 +717,6 @@ static void setup_environment(const void *fdt) sid[3] = crc32(0, (unsigned char *)&sid[1], 12); #endif
- /* Ensure the NIC specific bytes of the mac are not all 0 */ - if ((sid[3] & 0xffffff) == 0) - sid[3] |= 0x800000; - - for (i = 0; i < 4; i++) { - sprintf(ethaddr, "ethernet%d", i); - if (!fdt_get_alias(fdt, ethaddr)) - continue; - - if (i == 0) - strcpy(ethaddr, "ethaddr"); - else - sprintf(ethaddr, "eth%daddr", i); - - if (getenv(ethaddr)) - continue; - - /* Non OUI / registered MAC address */ - mac_addr[0] = (i << 4) | 0x02; - mac_addr[1] = (sid[0] >> 0) & 0xff; - mac_addr[2] = (sid[3] >> 24) & 0xff; - mac_addr[3] = (sid[3] >> 16) & 0xff; - mac_addr[4] = (sid[3] >> 8) & 0xff; - mac_addr[5] = (sid[3] >> 0) & 0xff; - - eth_setenv_enetaddr(ethaddr, mac_addr); - } - if (!getenv("serial#")) { snprintf(serial_string, sizeof(serial_string), "%08x%08x", sid[0], sid[3]);