mediatek: add driver for Adtran MFGINFO NVMEM layout
authorDaniel Golle <daniel@makrotopia.org>
Sat, 5 Oct 2024 20:43:48 +0000 (21:43 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Tue, 15 Oct 2024 16:55:05 +0000 (17:55 +0100)
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>
target/linux/mediatek/filogic/config-6.6
target/linux/mediatek/mt7622/config-6.6
target/linux/mediatek/mt7623/config-6.6
target/linux/mediatek/mt7629/config-6.6
target/linux/mediatek/patches-6.6/450-nvmem-add-layout-for-Adtran-devices.patch [new file with mode: 0644]

index 818bcfa081ea762129b2fec19287a201396ae903..7cf045ade2a5e2846f5aa6860ca691bebf26b39c 100644 (file)
@@ -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
index e7b6b46c84cf6226d92cbe529f5f914b64beb2f0..c18e62476f52779bc860ccbde401364df95e85bf 100644 (file)
@@ -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
index bb00bee8f31407b9822d2aa0cf92f6c42df525c5..e34822d99224857c03288a7274aec8b2b2be7529 100644 (file)
@@ -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
index 1748efab775fc6866389f5b0577e50be2348a6b9..81c07a54922569d2993b49b30a98a92afb1c087a 100644 (file)
@@ -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 (file)
index 0000000..496fc6c
--- /dev/null
@@ -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");