Hi Patrick

2 minor remarks below

On 2/15/22 16:08, Patrick Delaunay wrote:
> Add support of the permanent lock support in U-Boot proper
> when BSEC is not managed by secure monitor (TF-A SP_MIN or OP-TEE).
> 
> This patch avoid issue with stm32key command and fuse command

s/avoid/avoids

> on basic boot for this missing feature of U-Boot BSEC driver.
> 
> Reported-by: Johann Neuhauser <jneuhau...@dh-electronics.com>
> Signed-off-by: Patrick Delaunay <patrick.delau...@foss.st.com>
> ---
> 
>  arch/arm/mach-stm32mp/bsec.c | 90 +++++++++++++++++++++++++++++++++---
>  1 file changed, 84 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
> index 27d1829501..fd6e1a3957 100644
> --- a/arch/arm/mach-stm32mp/bsec.c
> +++ b/arch/arm/mach-stm32mp/bsec.c
> @@ -18,6 +18,7 @@
>  #include <linux/iopoll.h>
>  
>  #define BSEC_OTP_MAX_VALUE           95
> +#define BSEC_OTP_UPPER_START         32
>  #define BSEC_TIMEOUT_US                      10000
>  
>  /* BSEC REGISTER OFFSET (base relative) */
> @@ -41,6 +42,7 @@
>  /* BSEC_CONTROL Register */
>  #define BSEC_READ                    0x000
>  #define BSEC_WRITE                   0x100
> +#define BSEC_LOCK                    0x200
>  
>  /* LOCK Register */
>  #define OTP_LOCK_MASK                        0x1F
> @@ -61,6 +63,11 @@
>   */
>  #define BSEC_LOCK_PROGRAM            0x04
>  
> +/*
> + * OTP status: bit 0 permanent lock
> + */
> +#define BSEC_LOCK_PERM                       BIT(0)
> +
>  /**
>   * bsec_lock() - manage lock for each type SR/SP/SW
>   * @address: address of bsec IP register
> @@ -284,6 +291,65 @@ static int bsec_program_otp(struct udevice *dev, long 
> base, u32 val, u32 otp)
>       return ret;
>  }
>  
> +/**
> + * bsec_permanent_lock_otp() - permanent lock of OTP in SAFMEM
> + * @dev: bsec IP device
> + * @base: base address of bsec IP
> + * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
> + * Return: 0 if no error
> + */
> +static int bsec_permanent_lock_otp(struct udevice *dev, long base, uint32_t 
> otp)
> +{
> +     int ret;
> +     bool power_up = false;
> +     u32 val, addr;
> +
> +     /* check if safemem is power up */
> +     if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
> +             ret = bsec_power_safmem(base, true);
> +             if (ret)
> +                     return ret;
> +
> +             power_up = true;
> +     }
> +
> +     /*
> +      * low OTPs = 2 bits word for low OTPs, 1 bits per word for upper OTP

s/2 bits word/2 bits per word

> +      * and only 16 bits used in WRDATA
> +      */
> +     if (otp < BSEC_OTP_UPPER_START) {
> +             addr = otp / 8;
> +             val = 0x03 << ((otp * 2) & 0xF);
> +     } else {
> +             addr = BSEC_OTP_UPPER_START / 8 +
> +                    ((otp - BSEC_OTP_UPPER_START) / 16);
> +             val = 0x01 << (otp & 0xF);
> +     }
> +
> +     /* set value in write register*/
> +     writel(val, base + BSEC_OTP_WRDATA_OFF);
> +
> +     /* set BSEC_OTP_CTRL_OFF with the otp addr and lock request*/
> +     writel(addr | BSEC_WRITE | BSEC_LOCK, base + BSEC_OTP_CTRL_OFF);
> +
> +     /* check otp status*/
> +     ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
> +                              val, (val & BSEC_MODE_BUSY_MASK) == 0,
> +                              BSEC_TIMEOUT_US);
> +     if (ret)
> +             return ret;
> +
> +     if (val & BSEC_MODE_PROGFAIL_MASK)
> +             ret = -EACCES;
> +     else
> +             ret = bsec_check_error(base, otp);
> +
> +     if (power_up)
> +             bsec_power_safmem(base, false);
> +
> +     return ret;
> +}
> +
>  /* BSEC MISC driver *******************************************************/
>  struct stm32mp_bsec_plat {
>       u32 base;
> @@ -339,9 +405,14 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev, 
> u32 *val, u32 otp)
>  static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
>  {
>       struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
> +     u32 wrlock;
>  
>       /* return OTP permanent write lock status */
> -     *val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
> +     wrlock = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
> +
> +     *val = 0;
> +     if (wrlock)
> +             *val = BSEC_LOCK_PERM;
>  
>       return 0;
>  }
> @@ -377,15 +448,22 @@ static int stm32mp_bsec_write_shadow(struct udevice 
> *dev, u32 val, u32 otp)
>  
>  static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
>  {
> -     if (!IS_ENABLED(CONFIG_ARM_SMCCC) || IS_ENABLED(CONFIG_SPL_BUILD))
> -             return -ENOTSUPP;
> +     struct stm32mp_bsec_plat *plat;
> +
> +     /* only permanent write lock is supported in U-Boot */
> +     if (!(val & BSEC_LOCK_PERM)) {
> +             dev_dbg(dev, "lock option without BSEC_LOCK_PERM: %x\n", val);
> +             return 0; /* nothing to do */
> +     }
>  
> -     if (val == 1)
> +     if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
>               return stm32_smc_exec(STM32_SMC_BSEC,
>                                     STM32_SMC_WRLOCK_OTP,
>                                     otp, 0);
> -     if (val == 0)
> -             return 0; /* nothing to do */
> +
> +     plat = dev_get_plat(dev);
> +
> +     return bsec_permanent_lock_otp(dev, plat->base, otp);
>  
>       return -EINVAL;
>  }
Reviewed-by: Patrice Chotard <patrice.chot...@foss.st.com>

Thanks
Patrice

Reply via email to