On 2/12/20 7:37 PM, Patrick Delaunay wrote:
> Add BSEC lock access (read / write) at 0xC000 offset of misc driver.
> The write access only available for Trusted boot mode, based on new
> SMC STM32_SMC_WRLOCK_OTP.
>
> With the fuse command, the permanent lock status is accessed with
> 0x1000 offset (0xC000 - 0x800 for OTP sense/program
> divided by u32 size), for example:
>
> Read lock status of fuse 57 (0x39)
>
> STM32MP> fuse sense 0 0x1039 1
>
> Sensing bank 0:
>
> Word 0x1039:
>
> Set permanent lock of fuse 57 (0x39)
>
> STM32MP> fuse prog 0 0x1039 1
>
> Sensing bank 0:
>
> Word 0x1039:
>
> WARNING: the OTP lock is updated only after reboot
>
> WARING: Programming lock or fuses is an irreversible operation!
> This may brick your system.
>
> Signed-off-by: Patrick Delaunay
> ---
>
> arch/arm/mach-stm32mp/bsec.c | 88 +--
> arch/arm/mach-stm32mp/cpu.c | 6 --
> arch/arm/mach-stm32mp/include/mach/stm32.h| 9 +-
> .../mach-stm32mp/include/mach/stm32mp1_smc.h | 1 +
> doc/board/st/stm32mp1.rst | 34 ---
> 5 files changed, 95 insertions(+), 43 deletions(-)
>
> diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
> index 1d904caae1..3b923f088e 100644
> --- a/arch/arm/mach-stm32mp/bsec.c
> +++ b/arch/arm/mach-stm32mp/bsec.c
> @@ -12,8 +12,6 @@
> #include
>
> #define BSEC_OTP_MAX_VALUE 95
> -
> -#ifndef CONFIG_STM32MP1_TRUSTED
> #define BSEC_TIMEOUT_US 1
>
> /* BSEC REGISTER OFFSET (base relative) */
> @@ -24,9 +22,10 @@
> #define BSEC_OTP_LOCK_OFF0x010
> #define BSEC_DISTURBED_OFF 0x01C
> #define BSEC_ERROR_OFF 0x034
> -#define BSEC_SPLOCK_OFF 0x064 /* Program safmem sticky
> lock */
> -#define BSEC_SWLOCK_OFF 0x07C /* write in OTP sticky
> lock */
> -#define BSEC_SRLOCK_OFF 0x094 /* shadowing sticky lock
> */
> +#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet
> lock */
> +#define BSEC_SPLOCK_OFF 0x064 /* OTP write sticky lock
> */
> +#define BSEC_SWLOCK_OFF 0x07C /* shadow write sticky
> lock */
> +#define BSEC_SRLOCK_OFF 0x094 /* shadow read sticky
> lock */
> #define BSEC_OTP_DATA_OFF0x200
>
> /* BSEC_CONFIGURATION Register MASK */
> @@ -53,12 +52,12 @@
> #define BSEC_LOCK_PROGRAM0x04
>
> /**
> - * bsec_check_error() - Check status of one otp
> - * @base: base address of bsec IP
> + * bsec_lock() - manage lock for each type SR/SP/SW
> + * @address: address of bsec IP register
> * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
> - * Return: 0 if no error, -EAGAIN or -ENOTSUPP
> + * Return: true if locked else false
> */
> -static u32 bsec_check_error(u32 base, u32 otp)
> +static bool bsec_read_lock(u32 address, u32 otp)
> {
> u32 bit;
> u32 bank;
> @@ -66,21 +65,17 @@ static u32 bsec_check_error(u32 base, u32 otp)
> bit = 1 << (otp & OTP_LOCK_MASK);
> bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
>
> - if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
> - return -EAGAIN;
> - else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
> - return -ENOTSUPP;
> -
> - return 0;
> + return !!(readl(address + bank) & bit);
> }
>
> +#ifndef CONFIG_STM32MP1_TRUSTED
> /**
> - * bsec_lock() - manage lock for each type SR/SP/SW
> - * @address: address of bsec IP register
> + * bsec_check_error() - Check status of one otp
> + * @base: base address of bsec IP
> * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
> - * Return: true if locked else false
> + * Return: 0 if no error, -EAGAIN or -ENOTSUPP
> */
> -static bool bsec_read_lock(u32 address, u32 otp)
> +static u32 bsec_check_error(u32 base, u32 otp)
> {
> u32 bit;
> u32 bank;
> @@ -88,7 +83,12 @@ static bool bsec_read_lock(u32 address, u32 otp)
> bit = 1 << (otp & OTP_LOCK_MASK);
> bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
>
> - return !!(readl(address + bank) & bit);
> + if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
> + return -EAGAIN;
> + else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
> + return -ENOTSUPP;
> +
> + return 0;
> }
>
> /**
> @@ -324,6 +324,16 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev,
> u32 *val, u32 otp)
> #endif
> }
>
> +static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
> +{
> + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
> +
> + /* return OTP permanent write lock status */
> + *val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
> +
> + return 0;
> +}
> +
> static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)