mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
treewide: backport support for nvmem on non platform devices
This commit is contained in:
parent
5ac4c8546c
commit
7a7f9d647d
@ -1519,7 +1519,6 @@ static int ag71xx_probe(struct platform_device *pdev)
|
||||
struct net_device *dev;
|
||||
struct resource *res;
|
||||
struct ag71xx *ag;
|
||||
const void *mac_addr;
|
||||
u32 max_frame_len;
|
||||
int tx_size, err;
|
||||
|
||||
@ -1668,12 +1667,10 @@ static int ag71xx_probe(struct platform_device *pdev)
|
||||
ag->stop_desc->ctrl = 0;
|
||||
ag->stop_desc->next = (u32) ag->stop_desc_dma;
|
||||
|
||||
mac_addr = of_get_mac_address(np);
|
||||
if (IS_ERR_OR_NULL(mac_addr) || !is_valid_ether_addr(mac_addr)) {
|
||||
of_get_mac_address(np, dev->dev_addr);
|
||||
if (!is_valid_ether_addr(dev->dev_addr)) {
|
||||
dev_err(&pdev->dev, "invalid MAC address, using random address\n");
|
||||
eth_random_addr(dev->dev_addr);
|
||||
} else {
|
||||
memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,77 @@
|
||||
From f10843e04a075202dbb39dfcee047e3a2fdf5a8d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Mon, 12 Apr 2021 19:47:18 +0200
|
||||
Subject: of: net: fix of_get_mac_addr_nvmem() for non-platform devices
|
||||
|
||||
of_get_mac_address() already supports fetching the MAC address by an
|
||||
nvmem provider. But until now, it was just working for platform devices.
|
||||
Esp. it was not working for DSA ports and PCI devices. It gets more
|
||||
common that PCI devices have a device tree binding since SoCs contain
|
||||
integrated root complexes.
|
||||
|
||||
Use the nvmem of_* binding to fetch the nvmem cells by a struct
|
||||
device_node. We still have to try to read the cell by device first
|
||||
because there might be a nvmem_cell_lookup associated with that device.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/of/of_net.c | 35 ++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 30 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -59,15 +60,39 @@ static int of_get_mac_addr(struct device
|
||||
static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
|
||||
{
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
+ struct nvmem_cell *cell;
|
||||
+ const void *mac;
|
||||
+ size_t len;
|
||||
int ret;
|
||||
|
||||
- if (!pdev)
|
||||
- return -ENODEV;
|
||||
+ /* Try lookup by device first, there might be a nvmem_cell_lookup
|
||||
+ * associated with a given device.
|
||||
+ */
|
||||
+ if (pdev) {
|
||||
+ ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
+ put_device(&pdev->dev);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
|
||||
- ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
- put_device(&pdev->dev);
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+ kfree(mac);
|
||||
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/**
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,77 @@
|
||||
From f10843e04a075202dbb39dfcee047e3a2fdf5a8d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <michael@walle.cc>
|
||||
Date: Mon, 12 Apr 2021 19:47:18 +0200
|
||||
Subject: of: net: fix of_get_mac_addr_nvmem() for non-platform devices
|
||||
|
||||
of_get_mac_address() already supports fetching the MAC address by an
|
||||
nvmem provider. But until now, it was just working for platform devices.
|
||||
Esp. it was not working for DSA ports and PCI devices. It gets more
|
||||
common that PCI devices have a device tree binding since SoCs contain
|
||||
integrated root complexes.
|
||||
|
||||
Use the nvmem of_* binding to fetch the nvmem cells by a struct
|
||||
device_node. We still have to try to read the cell by device first
|
||||
because there might be a nvmem_cell_lookup associated with that device.
|
||||
|
||||
Signed-off-by: Michael Walle <michael@walle.cc>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/of/of_net.c | 35 ++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 30 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -53,15 +54,39 @@ static int of_get_mac_addr(struct device
|
||||
static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
|
||||
{
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
+ struct nvmem_cell *cell;
|
||||
+ const void *mac;
|
||||
+ size_t len;
|
||||
int ret;
|
||||
|
||||
- if (!pdev)
|
||||
- return -ENODEV;
|
||||
+ /* Try lookup by device first, there might be a nvmem_cell_lookup
|
||||
+ * associated with a given device.
|
||||
+ */
|
||||
+ if (pdev) {
|
||||
+ ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
+ put_device(&pdev->dev);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
|
||||
- ret = nvmem_get_mac_address(&pdev->dev, addr);
|
||||
- put_device(&pdev->dev);
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+ kfree(mac);
|
||||
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/**
|
@ -0,0 +1,102 @@
|
||||
From 6f8e5369ae054ec6c9265581d5a7e39738a5cd84 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Tue, 30 Mar 2021 13:16:38 +0200
|
||||
Subject: [PATCH 1/2] NET: add mtd-mac-address support to of_get_mac_address()
|
||||
|
||||
Many embedded devices have information such as mac addresses stored inside mtd
|
||||
devices. This patch allows us to add a property inside a node describing a
|
||||
network interface. The new property points at a mtd partition with an offset
|
||||
where the mac address can be found.
|
||||
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/of/of_net.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 74 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -95,6 +96,52 @@ static int of_get_mac_addr_nvmem(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int of_get_mac_address_mtd(struct device_node *np, u8 *addr)
|
||||
+{
|
||||
+#ifdef CONFIG_MTD
|
||||
+ struct platform_device *pdev = of_find_device_by_node(np);
|
||||
+ struct device_node *mtd_np = NULL;
|
||||
+ size_t retlen;
|
||||
+ int size, ret;
|
||||
+ struct mtd_info *mtd;
|
||||
+ const char *part;
|
||||
+ const __be32 *list;
|
||||
+ phandle phandle;
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+
|
||||
+ list = of_get_property(np, "mtd-mac-address", &size);
|
||||
+ if (!list || (size != (2 * sizeof(*list))))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ phandle = be32_to_cpup(list++);
|
||||
+ if (phandle)
|
||||
+ mtd_np = of_find_node_by_phandle(phandle);
|
||||
+
|
||||
+ if (!mtd_np)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ part = of_get_property(mtd_np, "label", NULL);
|
||||
+ if (!part)
|
||||
+ part = mtd_np->name;
|
||||
+
|
||||
+ mtd = get_mtd_device_nm(part);
|
||||
+ if (IS_ERR(mtd))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
|
||||
+ put_mtd_device(mtd);
|
||||
+
|
||||
+ if (!is_valid_ether_addr(mac))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+
|
||||
+ return 0;
|
||||
+#endif
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**
|
||||
* 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
|
||||
@@ -115,6 +162,10 @@ static int of_get_mac_addr_nvmem(struct
|
||||
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
|
||||
* but is all zeros.
|
||||
*
|
||||
+ *
|
||||
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
+ * specified mtd device.
|
||||
+ *
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
int of_get_mac_address(struct device_node *np, u8 *addr)
|
||||
@@ -136,6 +187,10 @@ int of_get_mac_address(struct device_nod
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
+ ret = of_get_mac_address_mtd(np, addr);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+
|
||||
return of_get_mac_addr_nvmem(np, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
@ -1,135 +0,0 @@
|
||||
From: John Crispin <blogic@openwrt.org>
|
||||
Subject: NET: add mtd-mac-address support to of_get_mac_address()
|
||||
|
||||
Many embedded devices have information such as mac addresses stored inside mtd
|
||||
devices. This patch allows us to add a property inside a node describing a
|
||||
network interface. The new property points at a mtd partition with an offset
|
||||
where the mac address can be found.
|
||||
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++++++++
|
||||
include/linux/of_net.h | 1 +
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -45,7 +46,7 @@ int of_get_phy_mode(struct device_node *
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_get_phy_mode);
|
||||
|
||||
-static const void *of_get_mac_addr(struct device_node *np, const char *name)
|
||||
+static void *of_get_mac_addr(struct device_node *np, const char *name)
|
||||
{
|
||||
struct property *pp = of_find_property(np, name, NULL);
|
||||
|
||||
@@ -78,6 +79,79 @@ static const void *of_get_mac_addr_nvmem
|
||||
return mac;
|
||||
}
|
||||
|
||||
+static const void *of_get_mac_address_mtd(struct device_node *np)
|
||||
+{
|
||||
+#ifdef CONFIG_MTD
|
||||
+ struct device_node *mtd_np = NULL;
|
||||
+ struct property *prop;
|
||||
+ size_t retlen;
|
||||
+ int size, ret;
|
||||
+ struct mtd_info *mtd;
|
||||
+ const char *part;
|
||||
+ const __be32 *list;
|
||||
+ phandle phandle;
|
||||
+ u32 mac_inc = 0;
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+ void *addr;
|
||||
+ u32 inc_idx;
|
||||
+
|
||||
+ list = of_get_property(np, "mtd-mac-address", &size);
|
||||
+ if (!list || (size != (2 * sizeof(*list))))
|
||||
+ return NULL;
|
||||
+
|
||||
+ phandle = be32_to_cpup(list++);
|
||||
+ if (phandle)
|
||||
+ mtd_np = of_find_node_by_phandle(phandle);
|
||||
+
|
||||
+ if (!mtd_np)
|
||||
+ return NULL;
|
||||
+
|
||||
+ part = of_get_property(mtd_np, "label", NULL);
|
||||
+ if (!part)
|
||||
+ part = mtd_np->name;
|
||||
+
|
||||
+ mtd = get_mtd_device_nm(part);
|
||||
+ if (IS_ERR(mtd))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
|
||||
+ put_mtd_device(mtd);
|
||||
+
|
||||
+ if (of_property_read_u32(np, "mtd-mac-address-increment-byte", &inc_idx))
|
||||
+ inc_idx = 5;
|
||||
+ if (inc_idx > 5)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!of_property_read_u32(np, "mtd-mac-address-increment", &mac_inc))
|
||||
+ mac[inc_idx] += mac_inc;
|
||||
+
|
||||
+ if (!is_valid_ether_addr(mac))
|
||||
+ return NULL;
|
||||
+
|
||||
+ addr = of_get_mac_addr(np, "mac-address");
|
||||
+ if (addr) {
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+ return addr;
|
||||
+ }
|
||||
+
|
||||
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
|
||||
+ if (!prop)
|
||||
+ return NULL;
|
||||
+
|
||||
+ prop->name = "mac-address";
|
||||
+ prop->length = ETH_ALEN;
|
||||
+ prop->value = kmemdup(mac, ETH_ALEN, GFP_KERNEL);
|
||||
+ if (!prop->value || of_add_property(np, prop))
|
||||
+ goto free;
|
||||
+
|
||||
+ return prop->value;
|
||||
+free:
|
||||
+ kfree(prop->value);
|
||||
+ kfree(prop);
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* 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
|
||||
@@ -98,12 +172,20 @@ static const void *of_get_mac_addr_nvmem
|
||||
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
|
||||
* but is all zeros.
|
||||
*
|
||||
+ *
|
||||
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
+ * specified mtd device, and store it as a 'mac-address' property
|
||||
+ *
|
||||
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
|
||||
*/
|
||||
const void *of_get_mac_address(struct device_node *np)
|
||||
{
|
||||
const void *addr;
|
||||
|
||||
+ addr = of_get_mac_address_mtd(np);
|
||||
+ if (addr)
|
||||
+ return addr;
|
||||
+
|
||||
addr = of_get_mac_addr(np, "mac-address");
|
||||
if (addr)
|
||||
return addr;
|
@ -0,0 +1,102 @@
|
||||
From 6f8e5369ae054ec6c9265581d5a7e39738a5cd84 Mon Sep 17 00:00:00 2001
|
||||
From: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
Date: Tue, 30 Mar 2021 13:16:38 +0200
|
||||
Subject: [PATCH 1/2] NET: add mtd-mac-address support to of_get_mac_address()
|
||||
|
||||
Many embedded devices have information such as mac addresses stored inside mtd
|
||||
devices. This patch allows us to add a property inside a node describing a
|
||||
network interface. The new property points at a mtd partition with an offset
|
||||
where the mac address can be found.
|
||||
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/of/of_net.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 74 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -89,6 +90,52 @@ static int of_get_mac_addr_nvmem(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int of_get_mac_address_mtd(struct device_node *np, u8 *addr)
|
||||
+{
|
||||
+#ifdef CONFIG_MTD
|
||||
+ struct platform_device *pdev = of_find_device_by_node(np);
|
||||
+ struct device_node *mtd_np = NULL;
|
||||
+ size_t retlen;
|
||||
+ int size, ret;
|
||||
+ struct mtd_info *mtd;
|
||||
+ const char *part;
|
||||
+ const __be32 *list;
|
||||
+ phandle phandle;
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+
|
||||
+ list = of_get_property(np, "mtd-mac-address", &size);
|
||||
+ if (!list || (size != (2 * sizeof(*list))))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ phandle = be32_to_cpup(list++);
|
||||
+ if (phandle)
|
||||
+ mtd_np = of_find_node_by_phandle(phandle);
|
||||
+
|
||||
+ if (!mtd_np)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ part = of_get_property(mtd_np, "label", NULL);
|
||||
+ if (!part)
|
||||
+ part = mtd_np->name;
|
||||
+
|
||||
+ mtd = get_mtd_device_nm(part);
|
||||
+ if (IS_ERR(mtd))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
|
||||
+ put_mtd_device(mtd);
|
||||
+
|
||||
+ if (!is_valid_ether_addr(mac))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+
|
||||
+ return 0;
|
||||
+#endif
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**
|
||||
* 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
|
||||
@@ -109,6 +156,10 @@ static int of_get_mac_addr_nvmem(struct
|
||||
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
|
||||
* but is all zeros.
|
||||
*
|
||||
+ *
|
||||
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
+ * specified mtd device.
|
||||
+ *
|
||||
* Return: 0 on success and errno in case of error.
|
||||
*/
|
||||
int of_get_mac_address(struct device_node *np, u8 *addr)
|
||||
@@ -130,6 +181,10 @@ int of_get_mac_address(struct device_nod
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
+ ret = of_get_mac_address_mtd(np, addr);
|
||||
+ if (!ret)
|
||||
+ return 0;
|
||||
+
|
||||
return of_get_mac_addr_nvmem(np, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_mac_address);
|
@ -1,135 +0,0 @@
|
||||
From: John Crispin <blogic@openwrt.org>
|
||||
Subject: NET: add mtd-mac-address support to of_get_mac_address()
|
||||
|
||||
Many embedded devices have information such as mac addresses stored inside mtd
|
||||
devices. This patch allows us to add a property inside a node describing a
|
||||
network interface. The new property points at a mtd partition with an offset
|
||||
where the mac address can be found.
|
||||
|
||||
Signed-off-by: John Crispin <blogic@openwrt.org>
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
drivers/of/of_net.c | 37 +++++++++++++++++++++++++++++++++++++
|
||||
include/linux/of_net.h | 1 +
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
--- a/drivers/of/of_net.c
|
||||
+++ b/drivers/of/of_net.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/device.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
|
||||
/**
|
||||
* of_get_phy_mode - Get phy mode for given device_node
|
||||
@@ -39,7 +40,7 @@ int of_get_phy_mode(struct device_node *
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_get_phy_mode);
|
||||
|
||||
-static const void *of_get_mac_addr(struct device_node *np, const char *name)
|
||||
+static void *of_get_mac_addr(struct device_node *np, const char *name)
|
||||
{
|
||||
struct property *pp = of_find_property(np, name, NULL);
|
||||
|
||||
@@ -72,6 +73,79 @@ static const void *of_get_mac_addr_nvmem
|
||||
return mac;
|
||||
}
|
||||
|
||||
+static const void *of_get_mac_address_mtd(struct device_node *np)
|
||||
+{
|
||||
+#ifdef CONFIG_MTD
|
||||
+ struct device_node *mtd_np = NULL;
|
||||
+ struct property *prop;
|
||||
+ size_t retlen;
|
||||
+ int size, ret;
|
||||
+ struct mtd_info *mtd;
|
||||
+ const char *part;
|
||||
+ const __be32 *list;
|
||||
+ phandle phandle;
|
||||
+ u32 mac_inc = 0;
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+ void *addr;
|
||||
+ u32 inc_idx;
|
||||
+
|
||||
+ list = of_get_property(np, "mtd-mac-address", &size);
|
||||
+ if (!list || (size != (2 * sizeof(*list))))
|
||||
+ return NULL;
|
||||
+
|
||||
+ phandle = be32_to_cpup(list++);
|
||||
+ if (phandle)
|
||||
+ mtd_np = of_find_node_by_phandle(phandle);
|
||||
+
|
||||
+ if (!mtd_np)
|
||||
+ return NULL;
|
||||
+
|
||||
+ part = of_get_property(mtd_np, "label", NULL);
|
||||
+ if (!part)
|
||||
+ part = mtd_np->name;
|
||||
+
|
||||
+ mtd = get_mtd_device_nm(part);
|
||||
+ if (IS_ERR(mtd))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, mac);
|
||||
+ put_mtd_device(mtd);
|
||||
+
|
||||
+ if (of_property_read_u32(np, "mtd-mac-address-increment-byte", &inc_idx))
|
||||
+ inc_idx = 5;
|
||||
+ if (inc_idx > 5)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!of_property_read_u32(np, "mtd-mac-address-increment", &mac_inc))
|
||||
+ mac[inc_idx] += mac_inc;
|
||||
+
|
||||
+ if (!is_valid_ether_addr(mac))
|
||||
+ return NULL;
|
||||
+
|
||||
+ addr = of_get_mac_addr(np, "mac-address");
|
||||
+ if (addr) {
|
||||
+ memcpy(addr, mac, ETH_ALEN);
|
||||
+ return addr;
|
||||
+ }
|
||||
+
|
||||
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
|
||||
+ if (!prop)
|
||||
+ return NULL;
|
||||
+
|
||||
+ prop->name = "mac-address";
|
||||
+ prop->length = ETH_ALEN;
|
||||
+ prop->value = kmemdup(mac, ETH_ALEN, GFP_KERNEL);
|
||||
+ if (!prop->value || of_add_property(np, prop))
|
||||
+ goto free;
|
||||
+
|
||||
+ return prop->value;
|
||||
+free:
|
||||
+ kfree(prop->value);
|
||||
+ kfree(prop);
|
||||
+#endif
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* 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
|
||||
@@ -92,12 +166,20 @@ static const void *of_get_mac_addr_nvmem
|
||||
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
|
||||
* but is all zeros.
|
||||
*
|
||||
+ *
|
||||
+ * If a mtd-mac-address property exists, try to fetch the MAC address from the
|
||||
+ * specified mtd device, and store it as a 'mac-address' property
|
||||
+ *
|
||||
* Return: Will be a valid pointer on success and ERR_PTR in case of error.
|
||||
*/
|
||||
const void *of_get_mac_address(struct device_node *np)
|
||||
{
|
||||
const void *addr;
|
||||
|
||||
+ addr = of_get_mac_address_mtd(np);
|
||||
+ if (addr)
|
||||
+ return addr;
|
||||
+
|
||||
addr = of_get_mac_addr(np, "mac-address");
|
||||
if (addr)
|
||||
return addr;
|
@ -904,8 +904,6 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
for_each_available_child_of_node(np, pnp) {
|
||||
const char *mac_addr;
|
||||
|
||||
/* this check is needed if parent and daughter dts have
|
||||
* different number of gmac nodes
|
||||
*/
|
||||
@ -914,9 +912,7 @@ static int edma_axi_probe(struct platform_device *pdev)
|
||||
break;
|
||||
}
|
||||
|
||||
mac_addr = of_get_mac_address(pnp);
|
||||
if (!IS_ERR(mac_addr))
|
||||
memcpy(edma_netdev[idx_mac]->dev_addr, mac_addr, ETH_ALEN);
|
||||
of_get_mac_address(pnp, edma_netdev[idx_mac]->dev_addr);
|
||||
|
||||
idx_mac++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user