[PATCH v9 06/12] firmware: raspberrypi: register nvmem driver
From: Gregor Herburger
Date: Wed Nov 11 2026 - 02:29:54 EST
The Raspberry Pi firmware exposes two regions with otp registers. The
first region called "customer otp" is available on all Raspberry Pi
models. The second is only available on the Raspberry Pi 5 (bcm2712).
Reviewed-by: Thomas Weißschuh <thomas.weissschuh@xxxxxxxxxxxxx>
Signed-off-by: Gregor Herburger <gregor.herburger@xxxxxxxxxxxxx>
---
drivers/firmware/raspberrypi.c | 59 +++++++++++++++++++++++++++++-
include/soc/bcm2835/raspberrypi-firmware.h | 5 +++
2 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 443459c8c90fa..755f845754c1c 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -25,12 +25,15 @@
static struct platform_device *rpi_hwmon;
static struct platform_device *rpi_clk;
static struct platform_device *rpi_rtc;
+static struct platform_device *rpi_otp_customer;
+static struct platform_device *rpi_otp_private;
struct rpi_firmware {
struct mbox_client cl;
struct mbox_chan *chan; /* The property channel. */
struct completion c;
u32 enabled;
+ enum rpi_firmware_soc soc;
struct kref consumers;
};
@@ -252,6 +255,47 @@ static void rpi_register_rtc_driver(struct device *dev)
rpi_rtc = pdev;
}
+static const struct rpi_otp_driver_data rpi_otp_customer_data = {
+ .name = "rpi-otp-customer",
+ .read_tag = RPI_FIRMWARE_GET_CUSTOMER_OTP,
+ .write_tag = RPI_FIRMWARE_SET_CUSTOMER_OTP,
+ .size = 32,
+ .root_only = false,
+};
+
+static const struct rpi_otp_driver_data rpi_otp_private_data = {
+ .name = "rpi-otp-private",
+ .read_tag = RPI_FIRMWARE_GET_PRIVATE_OTP,
+ .write_tag = RPI_FIRMWARE_SET_PRIVATE_OTP,
+ .size = 32,
+ .root_only = true,
+};
+
+static void rpi_register_otp_driver(struct device *dev)
+{
+ struct rpi_firmware *fw = dev_get_drvdata(dev);
+
+ rpi_otp_customer = platform_device_register_data(dev, "raspberrypi-otp",
+ PLATFORM_DEVID_AUTO,
+ &rpi_otp_customer_data,
+ sizeof(rpi_otp_customer_data));
+
+ if (IS_ERR(rpi_otp_customer))
+ dev_err(dev, "Failed to register customer OTP device: %pe\n",
+ rpi_otp_customer);
+
+ if (fw->soc == RPI_FIRMWARE_SOC_BCM2712) {
+ rpi_otp_private = platform_device_register_data(dev, "raspberrypi-otp",
+ PLATFORM_DEVID_AUTO,
+ &rpi_otp_private_data,
+ sizeof(rpi_otp_private_data));
+
+ if (IS_ERR(rpi_otp_private))
+ dev_err(dev, "Failed to register private OTP device: %pe\n",
+ rpi_otp_private);
+ }
+}
+
unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw, unsigned int id)
{
struct rpi_firmware_clk_rate_request msg =
@@ -320,6 +364,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
init_completion(&fw->c);
kref_init(&fw->consumers);
+ fw->soc = (uintptr_t)device_get_match_data(dev);
platform_set_drvdata(pdev, fw);
@@ -327,6 +372,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
rpi_register_hwmon_driver(dev, fw);
rpi_register_clk_driver(dev);
rpi_register_rtc_driver(dev);
+ rpi_register_otp_driver(dev);
return 0;
}
@@ -351,12 +397,23 @@ static void rpi_firmware_remove(struct platform_device *pdev)
rpi_clk = NULL;
platform_device_unregister(rpi_rtc);
rpi_rtc = NULL;
+ platform_device_unregister(rpi_otp_customer);
+ rpi_otp_customer = NULL;
+ platform_device_unregister(rpi_otp_private);
+ rpi_otp_private = NULL;
rpi_firmware_put(fw);
}
static const struct of_device_id rpi_firmware_of_match[] = {
- { .compatible = "raspberrypi,bcm2835-firmware", },
+ {
+ .compatible = "raspberrypi,bcm2835-firmware",
+ .data = (void *)RPI_FIRMWARE_SOC_BCM2835,
+ },
+ {
+ .compatible = "raspberrypi,bcm2712-firmware",
+ .data = (void *)RPI_FIRMWARE_SOC_BCM2712,
+ },
{},
};
MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 96ddf886d579e..2fb1ef2a33141 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -9,6 +9,11 @@
#include <linux/types.h>
#include <linux/of_device.h>
+enum rpi_firmware_soc {
+ RPI_FIRMWARE_SOC_BCM2835,
+ RPI_FIRMWARE_SOC_BCM2712,
+};
+
struct rpi_firmware;
enum rpi_firmware_property_status {
--
2.47.3