diff mbox

[U-Boot,PATCHv6,18/28] arm: sunxi: Expose function to generate sunxi-specific a MAC address

Message ID 20170515080244.21345-19-oliver@schinagl.nl
State Changes Requested
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Olliver Schinagl May 15, 2017, 8:02 a.m. UTC
Expose the function to generate a MAC adddress based on the serial number.
This can then later be moved completly out of the sunxi board specific stuff.

The setup_environment quirky function still exists as it is still used
to fixup the FDT for drivers that need the MAC address available in the
FDT. Once that is changed, we can clean up some more.

Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
---
 arch/arm/include/asm/arch-sunxi/sys_proto.h |   2 +
 board/sunxi/board.c                         | 146 ++++++++++++++++++----------
 2 files changed, 95 insertions(+), 53 deletions(-)

Comments

Joe Hershberger May 30, 2017, 9:19 p.m. UTC | #1
Typo in the subject line...

"arm: sunxi: Expose function to generate _a_ sunxi-specific MAC address"

On Mon, May 15, 2017 at 3:02 AM, Olliver Schinagl <oliver@schinagl.nl> wrote:
> Expose the function to generate a MAC adddress based on the serial number.
> This can then later be moved completly out of the sunxi board specific stuff.
>
> The setup_environment quirky function still exists as it is still used
> to fixup the FDT for drivers that need the MAC address available in the
> FDT. Once that is changed, we can clean up some more.
>
> Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>

Looks fine other than the subject.

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 850236ed42..f264c84b56 100644
--- a/arch/arm/include/asm/arch-sunxi/sys_proto.h
+++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h
@@ -30,4 +30,6 @@  void eth_init_board(void);
 static inline void eth_init_board(void) {}
 #endif
 
+int sunxi_gen_hwaddr(const int seq, unsigned char *enetaddr);
+
 #endif
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 01de42d031..db56fba233 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>
@@ -596,6 +597,73 @@  int g_dnl_board_usb_cable_connected(void)
 }
 #endif
 
+static int sunxi_get_board_serial(unsigned int *serial)
+{
+	int ret;
+
+	ret = sunxi_get_sid(serial);
+	if (!ret || serial[0])
+		return -ENOSYS;
+
+	/*
+	 * 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/serial based on only using word 3 for a
+	 * long time and changing a fixed mac-address/serial 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)
+	serial[3] = crc32(0, (unsigned char *)&serial[1], 12);
+#endif
+
+	return 0;
+}
+
+ /*
+  * Generate a MAC address based on device index and the serial number.
+  * The first half of the of the first octet holds the eth index.
+  *
+  * In the second octet we forcefully mark the MAC address to a locally
+  * administered MAC address.
+  *
+  */
+int sunxi_gen_hwaddr(const int seq, unsigned char *enetaddr)
+{
+	uint8_t mac_addr[ARP_HLEN] = { 0x00 };
+	unsigned int serial[4];
+	int ret;
+
+	if (!enetaddr || (seq < 0))
+		return -ENOSYS;
+
+	ret = sunxi_get_board_serial(serial);
+	if (!ret)
+		return ret;
+
+	/* Ensure the NIC specific bytes of the mac are not all 0 */
+	if ((serial[3] & 0xffffff) == 0)
+		serial[3] |= 0x800000;
+
+	mac_addr[0] = (seq << 4);
+	mac_addr[1] = (serial[0] >>  0) & 0xff;
+	mac_addr[2] = (serial[3] >> 24) & 0xff;
+	mac_addr[3] = (serial[3] >> 16) & 0xff;
+	mac_addr[4] = (serial[3] >>  8) & 0xff;
+	mac_addr[5] = (serial[3] >>  0) & 0xff;
+
+	set_local_ethaddr(mac_addr);
+	set_unicast_ethaddr(mac_addr);
+	memcpy(enetaddr, mac_addr, ARP_HLEN);
+
+	return 0;
+}
+
 #ifdef CONFIG_SERIAL_TAG
 void get_board_serial(struct tag_serialnr *serialnr)
 {
@@ -655,71 +723,35 @@  static void parse_spl_header(const uint32_t spl_addr)
  */
 static void setup_environment(const void *fdt)
 {
-	char serial_string[17] = { 0 };
-	unsigned int sid[4];
-	uint8_t mac_addr[6];
-	char ethaddr[16];
+	uint8_t enetaddr[ARP_HLEN];
+	char ethaddr[ETH_ENETADDR_ENV_NAME_LEN];
 	int i, 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;
-
-		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;
+	for (i = 0; i < 4; i++) {
+		sprintf(ethaddr, "ethernet%d", i);
+		if (!fdt_get_alias(fdt, 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;
+		if (i == 0)
+			strcpy(ethaddr, "ethaddr");
+		else
+			sprintf(ethaddr, "eth%daddr", i);
 
-			eth_setenv_enetaddr(ethaddr, mac_addr);
-		}
+		if (getenv(ethaddr))
+			continue;
 
-		if (!getenv("serial#")) {
-			snprintf(serial_string, sizeof(serial_string),
-				"%08x%08x", sid[0], sid[3]);
+		ret = sunxi_gen_hwaddr(i, enetaddr);
+		if (!ret)
+			return;
 
-			setenv("serial#", serial_string);
-		}
+		eth_setenv_enetaddr(ethaddr, enetaddr);
 	}
 }
 
 int misc_init_r(void)
 {
 	__maybe_unused int ret;
+	unsigned int serial[4];
 
 	setenv("fel_booted", NULL);
 	setenv("fel_scriptaddr", NULL);
@@ -730,6 +762,14 @@  int misc_init_r(void)
 	}
 
 	setup_environment(gd->fdt_blob);
+	if (!getenv("serial#") && sunxi_get_board_serial(serial)) {
+		char serial_string[17] = { 0 };
+
+		snprintf(serial_string, sizeof(serial_string),
+			 "%08x%08x", serial[0], serial[3]);
+
+		setenv("serial#", serial_string);
+	}
 
 #ifndef CONFIG_MACH_SUN9I
 	ret = sunxi_usb_phy_probe();