* [PATCH v6 01/10] soc: bcm2835: Use IS_REACHABLE for function declaration
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 16:00 ` sashiko-bot
2026-05-22 15:40 ` [PATCH v6 02/10] nvmem: core: Enforce stride and alignment checks for nvmem_device functions Gregor Herburger
` (8 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
The drivers that depend on the RASPBERRYPI_FIRMWARE use
depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
This should ensure that the driver is not compiled in when
RASPBERRYPI_FIRMWARE is 'm' on COMPILE_TEST which leads to linker
errors.
The same can be achieved by using IS_REACHABLE in the
raspberrypi-firmware header. This evaluates to false when invoked from
built-in code. This way the Kconfig can be written as
depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
Which is a more readable variant.
Suggested-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
include/soc/bcm2835/raspberrypi-firmware.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index e1f87fbfe5542..eb33838e0cd10 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -174,7 +174,7 @@ struct rpi_firmware_clk_rate_request {
.id = cpu_to_le32(_id), \
}
-#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
+#if IS_REACHABLE(CONFIG_RASPBERRYPI_FIRMWARE)
int rpi_firmware_property(struct rpi_firmware *fw,
u32 tag, void *data, size_t len);
int rpi_firmware_property_list(struct rpi_firmware *fw,
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v6 01/10] soc: bcm2835: Use IS_REACHABLE for function declaration
2026-05-22 15:40 ` [PATCH v6 01/10] soc: bcm2835: Use IS_REACHABLE for function declaration Gregor Herburger
@ 2026-05-22 16:00 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-05-22 16:00 UTC (permalink / raw)
To: Gregor Herburger; +Cc: conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Replacing IS_ENABLED() with IS_REACHABLE() introduces silent runtime failures (such as infinite probe-deferral loops or silently failing operations) by hiding unresolved module dependencies behind inline stubs.
--
commit 4df320b82133df67fcde1204534b53b54b092612
Author: Gregor Herburger <gregor.herburger@linutronix.de>
soc: bcm2835: Use IS_REACHABLE for function declaration
This commit modifies the raspberrypi-firmware header to use IS_REACHABLE
instead of IS_ENABLED for function declarations. It aims to simplify
Kconfig dependencies for dependent drivers while avoiding linker errors
during COMPILE_TEST builds where the firmware is modular.
> diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
> index e1f87fbfe5542..eb33838e0cd10 100644
> --- a/include/soc/bcm2835/raspberrypi-firmware.h
> +++ b/include/soc/bcm2835/raspberrypi-firmware.h
> @@ -174,7 +174,7 @@ struct rpi_firmware_clk_rate_request {
> .id = cpu_to_le32(_id), \
> }
>
> -#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
> +#if IS_REACHABLE(CONFIG_RASPBERRYPI_FIRMWARE)
[Severity: High]
Could this change introduce silent runtime failures for dependent drivers?
When a dependent driver is compiled as built-in (=y) via COMPILE_TEST while
the firmware is compiled as a module (=m), IS_REACHABLE evaluates to false.
This causes the compiler to silently substitute hardcoded inline stubs
instead of linking against the real firmware functions.
Consequently, the build succeeds but the drivers might fundamentally fail at
runtime. For example, devm_rpi_firmware_get() returning NULL could cause a
permanent -EPROBE_DEFER loop, or rpi_firmware_property() returning -ENOSYS
might break all NVMEM reads and writes.
The previous Kconfig dependency forced dependent drivers to =m in this
scenario, guaranteeing functional runtime behavior and using linker errors
to enforce correct configurations. Does using IS_REACHABLE here mask these
module dependencies in a way that breaks the drivers at runtime?
> int rpi_firmware_property(struct rpi_firmware *fw,
> u32 tag, void *data, size_t len);
> int rpi_firmware_property_list(struct rpi_firmware *fw,
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260522-rpi-otp-driver-v6-0-b0eac97d1428@linutronix.de?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v6 02/10] nvmem: core: Enforce stride and alignment checks for nvmem_device functions
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 01/10] soc: bcm2835: Use IS_REACHABLE for function declaration Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 03/10] dt-bindings: raspberrypi,bcm2835-firmware: Add bcm2712-firmware compatible Gregor Herburger
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
The stride and word_size attributes in the nvmem_config struct are
currently only used when reading/writing through sysfs functions
bin_attr_nvmem_read/bin_attr_nvmem_write and in the nvmem_cell api.
Reads and writes with nvmem_device_write/nvmem_device_read still allow
unaligned access.
Add a check to these functions to enforce word_size and stride_length
aligned reads and writes.
Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
drivers/nvmem/core.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 311cb2e5a5c02..6b313f63d07ef 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -2068,6 +2068,12 @@ int nvmem_device_read(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
+ if (!IS_ALIGNED(offset, nvmem->stride))
+ return -EINVAL;
+
+ if (!IS_ALIGNED(bytes, nvmem->word_size))
+ return -EINVAL;
+
rc = nvmem_reg_read(nvmem, offset, buf, bytes);
if (rc)
@@ -2096,6 +2102,12 @@ int nvmem_device_write(struct nvmem_device *nvmem,
if (!nvmem)
return -EINVAL;
+ if (!IS_ALIGNED(offset, nvmem->stride))
+ return -EINVAL;
+
+ if (!IS_ALIGNED(bytes, nvmem->word_size))
+ return -EINVAL;
+
rc = nvmem_reg_write(nvmem, offset, buf, bytes);
if (rc)
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v6 03/10] dt-bindings: raspberrypi,bcm2835-firmware: Add bcm2712-firmware compatible
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 01/10] soc: bcm2835: Use IS_REACHABLE for function declaration Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 02/10] nvmem: core: Enforce stride and alignment checks for nvmem_device functions Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 04/10] nvmem: Add the Raspberry Pi OTP driver Gregor Herburger
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Conor Dooley, Gregor Herburger
Add a compatible string for the bcm2712 firmware. The bcm2712-firmware
is compatible with the bcm2835-firmware so allow the bcm2835-firmware as
fallback.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
.../bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
index 983ea80eaec97..a3a5243b91706 100644
--- a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
+++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
@@ -21,9 +21,14 @@ select:
properties:
compatible:
- items:
- - const: raspberrypi,bcm2835-firmware
- - const: simple-mfd
+ oneOf:
+ - items:
+ - const: raspberrypi,bcm2835-firmware
+ - const: simple-mfd
+ - items:
+ - const: raspberrypi,bcm2712-firmware
+ - const: raspberrypi,bcm2835-firmware
+ - const: simple-mfd
mboxes:
maxItems: 1
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v6 04/10] nvmem: Add the Raspberry Pi OTP driver
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
` (2 preceding siblings ...)
2026-05-22 15:40 ` [PATCH v6 03/10] dt-bindings: raspberrypi,bcm2835-firmware: Add bcm2712-firmware compatible Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 18:18 ` sashiko-bot
2026-05-22 15:40 ` [PATCH v6 05/10] firmware: raspberrypi: register nvmem driver Gregor Herburger
` (5 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
Raspberry Pis have OTP registers which can be accessed through the
videocore firmware. Add a nvmem driver to support these OTP registers.
Reviewed-by: Stefan Wahren <wahrenst@gmx.net>
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
drivers/nvmem/Kconfig | 11 +++
drivers/nvmem/Makefile | 1 +
drivers/nvmem/raspberrypi-otp.c | 131 +++++++++++++++++++++++++++++
include/soc/bcm2835/raspberrypi-firmware.h | 10 +++
4 files changed, 153 insertions(+)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 74ddbd0f79b0e..a1922b48d0c2e 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -483,4 +483,15 @@ config NVMEM_QORIQ_EFUSE
This driver can also be built as a module. If so, the module
will be called nvmem_qoriq_efuse.
+config NVMEM_RASPBERRYPI_OTP
+ tristate "Raspberry Pi OTP support"
+ depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+ help
+ This driver provides access to the Raspberry Pi OTP memory via the
+ nvmem subsystem. The driver supports the customer OTP as well as the
+ device specific private key OTP (BCM2712 only).
+
+ This driver can also be built as a module. If so, the module
+ will be called raspberrypi-otp.
+
endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 7252b8ec88d46..8ca2095e068f3 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -95,3 +95,4 @@ obj-$(CONFIG_NVMEM_ZYNQMP) += nvmem_zynqmp_nvmem.o
nvmem_zynqmp_nvmem-y := zynqmp_nvmem.o
obj-$(CONFIG_NVMEM_QORIQ_EFUSE) += nvmem-qoriq-efuse.o
nvmem-qoriq-efuse-y := qoriq-efuse.o
+obj-$(CONFIG_NVMEM_RASPBERRYPI_OTP) += raspberrypi-otp.o
diff --git a/drivers/nvmem/raspberrypi-otp.c b/drivers/nvmem/raspberrypi-otp.c
new file mode 100644
index 0000000000000..2e2537ee6793b
--- /dev/null
+++ b/drivers/nvmem/raspberrypi-otp.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+struct rpi_otp_priv {
+ struct rpi_firmware *fw;
+ u32 read_tag;
+ u32 write_tag;
+};
+
+struct rpi_otp_header {
+ __le32 start;
+ __le32 count;
+ __le32 data[] __counted_by_le(count);
+};
+
+static int rpi_otp_read(void *context, unsigned int offset, void *buf, size_t bytes)
+{
+ struct rpi_otp_priv *priv = context;
+ struct rpi_otp_header *fwbuf;
+ u32 count;
+ int ret;
+
+ count = bytes / 4;
+
+ fwbuf = kzalloc(struct_size(fwbuf, data, count), GFP_KERNEL);
+ if (!fwbuf)
+ return -ENOMEM;
+
+ fwbuf->start = cpu_to_le32(offset / 4);
+ fwbuf->count = cpu_to_le32(count);
+
+ ret = rpi_firmware_property(priv->fw, priv->read_tag, fwbuf,
+ sizeof(struct rpi_otp_header) + bytes);
+ if (ret)
+ goto out;
+
+ memcpy(buf, fwbuf->data, bytes);
+
+out:
+ kfree(fwbuf);
+ return ret;
+}
+
+static int rpi_otp_write(void *context, unsigned int offset, void *val, size_t bytes)
+{
+ struct rpi_otp_priv *priv = context;
+ struct rpi_otp_header *fwbuf;
+ u32 count;
+ int ret;
+
+ count = bytes / 4;
+
+ fwbuf = kzalloc(struct_size(fwbuf, data, count), GFP_KERNEL);
+ if (!fwbuf)
+ return -ENOMEM;
+
+ fwbuf->start = cpu_to_le32(offset / 4);
+ fwbuf->count = cpu_to_le32(count);
+ memcpy(fwbuf->data, val, bytes);
+
+ ret = rpi_firmware_property(priv->fw, priv->write_tag, fwbuf,
+ sizeof(struct rpi_otp_header) + bytes);
+
+ kfree(fwbuf);
+ return ret;
+}
+
+static int rpi_otp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct nvmem_device *nvmem;
+ struct rpi_otp_priv *priv;
+ const struct rpi_otp_driver_data *data;
+ struct nvmem_config config = {
+ .read_only = false,
+ .word_size = 4,
+ .stride = 4,
+ .reg_read = rpi_otp_read,
+ .reg_write = rpi_otp_write,
+ .id = NVMEM_DEVID_NONE,
+ };
+
+ data = dev_get_platdata(dev);
+ if (!data)
+ return -ENODEV;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->fw = dev_get_drvdata(dev->parent);
+ priv->read_tag = data->read_tag;
+ priv->write_tag = data->write_tag;
+ config.dev = dev;
+ config.priv = priv;
+ config.name = data->name;
+ config.size = data->size;
+ config.root_only = data->root_only;
+
+ nvmem = devm_nvmem_register(dev, &config);
+ if (IS_ERR(nvmem))
+ return dev_err_probe(dev, PTR_ERR(nvmem), "error registering nvmem config\n");
+
+ return 0;
+}
+
+static const struct platform_device_id raspberrypi_otp_id[] = {
+ { "raspberrypi-otp" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, raspberrypi_otp_id);
+
+static struct platform_driver raspberrypi_otp_driver = {
+ .probe = rpi_otp_probe,
+ .driver = {
+ .name = "raspberrypi-otp",
+ },
+ .id_table = raspberrypi_otp_id,
+};
+module_platform_driver(raspberrypi_otp_driver);
+
+MODULE_AUTHOR("Gregor Herburger <gregor.herburger@linutronix.de>");
+MODULE_DESCRIPTION("Raspberry Pi OTP driver");
+MODULE_LICENSE("GPL");
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index eb33838e0cd10..1e5e5f7e378d0 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -92,6 +92,8 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050,
RPI_FIRMWARE_NOTIFY_XHCI_RESET = 0x00030058,
RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066,
+ RPI_FIRMWARE_GET_PRIVATE_OTP = 0x00030081,
+ RPI_FIRMWARE_SET_PRIVATE_OTP = 0x00038081,
/* Dispmanx TAGS */
RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001,
@@ -174,6 +176,14 @@ struct rpi_firmware_clk_rate_request {
.id = cpu_to_le32(_id), \
}
+struct rpi_otp_driver_data {
+ const char *name;
+ u32 read_tag;
+ u32 write_tag;
+ int size;
+ bool root_only;
+};
+
#if IS_REACHABLE(CONFIG_RASPBERRYPI_FIRMWARE)
int rpi_firmware_property(struct rpi_firmware *fw,
u32 tag, void *data, size_t len);
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v6 04/10] nvmem: Add the Raspberry Pi OTP driver
2026-05-22 15:40 ` [PATCH v6 04/10] nvmem: Add the Raspberry Pi OTP driver Gregor Herburger
@ 2026-05-22 18:18 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-05-22 18:18 UTC (permalink / raw)
To: Gregor Herburger; +Cc: devicetree, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Potential FORTIFY_SOURCE out-of-bounds panic in `rpi_otp_read()` due to missing short-read validation.
- [High] `devm`-allocated private data is used-after-free if an external consumer holds a reference to the nvmem device after driver unbind.
- [Medium] Unconditional write support can lead to silent write failures on read-only OTP regions.
--
commit dcc1b143736646b08c117f369ca02e22f47c7ba5
Author: Gregor Herburger <gregor.herburger@linutronix.de>
nvmem: Add the Raspberry Pi OTP driver
Raspberry Pis have OTP registers which can be accessed through the
videocore firmware. Add a nvmem driver to support these OTP registers.
> diff --git a/drivers/nvmem/raspberrypi-otp.c b/drivers/nvmem/raspberrypi-otp.c
> new file mode 100644
> index 0000000000000..2e2537ee6793b
> --- /dev/null
> +++ b/drivers/nvmem/raspberrypi-otp.c
> @@ -0,0 +1,131 @@
[ ... ]
> +static int rpi_otp_read(void *context, unsigned int offset, void *buf, size_t bytes)
> +{
> + struct rpi_otp_priv *priv = context;
> + struct rpi_otp_header *fwbuf;
> + u32 count;
> + int ret;
> +
> + count = bytes / 4;
> +
> + fwbuf = kzalloc(struct_size(fwbuf, data, count), GFP_KERNEL);
> + if (!fwbuf)
> + return -ENOMEM;
> +
> + fwbuf->start = cpu_to_le32(offset / 4);
> + fwbuf->count = cpu_to_le32(count);
> +
> + ret = rpi_firmware_property(priv->fw, priv->read_tag, fwbuf,
> + sizeof(struct rpi_otp_header) + bytes);
> + if (ret)
> + goto out;
> +
> + memcpy(buf, fwbuf->data, bytes);
[Severity: High]
Can this trigger a FORTIFY_SOURCE out-of-bounds panic?
The struct rpi_otp_header uses the __counted_by_le(count) attribute for the
flexible data array. If the firmware returns a short read or encounters an
error, it updates the count field to the actual number of words returned.
If count is reduced by the firmware, does this memcpy attempt to copy the
original requested size (bytes), exceeding the dynamically evaluated bounds
of fwbuf->data?
> +
> +out:
> + kfree(fwbuf);
> + return ret;
> +}
[ ... ]
> +static int rpi_otp_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct nvmem_device *nvmem;
> + struct rpi_otp_priv *priv;
> + const struct rpi_otp_driver_data *data;
> + struct nvmem_config config = {
> + .read_only = false,
[Severity: Medium]
Will this allow silent write failures on read-only OTP regions?
If a region (like the device-specific private key OTP) is read-only and
lacks a valid write_tag in the platform data, write_tag will be 0. When
rpi_otp_write() sends tag 0 (which corresponds to RPI_FIRMWARE_PROPERTY_END)
to the firmware, it interprets this as an empty property list and returns
success without writing any data.
Should the read_only flag be set dynamically based on whether a valid
write_tag is provided?
> + .word_size = 4,
> + .stride = 4,
> + .reg_read = rpi_otp_read,
> + .reg_write = rpi_otp_write,
> + .id = NVMEM_DEVID_NONE,
> + };
> +
> + data = dev_get_platdata(dev);
> + if (!data)
> + return -ENODEV;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->fw = dev_get_drvdata(dev->parent);
> + priv->read_tag = data->read_tag;
> + priv->write_tag = data->write_tag;
> + config.dev = dev;
> + config.priv = priv;
> + config.name = data->name;
> + config.size = data->size;
> + config.root_only = data->root_only;
> +
> + nvmem = devm_nvmem_register(dev, &config);
[Severity: High]
Could this lead to a use-after-free if an external consumer holds a
reference to the nvmem device after the driver unbinds?
The driver allocates the priv context using devm_kzalloc() and registers the
nvmem provider via devm_nvmem_register(). During driver unbind, devres cleans
up in reverse order: nvmem_unregister() is called, which drops the internal
kref, and then the priv memory is freed.
If an in-kernel consumer has acquired the nvmem device (e.g., via
nvmem_device_get()), the refcount remains greater than zero and the nvmem
device stays alive after priv is freed. If the consumer subsequently calls a
read or write operation, will rpi_otp_read() or rpi_otp_write() dereference
the freed priv pointer?
> + if (IS_ERR(nvmem))
> + return dev_err_probe(dev, PTR_ERR(nvmem), "error registering nvmem config\n");
> +
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260522-rpi-otp-driver-v6-0-b0eac97d1428@linutronix.de?part=4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v6 05/10] firmware: raspberrypi: register nvmem driver
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
` (3 preceding siblings ...)
2026-05-22 15:40 ` [PATCH v6 04/10] nvmem: Add the Raspberry Pi OTP driver Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 06/10] arm64: dts: broadcom: bcm2712: add raspberrypi,bcm2712-firmware compatible Gregor Herburger
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
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@linutronix.de>
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
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 0aa322e9a2e73..1d3b8c190b2fd 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -24,12 +24,15 @@
static struct platform_device *rpi_hwmon;
static struct platform_device *rpi_clk;
+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;
};
@@ -231,6 +234,47 @@ static void rpi_register_clk_driver(struct device *dev)
-1, NULL, 0);
}
+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 =
@@ -299,12 +343,14 @@ 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);
rpi_firmware_print_firmware_revision(fw);
rpi_register_hwmon_driver(dev, fw);
rpi_register_clk_driver(dev);
+ rpi_register_otp_driver(dev);
return 0;
}
@@ -327,12 +373,23 @@ static void rpi_firmware_remove(struct platform_device *pdev)
rpi_hwmon = NULL;
platform_device_unregister(rpi_clk);
rpi_clk = 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 1e5e5f7e378d0..a4c94b85b7aa9 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
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v6 06/10] arm64: dts: broadcom: bcm2712: add raspberrypi,bcm2712-firmware compatible
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
` (4 preceding siblings ...)
2026-05-22 15:40 ` [PATCH v6 05/10] firmware: raspberrypi: register nvmem driver Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 07/10] dt-bindings: raspberrypi,bcm2835-firmware: Drop unnecessary select Gregor Herburger
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
The Raspberry Pi 5 (BCM2712) firmware exposes additional features such
as the additional OTP register region called 'private OTP'.
Add the raspberrypi,bcm2712-firmware compatible to allow drivers to
distinguish this hardware variant while keeping
raspberrypi,bcm2835-firmware as a fallback for backward compatibility
with existing drivers.
Reviewed-by: Stefan Wahren <wahrenst@gmx.net>
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-base.dtsi | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-base.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-base.dtsi
index b7a6bc34ae1ab..4aa8ec7601b84 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-base.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b-base.dtsi
@@ -46,7 +46,9 @@ power_button: power-button {
firmware {
firmware: rpi-firmware {
- compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
+ compatible = "raspberrypi,bcm2712-firmware",
+ "raspberrypi,bcm2835-firmware",
+ "simple-mfd";
mboxes = <&mailbox>;
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v6 07/10] dt-bindings: raspberrypi,bcm2835-firmware: Drop unnecessary select
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
` (5 preceding siblings ...)
2026-05-22 15:40 ` [PATCH v6 06/10] arm64: dts: broadcom: bcm2712: add raspberrypi,bcm2712-firmware compatible Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 08/10] arm64: defconfig: Enable the raspberrypi otp driver as module Gregor Herburger
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Conor Dooley, Gregor Herburger
The "select" in schema is not necessary anymore since dtschema drops
simple-mfd when constructing the select/filter query for schemas with
compatibles.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
.../bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
index a3a5243b91706..7cf9a6fa1e5be 100644
--- a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
+++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml
@@ -10,15 +10,6 @@ maintainers:
- Eric Anholt <eric@anholt.net>
- Stefan Wahren <wahrenst@gmx.net>
-select:
- properties:
- compatible:
- contains:
- const: raspberrypi,bcm2835-firmware
-
- required:
- - compatible
-
properties:
compatible:
oneOf:
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v6 08/10] arm64: defconfig: Enable the raspberrypi otp driver as module
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
` (6 preceding siblings ...)
2026-05-22 15:40 ` [PATCH v6 07/10] dt-bindings: raspberrypi,bcm2835-firmware: Drop unnecessary select Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 09/10] ARM: bcm2835_defconfig: " Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 10/10] ARM: multi_v7_defconfig: " Gregor Herburger
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
Enable the newly added Raspberry Pi OTP driver as module to allow access
to the otp registers. This driver provides access to the OTP registers
present on all Raspberry Pi boards and the private OTP registers present
on the Raspberry Pi 5.
Enabling this in the generic arm64 defconfig allows standard upstream
kernels to use these registers on Raspberry Pi 3, 4 and 5 out of the
box.
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index e44e83bc57812..3abb3ca34c708 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1849,6 +1849,7 @@ CONFIG_NVMEM_SPMI_SDAM=m
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_NVMEM_UNIPHIER_EFUSE=y
CONFIG_NVMEM_ZYNQMP=m
+CONFIG_NVMEM_RASPBERRYPI_OTP=m
CONFIG_FPGA=y
CONFIG_FPGA_MGR_ALTERA_CVP=m
CONFIG_FPGA_MGR_STRATIX10_SOC=m
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v6 09/10] ARM: bcm2835_defconfig: Enable the raspberrypi otp driver as module
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
` (7 preceding siblings ...)
2026-05-22 15:40 ` [PATCH v6 08/10] arm64: defconfig: Enable the raspberrypi otp driver as module Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
2026-05-22 15:40 ` [PATCH v6 10/10] ARM: multi_v7_defconfig: " Gregor Herburger
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
Enable the newly added Raspberry Pi OTP driver as module to allow access
to the otp registers. This driver provides access to the OTP registers
present on all Raspberry Pi boards.
Enabling this in the bcm2835 defconfig allows standard upstream kernels
to use these registers out of the box.
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
arch/arm/configs/bcm2835_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 4a8ac09843d73..fd83bda9cfaaf 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -151,6 +151,8 @@ CONFIG_BCM2835_MBOX=y
CONFIG_RASPBERRYPI_POWER=y
CONFIG_PWM=y
CONFIG_PWM_BCM2835=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_RASPBERRYPI_OTP=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v6 10/10] ARM: multi_v7_defconfig: Enable the raspberrypi otp driver as module
2026-05-22 15:40 [PATCH v6 00/10] nvmem: Add Raspberry Pi OTP nvmem driver Gregor Herburger
` (8 preceding siblings ...)
2026-05-22 15:40 ` [PATCH v6 09/10] ARM: bcm2835_defconfig: " Gregor Herburger
@ 2026-05-22 15:40 ` Gregor Herburger
9 siblings, 0 replies; 13+ messages in thread
From: Gregor Herburger @ 2026-05-22 15:40 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Eric Anholt, Stefan Wahren, Srinivas Kandagatla, Kees Cook,
Gustavo A. R. Silva, Thomas Weißschuh, Russell King
Cc: devicetree, linux-rpi-kernel, linux-arm-kernel, linux-kernel,
linux-hardening, Gregor Herburger
Enable the newly added Raspberry Pi OTP driver as module to allow access
to the otp registers. This driver provides access to the OTP registers
present on all Raspberry Pi boards.
Enabling this in the multi_v7_defconfg allows standard upstream kernels
to use these registers out of the box.
Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index bcc9aabc12028..4b61ad5f46ce7 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1281,6 +1281,7 @@ CONFIG_NVMEM_ROCKCHIP_EFUSE=m
CONFIG_NVMEM_STM32_ROMEM=m
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_NVMEM_VF610_OCOTP=y
+CONFIG_NVMEM_RASPBERRYPI_OTP=m
CONFIG_FSI=m
CONFIG_FSI_MASTER_GPIO=m
CONFIG_FSI_MASTER_HUB=m
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread