* [PATCH v5 0/8] Add STM32 TAMP nvram driver support
@ 2026-11-05 12:02 Patrice Chotard
2026-11-05 12:02 ` [PATCH v5 1/8] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Patrice Chotard @ 2026-11-05 12:02 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,
Clément Le Goffic
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 v5:
- include DTS patches previously submitted separately in https://patchwork.kernel.org/series/1176665/
- Link to v4: https://patch.msgid.link/20261104-upstream_nvram_reworked-v4-0-144024496a44@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 (3):
dt-bindings: arm: stm32: allow TAMP nvram child node for syscon
arm64: dts: st: add TAMP backup register in stm32mp211.dtsi
arm64: dts: st: add TAMP backup register in stm32mp231.dtsi
Simeon Marijon (5):
dt-bindings: nvmem: add STM32MPX TAMP backup registers
nvmem: stm32: add TAMP nvmem driver
ARM: dts: stm32: add TAMP backup register in stm32mp131.dtsi
ARM: dts: stm32: add TAMP backup register in stm32mp151.dtsi
arm64: dts: st: add TAMP backup register in stm32mp251.dtsi
.../bindings/arm/stm32/st,stm32-syscon.yaml | 38 +-
.../bindings/nvmem/st,stm32-tamp-nvram.yaml | 57 ++
MAINTAINERS | 8 +
arch/arm/boot/dts/st/stm32mp131.dtsi | 34 ++
arch/arm/boot/dts/st/stm32mp151.dtsi | 83 +++
arch/arm64/boot/dts/st/stm32mp211.dtsi | 31 +
arch/arm64/boot/dts/st/stm32mp231.dtsi | 31 +
arch/arm64/boot/dts/st/stm32mp251.dtsi | 31 +
drivers/nvmem/Kconfig | 11 +
drivers/nvmem/Makefile | 2 +
drivers/nvmem/stm32-tamp-nvram.c | 680 +++++++++++++++++++++
11 files changed, 1003 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 v5 1/8] dt-bindings: nvmem: add STM32MPX TAMP backup registers 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard @ 2026-11-05 12:02 ` Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 2/8] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard ` (6 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:02 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 related [flat|nested] 11+ messages in thread
* [PATCH v5 2/8] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard 2026-11-05 12:02 ` [PATCH v5 1/8] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard @ 2026-11-05 12:03 ` Patrice Chotard 2026-11-05 12:10 ` sashiko-bot 2026-11-05 12:03 ` [PATCH v5 3/8] nvmem: stm32: add TAMP nvmem driver Patrice Chotard ` (5 subsequent siblings) 7 siblings, 1 reply; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:03 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 related [flat|nested] 11+ messages in thread
* Re: [PATCH v5 2/8] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon 2026-11-05 12:03 ` [PATCH v5 2/8] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard @ 2026-11-05 12:10 ` sashiko-bot 0 siblings, 0 replies; 11+ messages in thread From: sashiko-bot @ 2026-11-05 12:10 UTC (permalink / raw) To: Patrice Chotard; +Cc: devicetree, robh, conor+dt Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [Medium] dt-bindings: arm: stm32: requiring ranges on tamp breaks childless nodes - [Medium] dt-bindings: arm: stm32: unwieldy conditionals and #size-cells relaxation - [Low] dt-bindings: arm: stm32: truncated sentence in commit message -- commit e6c1079f034dff65c4f96319b3e627caa16315a4 Author: Patrice Chotard <patrice.chotard@foss.st.com> dt-bindings: arm: stm32: allow TAMP nvram child node for syscon This commit updates the STM32 syscon DT binding schema to allow an nvram child node and bus addressing properties (#address-cells, #size-cells, and ranges) for the st,stm32-tamp compatible. > dt-bindings: arm: stm32: allow TAMP nvram child node for syscon > > 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> [Severity: Low] As reported by Sashiko on v4 [1], was a line starting with #address-cells stripped by git commit in the middle of the second paragraph between "and only allowed" and "into the DTSI", leaving the sentence incomplete? > diff --git a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml > index a559f8b03b842..51cb565e05edb 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 [Severity: Medium] As reported by Sashiko on v4 [2], does unconditionally requiring #address-cells, #size-cells, and ranges in allOf whenever compatible contains st,stm32-tamp cause a validation regression for childless TAMP nodes and non-MFD TAMP compatibles? The ^nvram@[0-9a-f]+$ child node is optional, and properties.compatible in Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml permits both the two-item non-MFD form (st,stm32-tamp, syscon) and the three-item MFD form (st,stm32-tamp, syscon, simple-mfd): compatible: oneOf: - items: - enum: - st,stm32-tamp ... - const: syscon - items: - enum: - st,stm32-tamp ... - const: syscon - const: simple-mfd Existing device trees such as arch/arm/boot/dts/st/stm32mp151.dtsi define a childless tamp@5c00a000 node without #address-cells, #size-cells, or ranges: tamp: tamp@5c00a000 { compatible = "st,stm32-tamp", "syscon", "simple-mfd"; reg = <0x5c00a000 0x400>; }; Should #address-cells, #size-cells, and ranges only be allowed (or required via dependencies when a child node is present) rather than unconditionally required on all st,stm32-tamp nodes? > + 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 [Severity: Medium] As reported by Sashiko on v4 [3], does widening the top-level #size-cells in properties from const: 1 to enum: [1, 2] also relax validation for st,stm32mp23-syscfg and st,stm32mp25-syscfg so that they now accept #size-cells = <2>, even though their phy@2400 and phy@2800 child nodes only use 1 size cell? Also, since st,stm32-syscon.yaml now accumulates multiple per-compatible allOf conditional blocks (including this negated multi-compatible if-not block across st,stm32-tamp, st,stm32mp23-syscfg, and st,stm32mp25-syscfg) for divergent child nodes and addressing rules, would it be cleaner to split st,stm32-tamp into its own binding schema document rather than piling more variant conditionals onto st,stm32-syscon.yaml? [1] https://lore.kernel.org/r/20261104-upstream_nvram_reworked-v4-2-144024496a44@foss.st.com [2] https://lore.kernel.org/r/20261104-upstream_nvram_reworked-v4-2-144024496a44@foss.st.com [3] https://lore.kernel.org/r/20261104-upstream_nvram_reworked-v4-2-144024496a44@foss.st.com -- Sashiko AI review · https://sashiko.dev/#/patchset/20261105-upstream_nvram_reworked-v5-0-ddf7dbf1b298@foss.st.com?part=2 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v5 3/8] nvmem: stm32: add TAMP nvmem driver 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard 2026-11-05 12:02 ` [PATCH v5 1/8] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 2/8] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard @ 2026-11-05 12:03 ` Patrice Chotard 2026-11-05 12:16 ` sashiko-bot 2026-11-05 12:03 ` [PATCH v5 4/8] ARM: dts: stm32: add TAMP backup register in stm32mp131.dtsi Patrice Chotard ` (4 subsequent siblings) 7 siblings, 1 reply; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:03 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 related [flat|nested] 11+ messages in thread
* Re: [PATCH v5 3/8] nvmem: stm32: add TAMP nvmem driver 2026-11-05 12:03 ` [PATCH v5 3/8] nvmem: stm32: add TAMP nvmem driver Patrice Chotard @ 2026-11-05 12:16 ` sashiko-bot 0 siblings, 0 replies; 11+ messages in thread From: sashiko-bot @ 2026-11-05 12:16 UTC (permalink / raw) To: Patrice Chotard; +Cc: devicetree, robh, conor+dt Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] nvmem: stm32: broken empty zone handling in stm32_tamp_nvram_bkpreg_get_zone() -- commit cc344e612aad158ca9ed69f02f411f367bdfd26a Author: Simeon Marijon <simeon.marijon@foss.st.com> nvmem: stm32: add TAMP nvmem driver This commit adds an nvmem provider driver for the STMicroelectronics STM32 TAMP backup registers on STM32MP1 and STM32MP25 SoCs, checking hardware protection zones and compartment isolation rights before accessing the backup registers. > diff --git a/drivers/nvmem/stm32-tamp-nvram.c b/drivers/nvmem/stm32-tamp-nvram.c > new file mode 100644 > index 0000000000000..81096a5d02829 > --- /dev/null > +++ b/drivers/nvmem/stm32-tamp-nvram.c > @@ -0,0 +1,680 @@ [ ... ] > +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 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; > +} [ ... ] > + 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' : '-', [Severity: Medium] Can stm32_tamp_nvram_get_backup_zones() and stm32_tamp_nvram_bkpreg_get_zone() misclassify backup registers or misreport zone boundaries when one or more TAMP protection zones or RIF subzones are empty? In STM32MP1 and STM32MP25 TAMP hardware, the zone boundary fields in TAMP_SECCFGR and TAMP_BKPRIFRx (BKPWRIF1, BKPRWSEC, BKPWRIF2, BKPWSEC, BKPW3RIF1, BKPW3RIF0) define cumulative register offsets from TAMP_BKP0R. A zone k > 0 is empty when its offset equals the preceding zone's offset (so zones_end[k] == zones_end[k - 1] >= 0), or when a subzone offset field is left at 0 (so zones_end[k] == -1 while zones_end[k - 1] >= 0). In addition, on STM32MP25, BKPWRIF1 only subdivides Zone 1 (bounded by BKPRWSEC) and BKPWRIF2 only subdivides Zone 2 (bounded by BKPWSEC); if BKPWRIF1 >= BKPRWSEC or BKPWRIF2 >= BKPWSEC, Zone 1-RIF2 or Zone 2-RIF2 is disabled and Zone 1 or Zone 2 remains capped at BKPRWSEC or BKPWSEC. In stm32_tamp_nvram_get_backup_zones(), idx_bkpreg_zones_end[zone_idx] is set to offset_field - 1 without clamping BKPWRIF1 to BKPRWSEC or BKPWRIF2 to BKPWSEC and without normalizing empty zones. If BKPWRIF1 > BKPRWSEC or BKPWRIF2 > BKPWSEC, stm32_tamp_nvram_bkpreg_get_zone() checks idx_bkpreg_zones_end[BKPREG_PROTECTION_ZONE_1_RIF1] or idx_bkpreg_zones_end[BKPREG_PROTECTION_ZONE_2_RIF1] before the parent zone end (BKPRWSEC - 1 or BKPWSEC - 1), which would place registers beyond BKPRWSEC or BKPWSEC into Zone 1-RIF1 or Zone 2-RIF1 and apply the wrong access rights during stm32_tamp_nvram_read() and stm32_tamp_nvram_write(). Furthermore, stm32_tamp_nvram_bkpreg_get_zone() assumes an empty zone always has a negative end index (reg < 0). When zone k > 0 is empty because zones_end[k] == zones_end[k - 1] >= 0, calling stm32_tamp_nvram_rights(priv, zones_end[k], ...) in stm32_tamp_nvram_probe() matches zone k - 1 (the first zone with idx_bkpreg_zones_end >= reg) rather than treating zone k as empty. Conversely, if a subzone k > 0 has offset_field == 0 (zones_end[k] == -1) after a non-empty zone k - 1, stm32_tamp_nvram_probe() logs the start of zone k + 1 as zones_end[k] + 1 (0) instead of zones_end[k - 1] + 1. Should stm32_tamp_nvram_get_backup_zones() clamp the RIF1 subzone offsets to their parent zone boundaries, and should empty zones be tracked explicitly rather than relying on zones_end[k] < 0? -- Sashiko AI review · https://sashiko.dev/#/patchset/20261105-upstream_nvram_reworked-v5-0-ddf7dbf1b298@foss.st.com?part=3 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v5 4/8] ARM: dts: stm32: add TAMP backup register in stm32mp131.dtsi 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard ` (2 preceding siblings ...) 2026-11-05 12:03 ` [PATCH v5 3/8] nvmem: stm32: add TAMP nvmem driver Patrice Chotard @ 2026-11-05 12:03 ` Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 5/8] ARM: dts: stm32: add TAMP backup register in stm32mp151.dtsi Patrice Chotard ` (3 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:03 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> TAMP backup registers allow information sharing between different software components/execution levels. They are described individually as nvmem cells. Signed-off-by: Simeon Marijon <simeon.marijon@foss.st.com> Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> --- arch/arm/boot/dts/st/stm32mp131.dtsi | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/boot/dts/st/stm32mp131.dtsi b/arch/arm/boot/dts/st/stm32mp131.dtsi index ae45c2023afe..e1e943e9d5a6 100644 --- a/arch/arm/boot/dts/st/stm32mp131.dtsi +++ b/arch/arm/boot/dts/st/stm32mp131.dtsi @@ -1942,5 +1942,39 @@ gpioi: gpio@5000a000 { gpio-ranges = <&pinctrl 0 128 8>; }; }; + + tamp: tamp@5c00a000 { + compatible = "st,stm32-tamp", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x5c00a000 0x400>; + ranges; + + nvram: nvram@5c00a100 { + compatible = "st,stm32mp15-tamp-nvram"; + reg = <0x5c00a100 0x80>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + saes_secret_key: tamp-bkp@0 { + /* see saes secret key feature */ + reg = <0x0 0x20>; + }; + + boot_mode: tamp-bkp@78 { + /* see boot mode selection feature */ + reg = <0x78 0x4>; + }; + + boot_counter: tamp-bkp@7c { + /* see boot counter feature */ + reg = <0x7c 0x4>; + }; + }; + }; + }; }; }; -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 5/8] ARM: dts: stm32: add TAMP backup register in stm32mp151.dtsi 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard ` (3 preceding siblings ...) 2026-11-05 12:03 ` [PATCH v5 4/8] ARM: dts: stm32: add TAMP backup register in stm32mp131.dtsi Patrice Chotard @ 2026-11-05 12:03 ` Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 6/8] arm64: dts: st: add TAMP backup register in stm32mp211.dtsi Patrice Chotard ` (2 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:03 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> TAMP backup registers allow information sharing between different software components/execution levels. They are described individually as nvmem cells. Signed-off-by: Simeon Marijon <simeon.marijon@foss.st.com> Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> --- arch/arm/boot/dts/st/stm32mp151.dtsi | 83 ++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/arch/arm/boot/dts/st/stm32mp151.dtsi b/arch/arm/boot/dts/st/stm32mp151.dtsi index ae3188373238..ac7ed857cbf5 100644 --- a/arch/arm/boot/dts/st/stm32mp151.dtsi +++ b/arch/arm/boot/dts/st/stm32mp151.dtsi @@ -2060,7 +2060,90 @@ i2c6: i2c@5c009000 { tamp: tamp@5c00a000 { compatible = "st,stm32-tamp", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; reg = <0x5c00a000 0x400>; + ranges; + + nvram: nvram@5c00a100 { + compatible = "st,stm32mp15-tamp-nvram"; + reg = <0x5c00a100 0x80>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + wakeup_sec: tamp-bkp@0 { + reg = <0x0 0x4>; + }; + + m4_security_perimeter_exti1: tamp-bkp@4 { + /* see cortex-m4 wake up feature */ + reg = <0x4 0x4>; + }; + + m4_security_perimeter_exti2: tamp-bkp@8 { + /* see cortex-m4 wake up feature */ + reg = <0x8 0x4>; + }; + + m4_security_perimeter_exti3: tamp-bkp@c { + /* see cortex-m4 wake up feature */ + reg = <0xc 0x4>; + }; + + magic_number: tamp-bkp@10 { + /* see ddr and cpu wake up management feature */ + reg = <0x10 0x4>; + }; + + branch_address: tamp-bkp@14 { + /* see ddr and cpu wake up management feature */ + reg = <0x14 0x4>; + }; + + fwu_info: tamp-bkp@28 { + /* see firmware update info feature */ + reg = <0x28 0x4>; + }; + + copro_rsc_tbl_address: tamp-bkp@44 { + /* see cortex-m4 management feature */ + reg = <0x44 0x4>; + }; + + cortex_m_state: tamp-bkp@48 { + /* see cortex-m4 management feature */ + reg = <0x48 0x4>; + }; + + boot_mode: tamp-bkp@50 { + /* see boot mode selection feature */ + reg = <0x50 0x4>; + }; + + boot_counter: tamp-bkp@54 { + /* see boot counter feature */ + reg = <0x54 0x4>; + }; + + m4_wakeup_area_start: tamp-bkp@58 { + /* see cortex-m4 wake up feature */ + reg = <0x58 0x4>; + }; + + m4_wakeup_area_length: tamp-bkp@5c { + /* see cortex-m4 wake up feature */ + reg = <0x5c 0x4>; + }; + + m4_wakeup_area_hash: tamp-bkp@60 { + /* SHA-256 value see Cortex-M4 wake up feature */ + reg = <0x60 0x20>; + }; + }; + }; }; /* -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 6/8] arm64: dts: st: add TAMP backup register in stm32mp211.dtsi 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard ` (4 preceding siblings ...) 2026-11-05 12:03 ` [PATCH v5 5/8] ARM: dts: stm32: add TAMP backup register in stm32mp151.dtsi Patrice Chotard @ 2026-11-05 12:03 ` Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 7/8] arm64: dts: st: add TAMP backup register in stm32mp231.dtsi Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 8/8] arm64: dts: st: add TAMP backup register in stm32mp251.dtsi Patrice Chotard 7 siblings, 0 replies; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:03 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, Clément Le Goffic TAMP backup registers allow information sharing between different software components/execution levels. They are described individually as nvmem cells. Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com> Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> --- arch/arm64/boot/dts/st/stm32mp211.dtsi | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm64/boot/dts/st/stm32mp211.dtsi b/arch/arm64/boot/dts/st/stm32mp211.dtsi index 4bfd58b26b51..f9fe99dc90a3 100644 --- a/arch/arm64/boot/dts/st/stm32mp211.dtsi +++ b/arch/arm64/boot/dts/st/stm32mp211.dtsi @@ -133,6 +133,37 @@ syscfg: syscon@44230000 { reg = <0x44230000 0x0 0x10000>; }; + tamp: tamp@46010000 { + compatible = "st,stm32-tamp", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <2>; + reg = <0x46010000 0x0 0x400>; + ranges; + + nvram: nvram@46010100 { + compatible = "st,stm32mp25-tamp-nvram"; + reg = <0x46010100 0x0 0x200>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + boot_mode: tamp-bkp@180 { + reg = <0x180 0x4>; + }; + + rsc_tbl_addr: tamp-bkp@184 { + reg = <0x184 0x4>; + }; + + rsc_tbl_size: tamp-bkp@188 { + reg = <0x188 0x4>; + }; + }; + }; + }; + intc: interrupt-controller@4ac10000 { compatible = "arm,gic-400"; reg = <0x4ac10000 0x0 0x1000>, -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 7/8] arm64: dts: st: add TAMP backup register in stm32mp231.dtsi 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard ` (5 preceding siblings ...) 2026-11-05 12:03 ` [PATCH v5 6/8] arm64: dts: st: add TAMP backup register in stm32mp211.dtsi Patrice Chotard @ 2026-11-05 12:03 ` Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 8/8] arm64: dts: st: add TAMP backup register in stm32mp251.dtsi Patrice Chotard 7 siblings, 0 replies; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:03 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 TAMP backup registers allow information sharing between different software components/execution levels. They are described individually as nvmem cells. Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> --- arch/arm64/boot/dts/st/stm32mp231.dtsi | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm64/boot/dts/st/stm32mp231.dtsi b/arch/arm64/boot/dts/st/stm32mp231.dtsi index fefbf6f4f153..a1392aa9cab6 100644 --- a/arch/arm64/boot/dts/st/stm32mp231.dtsi +++ b/arch/arm64/boot/dts/st/stm32mp231.dtsi @@ -1265,6 +1265,37 @@ rtc: rtc@46000000 { status = "disabled"; }; + tamp: tamp@46010000 { + compatible = "st,stm32-tamp", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x46010000 0x400>; + ranges; + + nvram: nvram@46010100 { + compatible = "st,stm32mp25-tamp-nvram"; + reg = <0x46010100 0x200>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + boot_mode: tamp-bkp@180 { + reg = <0x180 0x4>; + }; + + rsc_tbl_addr: tamp-bkp@184 { + reg = <0x184 0x4>; + }; + + rsc_tbl_size: tamp-bkp@188 { + reg = <0x188 0x4>; + }; + }; + }; + }; + pinctrl_z: pinctrl@46200000 { compatible = "st,stm32mp257-z-pinctrl"; ranges = <0 0x46200000 0x400>; -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 8/8] arm64: dts: st: add TAMP backup register in stm32mp251.dtsi 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard ` (6 preceding siblings ...) 2026-11-05 12:03 ` [PATCH v5 7/8] arm64: dts: st: add TAMP backup register in stm32mp231.dtsi Patrice Chotard @ 2026-11-05 12:03 ` Patrice Chotard 7 siblings, 0 replies; 11+ messages in thread From: Patrice Chotard @ 2026-11-05 12:03 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> TAMP backup registers allow information sharing between different software components/execution levels. They are described individually as nvmem cells. Signed-off-by: Simeon Marijon <simeon.marijon@foss.st.com> Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> --- arch/arm64/boot/dts/st/stm32mp251.dtsi | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi index dac3d2d23ff0..9748834ae9de 100644 --- a/arch/arm64/boot/dts/st/stm32mp251.dtsi +++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi @@ -2242,6 +2242,37 @@ rtc: rtc@46000000 { status = "disabled"; }; + tamp: tamp@46010000 { + compatible = "st,stm32-tamp", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x46010000 0x400>; + ranges; + + nvram: nvram@46010100 { + compatible = "st,stm32mp25-tamp-nvram"; + reg = <0x46010100 0x200>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + boot_mode: tamp-bkp@180 { + reg = <0x180 0x4>; + }; + + rsc_tbl_addr: tamp-bkp@184 { + reg = <0x184 0x4>; + }; + + rsc_tbl_size: tamp-bkp@188 { + reg = <0x188 0x4>; + }; + }; + }; + }; + pinctrl_z: pinctrl@46200000 { #address-cells = <1>; #size-cells = <1>; -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-11-05 12:16 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-05 12:02 [PATCH v5 0/8] Add STM32 TAMP nvram driver support Patrice Chotard 2026-11-05 12:02 ` [PATCH v5 1/8] dt-bindings: nvmem: add STM32MPX TAMP backup registers Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 2/8] dt-bindings: arm: stm32: allow TAMP nvram child node for syscon Patrice Chotard 2026-11-05 12:10 ` sashiko-bot 2026-11-05 12:03 ` [PATCH v5 3/8] nvmem: stm32: add TAMP nvmem driver Patrice Chotard 2026-11-05 12:16 ` sashiko-bot 2026-11-05 12:03 ` [PATCH v5 4/8] ARM: dts: stm32: add TAMP backup register in stm32mp131.dtsi Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 5/8] ARM: dts: stm32: add TAMP backup register in stm32mp151.dtsi Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 6/8] arm64: dts: st: add TAMP backup register in stm32mp211.dtsi Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 7/8] arm64: dts: st: add TAMP backup register in stm32mp231.dtsi Patrice Chotard 2026-11-05 12:03 ` [PATCH v5 8/8] arm64: dts: st: add TAMP backup register in stm32mp251.dtsi Patrice Chotard
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox