board: ge: bx50v3: program MAC address to I210
authorHannu Lounento <hannu.lounento@ge.com>
Wed, 10 Jan 2018 19:31:31 +0000 (20:31 +0100)
committerStefano Babic <sbabic@denx.de>
Sun, 4 Feb 2018 11:00:58 +0000 (12:00 +0100)
There are two I210s on the b850v3 and one on the b450v3 and b650v3.
One is connected to Marvell 88e6240 which is already programmed.

Follow the flow documented in doc/README.enetaddr: set the
enet[0-9]*addr environment variable and let the driver program the
hardware.

The mapping from the driver's index to the environment variable's name
is documented in README: Note for Redundant Ethernet Interfaces. It is
assumed that eth_devices for the controllers on the board are always
indexed in the same order.

The environment variables are removed after programming the hardware
because the variables seem to influence MAC addresses also after U-Boot.
Specifically the MAC address of FEC (MC interface) would be incorrectly
set: 'ethaddr', which maps to the first I210 chip and is set to I210's
default address read from the driver by eth_write_hwaddr in eth_legacy.c
because the variable is undefined (not set even by bx50v3.c), would
result in the eth0 interface's MAC address to be set to I210's default
address.

Signed-off-by: Hannu Lounento <hannu.lounento@ge.com>
Signed-off-by: Ian Ray <ian.ray@ge.com>
Signed-off-by: Martyn Welch <martyn.welch@collabora.co.uk>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
board/ge/bx50v3/bx50v3.c

index 0468dcfa8e265e113f7c7d78f63c762e8b80f5a0..07b42988e4eba481692826e3ae613208cf9a6088 100644 (file)
@@ -30,6 +30,7 @@
 #include <pwm.h>
 #include <stdlib.h>
 #include "../common/vpd_reader.h"
+#include "../../../drivers/net/e1000.h"
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifndef CONFIG_SYS_I2C_EEPROM_ADDR
@@ -548,12 +549,14 @@ int overwrite_console(void)
 #define VPD_PRODUCT_B650 2
 #define VPD_PRODUCT_B450 3
 #define VPD_HAS_MAC1 0x1
+#define VPD_HAS_MAC2 0x2
 #define VPD_MAC_ADDRESS_LENGTH 6
 
 struct vpd_cache {
        u8 product_id;
        u8 has;
        unsigned char mac1[VPD_MAC_ADDRESS_LENGTH];
+       unsigned char mac2[VPD_MAC_ADDRESS_LENGTH];
 };
 
 /*
@@ -573,6 +576,10 @@ static int vpd_callback(void *userdata, u8 id, u8 version, u8 type,
                        vpd->has |= VPD_HAS_MAC1;
                        memcpy(vpd->mac1, data, VPD_MAC_ADDRESS_LENGTH);
                }
+               if (size >= 12) {
+                       vpd->has |= VPD_HAS_MAC2;
+                       memcpy(vpd->mac2, data + 6, VPD_MAC_ADDRESS_LENGTH);
+               }
        }
 
        return 0;
@@ -581,20 +588,26 @@ static int vpd_callback(void *userdata, u8 id, u8 version, u8 type,
 static void process_vpd(struct vpd_cache *vpd)
 {
        int fec_index = -1;
+       int i210_index = -1;
 
        switch (vpd->product_id) {
        case VPD_PRODUCT_B450:
                /* fall thru */
        case VPD_PRODUCT_B650:
+               i210_index = 0;
                fec_index = 1;
                break;
        case VPD_PRODUCT_B850:
+               i210_index = 1;
                fec_index = 2;
                break;
        }
 
        if (fec_index >= 0 && (vpd->has & VPD_HAS_MAC1))
                eth_env_set_enetaddr_by_index("eth", fec_index, vpd->mac1);
+
+       if (i210_index >= 0 && (vpd->has & VPD_HAS_MAC2))
+               eth_env_set_enetaddr_by_index("eth", i210_index, vpd->mac2);
 }
 
 static int read_vpd(uint eeprom_bus)
@@ -633,6 +646,8 @@ int board_eth_init(bd_t *bis)
        setup_iomux_enet();
        setup_pcie();
 
+       e1000_initialize(bis);
+
        return cpu_eth_init(bis);
 }
 
@@ -780,9 +795,29 @@ int board_late_init(void)
        return 0;
 }
 
+/*
+ * Removes the 'eth[0-9]*addr' environment variable with the given index
+ *
+ * @param index [in] the index of the eth_device whose variable is to be removed
+ */
+static void remove_ethaddr_env_var(int index)
+{
+       char env_var_name[9];
+
+       sprintf(env_var_name, index == 0 ? "ethaddr" : "eth%daddr", index);
+       env_set(env_var_name, NULL);
+}
+
 int last_stage_init(void)
 {
-       env_set("ethaddr", NULL);
+       int i;
+
+       /*
+        * Remove first three ethaddr which may have been created by
+        * function process_vpd().
+        */
+       for (i = 0; i < 3; ++i)
+               remove_ethaddr_env_var(i);
 
        return 0;
 }