From: Daniel Golle Date: Sat, 5 Oct 2024 20:43:48 +0000 (+0100) Subject: mediatek: add driver for Adtran MFGINFO NVMEM layout X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=175bd80349de886d27f79f12cb8e562a807cb5b5;p=openwrt%2Fstaging%2Fblocktrron.git 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 --- diff --git a/target/linux/mediatek/filogic/config-6.6 b/target/linux/mediatek/filogic/config-6.6 index 818bcfa081..7cf045ade2 100644 --- a/target/linux/mediatek/filogic/config-6.6 +++ b/target/linux/mediatek/filogic/config-6.6 @@ -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 diff --git a/target/linux/mediatek/mt7622/config-6.6 b/target/linux/mediatek/mt7622/config-6.6 index e7b6b46c84..c18e62476f 100644 --- a/target/linux/mediatek/mt7622/config-6.6 +++ b/target/linux/mediatek/mt7622/config-6.6 @@ -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 diff --git a/target/linux/mediatek/mt7623/config-6.6 b/target/linux/mediatek/mt7623/config-6.6 index bb00bee8f3..e34822d992 100644 --- a/target/linux/mediatek/mt7623/config-6.6 +++ b/target/linux/mediatek/mt7623/config-6.6 @@ -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 diff --git a/target/linux/mediatek/mt7629/config-6.6 b/target/linux/mediatek/mt7629/config-6.6 index 1748efab77..81c07a5492 100644 --- a/target/linux/mediatek/mt7629/config-6.6 +++ b/target/linux/mediatek/mt7629/config-6.6 @@ -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 diff --git a/target/linux/mediatek/patches-6.6/450-nvmem-add-layout-for-Adtran-devices.patch b/target/linux/mediatek/patches-6.6/450-nvmem-add-layout-for-Adtran-devices.patch new file mode 100644 index 0000000000..496fc6c53f --- /dev/null +++ b/target/linux/mediatek/patches-6.6/450-nvmem-add-layout-for-Adtran-devices.patch @@ -0,0 +1,191 @@ +From c22bc82183c2dea64919f975473ec518738baa3e Mon Sep 17 00:00:00 2001 +From: Daniel Golle +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * 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 "); ++MODULE_DESCRIPTION("NVMEM layout driver for Adtran mfginfo");