On 5/19/25 13:23, Patrice Chotard wrote:
> From: Simeon Marijon <simeon.mari...@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.mari...@foss.st.com>
> Signed-off-by: Patrice Chotard <patrice.chot...@foss.st.com>
> Reviewed-by: Patrick Delaunay <patrick.delau...@foss.st.com>
> 
> ---
> 
> Changes in v4:
>    - Replace stm32mp25 by stm32mp2
>    - Constify stm32_tamp_bkpreg_access field of stm32_tamp_nvram_priv struct
>    - Add get_access() callback in stm32_tamp_nvram_drvdata struct
> 
> Changes in v3:
>    - Fix typo in SPDX-License-Identifier
> 
> Changes in v2:
>    - Rename nvram.c to tamp_nvram.c
> 
>  arch/arm/mach-stm32mp/Kconfig      |   9 +
>  arch/arm/mach-stm32mp/Makefile     |   2 +
>  arch/arm/mach-stm32mp/tamp_nvram.c | 667 +++++++++++++++++++++++++++++
>  3 files changed, 678 insertions(+)
>  create mode 100644 arch/arm/mach-stm32mp/tamp_nvram.c
> 
> diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
> index 58250901101..09b7d5123ae 100644
> --- a/arch/arm/mach-stm32mp/Kconfig
> +++ b/arch/arm/mach-stm32mp/Kconfig
> @@ -139,6 +139,15 @@ config STM32_ECDSA_VERIFY
>         ROM API provided on STM32MP.
>         The ROM API is only available during SPL for now.
>  
> +config STM32MP_TAMP_NVMEM
> +     bool "STM32 TAMP backup registers via NVMEM API"
> +     select NVMEM
> +     default y
> +     help
> +       Say y to enable the uclass driver for TAMP Backup registers using the
> +       NVMEM API. It allows to access to boot mode or others shared 
> information
> +       between software components/execution levels.
> +
>  config CMD_STM32KEY
>       bool "command stm32key to fuse public key hash"
>       depends on CMDLINE
> diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
> index 103e3410ad9..ecd49fe668d 100644
> --- a/arch/arm/mach-stm32mp/Makefile
> +++ b/arch/arm/mach-stm32mp/Makefile
> @@ -13,6 +13,8 @@ obj-$(CONFIG_STM32MP13X) += stm32mp1/
>  obj-$(CONFIG_STM32MP25X) += stm32mp2/
>  
>  obj-$(CONFIG_MFD_STM32_TIMERS) += timers.o
> +obj-$(CONFIG_STM32MP_TAMP_NVMEM) += tamp_nvram.o
> +
>  obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o
>  ifndef CONFIG_XPL_BUILD
>  obj-y += cmd_stm32prog/
> diff --git a/arch/arm/mach-stm32mp/tamp_nvram.c 
> b/arch/arm/mach-stm32mp/tamp_nvram.c
> new file mode 100644
> index 00000000000..39cc2c111d8
> --- /dev/null
> +++ b/arch/arm/mach-stm32mp/tamp_nvram.c
> @@ -0,0 +1,667 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
> +/*
> + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
> + */
> +#define LOG_CATEGORY UCLASS_MISC
> +
> +#include <clk.h>
> +#include <dm.h>
> +#include <log.h>
> +#include <misc.h>
> +#include <regmap.h>
> +#include <tee.h>
> +#include <asm/io.h>
> +#include <dm/device.h>
> +#include <dm/device_compat.h>
> +#include <dm/devres.h>
> +
> +#define RIF_CID1                     0x1
> +#define CURRENT_CID                  RIF_CID1
> +#define NB_ZONES_STM32MP1            3
> +#define NB_ZONES_STM32MP2            7
> +
> +#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_plat {
> +     void __iomem *base;
> +     void __iomem *parent_base;
> +     fdt_size_t size;
> +     fdt_size_t parent_size;
> +     unsigned int nb_total_regs;
> +};
> +
> +struct stm32_tamp_nvram_priv {
> +     int *idx_bkpreg_zones_end;
> +     struct regmap *config_regmap;
> +     struct regmap *bkpregs_regmap;
> +     const enum stm32_tamp_bkpreg_access *bkpreg_access;
> +};
> +
> +struct stm32_tamp_nvram_drvdata {
> +     const unsigned int nb_zones;
> +     const struct reg_field *reg_fields;
> +     const enum stm32_tamp_bkpreg_access *(*get_access)(struct udevice *dev);
> +};
> +
> +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 
> stm32mp2_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 
> stm32mp2_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 
> stm32mp2_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 const 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 const enum stm32_tamp_bkpreg_access 
> *stm32mp1_tamp_get_access_rights(struct udevice *dev)
> +{
> +     return stm32mp1_tamp_bkpreg_access;
> +}
> +
> +static int stm32mp2_tamp_is_compartment_isolation_enabled(struct udevice 
> *dev)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     int nb_compartment_enabled = 0;
> +     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,
> +                                                  
> stm32mp2_tamp_nvram_rxcidcfg_cfen_fields[i]);
> +             if (IS_ERR_OR_NULL(cfen_field)) {
> +                     dev_err(dev, "Can't allocate field for reading 
> configuration\n");
> +                     return -ENOMEM;
> +             }
> +             if (regmap_field_read(cfen_field, &cfen) != 0) {
> +                     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 == 0)
> +             return 0;
> +     else if (nb_compartment_enabled == NB_COMPARTMENT_STM32MP2)
> +             return 1;
> +     else
> +             return -EINVAL;
> +}
> +
> +static bool *stm32mp2_tamp_get_compartment_owner(struct udevice *dev)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     struct regmap_field *cid_field;
> +     u32 cid_per_zone;
> +     int isolation_enabled;
> +     bool *compartment_owner;
> +
> +     isolation_enabled = stm32mp2_tamp_is_compartment_isolation_enabled(dev);
> +     if (isolation_enabled < 0)
> +             return NULL;
> +
> +     compartment_owner = devm_kcalloc(dev,
> +                                      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,
> +                                                         
> stm32mp2_tamp_nvram_rxcidcfg_fields[i]
> +                                                         );
> +
> +                     if (regmap_field_read(cid_field, &cid_per_zone) != 0) {
> +                             dev_err(dev, "Can't read field for registers 
> zones\n");
> +                             devm_regmap_field_free(dev, cid_field);
> +                             devm_kfree(dev, 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 const enum stm32_tamp_bkpreg_access 
> *stm32mp2_tamp_get_access_rights(struct udevice *dev)
> +{
> +     struct stm32_tamp_nvram_drvdata *drvdata =
> +             (struct stm32_tamp_nvram_drvdata *)dev_get_driver_data(dev);
> +     unsigned int nb_zones = drvdata->nb_zones;
> +     bool *compartment_owner;
> +     enum stm32_tamp_bkpreg_access *bkpreg_access;
> +
> +     compartment_owner = stm32mp2_tamp_get_compartment_owner(dev);
> +     if (IS_ERR(compartment_owner))
> +             return ERR_PTR(-ENODEV);
> +
> +     bkpreg_access = devm_kcalloc(dev,
> +                                  NB_ZONES_STM32MP2,
> +                                  sizeof(*bkpreg_access),
> +                                  GFP_KERNEL);
> +
> +     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);
> +                     return ERR_PTR(-ENODEV);
> +             }
> +     }
> +
> +     return bkpreg_access;
> +}
> +
> +static const struct stm32_tamp_nvram_drvdata stm32mp1_tamp_nvram = {
> +     .nb_zones = NB_ZONES_STM32MP1,
> +     .reg_fields = stm32mp1_tamp_nvram_zone_cfg_fields,
> +     .get_access = stm32mp1_tamp_get_access_rights,
> +};
> +
> +static const struct stm32_tamp_nvram_drvdata stm32mp2_tamp_nvram = {
> +     .nb_zones = NB_ZONES_STM32MP2,
> +     .reg_fields = stm32mp2_tamp_nvram_zone_cfg_fields,
> +     .get_access = stm32mp2_tamp_get_access_rights,
> +};
> +
> +static int stm32_tamp_nvram_bkpreg_get_zone_idx(struct udevice *dev, int reg)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     struct stm32_tamp_nvram_drvdata *drvdata =
> +             (struct stm32_tamp_nvram_drvdata *)dev_get_driver_data(dev);
> +     int *idx_bkpreg_zones_end = priv->idx_bkpreg_zones_end;
> +     int nb_zones = drvdata->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 udevice *dev, int reg, bool 
> read_only)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     int protection_zone_idx = stm32_tamp_nvram_bkpreg_get_zone_idx(dev, 
> 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 int stm32_tamp_nvram_write_byte(struct udevice *dev, u32 offset, u8 
> byte)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     int offset_aligned = ALIGN_DOWN(offset, sizeof(u32));
> +     int byte_in_word = offset - offset_aligned;
> +     u32 read_value, to_be_writen_value;
> +     u32 reg_idx = offset_aligned / sizeof(u32);
> +
> +     if (!stm32_tamp_nvram_rights(dev, reg_idx, false))
> +             return -EIO;
> +
> +     regmap_read(priv->bkpregs_regmap, offset_aligned, &read_value);
> +     to_be_writen_value = read_value & ~(0xFFUL << byte_in_word * 8);
> +     to_be_writen_value |=  (u32)byte << (byte_in_word * 8);
> +
> +     return regmap_write(priv->bkpregs_regmap, offset_aligned, 
> to_be_writen_value);
> +}
> +
> +static int stm32_tamp_nvram_read_byte(struct udevice *dev, unsigned int 
> offset, u8 *byte)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     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);
> +
> +     if (!stm32_tamp_nvram_rights(dev, reg_idx, true))
> +             return -EIO;
> +
> +     regmap_read(priv->bkpregs_regmap, offset_aligned, &read_value);
> +     *byte = (read_value >> (byte_in_word * 8)) & 0xFF;
> +
> +     return 0;
> +}
> +
> +static int stm32_tamp_nvram_read(struct udevice *dev, int offset, void *buf, 
> int size)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     u8 byte;
> +     u8 *buf_u8 = buf;
> +     u32 temp_u32;
> +     int i, ret;
> +     int total = offset + size;
> +     u32 reg_idx;
> +
> +     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(dev, reg_idx, true)) {
> +                             dev_dbg(dev, "Backup register %u is not allowed 
> to be read\n",
> +                                     reg_idx);
> +                             temp_u32 = 0;
> +                     } else {
> +                             regmap_read(priv->bkpregs_regmap, i, &temp_u32);
> +                     }
> +                     memcpy(buf_u8, &temp_u32, sizeof(u32));
> +                     buf_u8 += sizeof(u32);
> +                     i += sizeof(u32);
> +             } else {
> +                     ret = stm32_tamp_nvram_read_byte(dev, i, &byte);
> +                     if (ret != 0) {
> +                             dev_dbg(dev, "Backup register %u is not allowed 
> to be read\n",
> +                                     reg_idx);
> +                             byte = 0;
> +                     }
> +                     *buf_u8 = byte;
> +                     i++;
> +                     buf_u8++;
> +             }
> +     }
> +
> +     return size;
> +}
> +
> +static int stm32_tamp_nvram_write(struct udevice *dev, int offset, const 
> void *buf, int size)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     u8 *buf_u8 = (u8 *)buf;
> +     u32 temp_u32;
> +     size_t total = offset + size;
> +     int i, ret;
> +     u32 reg_idx;
> +
> +     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(dev, reg_idx, false)) {
> +                             memcpy(&temp_u32, buf_u8, sizeof(u32));
> +                             regmap_write(priv->bkpregs_regmap, i, temp_u32);
> +                     } else {
> +                             dev_dbg(dev, "Backup register %u is not allowed 
> to be written",
> +                                     reg_idx);
> +                     }
> +                     buf_u8 += sizeof(u32);
> +                     i += sizeof(u32);
> +             } else {
> +                     ret = stm32_tamp_nvram_write_byte(dev, i, *buf_u8);
> +                     if (ret != 0)
> +                             dev_dbg(dev, "Backup register %u is not allowed 
> to be written",
> +                                     reg_idx);
> +                     i++;
> +                     buf_u8++;
> +             }
> +     }
> +
> +     return size;
> +}
> +
> +static const struct misc_ops stm32_tamp_nvram_ops = {
> +     .read = stm32_tamp_nvram_read,
> +     .write = stm32_tamp_nvram_write,
> +};
> +
> +static u32 *stm32_tamp_nvram_get_backup_zones(struct udevice *dev)
> +{
> +     struct stm32_tamp_nvram_plat *plat = dev_get_plat(dev);
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     const struct stm32_tamp_nvram_drvdata *drvdata =
> +             (struct stm32_tamp_nvram_drvdata *)dev_get_driver_data(dev);
> +     int nb_zones = drvdata->nb_zones;
> +     int zone_idx;
> +     int *idx_bkpreg_zones_end;
> +     struct regmap *tamp_regmap = priv->config_regmap;
> +     u32 offset_field;
> +
> +     idx_bkpreg_zones_end = devm_kcalloc(dev,
> +                                         sizeof(*idx_bkpreg_zones_end),
> +                                         nb_zones,
> +                                         GFP_KERNEL);
> +     if (IS_ERR_OR_NULL(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 = 
> drvdata->reg_fields[zone_idx];
> +             struct regmap_field *field = devm_regmap_field_alloc(dev,
> +                                                                  
> tamp_regmap,
> +                                                                  reg_field);
> +
> +             if (IS_ERR_OR_NULL(field)) {
> +                     dev_err(dev, "Can't allocate registers zones\n");
> +                     devm_kfree(dev, idx_bkpreg_zones_end);
> +                     return ERR_PTR(-ENOMEM);
> +             }
> +             if (regmap_field_read(field, &offset_field) != 0) {
> +                     dev_err(dev, "Can't read field for registers zones\n");
> +                     devm_kfree(dev, idx_bkpreg_zones_end);
> +                     return ERR_PTR(-EIO);
> +             }
> +
> +             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] = plat->nb_total_regs - 1;
> +
> +     return idx_bkpreg_zones_end;
> +}
> +
> +static void stm32_tamp_nvram_print_zones(struct udevice *dev)
> +{
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     int *zones_end = priv->idx_bkpreg_zones_end;
> +
> +     if (device_is_compatible(dev, "st,stm32mp25-tamp-nvram")) {
> +             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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_1_RIF1],
> +                                             true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_1_RIF2],
> +                                             true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_2_RIF1],
> +                                             true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_2_RIF2],
> +                                             true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_3_RIF1],
> +                                             true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_3_RIF0],
> +                                             true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_3_RIF2],
> +                                             true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_3_RIF2],
> +                                             false) ?
> +                             'W' :
> +                             '-');
> +     } else if (device_is_compatible(dev, "st,stm32mp15-tamp-nvram")) {
> +             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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_1], true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_2], true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> 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(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_3], true) ?
> +                             'R' :
> +                             '-',
> +                     stm32_tamp_nvram_rights(dev, 
> zones_end[BKPREG_PROTECTION_ZONE_3], false) ?
> +                             'W' :
> +                             '-');
> +     }
> +}
> +
> +static int stm32_tamp_nvram_of_to_plat(struct udevice *dev)
> +{
> +     struct stm32_tamp_nvram_plat *plat = dev_get_plat(dev);
> +     fdt_addr_t addr = dev_read_addr_size_index(dev, 0, &plat->size);
> +     fdt_addr_t parent_addr = dev_read_addr_size_index(dev->parent, 0, 
> &plat->parent_size);
> +
> +     if (addr == FDT_ADDR_T_NONE)
> +             return -EINVAL;
> +     plat->base = (void __iomem *)addr;
> +
> +     if (parent_addr == FDT_ADDR_T_NONE)
> +             return -EINVAL;
> +     plat->parent_base = (void __iomem *)parent_addr;
> +
> +     if (plat->size == FDT_ADDR_T_NONE)
> +             return -EOPNOTSUPP;
> +
> +     plat->nb_total_regs =  plat->size / sizeof(uint32_t);
> +
> +     return 0;
> +}
> +
> +static int stm32_tamp_nvram_probe(struct udevice *dev)
> +{
> +     struct stm32_tamp_nvram_plat *plat = dev_get_plat(dev);
> +     struct stm32_tamp_nvram_priv *priv = dev_get_priv(dev);
> +     struct regmap_config config_regmap;
> +     struct regmap_config bckreg_regmap;
> +     const struct stm32_tamp_nvram_drvdata *drvdata =
> +             (struct stm32_tamp_nvram_drvdata *)dev_get_driver_data(dev);
> +
> +     config_regmap.r_start = (ulong)(plat->parent_base);
> +     config_regmap.r_size = plat->parent_size;
> +     config_regmap.reg_offset_shift = 0;
> +     config_regmap.width = REGMAP_SIZE_32;
> +     priv->config_regmap = devm_regmap_init(dev, NULL, NULL, &config_regmap);
> +
> +     bckreg_regmap.r_start = (ulong)(plat->base);
> +     bckreg_regmap.r_size = plat->size;
> +     bckreg_regmap.reg_offset_shift = 0;
> +     bckreg_regmap.width = REGMAP_SIZE_32;
> +     priv->bkpregs_regmap = devm_regmap_init(dev, NULL, NULL, 
> &bckreg_regmap);
> +
> +     priv->idx_bkpreg_zones_end = stm32_tamp_nvram_get_backup_zones(dev);
> +     if (IS_ERR_OR_NULL(priv->idx_bkpreg_zones_end)) {
> +             dev_err(dev, "Failed to get the backup zone from tamp 
> regs\n\n");
> +             return -ENODEV;
> +     }
> +
> +     priv->bkpreg_access = drvdata->get_access(dev);
> +     stm32_tamp_nvram_print_zones(dev);
> +
> +     return 0;
> +}
> +
> +static int stm32_tamp_nvram_remove(struct udevice *dev)
> +{
> +     return 0;
> +}
> +
> +static const struct udevice_id stm32_tamp_nvram_ids[] = {
> +     { .compatible = "st,stm32mp15-tamp-nvram", .data = 
> (ulong)&stm32mp1_tamp_nvram },
> +     { .compatible = "st,stm32mp25-tamp-nvram", .data = 
> (ulong)&stm32mp2_tamp_nvram },
> +     {},
> +};
> +
> +U_BOOT_DRIVER(stm32_tamp_nvram) = {
> +     .name = "stm32_tamp_nvram",
> +     .id = UCLASS_MISC,
> +     .of_match = stm32_tamp_nvram_ids,
> +     .priv_auto = sizeof(struct stm32_tamp_nvram_priv),
> +     .plat_auto = sizeof(struct stm32_tamp_nvram_plat),
> +     .ops = &stm32_tamp_nvram_ops,
> +     .of_to_plat = of_match_ptr(stm32_tamp_nvram_of_to_plat),
> +     .probe = stm32_tamp_nvram_probe,
> +     .remove = stm32_tamp_nvram_remove,
> +};
> +

Applied to u-boot-stm32/next

Thanks
Patrice

Reply via email to