summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2021-06-19 05:45:14 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2021-06-22 07:13:41 +0200
commit63fd2b318ea3866c46bd4f85b4a64a269512db35 (patch)
tree7bf734f70d32a74d80b2253978ca1b112d2407b9 /drivers
parent33be33ea617514df622a2a468b426e8a628c87e8 (diff)
downloadbarebox-63fd2b318ea3866c46bd4f85b4a64a269512db35.tar.gz
barebox-63fd2b318ea3866c46bd4f85b4a64a269512db35.tar.xz
of: of_net: sync of_get_mac_address with Linux for NVMEM support
We don't use of_get_mac_address anywhere, but it can come in handy as a last resort before barebox generates a random MAC address. With the existing implementation, that MAC address is written literally into the DT, so it's mainly useful when barebox is booted with an external device tree. The kernel implementation adds support for parsing the MAC address out of a revered mac-address nvmem cell, which is much more prevalent. Sync the implementation with Linux v5.13 in preparation for using it. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20210619034516.6737-12-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/of/of_net.c78
1 files changed, 64 insertions, 14 deletions
diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
index cee4597195..67015160e2 100644
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -9,6 +9,7 @@
#include <net.h>
#include <of_net.h>
#include <linux/phy.h>
+#include <linux/nvmem-consumer.h>
/**
* It maps 'enum phy_interface_t' found in include/linux/phy.h
@@ -67,12 +68,55 @@ int of_get_phy_mode(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_get_phy_mode);
+static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr)
+{
+ struct property *pp = of_find_property(np, name, NULL);
+
+ if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) {
+ memcpy(addr, pp->value, ETH_ALEN);
+ return 0;
+ }
+ return -ENODEV;
+}
+
+int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
+{
+ struct nvmem_cell *cell;
+ const void *mac;
+ size_t len;
+
+ if (!IS_ENABLED(CONFIG_NVMEM))
+ return -ENODEV;
+
+ cell = of_nvmem_cell_get(np, "mac-address");
+ if (IS_ERR(cell))
+ return PTR_ERR(cell);
+
+ mac = nvmem_cell_read(cell, &len);
+ nvmem_cell_put(cell);
+
+ if (IS_ERR(mac))
+ return PTR_ERR(mac);
+
+ if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
+ kfree(mac);
+ return -EINVAL;
+ }
+
+ memcpy(addr, mac, ETH_ALEN);
+ kfree(mac);
+
+ return 0;
+}
+
/**
* Search the device tree for the best MAC address to use. 'mac-address' is
* checked first, because that is supposed to contain to "most recent" MAC
* address. If that isn't set, then 'local-mac-address' is checked next,
- * because that is the default address. If that isn't set, then the obsolete
- * 'address' is checked, just in case we're using an old device tree.
+ * because that is the default address. If that isn't set, then the obsolete
+ * 'address' is checked, just in case we're using an old device tree. If any
+ * of the above isn't set, then try to get MAC address from nvmem cell named
+ * 'mac-address'.
*
* Note that the 'address' property is supposed to contain a virtual address of
* the register set, but some DTS files have redefined that property to be the
@@ -85,18 +129,24 @@ EXPORT_SYMBOL_GPL(of_get_phy_mode);
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
* but is all zeros.
*/
-const void *of_get_mac_address(struct device_node *np)
+int of_get_mac_address(struct device_node *np, u8 *addr)
{
- const void *p;
- int len, i;
- const char *str[] = { "mac-address", "local-mac-address", "address" };
-
- for (i = 0; i < ARRAY_SIZE(str); i++) {
- p = of_get_property(np, str[i], &len);
- if (p && (len == 6) && is_valid_ether_addr(p))
- return p;
- }
+ int ret;
+
+ if (!np)
+ return -ENODEV;
+
+ ret = of_get_mac_addr(np, "mac-address", addr);
+ if (!ret)
+ return 0;
+
+ ret = of_get_mac_addr(np, "local-mac-address", addr);
+ if (!ret)
+ return 0;
+
+ ret = of_get_mac_addr(np, "address", addr);
+ if (!ret)
+ return 0;
- return NULL;
+ return of_get_mac_addr_nvmem(np, addr);
}
-EXPORT_SYMBOL(of_get_mac_address);