1*ae6542f6SNicolas Le Bayon /* 2*ae6542f6SNicolas Le Bayon * Copyright (c) 2024, STMicroelectronics - All Rights Reserved 3*ae6542f6SNicolas Le Bayon * 4*ae6542f6SNicolas Le Bayon * SPDX-License-Identifier: BSD-3-Clause 5*ae6542f6SNicolas Le Bayon */ 6*ae6542f6SNicolas Le Bayon 7*ae6542f6SNicolas Le Bayon #include <assert.h> 8*ae6542f6SNicolas Le Bayon #include <limits.h> 9*ae6542f6SNicolas Le Bayon 10*ae6542f6SNicolas Le Bayon #include <arch_helpers.h> 11*ae6542f6SNicolas Le Bayon #include <common/debug.h> 12*ae6542f6SNicolas Le Bayon #include <drivers/st/bsec.h> 13*ae6542f6SNicolas Le Bayon #include <drivers/st/bsec3_reg.h> 14*ae6542f6SNicolas Le Bayon #include <drivers/st/stm32mp_reset.h> 15*ae6542f6SNicolas Le Bayon #include <lib/mmio.h> 16*ae6542f6SNicolas Le Bayon #include <lib/spinlock.h> 17*ae6542f6SNicolas Le Bayon #include <libfdt.h> 18*ae6542f6SNicolas Le Bayon 19*ae6542f6SNicolas Le Bayon #include <platform_def.h> 20*ae6542f6SNicolas Le Bayon 21*ae6542f6SNicolas Le Bayon #define BSEC_IP_VERSION_1_0 U(0x10) 22*ae6542f6SNicolas Le Bayon #define BSEC_IP_ID_3 U(0x100033) 23*ae6542f6SNicolas Le Bayon 24*ae6542f6SNicolas Le Bayon #define MAX_NB_TRIES U(3) 25*ae6542f6SNicolas Le Bayon 26*ae6542f6SNicolas Le Bayon /* 27*ae6542f6SNicolas Le Bayon * IP configuration 28*ae6542f6SNicolas Le Bayon */ 29*ae6542f6SNicolas Le Bayon #define BSEC_OTP_MASK GENMASK_32(4, 0) 30*ae6542f6SNicolas Le Bayon #define BSEC_OTP_BANK_SHIFT U(5) 31*ae6542f6SNicolas Le Bayon #define BSEC_TIMEOUT_VALUE U(0x800000) /* ~7sec @1.2GHz */ 32*ae6542f6SNicolas Le Bayon 33*ae6542f6SNicolas Le Bayon /* Magic use to indicated valid SHADOW = 'B' 'S' 'E' 'C' */ 34*ae6542f6SNicolas Le Bayon #define BSEC_MAGIC U(0x42534543) 35*ae6542f6SNicolas Le Bayon 36*ae6542f6SNicolas Le Bayon #define OTP_MAX_SIZE (STM32MP2_OTP_MAX_ID + U(1)) 37*ae6542f6SNicolas Le Bayon 38*ae6542f6SNicolas Le Bayon struct bsec_shadow { 39*ae6542f6SNicolas Le Bayon uint32_t magic; 40*ae6542f6SNicolas Le Bayon uint32_t state; 41*ae6542f6SNicolas Le Bayon uint32_t value[OTP_MAX_SIZE]; 42*ae6542f6SNicolas Le Bayon uint32_t status[OTP_MAX_SIZE]; 43*ae6542f6SNicolas Le Bayon }; 44*ae6542f6SNicolas Le Bayon 45*ae6542f6SNicolas Le Bayon static uint32_t otp_bank(uint32_t otp) 46*ae6542f6SNicolas Le Bayon { 47*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 48*ae6542f6SNicolas Le Bayon panic(); 49*ae6542f6SNicolas Le Bayon } 50*ae6542f6SNicolas Le Bayon 51*ae6542f6SNicolas Le Bayon return (otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT; 52*ae6542f6SNicolas Le Bayon } 53*ae6542f6SNicolas Le Bayon 54*ae6542f6SNicolas Le Bayon static uint32_t otp_bit_mask(uint32_t otp) 55*ae6542f6SNicolas Le Bayon { 56*ae6542f6SNicolas Le Bayon return BIT(otp & BSEC_OTP_MASK); 57*ae6542f6SNicolas Le Bayon } 58*ae6542f6SNicolas Le Bayon 59*ae6542f6SNicolas Le Bayon /* 60*ae6542f6SNicolas Le Bayon * bsec_get_status: return status register value. 61*ae6542f6SNicolas Le Bayon */ 62*ae6542f6SNicolas Le Bayon static uint32_t bsec_get_status(void) 63*ae6542f6SNicolas Le Bayon { 64*ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_OTPSR); 65*ae6542f6SNicolas Le Bayon } 66*ae6542f6SNicolas Le Bayon 67*ae6542f6SNicolas Le Bayon /* 68*ae6542f6SNicolas Le Bayon * bsec_get_version: return BSEC version. 69*ae6542f6SNicolas Le Bayon */ 70*ae6542f6SNicolas Le Bayon static uint32_t bsec_get_version(void) 71*ae6542f6SNicolas Le Bayon { 72*ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_VERR) & BSEC_VERR_MASK; 73*ae6542f6SNicolas Le Bayon } 74*ae6542f6SNicolas Le Bayon 75*ae6542f6SNicolas Le Bayon /* 76*ae6542f6SNicolas Le Bayon * bsec_get_id: return BSEC ID. 77*ae6542f6SNicolas Le Bayon */ 78*ae6542f6SNicolas Le Bayon static uint32_t bsec_get_id(void) 79*ae6542f6SNicolas Le Bayon { 80*ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_IPIDR); 81*ae6542f6SNicolas Le Bayon } 82*ae6542f6SNicolas Le Bayon 83*ae6542f6SNicolas Le Bayon static bool is_fuse_shadowed(uint32_t otp) 84*ae6542f6SNicolas Le Bayon { 85*ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp); 86*ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp); 87*ae6542f6SNicolas Le Bayon uint32_t bank_value; 88*ae6542f6SNicolas Le Bayon 89*ae6542f6SNicolas Le Bayon bank_value = mmio_read_32(BSEC_BASE + BSEC_SFSR(bank)); 90*ae6542f6SNicolas Le Bayon 91*ae6542f6SNicolas Le Bayon if ((bank_value & otp_mask) != 0U) { 92*ae6542f6SNicolas Le Bayon return true; 93*ae6542f6SNicolas Le Bayon } 94*ae6542f6SNicolas Le Bayon 95*ae6542f6SNicolas Le Bayon return false; 96*ae6542f6SNicolas Le Bayon } 97*ae6542f6SNicolas Le Bayon 98*ae6542f6SNicolas Le Bayon static void poll_otp_status_busy(void) 99*ae6542f6SNicolas Le Bayon { 100*ae6542f6SNicolas Le Bayon uint32_t timeout = BSEC_TIMEOUT_VALUE; 101*ae6542f6SNicolas Le Bayon 102*ae6542f6SNicolas Le Bayon while (((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) && (timeout != 0U)) { 103*ae6542f6SNicolas Le Bayon timeout--; 104*ae6542f6SNicolas Le Bayon } 105*ae6542f6SNicolas Le Bayon 106*ae6542f6SNicolas Le Bayon if ((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) { 107*ae6542f6SNicolas Le Bayon ERROR("BSEC timeout\n"); 108*ae6542f6SNicolas Le Bayon panic(); 109*ae6542f6SNicolas Le Bayon } 110*ae6542f6SNicolas Le Bayon } 111*ae6542f6SNicolas Le Bayon 112*ae6542f6SNicolas Le Bayon static uint32_t check_read_error(uint32_t otp) 113*ae6542f6SNicolas Le Bayon { 114*ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status(); 115*ae6542f6SNicolas Le Bayon 116*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_SECF) != 0U) { 117*ae6542f6SNicolas Le Bayon VERBOSE("BSEC read %u single error correction detected\n", otp); 118*ae6542f6SNicolas Le Bayon } 119*ae6542f6SNicolas Le Bayon 120*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_PPLF) != 0U) { 121*ae6542f6SNicolas Le Bayon VERBOSE("BSEC read %u permanent programming lock detected.\n", otp); 122*ae6542f6SNicolas Le Bayon } 123*ae6542f6SNicolas Le Bayon 124*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_PPLMF) != 0U) { 125*ae6542f6SNicolas Le Bayon ERROR("BSEC read %u error 0x%x\n", otp, status); 126*ae6542f6SNicolas Le Bayon return BSEC_ERROR; 127*ae6542f6SNicolas Le Bayon } 128*ae6542f6SNicolas Le Bayon 129*ae6542f6SNicolas Le Bayon if ((status & (BSEC_OTPSR_DISTURBF | BSEC_OTPSR_DEDF | BSEC_OTPSR_AMEF)) != 0U) { 130*ae6542f6SNicolas Le Bayon ERROR("BSEC read %u error 0x%x with invalid FVR\n", otp, status); 131*ae6542f6SNicolas Le Bayon return BSEC_RETRY; 132*ae6542f6SNicolas Le Bayon } 133*ae6542f6SNicolas Le Bayon 134*ae6542f6SNicolas Le Bayon return BSEC_OK; 135*ae6542f6SNicolas Le Bayon } 136*ae6542f6SNicolas Le Bayon 137*ae6542f6SNicolas Le Bayon static uint32_t check_program_error(uint32_t otp) 138*ae6542f6SNicolas Le Bayon { 139*ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status(); 140*ae6542f6SNicolas Le Bayon 141*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_PROGFAIL) != 0U) { 142*ae6542f6SNicolas Le Bayon ERROR("BSEC program %u error 0x%x\n", otp, status); 143*ae6542f6SNicolas Le Bayon return BSEC_RETRY; 144*ae6542f6SNicolas Le Bayon } 145*ae6542f6SNicolas Le Bayon 146*ae6542f6SNicolas Le Bayon return BSEC_OK; 147*ae6542f6SNicolas Le Bayon } 148*ae6542f6SNicolas Le Bayon 149*ae6542f6SNicolas Le Bayon static void check_reset_error(void) 150*ae6542f6SNicolas Le Bayon { 151*ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status(); 152*ae6542f6SNicolas Le Bayon 153*ae6542f6SNicolas Le Bayon /* check initial status reporting */ 154*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_BUSY) != 0U) { 155*ae6542f6SNicolas Le Bayon VERBOSE("BSEC reset and busy when OTPSR read\n"); 156*ae6542f6SNicolas Le Bayon } 157*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_HIDEUP) != 0U) { 158*ae6542f6SNicolas Le Bayon VERBOSE("BSEC upper fuse are not accessible (HIDEUP)\n"); 159*ae6542f6SNicolas Le Bayon } 160*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_OTPSEC) != 0U) { 161*ae6542f6SNicolas Le Bayon VERBOSE("BSEC reset single error correction detected\n"); 162*ae6542f6SNicolas Le Bayon } 163*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_OTPNVIR) == 0U) { 164*ae6542f6SNicolas Le Bayon VERBOSE("BSEC reset first fuse word 0 is detected zero\n"); 165*ae6542f6SNicolas Le Bayon } 166*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_OTPERR) != 0U) { 167*ae6542f6SNicolas Le Bayon ERROR("BSEC reset critical error 0x%x\n", status); 168*ae6542f6SNicolas Le Bayon panic(); 169*ae6542f6SNicolas Le Bayon } 170*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_FUSEOK) != BSEC_OTPSR_FUSEOK) { 171*ae6542f6SNicolas Le Bayon ERROR("BSEC reset critical error 0x%x\n", status); 172*ae6542f6SNicolas Le Bayon panic(); 173*ae6542f6SNicolas Le Bayon } 174*ae6542f6SNicolas Le Bayon } 175*ae6542f6SNicolas Le Bayon 176*ae6542f6SNicolas Le Bayon static bool is_bsec_write_locked(void) 177*ae6542f6SNicolas Le Bayon { 178*ae6542f6SNicolas Le Bayon return (mmio_read_32(BSEC_BASE + BSEC_LOCKR) & BSEC_LOCKR_GWLOCK_MASK) != 0U; 179*ae6542f6SNicolas Le Bayon } 180*ae6542f6SNicolas Le Bayon 181*ae6542f6SNicolas Le Bayon /* 182*ae6542f6SNicolas Le Bayon * bsec_probe: initialize BSEC driver. 183*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 184*ae6542f6SNicolas Le Bayon */ 185*ae6542f6SNicolas Le Bayon uint32_t bsec_probe(void) 186*ae6542f6SNicolas Le Bayon { 187*ae6542f6SNicolas Le Bayon uint32_t version = bsec_get_version(); 188*ae6542f6SNicolas Le Bayon uint32_t id = bsec_get_id(); 189*ae6542f6SNicolas Le Bayon 190*ae6542f6SNicolas Le Bayon if ((version != BSEC_IP_VERSION_1_0) || (id != BSEC_IP_ID_3)) { 191*ae6542f6SNicolas Le Bayon ERROR("%s: version = 0x%x, id = 0x%x\n", __func__, version, id); 192*ae6542f6SNicolas Le Bayon panic(); 193*ae6542f6SNicolas Le Bayon } 194*ae6542f6SNicolas Le Bayon 195*ae6542f6SNicolas Le Bayon check_reset_error(); 196*ae6542f6SNicolas Le Bayon 197*ae6542f6SNicolas Le Bayon return BSEC_OK; 198*ae6542f6SNicolas Le Bayon } 199*ae6542f6SNicolas Le Bayon 200*ae6542f6SNicolas Le Bayon /* 201*ae6542f6SNicolas Le Bayon * bsec_shadow_register: copy SAFMEM OTP to BSEC data. 202*ae6542f6SNicolas Le Bayon * otp: OTP number. 203*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 204*ae6542f6SNicolas Le Bayon */ 205*ae6542f6SNicolas Le Bayon static uint32_t bsec_shadow_register(uint32_t otp) 206*ae6542f6SNicolas Le Bayon { 207*ae6542f6SNicolas Le Bayon uint32_t result; 208*ae6542f6SNicolas Le Bayon uint32_t i; 209*ae6542f6SNicolas Le Bayon bool value; 210*ae6542f6SNicolas Le Bayon 211*ae6542f6SNicolas Le Bayon result = bsec_read_sr_lock(otp, &value); 212*ae6542f6SNicolas Le Bayon if (result != BSEC_OK) { 213*ae6542f6SNicolas Le Bayon WARN("BSEC: %u Sticky-read bit read Error %u\n", otp, result); 214*ae6542f6SNicolas Le Bayon } else if (value) { 215*ae6542f6SNicolas Le Bayon VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", otp); 216*ae6542f6SNicolas Le Bayon } 217*ae6542f6SNicolas Le Bayon 218*ae6542f6SNicolas Le Bayon for (i = 0U; i < MAX_NB_TRIES; i++) { 219*ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp); 220*ae6542f6SNicolas Le Bayon 221*ae6542f6SNicolas Le Bayon poll_otp_status_busy(); 222*ae6542f6SNicolas Le Bayon 223*ae6542f6SNicolas Le Bayon result = check_read_error(otp); 224*ae6542f6SNicolas Le Bayon if (result != BSEC_RETRY) { 225*ae6542f6SNicolas Le Bayon break; 226*ae6542f6SNicolas Le Bayon } 227*ae6542f6SNicolas Le Bayon } 228*ae6542f6SNicolas Le Bayon 229*ae6542f6SNicolas Le Bayon return result; 230*ae6542f6SNicolas Le Bayon } 231*ae6542f6SNicolas Le Bayon 232*ae6542f6SNicolas Le Bayon /* 233*ae6542f6SNicolas Le Bayon * bsec_write_otp: write a value in shadow OTP. 234*ae6542f6SNicolas Le Bayon * val: value to program. 235*ae6542f6SNicolas Le Bayon * otp: OTP number. 236*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 237*ae6542f6SNicolas Le Bayon */ 238*ae6542f6SNicolas Le Bayon uint32_t bsec_write_otp(uint32_t val, uint32_t otp) 239*ae6542f6SNicolas Le Bayon { 240*ae6542f6SNicolas Le Bayon bool state; 241*ae6542f6SNicolas Le Bayon uint32_t result; 242*ae6542f6SNicolas Le Bayon 243*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 244*ae6542f6SNicolas Le Bayon panic(); 245*ae6542f6SNicolas Le Bayon } 246*ae6542f6SNicolas Le Bayon 247*ae6542f6SNicolas Le Bayon if (!is_fuse_shadowed(otp)) { 248*ae6542f6SNicolas Le Bayon return BSEC_ERROR; 249*ae6542f6SNicolas Le Bayon } 250*ae6542f6SNicolas Le Bayon 251*ae6542f6SNicolas Le Bayon if (is_bsec_write_locked()) { 252*ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED; 253*ae6542f6SNicolas Le Bayon } 254*ae6542f6SNicolas Le Bayon 255*ae6542f6SNicolas Le Bayon result = bsec_read_sw_lock(otp, &state); 256*ae6542f6SNicolas Le Bayon if (result != BSEC_OK) { 257*ae6542f6SNicolas Le Bayon WARN("Shadow register is SW locked\n"); 258*ae6542f6SNicolas Le Bayon return result; 259*ae6542f6SNicolas Le Bayon } 260*ae6542f6SNicolas Le Bayon 261*ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_FVR(otp), val); 262*ae6542f6SNicolas Le Bayon 263*ae6542f6SNicolas Le Bayon return BSEC_OK; 264*ae6542f6SNicolas Le Bayon } 265*ae6542f6SNicolas Le Bayon 266*ae6542f6SNicolas Le Bayon /* 267*ae6542f6SNicolas Le Bayon * bsec_program_otp: program a bit in SAFMEM after the prog. 268*ae6542f6SNicolas Le Bayon * The OTP data is not refreshed. 269*ae6542f6SNicolas Le Bayon * val: value to program. 270*ae6542f6SNicolas Le Bayon * otp: OTP number. 271*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 272*ae6542f6SNicolas Le Bayon */ 273*ae6542f6SNicolas Le Bayon uint32_t bsec_program_otp(uint32_t val, uint32_t otp) 274*ae6542f6SNicolas Le Bayon { 275*ae6542f6SNicolas Le Bayon uint32_t result; 276*ae6542f6SNicolas Le Bayon uint32_t i; 277*ae6542f6SNicolas Le Bayon bool value; 278*ae6542f6SNicolas Le Bayon 279*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 280*ae6542f6SNicolas Le Bayon panic(); 281*ae6542f6SNicolas Le Bayon } 282*ae6542f6SNicolas Le Bayon 283*ae6542f6SNicolas Le Bayon if (is_bsec_write_locked() == true) { 284*ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED; 285*ae6542f6SNicolas Le Bayon } 286*ae6542f6SNicolas Le Bayon 287*ae6542f6SNicolas Le Bayon result = bsec_read_sp_lock(otp, &value); 288*ae6542f6SNicolas Le Bayon if (result != BSEC_OK) { 289*ae6542f6SNicolas Le Bayon WARN("BSEC: %u Sticky-prog bit read Error %u\n", otp, result); 290*ae6542f6SNicolas Le Bayon } else if (value) { 291*ae6542f6SNicolas Le Bayon WARN("BSEC: OTP locked, prog will be ignored\n"); 292*ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED; 293*ae6542f6SNicolas Le Bayon } 294*ae6542f6SNicolas Le Bayon 295*ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_WDR, val); 296*ae6542f6SNicolas Le Bayon 297*ae6542f6SNicolas Le Bayon for (i = 0U; i < MAX_NB_TRIES; i++) { 298*ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp | BSEC_OTPCR_PROG); 299*ae6542f6SNicolas Le Bayon 300*ae6542f6SNicolas Le Bayon poll_otp_status_busy(); 301*ae6542f6SNicolas Le Bayon 302*ae6542f6SNicolas Le Bayon result = check_program_error(otp); 303*ae6542f6SNicolas Le Bayon if (result != BSEC_RETRY) { 304*ae6542f6SNicolas Le Bayon break; 305*ae6542f6SNicolas Le Bayon } 306*ae6542f6SNicolas Le Bayon } 307*ae6542f6SNicolas Le Bayon 308*ae6542f6SNicolas Le Bayon return result; 309*ae6542f6SNicolas Le Bayon } 310*ae6542f6SNicolas Le Bayon 311*ae6542f6SNicolas Le Bayon /* 312*ae6542f6SNicolas Le Bayon * bsec_read_debug_conf: read debug configuration. 313*ae6542f6SNicolas Le Bayon */ 314*ae6542f6SNicolas Le Bayon uint32_t bsec_read_debug_conf(void) 315*ae6542f6SNicolas Le Bayon { 316*ae6542f6SNicolas Le Bayon return mmio_read_32(BSEC_BASE + BSEC_DENR); 317*ae6542f6SNicolas Le Bayon } 318*ae6542f6SNicolas Le Bayon 319*ae6542f6SNicolas Le Bayon static uint32_t bsec_lock_register_set(uint32_t offset, uint32_t mask) 320*ae6542f6SNicolas Le Bayon { 321*ae6542f6SNicolas Le Bayon uint32_t value = mmio_read_32(BSEC_BASE + offset); 322*ae6542f6SNicolas Le Bayon 323*ae6542f6SNicolas Le Bayon /* The lock is already set */ 324*ae6542f6SNicolas Le Bayon if ((value & mask) != 0U) { 325*ae6542f6SNicolas Le Bayon return BSEC_OK; 326*ae6542f6SNicolas Le Bayon } 327*ae6542f6SNicolas Le Bayon 328*ae6542f6SNicolas Le Bayon if (is_bsec_write_locked()) { 329*ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED; 330*ae6542f6SNicolas Le Bayon } 331*ae6542f6SNicolas Le Bayon 332*ae6542f6SNicolas Le Bayon value |= mask; 333*ae6542f6SNicolas Le Bayon 334*ae6542f6SNicolas Le Bayon mmio_write_32(BSEC_BASE + offset, value); 335*ae6542f6SNicolas Le Bayon 336*ae6542f6SNicolas Le Bayon return BSEC_OK; 337*ae6542f6SNicolas Le Bayon } 338*ae6542f6SNicolas Le Bayon 339*ae6542f6SNicolas Le Bayon static bool bsec_lock_register_get(uint32_t offset, uint32_t mask) 340*ae6542f6SNicolas Le Bayon { 341*ae6542f6SNicolas Le Bayon uint32_t value = mmio_read_32(BSEC_BASE + offset); 342*ae6542f6SNicolas Le Bayon 343*ae6542f6SNicolas Le Bayon return (value & mask) != 0U; 344*ae6542f6SNicolas Le Bayon } 345*ae6542f6SNicolas Le Bayon 346*ae6542f6SNicolas Le Bayon /* 347*ae6542f6SNicolas Le Bayon * bsec_set_sr_lock: set shadow-read lock. 348*ae6542f6SNicolas Le Bayon * otp: OTP number. 349*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 350*ae6542f6SNicolas Le Bayon */ 351*ae6542f6SNicolas Le Bayon uint32_t bsec_set_sr_lock(uint32_t otp) 352*ae6542f6SNicolas Le Bayon { 353*ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp); 354*ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp); 355*ae6542f6SNicolas Le Bayon 356*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 357*ae6542f6SNicolas Le Bayon panic(); 358*ae6542f6SNicolas Le Bayon } 359*ae6542f6SNicolas Le Bayon 360*ae6542f6SNicolas Le Bayon return bsec_lock_register_set(BSEC_SRLOCK(bank), otp_mask); 361*ae6542f6SNicolas Le Bayon } 362*ae6542f6SNicolas Le Bayon 363*ae6542f6SNicolas Le Bayon /* 364*ae6542f6SNicolas Le Bayon * bsec_read_sr_lock: read shadow-read lock. 365*ae6542f6SNicolas Le Bayon * otp: OTP number. 366*ae6542f6SNicolas Le Bayon * value: read value (true or false). 367*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 368*ae6542f6SNicolas Le Bayon */ 369*ae6542f6SNicolas Le Bayon uint32_t bsec_read_sr_lock(uint32_t otp, bool *value) 370*ae6542f6SNicolas Le Bayon { 371*ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp); 372*ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp); 373*ae6542f6SNicolas Le Bayon 374*ae6542f6SNicolas Le Bayon assert(value != NULL); 375*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 376*ae6542f6SNicolas Le Bayon panic(); 377*ae6542f6SNicolas Le Bayon } 378*ae6542f6SNicolas Le Bayon 379*ae6542f6SNicolas Le Bayon *value = bsec_lock_register_get(BSEC_SRLOCK(bank), otp_mask); 380*ae6542f6SNicolas Le Bayon 381*ae6542f6SNicolas Le Bayon return BSEC_OK; 382*ae6542f6SNicolas Le Bayon } 383*ae6542f6SNicolas Le Bayon 384*ae6542f6SNicolas Le Bayon /* 385*ae6542f6SNicolas Le Bayon * bsec_set_sw_lock: set shadow-write lock. 386*ae6542f6SNicolas Le Bayon * otp: OTP number. 387*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 388*ae6542f6SNicolas Le Bayon */ 389*ae6542f6SNicolas Le Bayon uint32_t bsec_set_sw_lock(uint32_t otp) 390*ae6542f6SNicolas Le Bayon { 391*ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp); 392*ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp); 393*ae6542f6SNicolas Le Bayon 394*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 395*ae6542f6SNicolas Le Bayon panic(); 396*ae6542f6SNicolas Le Bayon } 397*ae6542f6SNicolas Le Bayon 398*ae6542f6SNicolas Le Bayon return bsec_lock_register_set(BSEC_SWLOCK(bank), otp_mask); 399*ae6542f6SNicolas Le Bayon } 400*ae6542f6SNicolas Le Bayon 401*ae6542f6SNicolas Le Bayon /* 402*ae6542f6SNicolas Le Bayon * bsec_read_sw_lock: read shadow-write lock. 403*ae6542f6SNicolas Le Bayon * otp: OTP number. 404*ae6542f6SNicolas Le Bayon * value: read value (true or false). 405*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 406*ae6542f6SNicolas Le Bayon */ 407*ae6542f6SNicolas Le Bayon uint32_t bsec_read_sw_lock(uint32_t otp, bool *value) 408*ae6542f6SNicolas Le Bayon { 409*ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp); 410*ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp); 411*ae6542f6SNicolas Le Bayon 412*ae6542f6SNicolas Le Bayon assert(value != NULL); 413*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 414*ae6542f6SNicolas Le Bayon panic(); 415*ae6542f6SNicolas Le Bayon } 416*ae6542f6SNicolas Le Bayon 417*ae6542f6SNicolas Le Bayon *value = bsec_lock_register_get(BSEC_SWLOCK(bank), otp_mask); 418*ae6542f6SNicolas Le Bayon 419*ae6542f6SNicolas Le Bayon return BSEC_OK; 420*ae6542f6SNicolas Le Bayon } 421*ae6542f6SNicolas Le Bayon 422*ae6542f6SNicolas Le Bayon /* 423*ae6542f6SNicolas Le Bayon * bsec_set_sp_lock: set shadow-program lock. 424*ae6542f6SNicolas Le Bayon * otp: OTP number. 425*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 426*ae6542f6SNicolas Le Bayon */ 427*ae6542f6SNicolas Le Bayon uint32_t bsec_set_sp_lock(uint32_t otp) 428*ae6542f6SNicolas Le Bayon { 429*ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp); 430*ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp); 431*ae6542f6SNicolas Le Bayon 432*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 433*ae6542f6SNicolas Le Bayon panic(); 434*ae6542f6SNicolas Le Bayon } 435*ae6542f6SNicolas Le Bayon 436*ae6542f6SNicolas Le Bayon return bsec_lock_register_set(BSEC_SPLOCK(bank), otp_mask); 437*ae6542f6SNicolas Le Bayon } 438*ae6542f6SNicolas Le Bayon 439*ae6542f6SNicolas Le Bayon /* 440*ae6542f6SNicolas Le Bayon * bsec_read_sp_lock: read shadow-program lock. 441*ae6542f6SNicolas Le Bayon * otp: OTP number. 442*ae6542f6SNicolas Le Bayon * value: read value (true or false). 443*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 444*ae6542f6SNicolas Le Bayon */ 445*ae6542f6SNicolas Le Bayon uint32_t bsec_read_sp_lock(uint32_t otp, bool *value) 446*ae6542f6SNicolas Le Bayon { 447*ae6542f6SNicolas Le Bayon uint32_t bank = otp_bank(otp); 448*ae6542f6SNicolas Le Bayon uint32_t otp_mask = otp_bit_mask(otp); 449*ae6542f6SNicolas Le Bayon 450*ae6542f6SNicolas Le Bayon assert(value != NULL); 451*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 452*ae6542f6SNicolas Le Bayon panic(); 453*ae6542f6SNicolas Le Bayon } 454*ae6542f6SNicolas Le Bayon 455*ae6542f6SNicolas Le Bayon *value = bsec_lock_register_get(BSEC_SPLOCK(bank), otp_mask); 456*ae6542f6SNicolas Le Bayon 457*ae6542f6SNicolas Le Bayon return BSEC_OK; 458*ae6542f6SNicolas Le Bayon } 459*ae6542f6SNicolas Le Bayon 460*ae6542f6SNicolas Le Bayon /* 461*ae6542f6SNicolas Le Bayon * bsec_get_secure_state: read state in BSEC status register. 462*ae6542f6SNicolas Le Bayon * return: secure state 463*ae6542f6SNicolas Le Bayon */ 464*ae6542f6SNicolas Le Bayon uint32_t bsec_get_secure_state(void) 465*ae6542f6SNicolas Le Bayon { 466*ae6542f6SNicolas Le Bayon uint32_t state = BSEC_STATE_INVALID; 467*ae6542f6SNicolas Le Bayon uint32_t status = bsec_get_status(); 468*ae6542f6SNicolas Le Bayon uint32_t bsec_sr = mmio_read_32(BSEC_BASE + BSEC_SR); 469*ae6542f6SNicolas Le Bayon 470*ae6542f6SNicolas Le Bayon if ((status & BSEC_OTPSR_FUSEOK) == BSEC_OTPSR_FUSEOK) { 471*ae6542f6SNicolas Le Bayon /* NVSTATE is only valid if FUSEOK */ 472*ae6542f6SNicolas Le Bayon uint32_t nvstates = (bsec_sr & BSEC_SR_NVSTATE_MASK) >> BSEC_SR_NVSTATE_SHIFT; 473*ae6542f6SNicolas Le Bayon 474*ae6542f6SNicolas Le Bayon if (nvstates == BSEC_SR_NVSTATE_OPEN) { 475*ae6542f6SNicolas Le Bayon state = BSEC_STATE_SEC_OPEN; 476*ae6542f6SNicolas Le Bayon } else if (nvstates == BSEC_SR_NVSTATE_CLOSED) { 477*ae6542f6SNicolas Le Bayon state = BSEC_STATE_SEC_CLOSED; 478*ae6542f6SNicolas Le Bayon } else { 479*ae6542f6SNicolas Le Bayon VERBOSE("%s nvstates = %u\n", __func__, nvstates); 480*ae6542f6SNicolas Le Bayon } 481*ae6542f6SNicolas Le Bayon } 482*ae6542f6SNicolas Le Bayon 483*ae6542f6SNicolas Le Bayon return state; 484*ae6542f6SNicolas Le Bayon } 485*ae6542f6SNicolas Le Bayon 486*ae6542f6SNicolas Le Bayon /* 487*ae6542f6SNicolas Le Bayon * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value 488*ae6542f6SNicolas Le Bayon * val: read value. 489*ae6542f6SNicolas Le Bayon * otp: OTP number. 490*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 491*ae6542f6SNicolas Le Bayon */ 492*ae6542f6SNicolas Le Bayon uint32_t bsec_shadow_read_otp(uint32_t *val, uint32_t otp) 493*ae6542f6SNicolas Le Bayon { 494*ae6542f6SNicolas Le Bayon assert(val != NULL); 495*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 496*ae6542f6SNicolas Le Bayon panic(); 497*ae6542f6SNicolas Le Bayon } 498*ae6542f6SNicolas Le Bayon 499*ae6542f6SNicolas Le Bayon *val = 0U; 500*ae6542f6SNicolas Le Bayon 501*ae6542f6SNicolas Le Bayon if (is_bsec_write_locked()) { 502*ae6542f6SNicolas Le Bayon return BSEC_WRITE_LOCKED; 503*ae6542f6SNicolas Le Bayon } 504*ae6542f6SNicolas Le Bayon 505*ae6542f6SNicolas Le Bayon if (!is_fuse_shadowed(otp)) { 506*ae6542f6SNicolas Le Bayon uint32_t result = bsec_shadow_register(otp); 507*ae6542f6SNicolas Le Bayon 508*ae6542f6SNicolas Le Bayon if (result != BSEC_OK) { 509*ae6542f6SNicolas Le Bayon ERROR("BSEC: %u Shadowing Error %u\n", otp, result); 510*ae6542f6SNicolas Le Bayon return result; 511*ae6542f6SNicolas Le Bayon } 512*ae6542f6SNicolas Le Bayon } 513*ae6542f6SNicolas Le Bayon 514*ae6542f6SNicolas Le Bayon *val = mmio_read_32(BSEC_BASE + BSEC_FVR(otp)); 515*ae6542f6SNicolas Le Bayon 516*ae6542f6SNicolas Le Bayon return BSEC_OK; 517*ae6542f6SNicolas Le Bayon } 518*ae6542f6SNicolas Le Bayon 519*ae6542f6SNicolas Le Bayon /* 520*ae6542f6SNicolas Le Bayon * bsec_read_otp: read an OTP data value. 521*ae6542f6SNicolas Le Bayon * val: read value. 522*ae6542f6SNicolas Le Bayon * otp: OTP number. 523*ae6542f6SNicolas Le Bayon * return value: BSEC_OK if no error. 524*ae6542f6SNicolas Le Bayon */ 525*ae6542f6SNicolas Le Bayon uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) 526*ae6542f6SNicolas Le Bayon { 527*ae6542f6SNicolas Le Bayon assert(val != NULL); 528*ae6542f6SNicolas Le Bayon if (otp > STM32MP2_OTP_MAX_ID) { 529*ae6542f6SNicolas Le Bayon panic(); 530*ae6542f6SNicolas Le Bayon } 531*ae6542f6SNicolas Le Bayon 532*ae6542f6SNicolas Le Bayon return bsec_shadow_read_otp(val, otp); 533*ae6542f6SNicolas Le Bayon } 534