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