* [PATCH v4 0/3] Add STM32 TAMP nvram driver support
@ 2026-11-04 15:20 Patrice Chotard
2026-11-04 15:20 ` [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Patrice Chotard @ 2026-11-04 15:20 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla
Cc: Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel, Patrice Chotard, Gatien Chevallier
Propose bindings and driver to enable TAMP nvram driver
support for STM32MP SoC's family.
It allows to expose TAMP backup registers as nvmem cells.
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
---
Changes in v4:
- Make usage of of_device_get_match_data() wrapper.
- Rework ioremap of syscon's memory region to avoid overlapping
between parent and child node. This allows to remove
bkpregs_regmap_cfg declaration for both STM32MP1 and STM32MP2.
_ Add select MFD_SYSCON in Kconfig.
- Link to v3: https://patch.msgid.link/20261016-upstream_nvram_reworked-v3-0-f65908490cf7@foss.st.com
Changes in v3:
- Fix issue found by sashiko-bot:
- rely on the already resolved priv->data->nb_zones instead of
of_device_is_compatible() to set priv->bkpreg_access
- Fix max_register of stm32mp1_tamp_nvram_regmap_cfg and
stm32mp2_tamp_nvram_regmap_cfg
- Update zones_end type to int*
- Replace both memcpy by put_unaligned_le32 and get_unaligned_le32
- Link to v2: https://patch.msgid.link/20260930-upstream_nvram_reworked-v2-0-cfda749ee0b7@foss.st.com
Changes in v2:
- Update commit title of nvmem dt-bindings's patch.
- Add required compatible for patternProperties in stm32/st,stm32-syscon.yaml.
- Fix issue found by sashiko-bot:
- Add freeing compartment_owner.
- Replace regmap_read/regmap_write by regmap_update_bits in stm32_tamp_nvram_write_byte().
- Update error return in stm32_tamp_nvram_read_byte(), stm32_tamp_nvram_write_byte(),
stm32_tamp_nvram_read() and stm32_tamp_nvram_write() to return the actual regmap_read() /
regmap_write() error instead of -EIO.
- Add freeing field and update error return values for stm32_tamp_nvram_get_backup_zones().
- Update error return for stm32_tamp_nvram_probe().
- Link to v1: https://patch.msgid.link/20260910-upstream_nvram_reworked-v1-0-521c16175cef@foss.st.com
To: Simeon Marijon <simeon.marijon@foss.st.com>
To: Patrice Chotard <patrice.chotard@foss.st.com>
To: Srinivas Kandagatla <srini@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Maxime Coquelin <mcoquelin.stm32@gmail.com>
To: Alexandre Torgue <alexandre.torgue@foss.st.com>
To: Christophe Roullier <christophe.roullier@foss.st.com>
Cc: linux-stm32@st-md-mailman.stormreply.com
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
Patrice Chotard (1):
dt-bindings: arm: stm32: allow TAMP nvram child node for syscon
Simeon Marijon (2):
dt-bindings: nvmem: add STM32MPX TAMP backup registers
nvmem: stm32: add TAMP nvmem driver
.../bindings/arm/stm32/st,stm32-syscon.yaml | 38 +-
.../bindings/nvmem/st,stm32-tamp-nvram.yaml | 57 ++
MAINTAINERS | 8 +
drivers/nvmem/Kconfig | 11 +
drivers/nvmem/Makefile | 2 +
drivers/nvmem/stm32-tamp-nvram.c | 680 +++++++++++++++++++++
6 files changed, 793 insertions(+), 3 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20260909-upstream_nvram_reworked-f84a4b37817c
Best regards,
--
Patrice Chotard <patrice.chotard@foss.st.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers
2026-11-04 15:20 [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice Chotard
@ 2026-11-04 15:20 ` Patrice Chotard
2026-11-06 10:16 ` Krzysztof Kozlowski
2026-11-04 15:20 ` [PATCH v4 2/3] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Patrice Chotard @ 2026-11-04 15:20 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla
Cc: Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel, Patrice Chotard
From: Simeon Marijon <simeon.marijon@foss.st.com>
Adds the binding documentation for TAMP backup registers.
The backup registers is a part of the TAMP device of STM32 MPU.
Signed-off-by: Simeon Marijon <simeon.marijon@foss.st.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
---
.../bindings/nvmem/st,stm32-tamp-nvram.yaml | 57 ++++++++++++++++++++++
MAINTAINERS | 7 +++
2 files changed, 64 insertions(+)
diff --git a/Documentation/devicetree/bindings/nvmem/st,stm32-tamp-nvram.yaml b/Documentation/devicetree/bindings/nvmem/st,stm32-tamp-nvram.yaml
new file mode 100644
index 000000000000..4af3b88db566
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/st,stm32-tamp-nvram.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/st,stm32-tamp-nvram.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STM32 backup registers as NVMEM
+
+description: |
+ This represents STM32 backup registers area presented as nvmem cells.
+ This contains various information (e.g. boot mode passed to bootloaders).
+
+maintainers:
+ - Simeon Marijon <simeon.marijon@foss.st.com>
+ - Patrice Chotard <patrice.chotard@foss.st.com>
+
+allOf:
+ - $ref: nvmem.yaml#
+
+properties:
+ compatible:
+ enum:
+ - st,stm32mp15-tamp-nvram
+ - st,stm32mp25-tamp-nvram
+
+ reg:
+ description:
+ TAMP Registers bank location and size.
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ nvram: nvram@5c00a100 {
+ reg = <0x5c00a100 0x80>;
+ compatible = "st,stm32mp15-tamp-nvram";
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells */
+ wakeup_sec: tamp-bkp@0 {
+ reg = <0x0 0x4>;
+ };
+ boot_mode: tamp-bkp@50 {
+ /*see boot mode selection feature*/
+ reg = <0x50 0x4>;
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 93abbb315065..13f5c94b0bf8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26918,6 +26918,13 @@ F: Documentation/arch/arm/stm32/stm32-dma-mdma-chaining.rst
F: Documentation/devicetree/bindings/dma/stm32/
F: drivers/dma/stm32/
+STM32 TAMP DRIVERS
+M: Simeon Marijon <simeon.marijon@foss.st.com>
+M: Patrice Chotard <patrice.chotard@foss.st.com>
+L: linux-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/nvmem/st,stm32-tamp-nvram.yaml
+
STM32 TIMER/LPTIMER DRIVERS
M: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
S: Maintained
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 2/3] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon
2026-11-04 15:20 [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice Chotard
2026-11-04 15:20 ` [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard
@ 2026-11-04 15:20 ` Patrice Chotard
2026-11-06 10:21 ` Krzysztof Kozlowski
2026-11-04 15:20 ` [PATCH v4 3/3] nvmem: stm32: add TAMP nvmem driver Patrice Chotard
2026-11-05 11:39 ` [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice CHOTARD
3 siblings, 1 reply; 11+ messages in thread
From: Patrice Chotard @ 2026-11-04 15:20 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla
Cc: Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel, Patrice Chotard
The STM32 TAMP node (compatible "st,stm32-tamp", "syscon", "simple-mfd")
exposes its backup registers through an nvram child node described by
nvmem/st,stm32-tamp-nvram.yaml. That requires the TAMP node to carry
"#address-cells", "#size-cells", "ranges" and an "nvram@..." child.
st,stm32-syscon.yaml uses "additionalProperties: false" and only allowed
into the DTSI made "make dtbs_check" fail on every STM32MP TAMP node:
tamp@5c00a000 (st,stm32-tamp): 'nvram@5c00a100', 'ranges' do not match
any of the regexes: '^pinctrl-[0-9]+$'
Allow the addressing properties and the nvram child, gated on the
st,stm32-tamp compatible so the other syscon variants stay strict.
"#size-cells" may be 1 or 2: the STM32MP21 soc bus uses two size cells
(an empty "ranges" requires the node to match its parent) while the
other STM32MP SoCs use one.
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
---
.../bindings/arm/stm32/st,stm32-syscon.yaml | 38 ++++++++++++++++++++--
1 file changed, 35 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
index a559f8b03b84..51cb565e05ed 100644
--- a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
@@ -43,13 +43,19 @@ properties:
const: 1
"#size-cells":
- const: 1
+ enum: [1, 2]
+
+ ranges: true
patternProperties:
"^phy@2[48]00$":
type: object
$ref: /schemas/phy/st,stm32-usb2phy.yaml
+ "^nvram@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/nvmem/st,stm32-tamp-nvram.yaml
+
required:
- compatible
- reg
@@ -84,11 +90,37 @@ allOf:
- phy@2800
else:
properties:
- '#address-cells': false
'#clock-cells': false
- '#size-cells': false
phy@2400: false
phy@2800: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,stm32-tamp
+ then:
+ required:
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+ else:
+ properties:
+ ranges: false
+ patternProperties:
+ "^nvram@[0-9a-f]+$": false
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - st,stm32-tamp
+ - st,stm32mp23-syscfg
+ - st,stm32mp25-syscfg
+ then:
+ properties:
+ '#address-cells': false
+ '#size-cells': false
additionalProperties: false
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 3/3] nvmem: stm32: add TAMP nvmem driver
2026-11-04 15:20 [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice Chotard
2026-11-04 15:20 ` [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard
2026-11-04 15:20 ` [PATCH v4 2/3] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard
@ 2026-11-04 15:20 ` Patrice Chotard
2026-11-05 11:39 ` [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice CHOTARD
3 siblings, 0 replies; 11+ messages in thread
From: Patrice Chotard @ 2026-11-04 15:20 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla
Cc: Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel, Patrice Chotard, Gatien Chevallier
From: Simeon Marijon <simeon.marijon@foss.st.com>
TAMP backup registers will be exposed as nvmem cells.
Each registers ([0..127] for STM32MP2, [0..31] for STM32MP1) could be
exposed as nvmem cells under the nvram node in device tree.
Signed-off-by: Simeon Marijon <simeon.marijon@foss.st.com>
Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
---
MAINTAINERS | 1 +
drivers/nvmem/Kconfig | 11 +
drivers/nvmem/Makefile | 2 +
drivers/nvmem/stm32-tamp-nvram.c | 680 +++++++++++++++++++++++++++++++++++++++
4 files changed, 694 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 13f5c94b0bf8..eb7b9f746be6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26924,6 +26924,7 @@ M: Patrice Chotard <patrice.chotard@foss.st.com>
L: linux-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/nvmem/st,stm32-tamp-nvram.yaml
+F: drivers/nvmem/stm32-tamp-nvram.c
STM32 TIMER/LPTIMER DRIVERS
M: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index d2f5bb236663..a0675f89015c 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -516,6 +516,17 @@ config NVMEM_STM32_ROMEM
This driver can also be built as a module. If so, the module
will be called nvmem-stm32-romem.
+config NVMEM_STM32_TAMP
+ tristate "STMicroelectronics STM32 TAMP backup registers support"
+ depends on ARCH_STM32 || COMPILE_TEST
+ select MFD_SYSCON
+ help
+ Say y here to enable access for STMicroelectronics STM32
+ TAMP backup registers.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_stm32_tamp_nvram.
+
config NVMEM_SUNPLUS_OCOTP
tristate "Sunplus SoC OTP support"
depends on SOC_SP7021 || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 5e70bad9f0f9..73ec68e53556 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -88,6 +88,8 @@ nvmem_sprd_efuse-y := sprd-efuse.o
obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
nvmem_stm32_romem-y := stm32-romem.o
nvmem_stm32_romem-$(CONFIG_NVMEM_STM32_BSEC_OPTEE_TA) += stm32-bsec-optee-ta.o
+obj-$(CONFIG_NVMEM_STM32_TAMP) += nvmem_stm32_tamp_nvram.o
+nvmem_stm32_tamp_nvram-y := stm32-tamp-nvram.o
obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
nvmem_sunplus_ocotp-y := sunplus-ocotp.o
obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
diff --git a/drivers/nvmem/stm32-tamp-nvram.c b/drivers/nvmem/stm32-tamp-nvram.c
new file mode 100644
index 000000000000..81096a5d0282
--- /dev/null
+++ b/drivers/nvmem/stm32-tamp-nvram.c
@@ -0,0 +1,680 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STM32 Tamp backup registers access driver
+ *
+ * Copyright (C) 2026, STMicroelectronics - All Rights Reserved
+ * Author: Simeon Marijon <simeon.marijon@foss.st.com> for STMicroelectronics.
+ */
+
+#include <linux/align.h>
+#include <linux/bits.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+
+#define RIF_CID1 0x1
+#define CURRENT_CID RIF_CID1
+#define NB_ZONES_STM32MP1 3
+#define NB_ZONES_STM32MP2 7
+#define NB_REGS_STM32MP1 32
+#define NB_REGS_STM32MP2 128
+
+#define _TAMP_SECCFGR 0x20U
+#define _TAMP_BKPRIFR(x) (0x70U + 0x4U * ((x) - 1))
+#define _TAMP_RXCIDCFGR(x) (0x80U + 0x4U * ((x)))
+
+#define BKPREG_PROTECTION_ZONE_1 0
+#define BKPREG_PROTECTION_ZONE_2 1
+#define BKPREG_PROTECTION_ZONE_3 2
+
+#define BKPREG_PROTECTION_ZONE_1_RIF1 0
+#define BKPREG_PROTECTION_ZONE_1_RIF2 1
+#define BKPREG_PROTECTION_ZONE_2_RIF1 2
+#define BKPREG_PROTECTION_ZONE_2_RIF2 3
+#define BKPREG_PROTECTION_ZONE_3_RIF1 4
+#define BKPREG_PROTECTION_ZONE_3_RIF0 5
+#define BKPREG_PROTECTION_ZONE_3_RIF2 6
+#define NB_COMPARTMENT_STM32MP2 3
+
+enum stm32_tamp_bkpreg_access {
+ BKP_READ_WRITE,
+ BKP_READ,
+ BKP_NO
+};
+
+struct stm32_tamp_nvram_priv {
+ struct nvmem_config cfg;
+ const struct stm32_tamp_nvram_plat *data;
+ int *idx_bkpreg_zones_end;
+ struct device *dev;
+ struct regmap *config_regmap;
+ struct regmap *bkpregs_regmap;
+ unsigned int bkpregs_offset;
+ enum stm32_tamp_bkpreg_access *bkpreg_access;
+};
+
+struct stm32_tamp_nvram_plat {
+ const unsigned int nb_zones;
+ const unsigned int nb_regs;
+ const struct reg_field *config_reg_fields;
+};
+
+static const struct reg_field stm32mp1_tamp_nvram_zone_cfg_fields[NB_ZONES_STM32MP1 - 1] = {
+ [BKPREG_PROTECTION_ZONE_1] = REG_FIELD(_TAMP_SECCFGR, 0, 7),
+ [BKPREG_PROTECTION_ZONE_2] = REG_FIELD(_TAMP_SECCFGR, 16, 23),
+};
+
+static const struct reg_field stm32mp25_tamp_nvram_zone_cfg_fields[NB_ZONES_STM32MP2 - 1] = {
+ [BKPREG_PROTECTION_ZONE_1_RIF1] = REG_FIELD(_TAMP_BKPRIFR(1), 0, 7),
+ [BKPREG_PROTECTION_ZONE_1_RIF2] = REG_FIELD(_TAMP_SECCFGR, 0, 7),
+ [BKPREG_PROTECTION_ZONE_2_RIF1] = REG_FIELD(_TAMP_BKPRIFR(2), 0, 7),
+ [BKPREG_PROTECTION_ZONE_2_RIF2] = REG_FIELD(_TAMP_SECCFGR, 16, 23),
+ [BKPREG_PROTECTION_ZONE_3_RIF1] = REG_FIELD(_TAMP_BKPRIFR(3), 0, 7),
+ [BKPREG_PROTECTION_ZONE_3_RIF0] = REG_FIELD(_TAMP_BKPRIFR(3), 16, 23),
+};
+
+static const struct reg_field stm32mp25_tamp_nvram_rxcidcfg_cfen_fields[NB_COMPARTMENT_STM32MP2] = {
+ REG_FIELD(_TAMP_RXCIDCFGR(0), 0, 0),
+ REG_FIELD(_TAMP_RXCIDCFGR(1), 0, 0),
+ REG_FIELD(_TAMP_RXCIDCFGR(2), 0, 0),
+};
+
+static const struct reg_field stm32mp25_tamp_nvram_rxcidcfg_fields[NB_COMPARTMENT_STM32MP2] = {
+ REG_FIELD(_TAMP_RXCIDCFGR(0), 4, 6),
+ REG_FIELD(_TAMP_RXCIDCFGR(1), 4, 6),
+ REG_FIELD(_TAMP_RXCIDCFGR(2), 4, 6),
+};
+
+static enum stm32_tamp_bkpreg_access stm32mp1_tamp_bkpreg_access[NB_ZONES_STM32MP1] = {
+ [BKPREG_PROTECTION_ZONE_1] = BKP_NO,
+ [BKPREG_PROTECTION_ZONE_2] = BKP_READ,
+ [BKPREG_PROTECTION_ZONE_3] = BKP_READ_WRITE,
+};
+
+static int stm32_tamp_is_compartment_isolation_enabled_mp2x(struct stm32_tamp_nvram_priv *priv)
+{
+ int nb_compartment_enabled = 0;
+ struct device *dev = priv->dev;
+ u32 cfen;
+ struct regmap_field *cfen_field;
+
+ for (int i = 0; i < NB_COMPARTMENT_STM32MP2; i++) {
+ cfen_field = devm_regmap_field_alloc(dev,
+ priv->config_regmap,
+ stm32mp25_tamp_nvram_rxcidcfg_cfen_fields[i]);
+ if (IS_ERR(cfen_field)) {
+ dev_err(dev, "Can't allocate field for reading configuration\n");
+ return PTR_ERR(cfen_field);
+ }
+
+ if (regmap_field_read(cfen_field, &cfen)) {
+ dev_err(dev, "Can't read field for registers zones\n");
+ devm_regmap_field_free(dev, cfen_field);
+ return -EINVAL;
+ }
+
+ nb_compartment_enabled += cfen;
+ devm_regmap_field_free(dev, cfen_field);
+ }
+
+ if (!nb_compartment_enabled)
+ return 0;
+ else if (nb_compartment_enabled == NB_COMPARTMENT_STM32MP2)
+ return 1;
+ else
+ return -EINVAL;
+}
+
+static bool *stm32_tamp_get_compartment_owner_mp2x(struct stm32_tamp_nvram_priv *priv)
+{
+ struct device *dev = priv->dev;
+ struct regmap_field *cid_field;
+ u32 cid_per_zone;
+ int isolation_enabled;
+ bool *compartment_owner;
+
+ isolation_enabled = stm32_tamp_is_compartment_isolation_enabled_mp2x(priv);
+ if (isolation_enabled < 0)
+ return ERR_PTR(-EINVAL);
+
+ compartment_owner = kcalloc(NB_COMPARTMENT_STM32MP2,
+ sizeof(*compartment_owner),
+ GFP_KERNEL);
+
+ if (!compartment_owner)
+ return ERR_PTR(-ENOMEM);
+
+ for (int i = 0; i < NB_COMPARTMENT_STM32MP2; i++) {
+ if (isolation_enabled) {
+ cid_field = devm_regmap_field_alloc(dev,
+ priv->config_regmap,
+ stm32mp25_tamp_nvram_rxcidcfg_fields[i]
+ );
+ if (IS_ERR(cid_field)) {
+ kfree(compartment_owner);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ if (regmap_field_read(cid_field, &cid_per_zone)) {
+ dev_err(dev, "Can't read field for registers zones\n");
+ devm_regmap_field_free(dev, cid_field);
+ kfree(compartment_owner);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (cid_per_zone == CURRENT_CID)
+ compartment_owner[i] = true;
+ else
+ compartment_owner[i] = false;
+
+ devm_regmap_field_free(dev, cid_field);
+ } else {
+ compartment_owner[i] = true;
+ }
+ }
+
+ return compartment_owner;
+}
+
+static enum stm32_tamp_bkpreg_access *stm32_tamp_get_access_rights_mp2x(struct stm32_tamp_nvram_priv
+ *priv)
+{
+ struct device *dev = priv->dev;
+ unsigned int nb_zones = priv->data->nb_zones;
+ bool *compartment_owner;
+ enum stm32_tamp_bkpreg_access *bkpreg_access;
+
+ compartment_owner = stm32_tamp_get_compartment_owner_mp2x(priv);
+ if (IS_ERR(compartment_owner))
+ return ERR_PTR(-ENODEV);
+
+ bkpreg_access = devm_kcalloc(dev,
+ NB_ZONES_STM32MP2,
+ sizeof(*bkpreg_access),
+ GFP_KERNEL);
+
+ if (!bkpreg_access) {
+ kfree(compartment_owner);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for (int protection_zone_idx = 0; protection_zone_idx < nb_zones;
+ protection_zone_idx++) {
+ switch (protection_zone_idx) {
+ case BKPREG_PROTECTION_ZONE_1_RIF1:
+ bkpreg_access[protection_zone_idx] = BKP_NO;
+ break;
+ case BKPREG_PROTECTION_ZONE_1_RIF2:
+ bkpreg_access[protection_zone_idx] = BKP_NO;
+ break;
+ case BKPREG_PROTECTION_ZONE_2_RIF1:
+ if (compartment_owner[1] || compartment_owner[2])
+ bkpreg_access[protection_zone_idx] = BKP_READ;
+ else
+ bkpreg_access[protection_zone_idx] = BKP_NO;
+ break;
+ case BKPREG_PROTECTION_ZONE_2_RIF2:
+ if (compartment_owner[1] || compartment_owner[2])
+ bkpreg_access[protection_zone_idx] = BKP_READ;
+ else
+ bkpreg_access[protection_zone_idx] = BKP_NO;
+ break;
+ case BKPREG_PROTECTION_ZONE_3_RIF1:
+ if (compartment_owner[1])
+ bkpreg_access[protection_zone_idx] = BKP_READ_WRITE;
+ else if (compartment_owner[0] || compartment_owner[2])
+ bkpreg_access[protection_zone_idx] = BKP_READ;
+ else
+ bkpreg_access[protection_zone_idx] = BKP_NO;
+ break;
+ case BKPREG_PROTECTION_ZONE_3_RIF0:
+ if (compartment_owner[0])
+ bkpreg_access[protection_zone_idx] = BKP_READ_WRITE;
+ else if (compartment_owner[1] || compartment_owner[2])
+ bkpreg_access[protection_zone_idx] = BKP_READ;
+ else
+ bkpreg_access[protection_zone_idx] = BKP_NO;
+ break;
+ case BKPREG_PROTECTION_ZONE_3_RIF2:
+ if (compartment_owner[2])
+ bkpreg_access[protection_zone_idx] = BKP_READ_WRITE;
+ else if (compartment_owner[0] || compartment_owner[1])
+ bkpreg_access[protection_zone_idx] = BKP_READ;
+ else
+ bkpreg_access[protection_zone_idx] = BKP_NO;
+ break;
+ default:
+ devm_kfree(dev, bkpreg_access);
+ kfree(compartment_owner);
+ return ERR_PTR(-ENODEV);
+ }
+ }
+
+ kfree(compartment_owner);
+
+ return bkpreg_access;
+}
+
+static int stm32_tamp_nvram_bkpreg_get_zone(struct stm32_tamp_nvram_priv *priv, int reg)
+{
+ int *idx_bkpreg_zones_end = priv->idx_bkpreg_zones_end;
+ int nb_zones = priv->data->nb_zones;
+ int protection_zone_idx;
+
+ if (reg < 0)
+ return -1; /* negative reg is the boundary of an empty zone */
+
+ for (protection_zone_idx = 0; protection_zone_idx < nb_zones; protection_zone_idx++) {
+ if (reg <= idx_bkpreg_zones_end[protection_zone_idx])
+ break;
+ }
+
+ if (protection_zone_idx >= nb_zones)
+ return -1; /* the reg is not a part of any zone */
+
+ return protection_zone_idx;
+}
+
+static bool stm32_tamp_nvram_rights(struct stm32_tamp_nvram_priv *priv, int reg, bool read_only)
+{
+ struct device *dev = priv->dev;
+ int protection_zone_idx = stm32_tamp_nvram_bkpreg_get_zone(priv, reg);
+
+ if (protection_zone_idx < 0)
+ return false;
+
+ switch (priv->bkpreg_access[protection_zone_idx]) {
+ case BKP_READ_WRITE:
+ return true;
+ case BKP_READ:
+ return read_only;
+ case BKP_NO:
+ return false;
+ default:
+ dev_err(dev, "Can't get access rights for the zone\n");
+ return false;
+ }
+
+ return false;
+}
+
+static const struct stm32_tamp_nvram_plat stm32mp1_tamp_nvram = {
+ .nb_zones = NB_ZONES_STM32MP1,
+ .nb_regs = NB_REGS_STM32MP1,
+ .config_reg_fields = stm32mp1_tamp_nvram_zone_cfg_fields,
+};
+
+static const struct stm32_tamp_nvram_plat stm32mp25_tamp_nvram = {
+ .nb_zones = NB_ZONES_STM32MP2,
+ .nb_regs = NB_REGS_STM32MP2,
+ .config_reg_fields = stm32mp25_tamp_nvram_zone_cfg_fields,
+};
+
+static int stm32_tamp_nvram_write_byte(struct stm32_tamp_nvram_priv *priv, u32 offset, u8 byte)
+{
+ int offset_aligned = ALIGN_DOWN(offset, sizeof(u32));
+ unsigned int shift = (offset - offset_aligned) * 8;
+ u32 reg_idx = offset_aligned / sizeof(u32);
+
+ if (!stm32_tamp_nvram_rights(priv, reg_idx, false))
+ return -EACCES;
+
+ return regmap_update_bits(priv->bkpregs_regmap, priv->bkpregs_offset + offset_aligned,
+ 0xFFUL << shift, (u32)byte << shift);
+}
+
+static int stm32_tamp_nvram_read_byte(struct stm32_tamp_nvram_priv *priv, u32 offset, u8 *byte)
+{
+ int offset_aligned = ALIGN_DOWN(offset, sizeof(u32));
+ int byte_in_word = offset - offset_aligned;
+ u32 read_value;
+ u32 reg_idx = offset_aligned / sizeof(u32);
+ int ret;
+
+ if (!stm32_tamp_nvram_rights(priv, reg_idx, true))
+ return -EACCES;
+
+ ret = regmap_read(priv->bkpregs_regmap, priv->bkpregs_offset + offset_aligned,
+ &read_value);
+ if (ret)
+ return ret;
+
+ *byte = (read_value >> (byte_in_word * 8)) & 0xFF;
+
+ return 0;
+}
+
+static int stm32_tamp_nvram_read(void *context, unsigned int offset, void *buf, size_t bytes)
+{
+ struct stm32_tamp_nvram_priv *priv = context;
+ struct device *dev = priv->dev;
+ u32 temp_u32;
+ u32 reg_idx;
+ int i, ret;
+ size_t total = offset + bytes;
+ u8 byte;
+ u8 *buf_u8 = buf;
+
+ i = offset;
+ while (i < total) {
+ reg_idx = i / sizeof(u32);
+ if (i + sizeof(u32) <= total && IS_ALIGNED(i, sizeof(u32))) {
+ if (!stm32_tamp_nvram_rights(priv, reg_idx, true)) {
+ dev_dbg(dev, "Backup register %u is not allowed to be read\n",
+ reg_idx);
+ temp_u32 = 0;
+ } else {
+ ret = regmap_read(priv->bkpregs_regmap,
+ priv->bkpregs_offset + i, &temp_u32);
+ if (ret)
+ return ret;
+ }
+ put_unaligned_le32(temp_u32, buf_u8);
+ buf_u8 += sizeof(u32);
+ i += sizeof(u32);
+ } else {
+ ret = stm32_tamp_nvram_read_byte(priv, i, &byte);
+ if (ret == -EACCES) {
+ dev_dbg(dev, "Backup register %u is not allowed to be read\n",
+ reg_idx);
+ byte = 0;
+ } else if (ret) {
+ return ret;
+ }
+
+ *buf_u8 = byte;
+ i++;
+ buf_u8++;
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_tamp_nvram_write(void *context, unsigned int offset, void *buf, size_t bytes)
+{
+ struct stm32_tamp_nvram_priv *priv = context;
+ struct device *dev = priv->dev;
+ u32 temp_u32;
+ u32 reg_idx;
+ int i, ret;
+ size_t total = offset + bytes;
+ u8 *buf_u8 = (u8 *)buf;
+
+ i = offset;
+ while (i < total) {
+ reg_idx = i / sizeof(u32);
+ if (i + sizeof(u32) <= total && IS_ALIGNED(i, sizeof(u32))) {
+ if (stm32_tamp_nvram_rights(priv, reg_idx, false)) {
+ temp_u32 = get_unaligned_le32(buf_u8);
+ ret = regmap_write(priv->bkpregs_regmap,
+ priv->bkpregs_offset + i, temp_u32);
+ if (ret)
+ return ret;
+ } else {
+ dev_dbg(dev, "Backup register %u is not allowed to be written\n",
+ reg_idx);
+ }
+ buf_u8 += sizeof(u32);
+ i += sizeof(u32);
+ } else {
+ ret = stm32_tamp_nvram_write_byte(priv, i, *buf_u8);
+ if (ret == -EACCES) {
+ dev_dbg(dev, "Backup register %u is not allowed to be written\n",
+ reg_idx);
+ } else if (ret) {
+ return ret;
+ }
+
+ i++;
+ buf_u8++;
+ }
+ }
+
+ return 0;
+}
+
+static int *stm32_tamp_nvram_get_backup_zones(struct stm32_tamp_nvram_priv *priv)
+{
+ struct device *dev = priv->dev;
+ struct regmap *tamp_regmap = priv->config_regmap;
+ u32 offset_field;
+ int nb_zones = priv->data->nb_zones;
+ int zone_idx;
+ int *idx_bkpreg_zones_end;
+
+ idx_bkpreg_zones_end = devm_kcalloc(dev,
+ nb_zones,
+ sizeof(*idx_bkpreg_zones_end),
+ GFP_KERNEL);
+ if (!idx_bkpreg_zones_end) {
+ dev_err(dev, "Can't allocate registers zones\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Get the n-1 frontiers of zone within the tamp configuration registers */
+ for (zone_idx = 0; zone_idx < nb_zones - 1; zone_idx++) {
+ const struct reg_field reg_field = priv->data->config_reg_fields[zone_idx];
+ struct regmap_field *field;
+ int ret;
+
+ field = devm_regmap_field_alloc(dev, tamp_regmap, reg_field);
+ if (IS_ERR(field)) {
+ dev_err(dev, "Can't allocate registers zones\n");
+ devm_kfree(dev, idx_bkpreg_zones_end);
+ return ERR_CAST(field);
+ }
+
+ ret = regmap_field_read(field, &offset_field);
+ devm_regmap_field_free(dev, field);
+ if (ret) {
+ dev_err(dev, "Can't read field for registers zones\n");
+ devm_kfree(dev, idx_bkpreg_zones_end);
+ return ERR_PTR(ret);
+ }
+
+ idx_bkpreg_zones_end[zone_idx] = offset_field - 1;
+ }
+
+ /* The last zone end is defined by the number of registers in TAMP */
+ idx_bkpreg_zones_end[zone_idx] = priv->data->nb_regs - 1;
+
+ return idx_bkpreg_zones_end;
+}
+
+static const struct of_device_id stm32_tamp_nvram_of_match[] = {
+ { .compatible = "st,stm32mp15-tamp-nvram",
+ .data = &stm32mp1_tamp_nvram },
+ { .compatible = "st,stm32mp25-tamp-nvram",
+ .data = &stm32mp25_tamp_nvram },
+ {},
+};
+
+static int stm32_tamp_nvram_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct stm32_tamp_nvram_priv *priv;
+ struct resource *res, parent_res;
+ int *zones_end;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = &pdev->dev;
+ priv->data = of_device_get_match_data(dev);
+ if (!priv->data) {
+ dev_err(dev, "Can't get platform data of the node\n");
+ return -ENODEV;
+ }
+
+ priv->config_regmap = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(priv->config_regmap))
+ return dev_err_probe(dev, PTR_ERR(priv->config_regmap),
+ "Can't get TAMP syscon regmap\n");
+
+ priv->idx_bkpreg_zones_end = stm32_tamp_nvram_get_backup_zones(priv);
+ if (IS_ERR(priv->idx_bkpreg_zones_end))
+ return dev_err_probe(dev, PTR_ERR(priv->idx_bkpreg_zones_end),
+ "Can't determine protection zone\n");
+
+ zones_end = priv->idx_bkpreg_zones_end;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ dev_err(dev, "Can't get resource\n");
+ return -ENODEV;
+ }
+
+ /*
+ * The backup registers belong to the parent TAMP syscon, which other
+ * drivers (e.g. remoteproc) also access: go through the syscon regmap
+ * so that all accesses are serialized by the same lock.
+ */
+ if (of_address_to_resource(dev->parent->of_node, 0, &parent_res) ||
+ !resource_contains(&parent_res, res))
+ return dev_err_probe(dev, -EINVAL,
+ "Backup registers not within TAMP parent range\n");
+
+ priv->bkpregs_regmap = priv->config_regmap;
+ priv->bkpregs_offset = res->start - parent_res.start;
+
+ priv->cfg.name = "stm32-tamp-nvram";
+ priv->cfg.word_size = 1;
+ priv->cfg.stride = 1;
+ priv->cfg.dev = dev;
+ priv->cfg.priv = priv;
+ priv->cfg.owner = THIS_MODULE;
+ priv->cfg.type = NVMEM_TYPE_BATTERY_BACKED;
+ priv->cfg.size = resource_size(res);
+ priv->cfg.reg_read = stm32_tamp_nvram_read;
+ priv->cfg.reg_write = stm32_tamp_nvram_write;
+
+ if (priv->data->nb_zones == NB_ZONES_STM32MP2) {
+ priv->bkpreg_access = stm32_tamp_get_access_rights_mp2x(priv);
+
+ if (IS_ERR(priv->bkpreg_access))
+ return PTR_ERR(priv->bkpreg_access);
+
+ dev_dbg(dev, "\n"
+ "Zone 1-RIF1 %3d - %3d %c%c\n"
+ "Zone 1-RIF2 %3d - %3d %c%c\n"
+ "Zone 2-RIF1 %3d - %3d %c%c\n"
+ "Zone 2-RIF2 %3d - %3d %c%c\n"
+ "Zone 3-RIF1 %3d - %3d %c%c\n"
+ "Zone 3-RIF0 %3d - %3d %c%c\n"
+ "Zone 3-RIF2 %3d - %3d %c%c\n",
+ 0,
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF1],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF1],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF1],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF1] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF2],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF2],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF2],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_1_RIF2] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF1],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF1],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF1],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF1] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF2],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF2],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF2],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_2_RIF2] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF1],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF1],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF1],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF1] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF0],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF0],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF0],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF0] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF2],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF2],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3_RIF2],
+ false) ? 'W' : '-'
+ );
+ } else if (priv->data->nb_zones == NB_ZONES_STM32MP1) {
+ priv->bkpreg_access = stm32mp1_tamp_bkpreg_access;
+
+ dev_dbg(dev, "\n"
+ "Zone 1 %3d - %3d %c%c\n"
+ "Zone 2 %3d - %3d %c%c\n"
+ "Zone 3 %3d - %3d %c%c\n",
+ 0,
+ zones_end[BKPREG_PROTECTION_ZONE_1],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_1],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_1],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_1] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_2],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_2],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_2],
+ false) ? 'W' : '-',
+ zones_end[BKPREG_PROTECTION_ZONE_2] + 1,
+ zones_end[BKPREG_PROTECTION_ZONE_3],
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3],
+ true) ? 'R' : '-',
+ stm32_tamp_nvram_rights(priv,
+ zones_end[BKPREG_PROTECTION_ZONE_3],
+ false) ? 'W' : '-');
+ }
+
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &priv->cfg));
+}
+
+MODULE_DEVICE_TABLE(of, stm32_tamp_nvram_of_match);
+
+static struct platform_driver stm32_tamp_nvram_driver = {
+ .probe = stm32_tamp_nvram_probe,
+ .driver = {
+ .name = "stm32-tamp-nvram",
+ .of_match_table = stm32_tamp_nvram_of_match,
+ },
+};
+
+module_platform_driver(stm32_tamp_nvram_driver)
+MODULE_AUTHOR("Simeon Marijon <simeon.marijon@foss.st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 NVMEM TAMP Backup registers");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 0/3] Add STM32 TAMP nvram driver support
2026-11-04 15:20 [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice Chotard
` (2 preceding siblings ...)
2026-11-04 15:20 ` [PATCH v4 3/3] nvmem: stm32: add TAMP nvmem driver Patrice Chotard
@ 2026-11-05 11:39 ` Patrice CHOTARD
3 siblings, 0 replies; 11+ messages in thread
From: Patrice CHOTARD @ 2026-11-05 11:39 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla
Cc: Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel, Gatien Chevallier
Don't take care of this series, a new one is on-going which will include https://patchwork.kernel.org/series/1176665/
On 11/4/26 16:20, Patrice Chotard wrote:
> Propose bindings and driver to enable TAMP nvram driver
> support for STM32MP SoC's family.
> It allows to expose TAMP backup registers as nvmem cells.
>
> Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
> ---
> Changes in v4:
> - Make usage of of_device_get_match_data() wrapper.
> - Rework ioremap of syscon's memory region to avoid overlapping
> between parent and child node. This allows to remove
> bkpregs_regmap_cfg declaration for both STM32MP1 and STM32MP2.
> _ Add select MFD_SYSCON in Kconfig.
> - Link to v3: https://patch.msgid.link/20261016-upstream_nvram_reworked-v3-0-f65908490cf7@foss.st.com
>
> Changes in v3:
> - Fix issue found by sashiko-bot:
> - rely on the already resolved priv->data->nb_zones instead of
> of_device_is_compatible() to set priv->bkpreg_access
> - Fix max_register of stm32mp1_tamp_nvram_regmap_cfg and
> stm32mp2_tamp_nvram_regmap_cfg
> - Update zones_end type to int*
> - Replace both memcpy by put_unaligned_le32 and get_unaligned_le32
> - Link to v2: https://patch.msgid.link/20260930-upstream_nvram_reworked-v2-0-cfda749ee0b7@foss.st.com
>
> Changes in v2:
> - Update commit title of nvmem dt-bindings's patch.
> - Add required compatible for patternProperties in stm32/st,stm32-syscon.yaml.
> - Fix issue found by sashiko-bot:
> - Add freeing compartment_owner.
> - Replace regmap_read/regmap_write by regmap_update_bits in stm32_tamp_nvram_write_byte().
> - Update error return in stm32_tamp_nvram_read_byte(), stm32_tamp_nvram_write_byte(),
> stm32_tamp_nvram_read() and stm32_tamp_nvram_write() to return the actual regmap_read() /
> regmap_write() error instead of -EIO.
> - Add freeing field and update error return values for stm32_tamp_nvram_get_backup_zones().
> - Update error return for stm32_tamp_nvram_probe().
> - Link to v1: https://patch.msgid.link/20260910-upstream_nvram_reworked-v1-0-521c16175cef@foss.st.com
>
> To: Simeon Marijon <simeon.marijon@foss.st.com>
> To: Patrice Chotard <patrice.chotard@foss.st.com>
> To: Srinivas Kandagatla <srini@kernel.org>
> To: Rob Herring <robh@kernel.org>
> To: Krzysztof Kozlowski <krzk+dt@kernel.org>
> To: Conor Dooley <conor+dt@kernel.org>
> To: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> To: Alexandre Torgue <alexandre.torgue@foss.st.com>
> To: Christophe Roullier <christophe.roullier@foss.st.com>
> Cc: linux-stm32@st-md-mailman.stormreply.com
> Cc: devicetree@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
>
> ---
> Patrice Chotard (1):
> dt-bindings: arm: stm32: allow TAMP nvram child node for syscon
>
> Simeon Marijon (2):
> dt-bindings: nvmem: add STM32MPX TAMP backup registers
> nvmem: stm32: add TAMP nvmem driver
>
> .../bindings/arm/stm32/st,stm32-syscon.yaml | 38 +-
> .../bindings/nvmem/st,stm32-tamp-nvram.yaml | 57 ++
> MAINTAINERS | 8 +
> drivers/nvmem/Kconfig | 11 +
> drivers/nvmem/Makefile | 2 +
> drivers/nvmem/stm32-tamp-nvram.c | 680 +++++++++++++++++++++
> 6 files changed, 793 insertions(+), 3 deletions(-)
> ---
> base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
> change-id: 20260909-upstream_nvram_reworked-f84a4b37817c
>
> Best regards,
> --
> Patrice Chotard <patrice.chotard@foss.st.com>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers
2026-11-04 15:20 ` [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard
@ 2026-11-06 10:16 ` Krzysztof Kozlowski
2026-11-06 10:33 ` Patrice CHOTARD
0 siblings, 1 reply; 11+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-06 10:16 UTC (permalink / raw)
To: Patrice Chotard
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla,
Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel
On Wed, Nov 04, 2026 at 04:20:08PM +0100, Patrice Chotard wrote:
> + nvmem-layout {
> + compatible = "fixed-layout";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + /* Data cells */
> + wakeup_sec: tamp-bkp@0 {
> + reg = <0x0 0x4>;
> + };
> + boot_mode: tamp-bkp@50 {
> + /*see boot mode selection feature*/
> + reg = <0x50 0x4>;
Mixed up indentation. Please also run scripts/dtc/dt-check-style and fix
obvious issues.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 2/3] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon
2026-11-04 15:20 ` [PATCH v4 2/3] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard
@ 2026-11-06 10:21 ` Krzysztof Kozlowski
2026-11-06 10:46 ` Patrice CHOTARD
0 siblings, 1 reply; 11+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-06 10:21 UTC (permalink / raw)
To: Patrice Chotard
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla,
Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel
On Wed, Nov 04, 2026 at 04:20:09PM +0100, Patrice Chotard wrote:
> The STM32 TAMP node (compatible "st,stm32-tamp", "syscon", "simple-mfd")
> exposes its backup registers through an nvram child node described by
> nvmem/st,stm32-tamp-nvram.yaml. That requires the TAMP node to carry
> "#address-cells", "#size-cells", "ranges" and an "nvram@..." child.
>
> st,stm32-syscon.yaml uses "additionalProperties: false" and only allowed
> into the DTSI made "make dtbs_check" fail on every STM32MP TAMP node:
>
> tamp@5c00a000 (st,stm32-tamp): 'nvram@5c00a100', 'ranges' do not match
> any of the regexes: '^pinctrl-[0-9]+$'
>
> Allow the addressing properties and the nvram child, gated on the
> st,stm32-tamp compatible so the other syscon variants stay strict.
> "#size-cells" may be 1 or 2: the STM32MP21 soc bus uses two size cells
> (an empty "ranges" requires the node to match its parent) while the
> other STM32MP SoCs use one.
>
> Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
> ---
> .../bindings/arm/stm32/st,stm32-syscon.yaml | 38 ++++++++++++++++++++--
> 1 file changed, 35 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
> index a559f8b03b84..51cb565e05ed 100644
> --- a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
> +++ b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
> @@ -43,13 +43,19 @@ properties:
> const: 1
>
> "#size-cells":
> - const: 1
> + enum: [1, 2]
> +
> + ranges: true
Addition of ranges should be separate commit, because you are fixing
existing device which can have phy child.
>
> patternProperties:
> "^phy@2[48]00$":
> type: object
> $ref: /schemas/phy/st,stm32-usb2phy.yaml
>
> + "^nvram@[0-9a-f]+$":
> + type: object
> + $ref: /schemas/nvmem/st,stm32-tamp-nvram.yaml
> +
> required:
> - compatible
> - reg
> @@ -84,11 +90,37 @@ allOf:
> - phy@2800
> else:
> properties:
> - '#address-cells': false
> '#clock-cells': false
> - '#size-cells': false
> phy@2400: false
> phy@2800: false
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: st,stm32-tamp
> + then:
> + required:
> + - "#address-cells"
> + - "#size-cells"
> + - ranges
This has ABI impact and is not really necessary, as the child node is
not required either. Drop these three.
> + else:
> + properties:
> + ranges: false
> + patternProperties:
> + "^nvram@[0-9a-f]+$": false
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers
2026-11-06 10:16 ` Krzysztof Kozlowski
@ 2026-11-06 10:33 ` Patrice CHOTARD
2026-11-06 11:00 ` Krzysztof Kozlowski
0 siblings, 1 reply; 11+ messages in thread
From: Patrice CHOTARD @ 2026-11-06 10:33 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla,
Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel
On 11/6/26 11:16, Krzysztof Kozlowski wrote:
> On Wed, Nov 04, 2026 at 04:20:08PM +0100, Patrice Chotard wrote:
>> + nvmem-layout {
>> + compatible = "fixed-layout";
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> +
>> + /* Data cells */
>> + wakeup_sec: tamp-bkp@0 {
>> + reg = <0x0 0x4>;
>> + };
>> + boot_mode: tamp-bkp@50 {
>> + /*see boot mode selection feature*/
>> + reg = <0x50 0x4>;
>
> Mixed up indentation. Please also run scripts/dtc/dt-check-style and fix
> obvious issues.
Hi Krzysztof
scripts/dtc/dt-check-style doesn't return any errors.
Patrice
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 2/3] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon
2026-11-06 10:21 ` Krzysztof Kozlowski
@ 2026-11-06 10:46 ` Patrice CHOTARD
0 siblings, 0 replies; 11+ messages in thread
From: Patrice CHOTARD @ 2026-11-06 10:46 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla,
Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel
On 11/6/26 11:21, Krzysztof Kozlowski wrote:
> On Wed, Nov 04, 2026 at 04:20:09PM +0100, Patrice Chotard wrote:
>> The STM32 TAMP node (compatible "st,stm32-tamp", "syscon", "simple-mfd")
>> exposes its backup registers through an nvram child node described by
>> nvmem/st,stm32-tamp-nvram.yaml. That requires the TAMP node to carry
>> "#address-cells", "#size-cells", "ranges" and an "nvram@..." child.
>>
>> st,stm32-syscon.yaml uses "additionalProperties: false" and only allowed
>> into the DTSI made "make dtbs_check" fail on every STM32MP TAMP node:
>>
>> tamp@5c00a000 (st,stm32-tamp): 'nvram@5c00a100', 'ranges' do not match
>> any of the regexes: '^pinctrl-[0-9]+$'
>>
>> Allow the addressing properties and the nvram child, gated on the
>> st,stm32-tamp compatible so the other syscon variants stay strict.
>> "#size-cells" may be 1 or 2: the STM32MP21 soc bus uses two size cells
>> (an empty "ranges" requires the node to match its parent) while the
>> other STM32MP SoCs use one.
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
>> ---
>> .../bindings/arm/stm32/st,stm32-syscon.yaml | 38 ++++++++++++++++++++--
>> 1 file changed, 35 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
>> index a559f8b03b84..51cb565e05ed 100644
>> --- a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
>> +++ b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
>> @@ -43,13 +43,19 @@ properties:
>> const: 1
>>
>> "#size-cells":
>> - const: 1
>> + enum: [1, 2]
>> +
>> + ranges: true
>
> Addition of ranges should be separate commit, because you are fixing
> existing device which can have phy child.
>
>>
>> patternProperties:
>> "^phy@2[48]00$":
>> type: object
>> $ref: /schemas/phy/st,stm32-usb2phy.yaml
>>
>> + "^nvram@[0-9a-f]+$":
>> + type: object
>> + $ref: /schemas/nvmem/st,stm32-tamp-nvram.yaml
>> +
>> required:
>> - compatible
>> - reg
>> @@ -84,11 +90,37 @@ allOf:
>> - phy@2800
>> else:
>> properties:
>> - '#address-cells': false
>> '#clock-cells': false
>> - '#size-cells': false
>> phy@2400: false
>> phy@2800: false
>> + - if:
>> + properties:
>> + compatible:
>> + contains:
>> + const: st,stm32-tamp
>> + then:
>> + required:
>> + - "#address-cells"
>> + - "#size-cells"
>> + - ranges
>
> This has ABI impact and is not really necessary, as the child node is
> not required either. Drop these three.
>
I send this series too quickly, before you made your reply on v3 [1]
[1] https://lore.kernel.org/linux-arm-kernel/b81b8404-572b-4ea4-91ab-6e201f0352b9@kernel.org/
Sorry for that, the v5 is already available on mailing list.
Patrice
>> + else:
>> + properties:
>> + ranges: false
>> + patternProperties:
>> + "^nvram@[0-9a-f]+$": false
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers
2026-11-06 10:33 ` Patrice CHOTARD
@ 2026-11-06 11:00 ` Krzysztof Kozlowski
2026-11-06 11:13 ` Patrice CHOTARD
0 siblings, 1 reply; 11+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-06 11:00 UTC (permalink / raw)
To: Patrice CHOTARD
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla,
Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel
On 06/11/2026 11:33, Patrice CHOTARD wrote:
>
>
> On 11/6/26 11:16, Krzysztof Kozlowski wrote:
>> On Wed, Nov 04, 2026 at 04:20:08PM +0100, Patrice Chotard wrote:
>>> + nvmem-layout {
>>> + compatible = "fixed-layout";
>>> + #address-cells = <1>;
>>> + #size-cells = <1>;
>>> +
>>> + /* Data cells */
>>> + wakeup_sec: tamp-bkp@0 {
>>> + reg = <0x0 0x4>;
>>> + };
>>> + boot_mode: tamp-bkp@50 {
>>> + /*see boot mode selection feature*/
>>> + reg = <0x50 0x4>;
>>
>> Mixed up indentation. Please also run scripts/dtc/dt-check-style and fix
>> obvious issues.
>
> Hi Krzysztof
>
> scripts/dtc/dt-check-style doesn't return any errors.
Yes, bindings should adhere to strict mode, see line ~40 in DT
submitting patches doc. Srtict mode would complain:
Documentation/devicetree/bindings/nvmem/st,stm32-tamp-nvram.yaml:50:
example 0 [indent-consistent] indent mismatch (expected depth 3 * ' ')
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers
2026-11-06 11:00 ` Krzysztof Kozlowski
@ 2026-11-06 11:13 ` Patrice CHOTARD
0 siblings, 0 replies; 11+ messages in thread
From: Patrice CHOTARD @ 2026-11-06 11:13 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Christophe Roullier, Srinivas Kandagatla,
Simeon Marijon, linux-stm32, devicetree, linux-arm-kernel,
linux-kernel
On 11/6/26 12:00, Krzysztof Kozlowski wrote:
> On 06/11/2026 11:33, Patrice CHOTARD wrote:
>>
>>
>> On 11/6/26 11:16, Krzysztof Kozlowski wrote:
>>> On Wed, Nov 04, 2026 at 04:20:08PM +0100, Patrice Chotard wrote:
>>>> + nvmem-layout {
>>>> + compatible = "fixed-layout";
>>>> + #address-cells = <1>;
>>>> + #size-cells = <1>;
>>>> +
>>>> + /* Data cells */
>>>> + wakeup_sec: tamp-bkp@0 {
>>>> + reg = <0x0 0x4>;
>>>> + };
>>>> + boot_mode: tamp-bkp@50 {
>>>> + /*see boot mode selection feature*/
>>>> + reg = <0x50 0x4>;
>>>
>>> Mixed up indentation. Please also run scripts/dtc/dt-check-style and fix
>>> obvious issues.
>>
>> Hi Krzysztof
>>
>> scripts/dtc/dt-check-style doesn't return any errors.
>
> Yes, bindings should adhere to strict mode, see line ~40 in DT
> submitting patches doc. Srtict mode would complain:
>
> Documentation/devicetree/bindings/nvmem/st,stm32-tamp-nvram.yaml:50:
> example 0 [indent-consistent] indent mismatch (expected depth 3 * ' ')
Ok thanks for pointing this.
As the v5 is already available on mailing list, it will trigger the same remark.
it will be fixed in v6, once you will have reviewed the v5.
Patrice
>
>
> Best regards,
> Krzysztof
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-11-06 11:13 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04 15:20 [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice Chotard
2026-11-04 15:20 ` [PATCH v4 1/3] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard
2026-11-06 10:16 ` Krzysztof Kozlowski
2026-11-06 10:33 ` Patrice CHOTARD
2026-11-06 11:00 ` Krzysztof Kozlowski
2026-11-06 11:13 ` Patrice CHOTARD
2026-11-04 15:20 ` [PATCH v4 2/3] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard
2026-11-06 10:21 ` Krzysztof Kozlowski
2026-11-06 10:46 ` Patrice CHOTARD
2026-11-04 15:20 ` [PATCH v4 3/3] nvmem: stm32: add TAMP nvmem driver Patrice Chotard
2026-11-05 11:39 ` [PATCH v4 0/3] Add STM32 TAMP nvram driver support Patrice CHOTARD
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®