summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
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);