From 1c1dcb800c003a4ccdfcb77795dad286c7f7268b Mon Sep 17 00:00:00 2001 From: SongJun Li Date: Fri, 12 Dec 2025 15:18:23 +0800 Subject: [PATCH 1/5] arm64: dts: rockchip: radxa-e24c: read MAC addresses from EEPROM Signed-off-by: SongJun Li --- arch/arm64/boot/dts/rockchip/rk3528-radxa-e24c.dts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e24c.dts b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e24c.dts index aed681893afe3..7f130a728e20e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e24c.dts +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e24c.dts @@ -379,28 +379,28 @@ port@0 { reg = <0>; label = "wan"; - local-mac-address = [00 48 54 20 00 00]; + mac-at-eeprom = <&eeprom 0x9E 0x06>; phy-handle = <&phy0>; }; port@1 { reg = <1>; label = "lan1"; - local-mac-address = [00 48 54 20 00 01]; + mac-at-eeprom = <&eeprom 0xA4 0x06>; phy-handle = <&phy1>; }; port@2 { reg = <2>; label = "lan2"; - local-mac-address = [00 48 54 20 00 02]; + mac-at-eeprom = <&eeprom 0xAA 0x06>; phy-handle = <&phy2>; }; port@3 { reg = <3>; label = "lan3"; - local-mac-address = [00 48 54 20 00 03]; + mac-at-eeprom = <&eeprom 0xB0 0x06>; phy-handle = <&phy3>; }; @@ -408,7 +408,6 @@ reg = <6>; label = "cpu"; ethernet = <&gmac1>; - local-mac-address = [00 48 54 20 00 33]; phy-mode = "rgmii"; tx-internal-delay-ps = <2000>; rx-internal-delay-ps = <2000>; From b428a7602457e5ecd3dc9f55aa9ed3f4df0e0912 Mon Sep 17 00:00:00 2001 From: SongJun Li Date: Fri, 12 Dec 2025 15:18:58 +0800 Subject: [PATCH 2/5] net: dsa: add support for reading port MAC addresses from EEPROM Signed-off-by: SongJun Li --- net/dsa/dsa2.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 5417f7b1187cb..87a669646ba8b 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "dsa_priv.h" @@ -527,6 +528,78 @@ static void dsa_port_devlink_teardown(struct dsa_port *dp) devlink_port_fini(dlp); } +int dsa_port_read_mac_from_eeprom(struct dsa_port *dp) +{ + struct device_node *np = dp->dn; + struct device_node *eeprom_np; + struct i2c_client *client; + struct i2c_adapter *adap; + struct i2c_msg msg[2]; + u32 offset, len; + u8 offbuf[1]; + int ret; + + if (!np) + return -EINVAL; + + /* Format: mac-at-eeprom = <&eeprom offset len>; */ + eeprom_np = of_parse_phandle(np, "mac-at-eeprom", 0); + if (!eeprom_np) + return -ENOENT; + + of_property_read_u32_index(np, "mac-at-eeprom", 1, &offset); + of_property_read_u32_index(np, "mac-at-eeprom", 2, &len); + + if (len != ETH_ALEN) + return -EINVAL; + + client = of_find_i2c_device_by_node(eeprom_np); + if (!client) + return -ENODEV; + + adap = client->adapter; + + /* 24c16 offset = 1 byte */ + offbuf[0] = offset & 0xff; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = offbuf; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = ETH_ALEN; + msg[1].buf = dp->mac; + + ret = i2c_transfer(adap, msg, 2); + if (ret != 2) + return -EIO; + + return is_valid_ether_addr(dp->mac) ? 0 : -EINVAL; +} +EXPORT_SYMBOL_GPL(dsa_port_read_mac_from_eeprom); + +static bool dsa_port_get_mac(struct dsa_port *dp, u8 *mac) +{ + /* 1. try EEPROM */ + if (dsa_port_read_mac_from_eeprom(dp) == 0 && + is_valid_ether_addr(dp->mac)) { + ether_addr_copy(mac, dp->mac); + return true; + } + + /* 2. try DTS */ + if (!of_get_mac_address(dp->dn, mac) && + is_valid_ether_addr(mac)) { + return true; + } + + /* 3. fallback */ + eth_random_addr(mac); + return true; +} + static int dsa_port_setup(struct dsa_port *dp) { struct devlink_port *dlp = &dp->devlink_port; @@ -583,7 +656,8 @@ static int dsa_port_setup(struct dsa_port *dp) break; case DSA_PORT_TYPE_USER: - of_get_mac_address(dp->dn, dp->mac); + dsa_port_get_mac(dp, dp->mac); + pr_info("dsa port %s mac = %pM\n", dp->name, dp->mac); err = dsa_slave_create(dp); if (err) break; From 5b9f3e00e52763078ced369726677d6d51f2dd74 Mon Sep 17 00:00:00 2001 From: SongJun Li Date: Wed, 24 Dec 2025 11:35:12 +0800 Subject: [PATCH 3/5] net: dsa: improve mac-at-eeprom handling and prefer DTS MAC Signed-off-by: SongJun Li --- net/dsa/dsa2.c | 65 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 87a669646ba8b..cbab2e8694e21 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -533,7 +533,7 @@ int dsa_port_read_mac_from_eeprom(struct dsa_port *dp) struct device_node *np = dp->dn; struct device_node *eeprom_np; struct i2c_client *client; - struct i2c_adapter *adap; + struct i2c_adapter *adapter; struct i2c_msg msg[2]; u32 offset, len; u8 offbuf[1]; @@ -547,19 +547,46 @@ int dsa_port_read_mac_from_eeprom(struct dsa_port *dp) if (!eeprom_np) return -ENOENT; - of_property_read_u32_index(np, "mac-at-eeprom", 1, &offset); - of_property_read_u32_index(np, "mac-at-eeprom", 2, &len); + ret = of_property_read_u32_index(np, "mac-at-eeprom", 1, &offset); + if (ret) { + dev_err(dp->ds->dev, + "failed to read mac-at-eeprom offset\n"); + goto out_put_np; + } - if (len != ETH_ALEN) - return -EINVAL; + ret = of_property_read_u32_index(np, "mac-at-eeprom", 2, &len); + if (ret) { + dev_err(dp->ds->dev, + "failed to read mac-at-eeprom length\n"); + goto out_put_np; + } + + if (len != ETH_ALEN) { + ret = -EINVAL; + goto out_put_np; + } + + /* 24c16 uses 1-byte address */ + if (offset > 0xff) { + dev_err(dp->ds->dev, + "mac-at-eeprom offset %u out of range\n", offset); + ret = -EINVAL; + goto out_put_np; + } client = of_find_i2c_device_by_node(eeprom_np); - if (!client) + if (!client) { + ret = -ENODEV; + goto out_put_np; + } + + of_node_put(eeprom_np); + + if (!get_device(&client->dev)) return -ENODEV; - adap = client->adapter; + adapter = client->adapter; - /* 24c16 offset = 1 byte */ offbuf[0] = offset & 0xff; msg[0].addr = client->addr; @@ -572,26 +599,32 @@ int dsa_port_read_mac_from_eeprom(struct dsa_port *dp) msg[1].len = ETH_ALEN; msg[1].buf = dp->mac; - ret = i2c_transfer(adap, msg, 2); + ret = i2c_transfer(adapter, msg, 2); + put_device(&client->dev); + if (ret != 2) return -EIO; return is_valid_ether_addr(dp->mac) ? 0 : -EINVAL; + +out_put_np: + of_node_put(eeprom_np); + return ret; } EXPORT_SYMBOL_GPL(dsa_port_read_mac_from_eeprom); static bool dsa_port_get_mac(struct dsa_port *dp, u8 *mac) { - /* 1. try EEPROM */ - if (dsa_port_read_mac_from_eeprom(dp) == 0 && - is_valid_ether_addr(dp->mac)) { - ether_addr_copy(mac, dp->mac); + /* 1. try DTS */ + if (!of_get_mac_address(dp->dn, mac) && + is_valid_ether_addr(mac)) { return true; } - /* 2. try DTS */ - if (!of_get_mac_address(dp->dn, mac) && - is_valid_ether_addr(mac)) { + /* 2. try EEPROM */ + if (dsa_port_read_mac_from_eeprom(dp) == 0 && + is_valid_ether_addr(dp->mac)) { + ether_addr_copy(mac, dp->mac); return true; } From 39eecba03bb45d0b61b3ed6ff41d78496e85f147 Mon Sep 17 00:00:00 2001 From: SongJun Li Date: Mon, 29 Dec 2025 16:00:41 +0800 Subject: [PATCH 4/5] net: dsa: validate EEPROM MAC address range Signed-off-by: SongJun Li --- net/dsa/dsa2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index cbab2e8694e21..88ae1ca426e5e 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -567,9 +567,10 @@ int dsa_port_read_mac_from_eeprom(struct dsa_port *dp) } /* 24c16 uses 1-byte address */ - if (offset > 0xff) { + if (offset > 0xff || offset > 0x100 - len) { dev_err(dp->ds->dev, - "mac-at-eeprom offset %u out of range\n", offset); + "mac-at-eeprom offset %u + len %u out of range\n", + offset, len); ret = -EINVAL; goto out_put_np; } From 05eaa51cea4ca2f6cd95da9bb0af7bf1c1c3d0c7 Mon Sep 17 00:00:00 2001 From: SongJun Li Date: Mon, 29 Dec 2025 16:09:03 +0800 Subject: [PATCH 5/5] net: dsa: fix indentation in mac-at-eeprom error message Signed-off-by: SongJun Li --- net/dsa/dsa2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 88ae1ca426e5e..c7309fee3f06b 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -569,8 +569,8 @@ int dsa_port_read_mac_from_eeprom(struct dsa_port *dp) /* 24c16 uses 1-byte address */ if (offset > 0xff || offset > 0x100 - len) { dev_err(dp->ds->dev, - "mac-at-eeprom offset %u + len %u out of range\n", - offset, len); + "mac-at-eeprom offset %u + len %u out of range\n", + offset, len); ret = -EINVAL; goto out_put_np; }