diff mbox

[U-Boot,06/11] arm: sunxi: Use read_rom_hwaddr() to obtain MAC address

Message ID 20161108155437.1085-7-oliver@schinagl.nl
State Superseded
Delegated to: Joe Hershberger
Headers show

Commit Message

Olliver Schinagl Nov. 8, 2016, 3:54 p.m. UTC
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(-)

Comments

Joe Hershberger Nov. 15, 2016, 3:21 a.m. UTC | #1
On Tue, Nov 8, 2016 at 9:54 AM, Olliver Schinagl <oliver@schinagl.nl> wrote:
> 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>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>
diff mbox

Patch

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]);