mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-18 21:28:02 +00:00
mediatek: add driver for Adtran MFGINFO NVMEM layout
This driver allows retrieving MAC addresses and other factory information via the NVMEM framework on Adtran devices. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
330321421a
commit
175bd80349
@ -313,6 +313,7 @@ CONFIG_NR_CPUS=4
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_BLOCK=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_NVMEM_LAYOUT_ADTRAN=y
|
||||
CONFIG_NVMEM_MTK_EFUSE=y
|
||||
CONFIG_NVMEM_SYSFS=y
|
||||
CONFIG_OF=y
|
||||
|
@ -314,7 +314,9 @@ CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=2
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_BLOCK=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_NVMEM_LAYOUT_ADTRAN=y
|
||||
CONFIG_NVMEM_MTK_EFUSE=y
|
||||
CONFIG_NVMEM_SYSFS=y
|
||||
CONFIG_OF=y
|
||||
|
@ -436,6 +436,7 @@ CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
# CONFIG_NVMEM_LAYOUT_ADTRAN is not set
|
||||
CONFIG_NVMEM_MTK_EFUSE=y
|
||||
# CONFIG_NVMEM_SPMI_SDAM is not set
|
||||
CONFIG_NVMEM_SYSFS=y
|
||||
|
@ -239,6 +239,7 @@ CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=2
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
# CONFIG_NVMEM_LAYOUT_ADTRAN is not set
|
||||
# CONFIG_NVMEM_MTK_EFUSE is not set
|
||||
CONFIG_NVMEM_SYSFS=y
|
||||
CONFIG_OF=y
|
||||
|
@ -0,0 +1,191 @@
|
||||
From c22bc82183c2dea64919f975473ec518738baa3e Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Wed, 12 Jul 2023 13:38:35 +0100
|
||||
Subject: [PATCH] nvmem: add layout for Adtran devices
|
||||
|
||||
Adtran stores unique factory data on GPT partitions on the eMMC.
|
||||
Using blk-nvmem the 'mfginfo' partition gets exposes as NVMEM provider.
|
||||
|
||||
Add layout driver to parse mfginfo, mainly to provide MAC addresses to
|
||||
Ethernet and wireless interfaces.
|
||||
|
||||
Variable names are converted to lower-case and '_' is replaced with '-'
|
||||
in order to comply with the device tree node naming convention.
|
||||
The main MAC address always ends on a 0 and up to 16 addresses are
|
||||
alocated for each device to use for various interfaces.
|
||||
|
||||
Implement post-processing function for 'MFG_MAC' variable ('mfg-mac'
|
||||
node name in device tree) adding the nvmem cell index to the least
|
||||
significant digit of the MAC address.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/nvmem/layouts/Kconfig | 9 +++
|
||||
drivers/nvmem/layouts/Makefile | 1 +
|
||||
drivers/nvmem/layouts/adtran.c | 135 +++++++++++++++++++++++++++++++++
|
||||
3 files changed, 145 insertions(+)
|
||||
create mode 100644 drivers/nvmem/layouts/adtran.c
|
||||
|
||||
--- a/drivers/nvmem/layouts/Kconfig
|
||||
+++ b/drivers/nvmem/layouts/Kconfig
|
||||
@@ -8,6 +8,15 @@ if NVMEM_LAYOUTS
|
||||
|
||||
menu "Layout Types"
|
||||
|
||||
+config NVMEM_LAYOUT_ADTRAN
|
||||
+ tristate "Adtran mfginfo layout support"
|
||||
+ select GENERIC_NET_UTILS
|
||||
+ help
|
||||
+ Say Y here if you want to support the layout used by Adtran for
|
||||
+ mfginfo.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
config NVMEM_LAYOUT_SL28_VPD
|
||||
tristate "Kontron sl28 VPD layout support"
|
||||
select CRC8
|
||||
--- a/drivers/nvmem/layouts/Makefile
|
||||
+++ b/drivers/nvmem/layouts/Makefile
|
||||
@@ -6,3 +6,4 @@
|
||||
obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
|
||||
obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
|
||||
obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o
|
||||
+obj-$(CONFIG_NVMEM_LAYOUT_ADTRAN) += adtran.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/nvmem/layouts/adtran.c
|
||||
@@ -0,0 +1,135 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+#include <linux/ctype.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/nvmem-consumer.h>
|
||||
+#include <linux/nvmem-provider.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+/*
|
||||
+ * Adtran devices usually come with a main MAC address ending on 0 and
|
||||
+ * hence may have up to 16 MAC addresses per device.
|
||||
+ * The main MAC address is stored as variable MFG_MAC in ASCII format.
|
||||
+ */
|
||||
+static int adtran_mac_address_pp(void *priv, const char *id, int index,
|
||||
+ unsigned int offset, void *buf,
|
||||
+ size_t bytes)
|
||||
+{
|
||||
+ u8 mac[ETH_ALEN];
|
||||
+
|
||||
+ if (WARN_ON(bytes != 3 * ETH_ALEN - 1))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!mac_pton(buf, mac))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (index)
|
||||
+ eth_addr_add(mac, index);
|
||||
+
|
||||
+ ether_addr_copy(buf, mac);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int adtran_add_cells(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ struct nvmem_device *nvmem = layout->nvmem;
|
||||
+ struct nvmem_cell_info info;
|
||||
+ struct device_node *layout_np;
|
||||
+ char mfginfo[1024], *c, *t, *p;
|
||||
+ int ret = -EINVAL;
|
||||
+
|
||||
+ ret = nvmem_device_read(nvmem, 0, sizeof(mfginfo), mfginfo);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ else if (ret != sizeof(mfginfo))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ layout_np = of_nvmem_layout_get_container(nvmem);
|
||||
+ if (!layout_np)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ c = mfginfo;
|
||||
+ while (*c != 0xff) {
|
||||
+ memset(&info, 0, sizeof(info));
|
||||
+ if (*c == '#')
|
||||
+ goto nextline;
|
||||
+
|
||||
+ t = strchr(c, '=');
|
||||
+ if (!t)
|
||||
+ goto nextline;
|
||||
+
|
||||
+ *t = '\0';
|
||||
+ ++t;
|
||||
+ info.offset = t - mfginfo;
|
||||
+ /* process variable name: convert to lower-case, '_' -> '-' */
|
||||
+ p = c;
|
||||
+ do {
|
||||
+ *p = tolower(*p);
|
||||
+ if (*p == '_')
|
||||
+ *p = '-';
|
||||
+ } while (*++p);
|
||||
+ info.name = c;
|
||||
+ c = strchr(t, 0xa); /* find newline */
|
||||
+ if (!c)
|
||||
+ break;
|
||||
+
|
||||
+ info.bytes = c - t;
|
||||
+ if (!strcmp(info.name, "mfg-mac")) {
|
||||
+ info.raw_len = info.bytes;
|
||||
+ info.bytes = ETH_ALEN;
|
||||
+ info.read_post_process = adtran_mac_address_pp;
|
||||
+ }
|
||||
+
|
||||
+ info.np = of_get_child_by_name(layout_np, info.name);
|
||||
+ ret = nvmem_add_one_cell(nvmem, &info);
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+
|
||||
+ ++c;
|
||||
+ continue;
|
||||
+
|
||||
+nextline:
|
||||
+ c = strchr(c, 0xa); /* find newline */
|
||||
+ if (!c)
|
||||
+ break;
|
||||
+ ++c;
|
||||
+ }
|
||||
+
|
||||
+ of_node_put(layout_np);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int adtran_probe(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ layout->add_cells = adtran_add_cells;
|
||||
+
|
||||
+ return nvmem_layout_register(layout);
|
||||
+}
|
||||
+
|
||||
+static void adtran_remove(struct nvmem_layout *layout)
|
||||
+{
|
||||
+ nvmem_layout_unregister(layout);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id adtran_of_match_table[] = {
|
||||
+ { .compatible = "adtran,mfginfo" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, adtran_of_match_table);
|
||||
+
|
||||
+static struct nvmem_layout_driver adtran_layout = {
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "adtran-layout",
|
||||
+ .of_match_table = adtran_of_match_table,
|
||||
+ },
|
||||
+ .probe = adtran_probe,
|
||||
+ .remove = adtran_remove,
|
||||
+};
|
||||
+module_nvmem_layout_driver(adtran_layout);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
|
||||
+MODULE_DESCRIPTION("NVMEM layout driver for Adtran mfginfo");
|
Loading…
Reference in New Issue
Block a user