From: Alexey Charkov <alchark@flipper.net>
To: Srinivas Kandagatla <srini@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Heiko Stuebner <heiko@sntech.de>,
Michael Walle <michael@walle.cc>,
Miquel Raynal <miquel.raynal@bootlin.com>,
Finley Xiao <finley.xiao@rock-chips.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-rockchip@lists.infradead.org,
linux-arm-kernel@lists.infradead.org,
Alexey Charkov <alchark@flipper.net>
Subject: [PATCH v2 3/4] nvmem: layouts: Add Rockchip OTP CPUID layout driver
Date: Wed, 02 Sep 2026 17:07:54 +0400 [thread overview]
Message-ID: <20260902-rk3576-otp-cpuid-mac-v2-3-e4b7fe2ab13f@flipper.net> (raw)
In-Reply-To: <20260902-rk3576-otp-cpuid-mac-v2-0-e4b7fe2ab13f@flipper.net>
Rockchip SoCs customarily use the CPU ID programmed into their on-chip OTP
memory to derive stable Ethernet MAC addresses even when a board doesn't
otherwise have dedicated storage for those. The derivation depends on the
particular bootloader implementation (e.g. it is done by upstream U-Boot,
which patches the derived MAC addresses at runtime into the device tree it
hands to the kernel). Using less featureful bootloaders, such as direct
boot to Linux from SPL, leaves the kernel with only a random MAC address
instead, even though everything required for the derivation is equally
available to Linux as it is to U-Boot.
Reproduce the same derivation in the kernel and expose the result as an
nvmem cell named "mac-address", so that of_get_mac_address() picks it up
through its standard nvmem fallback. The address index comes from the DT
phandle argument, which lets both interfaces of a dual Ethernet board
share a single cell.
Enable the layout by default on Rockchip, as consumers of its cells would
otherwise defer their probe indefinitely.
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Alexey Charkov <alchark@flipper.net>
---
MAINTAINERS | 1 +
drivers/nvmem/layouts/Kconfig | 13 ++++
drivers/nvmem/layouts/Makefile | 1 +
drivers/nvmem/layouts/rockchip-otp-cpuid.c | 119 +++++++++++++++++++++++++++++
4 files changed, 134 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index f3d07ce7b3c8..73e0531445be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23727,6 +23727,7 @@ M: Alexey Charkov <alchark@flipper.net>
L: linux-rockchip@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/nvmem/layouts/rockchip,rk3576-otp-cpuid.yaml
+F: drivers/nvmem/layouts/rockchip-otp-cpuid.c
ROCKCHIP RK3568 RANDOM NUMBER GENERATOR SUPPORT
M: Daniel Golle <daniel@makrotopia.org>
diff --git a/drivers/nvmem/layouts/Kconfig b/drivers/nvmem/layouts/Kconfig
index 5e586dfebe47..6e2511ac6f7e 100644
--- a/drivers/nvmem/layouts/Kconfig
+++ b/drivers/nvmem/layouts/Kconfig
@@ -26,6 +26,19 @@ config NVMEM_LAYOUT_ONIE_TLV
If unsure, say N.
+config NVMEM_LAYOUT_ROCKCHIP_OTP_CPUID
+ tristate "Rockchip OTP CPU ID layout support"
+ default ARCH_ROCKCHIP
+ select CRYPTO_LIB_SHA256
+ help
+ Say Y here if you want to expose the MAC addresses that Rockchip
+ bootloaders derive from the CPU ID programmed into the OTP memory of
+ Rockchip SoCs. Boards which have no other source of MAC addresses
+ need this to get stable ones when the bootloader does not patch them
+ into the device tree.
+
+ If unsure, say N.
+
config NVMEM_LAYOUT_U_BOOT_ENV
tristate "U-Boot environment variables layout"
select CRC32
diff --git a/drivers/nvmem/layouts/Makefile b/drivers/nvmem/layouts/Makefile
index dd6c6c70b1a9..a0ade4c22c79 100644
--- a/drivers/nvmem/layouts/Makefile
+++ b/drivers/nvmem/layouts/Makefile
@@ -6,4 +6,5 @@
obj-$(CONFIG_NVMEM_LAYOUTS) += fixed-layout.o
obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
+obj-$(CONFIG_NVMEM_LAYOUT_ROCKCHIP_OTP_CPUID) += rockchip-otp-cpuid.o
obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o
diff --git a/drivers/nvmem/layouts/rockchip-otp-cpuid.c b/drivers/nvmem/layouts/rockchip-otp-cpuid.c
new file mode 100644
index 000000000000..61f509c4a8cf
--- /dev/null
+++ b/drivers/nvmem/layouts/rockchip-otp-cpuid.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: 2026 Flipper FZCO
+/*
+ * NVMEM layout for the CPU ID in Rockchip OTP memory
+ */
+
+#include <crypto/sha2.h>
+#include <linux/device-id/of.h>
+#include <linux/etherdevice.h>
+#include <linux/hex.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <uapi/linux/if_ether.h>
+
+#define ROCKCHIP_CPUID_LEN 16
+
+struct rockchip_cpuid_data {
+ unsigned int offset;
+};
+
+static int rockchip_cpuid_mac_pp(void *priv, const char *id, int index,
+ unsigned int offset, void *buf, size_t bytes)
+{
+ char cpuid[ROCKCHIP_CPUID_LEN * 2];
+ u8 digest[SHA256_DIGEST_SIZE];
+ u8 *mac = buf;
+
+ if (bytes != ROCKCHIP_CPUID_LEN)
+ return -EINVAL;
+
+ if (index < 0 || index > 1)
+ return -EINVAL;
+
+ /* The buffer still holds the raw CPU ID at this point */
+ bin2hex(cpuid, mac, ROCKCHIP_CPUID_LEN);
+
+ sha256(cpuid, sizeof(cpuid), digest);
+
+ memcpy(mac, digest, ETH_ALEN);
+ mac[0] &= 0xfe; /* clear the multicast bit */
+ mac[0] |= 0x02; /* set the locally administered bit */
+ mac[5] ^= index;
+
+ if (!is_valid_ether_addr(mac))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int rockchip_cpuid_add_cells(struct nvmem_layout *layout)
+{
+ const struct rockchip_cpuid_data *data;
+ struct nvmem_cell_info info = {0};
+ struct device_node *layout_np;
+ int ret;
+
+ data = of_device_get_match_data(&layout->dev);
+ if (!data)
+ return -EINVAL;
+
+ layout_np = of_nvmem_layout_get_container(layout->nvmem);
+ if (!layout_np)
+ return -ENOENT;
+
+ info.name = "mac-address";
+ info.offset = data->offset;
+ info.raw_len = ROCKCHIP_CPUID_LEN;
+ info.bytes = ETH_ALEN;
+ info.read_post_process = rockchip_cpuid_mac_pp;
+ info.np = of_get_child_by_name(layout_np, info.name);
+
+ of_node_put(layout_np);
+
+ ret = nvmem_add_one_cell(layout->nvmem, &info);
+ if (ret)
+ of_node_put(info.np);
+
+ return ret;
+}
+
+static int rockchip_cpuid_probe(struct nvmem_layout *layout)
+{
+ layout->add_cells = rockchip_cpuid_add_cells;
+
+ return nvmem_layout_register(layout);
+}
+
+static void rockchip_cpuid_remove(struct nvmem_layout *layout)
+{
+ nvmem_layout_unregister(layout);
+}
+
+static const struct rockchip_cpuid_data rk3576_cpuid_data = {
+ .offset = 0x0a,
+};
+
+static const struct of_device_id rockchip_cpuid_of_match_table[] = {
+ {
+ .compatible = "rockchip,rk3576-otp-cpuid",
+ .data = &rk3576_cpuid_data,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rockchip_cpuid_of_match_table);
+
+static struct nvmem_layout_driver rockchip_cpuid_layout = {
+ .driver = {
+ .name = "rockchip-otp-cpuid-layout",
+ .of_match_table = rockchip_cpuid_of_match_table,
+ },
+ .probe = rockchip_cpuid_probe,
+ .remove = rockchip_cpuid_remove,
+};
+module_nvmem_layout_driver(rockchip_cpuid_layout);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexey Charkov <alchark@flipper.net>");
+MODULE_DESCRIPTION("NVMEM layout driver for the CPU ID in Rockchip OTP memory");
--
2.54.0
next prev parent reply other threads:[~2026-09-02 13:08 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 13:07 [PATCH v2 0/4] nvmem: Derive Rockchip MAC addresses from the OTP CPU ID Alexey Charkov
2026-09-02 13:07 ` [PATCH v2 1/4] nvmem: rockchip-otp: Serialize reads Alexey Charkov
2026-09-02 13:07 ` [PATCH v2 2/4] dt-bindings: nvmem: layouts: Add Rockchip OTP CPUID layout Alexey Charkov
2026-09-02 13:07 ` Alexey Charkov [this message]
2026-09-14 22:23 ` [PATCH v2 3/4] nvmem: layouts: Add Rockchip OTP CPUID layout driver Srinivas Kandagatla
2026-09-02 13:07 ` [PATCH v2 4/4] arm64: dts: rockchip: Derive GMAC MAC addresses from OTP on RK3576 Alexey Charkov
2026-09-10 14:48 ` [PATCH v2 0/4] nvmem: Derive Rockchip MAC addresses from the OTP CPU ID Alexey Charkov
2026-09-17 22:18 ` Rob Herring
2026-09-18 7:08 ` Alexey Charkov
2026-09-10 16:49 ` Ricardo Pardini
2026-09-14 22:13 ` (subset) " Srinivas Kandagatla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260902-rk3576-otp-cpuid-mac-v2-3-e4b7fe2ab13f@flipper.net \
--to=alchark@flipper.net \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=finley.xiao@rock-chips.com \
--cc=gregkh@linuxfoundation.org \
--cc=heiko@sntech.de \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=michael@walle.cc \
--cc=miquel.raynal@bootlin.com \
--cc=robh@kernel.org \
--cc=srini@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®