mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-06-13 23:42:04 +08: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 net_device *dev;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct ag71xx *ag;
|
struct ag71xx *ag;
|
||||||
const void *mac_addr;
|
|
||||||
u32 max_frame_len;
|
u32 max_frame_len;
|
||||||
int tx_size, err;
|
int tx_size, err;
|
||||||
|
|
||||||
@ -1668,12 +1667,10 @@ static int ag71xx_probe(struct platform_device *pdev)
|
|||||||
ag->stop_desc->ctrl = 0;
|
ag->stop_desc->ctrl = 0;
|
||||||
ag->stop_desc->next = (u32) ag->stop_desc_dma;
|
ag->stop_desc->next = (u32) ag->stop_desc_dma;
|
||||||
|
|
||||||
mac_addr = of_get_mac_address(np);
|
of_get_mac_address(np, dev->dev_addr);
|
||||||
if (IS_ERR_OR_NULL(mac_addr) || !is_valid_ether_addr(mac_addr)) {
|
if (!is_valid_ether_addr(dev->dev_addr)) {
|
||||||
dev_err(&pdev->dev, "invalid MAC address, using random address\n");
|
dev_err(&pdev->dev, "invalid MAC address, using random address\n");
|
||||||
eth_random_addr(dev->dev_addr);
|
eth_random_addr(dev->dev_addr);
|
||||||
} else {
|
|
||||||
memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
|
#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) {
|
for_each_available_child_of_node(np, pnp) {
|
||||||
const char *mac_addr;
|
|
||||||
|
|
||||||
/* this check is needed if parent and daughter dts have
|
/* this check is needed if parent and daughter dts have
|
||||||
* different number of gmac nodes
|
* different number of gmac nodes
|
||||||
*/
|
*/
|
||||||
@ -914,9 +912,7 @@ static int edma_axi_probe(struct platform_device *pdev)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mac_addr = of_get_mac_address(pnp);
|
of_get_mac_address(pnp, edma_netdev[idx_mac]->dev_addr);
|
||||||
if (!IS_ERR(mac_addr))
|
|
||||||
memcpy(edma_netdev[idx_mac]->dev_addr, mac_addr, ETH_ALEN);
|
|
||||||
|
|
||||||
idx_mac++;
|
idx_mac++;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user