1*072d7532SNicolas Le Bayon /* 2*072d7532SNicolas Le Bayon * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved 3*072d7532SNicolas Le Bayon * 4*072d7532SNicolas Le Bayon * SPDX-License-Identifier: BSD-3-Clause 5*072d7532SNicolas Le Bayon */ 6*072d7532SNicolas Le Bayon 7*072d7532SNicolas Le Bayon #include <assert.h> 8*072d7532SNicolas Le Bayon #include <limits.h> 9*072d7532SNicolas Le Bayon 10*072d7532SNicolas Le Bayon #include <arch_helpers.h> 11*072d7532SNicolas Le Bayon #include <common/debug.h> 12*072d7532SNicolas Le Bayon #include <drivers/st/bsec.h> 13*072d7532SNicolas Le Bayon #include <drivers/st/bsec2_reg.h> 14*072d7532SNicolas Le Bayon #include <lib/mmio.h> 15*072d7532SNicolas Le Bayon #include <lib/spinlock.h> 16*072d7532SNicolas Le Bayon #include <libfdt.h> 17*072d7532SNicolas Le Bayon 18*072d7532SNicolas Le Bayon #include <platform_def.h> 19*072d7532SNicolas Le Bayon 20*072d7532SNicolas Le Bayon #define BSEC_IP_VERSION_1_1 U(0x11) 21*072d7532SNicolas Le Bayon #define BSEC_IP_VERSION_2_0 U(0x20) 22*072d7532SNicolas Le Bayon #define BSEC_IP_ID_2 U(0x100032) 23*072d7532SNicolas Le Bayon 24*072d7532SNicolas Le Bayon #define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) 25*072d7532SNicolas Le Bayon 26*072d7532SNicolas Le Bayon static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused; 27*072d7532SNicolas Le Bayon 28*072d7532SNicolas Le Bayon static uint32_t bsec_power_safmem(bool power); 29*072d7532SNicolas Le Bayon 30*072d7532SNicolas Le Bayon /* BSEC access protection */ 31*072d7532SNicolas Le Bayon static spinlock_t bsec_spinlock; 32*072d7532SNicolas Le Bayon static uintptr_t bsec_base; 33*072d7532SNicolas Le Bayon 34*072d7532SNicolas Le Bayon static void bsec_lock(void) 35*072d7532SNicolas Le Bayon { 36*072d7532SNicolas Le Bayon if (stm32mp_lock_available()) { 37*072d7532SNicolas Le Bayon spin_lock(&bsec_spinlock); 38*072d7532SNicolas Le Bayon } 39*072d7532SNicolas Le Bayon } 40*072d7532SNicolas Le Bayon 41*072d7532SNicolas Le Bayon static void bsec_unlock(void) 42*072d7532SNicolas Le Bayon { 43*072d7532SNicolas Le Bayon if (stm32mp_lock_available()) { 44*072d7532SNicolas Le Bayon spin_unlock(&bsec_spinlock); 45*072d7532SNicolas Le Bayon } 46*072d7532SNicolas Le Bayon } 47*072d7532SNicolas Le Bayon 48*072d7532SNicolas Le Bayon static bool is_otp_invalid_mode(void) 49*072d7532SNicolas Le Bayon { 50*072d7532SNicolas Le Bayon bool ret = ((bsec_get_status() & BSEC_MODE_INVALID) == BSEC_MODE_INVALID); 51*072d7532SNicolas Le Bayon 52*072d7532SNicolas Le Bayon if (ret) { 53*072d7532SNicolas Le Bayon ERROR("OTP mode is OTP-INVALID\n"); 54*072d7532SNicolas Le Bayon } 55*072d7532SNicolas Le Bayon 56*072d7532SNicolas Le Bayon return ret; 57*072d7532SNicolas Le Bayon } 58*072d7532SNicolas Le Bayon 59*072d7532SNicolas Le Bayon #if defined(IMAGE_BL32) 60*072d7532SNicolas Le Bayon static int bsec_get_dt_node(struct dt_node_info *info) 61*072d7532SNicolas Le Bayon { 62*072d7532SNicolas Le Bayon int node; 63*072d7532SNicolas Le Bayon 64*072d7532SNicolas Le Bayon node = dt_get_node(info, -1, DT_BSEC_COMPAT); 65*072d7532SNicolas Le Bayon if (node < 0) { 66*072d7532SNicolas Le Bayon return -FDT_ERR_NOTFOUND; 67*072d7532SNicolas Le Bayon } 68*072d7532SNicolas Le Bayon 69*072d7532SNicolas Le Bayon return node; 70*072d7532SNicolas Le Bayon } 71*072d7532SNicolas Le Bayon 72*072d7532SNicolas Le Bayon static void enable_non_secure_access(uint32_t otp) 73*072d7532SNicolas Le Bayon { 74*072d7532SNicolas Le Bayon otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT); 75*072d7532SNicolas Le Bayon 76*072d7532SNicolas Le Bayon if (bsec_shadow_register(otp) != BSEC_OK) { 77*072d7532SNicolas Le Bayon panic(); 78*072d7532SNicolas Le Bayon } 79*072d7532SNicolas Le Bayon } 80*072d7532SNicolas Le Bayon 81*072d7532SNicolas Le Bayon static bool non_secure_can_access(uint32_t otp) 82*072d7532SNicolas Le Bayon { 83*072d7532SNicolas Le Bayon return (otp_nsec_access[otp / __WORD_BIT] & 84*072d7532SNicolas Le Bayon BIT(otp % __WORD_BIT)) != 0U; 85*072d7532SNicolas Le Bayon } 86*072d7532SNicolas Le Bayon 87*072d7532SNicolas Le Bayon static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node) 88*072d7532SNicolas Le Bayon { 89*072d7532SNicolas Le Bayon int bsec_subnode; 90*072d7532SNicolas Le Bayon 91*072d7532SNicolas Le Bayon fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { 92*072d7532SNicolas Le Bayon const fdt32_t *cuint; 93*072d7532SNicolas Le Bayon uint32_t otp; 94*072d7532SNicolas Le Bayon uint32_t i; 95*072d7532SNicolas Le Bayon uint32_t size; 96*072d7532SNicolas Le Bayon uint32_t offset; 97*072d7532SNicolas Le Bayon uint32_t length; 98*072d7532SNicolas Le Bayon 99*072d7532SNicolas Le Bayon cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL); 100*072d7532SNicolas Le Bayon if (cuint == NULL) { 101*072d7532SNicolas Le Bayon panic(); 102*072d7532SNicolas Le Bayon } 103*072d7532SNicolas Le Bayon 104*072d7532SNicolas Le Bayon offset = fdt32_to_cpu(*cuint); 105*072d7532SNicolas Le Bayon cuint++; 106*072d7532SNicolas Le Bayon length = fdt32_to_cpu(*cuint); 107*072d7532SNicolas Le Bayon 108*072d7532SNicolas Le Bayon otp = offset / sizeof(uint32_t); 109*072d7532SNicolas Le Bayon 110*072d7532SNicolas Le Bayon if (otp < STM32MP1_UPPER_OTP_START) { 111*072d7532SNicolas Le Bayon unsigned int otp_end = round_up(offset + length, 112*072d7532SNicolas Le Bayon sizeof(uint32_t)) / 113*072d7532SNicolas Le Bayon sizeof(uint32_t); 114*072d7532SNicolas Le Bayon 115*072d7532SNicolas Le Bayon if (otp_end > STM32MP1_UPPER_OTP_START) { 116*072d7532SNicolas Le Bayon /* 117*072d7532SNicolas Le Bayon * OTP crosses Lower/Upper boundary, consider 118*072d7532SNicolas Le Bayon * only the upper part. 119*072d7532SNicolas Le Bayon */ 120*072d7532SNicolas Le Bayon otp = STM32MP1_UPPER_OTP_START; 121*072d7532SNicolas Le Bayon length -= (STM32MP1_UPPER_OTP_START * 122*072d7532SNicolas Le Bayon sizeof(uint32_t)) - offset; 123*072d7532SNicolas Le Bayon offset = STM32MP1_UPPER_OTP_START * 124*072d7532SNicolas Le Bayon sizeof(uint32_t); 125*072d7532SNicolas Le Bayon 126*072d7532SNicolas Le Bayon WARN("OTP crosses Lower/Upper boundary\n"); 127*072d7532SNicolas Le Bayon } else { 128*072d7532SNicolas Le Bayon continue; 129*072d7532SNicolas Le Bayon } 130*072d7532SNicolas Le Bayon } 131*072d7532SNicolas Le Bayon 132*072d7532SNicolas Le Bayon if ((fdt_getprop(fdt, bsec_subnode, 133*072d7532SNicolas Le Bayon "st,non-secure-otp", NULL)) == NULL) { 134*072d7532SNicolas Le Bayon continue; 135*072d7532SNicolas Le Bayon } 136*072d7532SNicolas Le Bayon 137*072d7532SNicolas Le Bayon if (((offset % sizeof(uint32_t)) != 0U) || 138*072d7532SNicolas Le Bayon ((length % sizeof(uint32_t)) != 0U)) { 139*072d7532SNicolas Le Bayon ERROR("Unaligned non-secure OTP\n"); 140*072d7532SNicolas Le Bayon panic(); 141*072d7532SNicolas Le Bayon } 142*072d7532SNicolas Le Bayon 143*072d7532SNicolas Le Bayon size = length / sizeof(uint32_t); 144*072d7532SNicolas Le Bayon 145*072d7532SNicolas Le Bayon for (i = otp; i < (otp + size); i++) { 146*072d7532SNicolas Le Bayon enable_non_secure_access(i); 147*072d7532SNicolas Le Bayon } 148*072d7532SNicolas Le Bayon } 149*072d7532SNicolas Le Bayon } 150*072d7532SNicolas Le Bayon 151*072d7532SNicolas Le Bayon static void bsec_late_init(void) 152*072d7532SNicolas Le Bayon { 153*072d7532SNicolas Le Bayon void *fdt; 154*072d7532SNicolas Le Bayon int node; 155*072d7532SNicolas Le Bayon struct dt_node_info bsec_info; 156*072d7532SNicolas Le Bayon 157*072d7532SNicolas Le Bayon if (fdt_get_address(&fdt) == 0) { 158*072d7532SNicolas Le Bayon panic(); 159*072d7532SNicolas Le Bayon } 160*072d7532SNicolas Le Bayon 161*072d7532SNicolas Le Bayon node = bsec_get_dt_node(&bsec_info); 162*072d7532SNicolas Le Bayon if (node < 0) { 163*072d7532SNicolas Le Bayon panic(); 164*072d7532SNicolas Le Bayon } 165*072d7532SNicolas Le Bayon 166*072d7532SNicolas Le Bayon assert(bsec_base == bsec_info.base); 167*072d7532SNicolas Le Bayon 168*072d7532SNicolas Le Bayon bsec_dt_otp_nsec_access(fdt, node); 169*072d7532SNicolas Le Bayon } 170*072d7532SNicolas Le Bayon #endif 171*072d7532SNicolas Le Bayon 172*072d7532SNicolas Le Bayon static uint32_t otp_bank_offset(uint32_t otp) 173*072d7532SNicolas Le Bayon { 174*072d7532SNicolas Le Bayon assert(otp <= STM32MP1_OTP_MAX_ID); 175*072d7532SNicolas Le Bayon 176*072d7532SNicolas Le Bayon return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * 177*072d7532SNicolas Le Bayon sizeof(uint32_t); 178*072d7532SNicolas Le Bayon } 179*072d7532SNicolas Le Bayon 180*072d7532SNicolas Le Bayon /* 181*072d7532SNicolas Le Bayon * bsec_check_error: check BSEC error status. 182*072d7532SNicolas Le Bayon * otp: OTP number. 183*072d7532SNicolas Le Bayon * check_disturbed: check only error (false), 184*072d7532SNicolas Le Bayon * or error and disturbed status (true). 185*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 186*072d7532SNicolas Le Bayon */ 187*072d7532SNicolas Le Bayon static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed) 188*072d7532SNicolas Le Bayon { 189*072d7532SNicolas Le Bayon uint32_t bit = BIT(otp & BSEC_OTP_MASK); 190*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 191*072d7532SNicolas Le Bayon 192*072d7532SNicolas Le Bayon if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) { 193*072d7532SNicolas Le Bayon return BSEC_ERROR; 194*072d7532SNicolas Le Bayon } 195*072d7532SNicolas Le Bayon 196*072d7532SNicolas Le Bayon if (!check_disturbed) { 197*072d7532SNicolas Le Bayon return BSEC_OK; 198*072d7532SNicolas Le Bayon } 199*072d7532SNicolas Le Bayon 200*072d7532SNicolas Le Bayon if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { 201*072d7532SNicolas Le Bayon return BSEC_DISTURBED; 202*072d7532SNicolas Le Bayon } 203*072d7532SNicolas Le Bayon 204*072d7532SNicolas Le Bayon return BSEC_OK; 205*072d7532SNicolas Le Bayon } 206*072d7532SNicolas Le Bayon 207*072d7532SNicolas Le Bayon /* 208*072d7532SNicolas Le Bayon * bsec_probe: initialize BSEC driver. 209*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 210*072d7532SNicolas Le Bayon */ 211*072d7532SNicolas Le Bayon uint32_t bsec_probe(void) 212*072d7532SNicolas Le Bayon { 213*072d7532SNicolas Le Bayon bsec_base = BSEC_BASE; 214*072d7532SNicolas Le Bayon 215*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 216*072d7532SNicolas Le Bayon return BSEC_ERROR; 217*072d7532SNicolas Le Bayon } 218*072d7532SNicolas Le Bayon 219*072d7532SNicolas Le Bayon if ((((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_1_1) && 220*072d7532SNicolas Le Bayon ((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_2_0)) || 221*072d7532SNicolas Le Bayon (bsec_get_id() != BSEC_IP_ID_2)) { 222*072d7532SNicolas Le Bayon panic(); 223*072d7532SNicolas Le Bayon } 224*072d7532SNicolas Le Bayon 225*072d7532SNicolas Le Bayon #if defined(IMAGE_BL32) 226*072d7532SNicolas Le Bayon bsec_late_init(); 227*072d7532SNicolas Le Bayon #endif 228*072d7532SNicolas Le Bayon return BSEC_OK; 229*072d7532SNicolas Le Bayon } 230*072d7532SNicolas Le Bayon 231*072d7532SNicolas Le Bayon /* 232*072d7532SNicolas Le Bayon * bsec_get_base: return BSEC base address. 233*072d7532SNicolas Le Bayon */ 234*072d7532SNicolas Le Bayon uint32_t bsec_get_base(void) 235*072d7532SNicolas Le Bayon { 236*072d7532SNicolas Le Bayon return bsec_base; 237*072d7532SNicolas Le Bayon } 238*072d7532SNicolas Le Bayon 239*072d7532SNicolas Le Bayon /* 240*072d7532SNicolas Le Bayon * bsec_set_config: enable and configure BSEC. 241*072d7532SNicolas Le Bayon * cfg: pointer to param structure used to set register. 242*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 243*072d7532SNicolas Le Bayon */ 244*072d7532SNicolas Le Bayon uint32_t bsec_set_config(struct bsec_config *cfg) 245*072d7532SNicolas Le Bayon { 246*072d7532SNicolas Le Bayon uint32_t value; 247*072d7532SNicolas Le Bayon uint32_t result; 248*072d7532SNicolas Le Bayon 249*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 250*072d7532SNicolas Le Bayon return BSEC_ERROR; 251*072d7532SNicolas Le Bayon } 252*072d7532SNicolas Le Bayon 253*072d7532SNicolas Le Bayon value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) & 254*072d7532SNicolas Le Bayon BSEC_CONF_FRQ_MASK) | 255*072d7532SNicolas Le Bayon (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) & 256*072d7532SNicolas Le Bayon BSEC_CONF_PRG_WIDTH_MASK) | 257*072d7532SNicolas Le Bayon (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) & 258*072d7532SNicolas Le Bayon BSEC_CONF_TREAD_MASK)); 259*072d7532SNicolas Le Bayon 260*072d7532SNicolas Le Bayon bsec_lock(); 261*072d7532SNicolas Le Bayon 262*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value); 263*072d7532SNicolas Le Bayon 264*072d7532SNicolas Le Bayon bsec_unlock(); 265*072d7532SNicolas Le Bayon 266*072d7532SNicolas Le Bayon result = bsec_power_safmem((bool)cfg->power & 267*072d7532SNicolas Le Bayon BSEC_CONF_POWER_UP_MASK); 268*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 269*072d7532SNicolas Le Bayon return result; 270*072d7532SNicolas Le Bayon } 271*072d7532SNicolas Le Bayon 272*072d7532SNicolas Le Bayon value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) & 273*072d7532SNicolas Le Bayon UPPER_OTP_LOCK_MASK) | 274*072d7532SNicolas Le Bayon (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) & 275*072d7532SNicolas Le Bayon DENREG_LOCK_MASK) | 276*072d7532SNicolas Le Bayon (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) & 277*072d7532SNicolas Le Bayon GPLOCK_LOCK_MASK)); 278*072d7532SNicolas Le Bayon 279*072d7532SNicolas Le Bayon bsec_lock(); 280*072d7532SNicolas Le Bayon 281*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value); 282*072d7532SNicolas Le Bayon 283*072d7532SNicolas Le Bayon bsec_unlock(); 284*072d7532SNicolas Le Bayon 285*072d7532SNicolas Le Bayon return BSEC_OK; 286*072d7532SNicolas Le Bayon } 287*072d7532SNicolas Le Bayon 288*072d7532SNicolas Le Bayon /* 289*072d7532SNicolas Le Bayon * bsec_get_config: return config parameters set in BSEC registers. 290*072d7532SNicolas Le Bayon * cfg: config param return. 291*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 292*072d7532SNicolas Le Bayon */ 293*072d7532SNicolas Le Bayon uint32_t bsec_get_config(struct bsec_config *cfg) 294*072d7532SNicolas Le Bayon { 295*072d7532SNicolas Le Bayon uint32_t value; 296*072d7532SNicolas Le Bayon 297*072d7532SNicolas Le Bayon if (cfg == NULL) { 298*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 299*072d7532SNicolas Le Bayon } 300*072d7532SNicolas Le Bayon 301*072d7532SNicolas Le Bayon value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); 302*072d7532SNicolas Le Bayon cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >> 303*072d7532SNicolas Le Bayon BSEC_CONF_POWER_UP_SHIFT); 304*072d7532SNicolas Le Bayon cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >> 305*072d7532SNicolas Le Bayon BSEC_CONF_FRQ_SHIFT); 306*072d7532SNicolas Le Bayon cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >> 307*072d7532SNicolas Le Bayon BSEC_CONF_PRG_WIDTH_SHIFT); 308*072d7532SNicolas Le Bayon cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >> 309*072d7532SNicolas Le Bayon BSEC_CONF_TREAD_SHIFT); 310*072d7532SNicolas Le Bayon 311*072d7532SNicolas Le Bayon value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF); 312*072d7532SNicolas Le Bayon cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >> 313*072d7532SNicolas Le Bayon UPPER_OTP_LOCK_SHIFT); 314*072d7532SNicolas Le Bayon cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >> 315*072d7532SNicolas Le Bayon DENREG_LOCK_SHIFT); 316*072d7532SNicolas Le Bayon cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >> 317*072d7532SNicolas Le Bayon GPLOCK_LOCK_SHIFT); 318*072d7532SNicolas Le Bayon 319*072d7532SNicolas Le Bayon return BSEC_OK; 320*072d7532SNicolas Le Bayon } 321*072d7532SNicolas Le Bayon 322*072d7532SNicolas Le Bayon /* 323*072d7532SNicolas Le Bayon * bsec_shadow_register: copy SAFMEM OTP to BSEC data. 324*072d7532SNicolas Le Bayon * otp: OTP number. 325*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 326*072d7532SNicolas Le Bayon */ 327*072d7532SNicolas Le Bayon uint32_t bsec_shadow_register(uint32_t otp) 328*072d7532SNicolas Le Bayon { 329*072d7532SNicolas Le Bayon uint32_t result; 330*072d7532SNicolas Le Bayon bool value; 331*072d7532SNicolas Le Bayon bool power_up = false; 332*072d7532SNicolas Le Bayon 333*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 334*072d7532SNicolas Le Bayon return BSEC_ERROR; 335*072d7532SNicolas Le Bayon } 336*072d7532SNicolas Le Bayon 337*072d7532SNicolas Le Bayon result = bsec_read_sr_lock(otp, &value); 338*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 339*072d7532SNicolas Le Bayon ERROR("BSEC: %u Sticky-read bit read Error %u\n", otp, result); 340*072d7532SNicolas Le Bayon return result; 341*072d7532SNicolas Le Bayon } 342*072d7532SNicolas Le Bayon 343*072d7532SNicolas Le Bayon if (value) { 344*072d7532SNicolas Le Bayon VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", 345*072d7532SNicolas Le Bayon otp); 346*072d7532SNicolas Le Bayon } 347*072d7532SNicolas Le Bayon 348*072d7532SNicolas Le Bayon if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { 349*072d7532SNicolas Le Bayon result = bsec_power_safmem(true); 350*072d7532SNicolas Le Bayon 351*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 352*072d7532SNicolas Le Bayon return result; 353*072d7532SNicolas Le Bayon } 354*072d7532SNicolas Le Bayon 355*072d7532SNicolas Le Bayon power_up = true; 356*072d7532SNicolas Le Bayon } 357*072d7532SNicolas Le Bayon 358*072d7532SNicolas Le Bayon bsec_lock(); 359*072d7532SNicolas Le Bayon 360*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ); 361*072d7532SNicolas Le Bayon 362*072d7532SNicolas Le Bayon while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { 363*072d7532SNicolas Le Bayon ; 364*072d7532SNicolas Le Bayon } 365*072d7532SNicolas Le Bayon 366*072d7532SNicolas Le Bayon result = bsec_check_error(otp, true); 367*072d7532SNicolas Le Bayon 368*072d7532SNicolas Le Bayon bsec_unlock(); 369*072d7532SNicolas Le Bayon 370*072d7532SNicolas Le Bayon if (power_up) { 371*072d7532SNicolas Le Bayon if (bsec_power_safmem(false) != BSEC_OK) { 372*072d7532SNicolas Le Bayon panic(); 373*072d7532SNicolas Le Bayon } 374*072d7532SNicolas Le Bayon } 375*072d7532SNicolas Le Bayon 376*072d7532SNicolas Le Bayon return result; 377*072d7532SNicolas Le Bayon } 378*072d7532SNicolas Le Bayon 379*072d7532SNicolas Le Bayon /* 380*072d7532SNicolas Le Bayon * bsec_read_otp: read an OTP data value. 381*072d7532SNicolas Le Bayon * val: read value. 382*072d7532SNicolas Le Bayon * otp: OTP number. 383*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 384*072d7532SNicolas Le Bayon */ 385*072d7532SNicolas Le Bayon uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) 386*072d7532SNicolas Le Bayon { 387*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 388*072d7532SNicolas Le Bayon return BSEC_ERROR; 389*072d7532SNicolas Le Bayon } 390*072d7532SNicolas Le Bayon 391*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 392*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 393*072d7532SNicolas Le Bayon } 394*072d7532SNicolas Le Bayon 395*072d7532SNicolas Le Bayon *val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF + 396*072d7532SNicolas Le Bayon (otp * sizeof(uint32_t))); 397*072d7532SNicolas Le Bayon 398*072d7532SNicolas Le Bayon return BSEC_OK; 399*072d7532SNicolas Le Bayon } 400*072d7532SNicolas Le Bayon 401*072d7532SNicolas Le Bayon /* 402*072d7532SNicolas Le Bayon * bsec_write_otp: write value in BSEC data register. 403*072d7532SNicolas Le Bayon * val: value to write. 404*072d7532SNicolas Le Bayon * otp: OTP number. 405*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 406*072d7532SNicolas Le Bayon */ 407*072d7532SNicolas Le Bayon uint32_t bsec_write_otp(uint32_t val, uint32_t otp) 408*072d7532SNicolas Le Bayon { 409*072d7532SNicolas Le Bayon uint32_t result; 410*072d7532SNicolas Le Bayon bool value; 411*072d7532SNicolas Le Bayon 412*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 413*072d7532SNicolas Le Bayon return BSEC_ERROR; 414*072d7532SNicolas Le Bayon } 415*072d7532SNicolas Le Bayon 416*072d7532SNicolas Le Bayon result = bsec_read_sw_lock(otp, &value); 417*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 418*072d7532SNicolas Le Bayon ERROR("BSEC: %u Sticky-write bit read Error %u\n", otp, result); 419*072d7532SNicolas Le Bayon return result; 420*072d7532SNicolas Le Bayon } 421*072d7532SNicolas Le Bayon 422*072d7532SNicolas Le Bayon if (value) { 423*072d7532SNicolas Le Bayon VERBOSE("BSEC: OTP %u is locked and write will be ignored\n", 424*072d7532SNicolas Le Bayon otp); 425*072d7532SNicolas Le Bayon } 426*072d7532SNicolas Le Bayon 427*072d7532SNicolas Le Bayon /* Ensure integrity of each register access sequence */ 428*072d7532SNicolas Le Bayon bsec_lock(); 429*072d7532SNicolas Le Bayon 430*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF + 431*072d7532SNicolas Le Bayon (otp * sizeof(uint32_t)), val); 432*072d7532SNicolas Le Bayon 433*072d7532SNicolas Le Bayon bsec_unlock(); 434*072d7532SNicolas Le Bayon 435*072d7532SNicolas Le Bayon return result; 436*072d7532SNicolas Le Bayon } 437*072d7532SNicolas Le Bayon 438*072d7532SNicolas Le Bayon /* 439*072d7532SNicolas Le Bayon * bsec_program_otp: program a bit in SAFMEM after the prog. 440*072d7532SNicolas Le Bayon * The OTP data is not refreshed. 441*072d7532SNicolas Le Bayon * val: value to program. 442*072d7532SNicolas Le Bayon * otp: OTP number. 443*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 444*072d7532SNicolas Le Bayon */ 445*072d7532SNicolas Le Bayon uint32_t bsec_program_otp(uint32_t val, uint32_t otp) 446*072d7532SNicolas Le Bayon { 447*072d7532SNicolas Le Bayon uint32_t result; 448*072d7532SNicolas Le Bayon bool power_up = false; 449*072d7532SNicolas Le Bayon bool sp_lock; 450*072d7532SNicolas Le Bayon bool perm_lock; 451*072d7532SNicolas Le Bayon 452*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 453*072d7532SNicolas Le Bayon return BSEC_ERROR; 454*072d7532SNicolas Le Bayon } 455*072d7532SNicolas Le Bayon 456*072d7532SNicolas Le Bayon result = bsec_read_sp_lock(otp, &sp_lock); 457*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 458*072d7532SNicolas Le Bayon ERROR("BSEC: %u Sticky-prog bit read Error %u\n", otp, result); 459*072d7532SNicolas Le Bayon return result; 460*072d7532SNicolas Le Bayon } 461*072d7532SNicolas Le Bayon 462*072d7532SNicolas Le Bayon result = bsec_read_permanent_lock(otp, &perm_lock); 463*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 464*072d7532SNicolas Le Bayon ERROR("BSEC: %u permanent bit read Error %u\n", otp, result); 465*072d7532SNicolas Le Bayon return result; 466*072d7532SNicolas Le Bayon } 467*072d7532SNicolas Le Bayon 468*072d7532SNicolas Le Bayon if (sp_lock || perm_lock) { 469*072d7532SNicolas Le Bayon WARN("BSEC: OTP locked, prog will be ignored\n"); 470*072d7532SNicolas Le Bayon return BSEC_PROG_FAIL; 471*072d7532SNicolas Le Bayon } 472*072d7532SNicolas Le Bayon 473*072d7532SNicolas Le Bayon if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) & 474*072d7532SNicolas Le Bayon BIT(BSEC_LOCK_PROGRAM)) != 0U) { 475*072d7532SNicolas Le Bayon WARN("BSEC: GPLOCK activated, prog will be ignored\n"); 476*072d7532SNicolas Le Bayon } 477*072d7532SNicolas Le Bayon 478*072d7532SNicolas Le Bayon if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { 479*072d7532SNicolas Le Bayon result = bsec_power_safmem(true); 480*072d7532SNicolas Le Bayon 481*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 482*072d7532SNicolas Le Bayon return result; 483*072d7532SNicolas Le Bayon } 484*072d7532SNicolas Le Bayon 485*072d7532SNicolas Le Bayon power_up = true; 486*072d7532SNicolas Le Bayon } 487*072d7532SNicolas Le Bayon 488*072d7532SNicolas Le Bayon bsec_lock(); 489*072d7532SNicolas Le Bayon 490*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val); 491*072d7532SNicolas Le Bayon 492*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE); 493*072d7532SNicolas Le Bayon 494*072d7532SNicolas Le Bayon while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { 495*072d7532SNicolas Le Bayon ; 496*072d7532SNicolas Le Bayon } 497*072d7532SNicolas Le Bayon 498*072d7532SNicolas Le Bayon if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { 499*072d7532SNicolas Le Bayon result = BSEC_PROG_FAIL; 500*072d7532SNicolas Le Bayon } else { 501*072d7532SNicolas Le Bayon result = bsec_check_error(otp, true); 502*072d7532SNicolas Le Bayon } 503*072d7532SNicolas Le Bayon 504*072d7532SNicolas Le Bayon bsec_unlock(); 505*072d7532SNicolas Le Bayon 506*072d7532SNicolas Le Bayon if (power_up) { 507*072d7532SNicolas Le Bayon if (bsec_power_safmem(false) != BSEC_OK) { 508*072d7532SNicolas Le Bayon panic(); 509*072d7532SNicolas Le Bayon } 510*072d7532SNicolas Le Bayon } 511*072d7532SNicolas Le Bayon 512*072d7532SNicolas Le Bayon return result; 513*072d7532SNicolas Le Bayon } 514*072d7532SNicolas Le Bayon 515*072d7532SNicolas Le Bayon /* 516*072d7532SNicolas Le Bayon * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM. 517*072d7532SNicolas Le Bayon * otp: OTP number. 518*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 519*072d7532SNicolas Le Bayon */ 520*072d7532SNicolas Le Bayon uint32_t bsec_permanent_lock_otp(uint32_t otp) 521*072d7532SNicolas Le Bayon { 522*072d7532SNicolas Le Bayon uint32_t result; 523*072d7532SNicolas Le Bayon bool power_up = false; 524*072d7532SNicolas Le Bayon uint32_t data; 525*072d7532SNicolas Le Bayon uint32_t addr; 526*072d7532SNicolas Le Bayon 527*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 528*072d7532SNicolas Le Bayon return BSEC_ERROR; 529*072d7532SNicolas Le Bayon } 530*072d7532SNicolas Le Bayon 531*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 532*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 533*072d7532SNicolas Le Bayon } 534*072d7532SNicolas Le Bayon 535*072d7532SNicolas Le Bayon if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { 536*072d7532SNicolas Le Bayon result = bsec_power_safmem(true); 537*072d7532SNicolas Le Bayon 538*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 539*072d7532SNicolas Le Bayon return result; 540*072d7532SNicolas Le Bayon } 541*072d7532SNicolas Le Bayon 542*072d7532SNicolas Le Bayon power_up = true; 543*072d7532SNicolas Le Bayon } 544*072d7532SNicolas Le Bayon 545*072d7532SNicolas Le Bayon if (otp < STM32MP1_UPPER_OTP_START) { 546*072d7532SNicolas Le Bayon addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT; 547*072d7532SNicolas Le Bayon data = DATA_LOWER_OTP_PERLOCK_BIT << 548*072d7532SNicolas Le Bayon ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U); 549*072d7532SNicolas Le Bayon } else { 550*072d7532SNicolas Le Bayon addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U; 551*072d7532SNicolas Le Bayon data = DATA_UPPER_OTP_PERLOCK_BIT << 552*072d7532SNicolas Le Bayon (otp & DATA_UPPER_OTP_PERLOCK_MASK); 553*072d7532SNicolas Le Bayon } 554*072d7532SNicolas Le Bayon 555*072d7532SNicolas Le Bayon bsec_lock(); 556*072d7532SNicolas Le Bayon 557*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data); 558*072d7532SNicolas Le Bayon 559*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, 560*072d7532SNicolas Le Bayon addr | BSEC_WRITE | BSEC_LOCK); 561*072d7532SNicolas Le Bayon 562*072d7532SNicolas Le Bayon while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { 563*072d7532SNicolas Le Bayon ; 564*072d7532SNicolas Le Bayon } 565*072d7532SNicolas Le Bayon 566*072d7532SNicolas Le Bayon if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { 567*072d7532SNicolas Le Bayon result = BSEC_PROG_FAIL; 568*072d7532SNicolas Le Bayon } else { 569*072d7532SNicolas Le Bayon result = bsec_check_error(otp, false); 570*072d7532SNicolas Le Bayon } 571*072d7532SNicolas Le Bayon 572*072d7532SNicolas Le Bayon bsec_unlock(); 573*072d7532SNicolas Le Bayon 574*072d7532SNicolas Le Bayon if (power_up) { 575*072d7532SNicolas Le Bayon if (bsec_power_safmem(false) != BSEC_OK) { 576*072d7532SNicolas Le Bayon panic(); 577*072d7532SNicolas Le Bayon } 578*072d7532SNicolas Le Bayon } 579*072d7532SNicolas Le Bayon 580*072d7532SNicolas Le Bayon return result; 581*072d7532SNicolas Le Bayon } 582*072d7532SNicolas Le Bayon 583*072d7532SNicolas Le Bayon /* 584*072d7532SNicolas Le Bayon * bsec_write_debug_conf: write value in debug feature. 585*072d7532SNicolas Le Bayon * to enable/disable debug service. 586*072d7532SNicolas Le Bayon * val: value to write. 587*072d7532SNicolas Le Bayon * return value: none. 588*072d7532SNicolas Le Bayon */ 589*072d7532SNicolas Le Bayon void bsec_write_debug_conf(uint32_t val) 590*072d7532SNicolas Le Bayon { 591*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 592*072d7532SNicolas Le Bayon return; 593*072d7532SNicolas Le Bayon } 594*072d7532SNicolas Le Bayon 595*072d7532SNicolas Le Bayon bsec_lock(); 596*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_DEN_OFF, val & BSEC_DEN_ALL_MSK); 597*072d7532SNicolas Le Bayon bsec_unlock(); 598*072d7532SNicolas Le Bayon } 599*072d7532SNicolas Le Bayon 600*072d7532SNicolas Le Bayon /* 601*072d7532SNicolas Le Bayon * bsec_read_debug_conf: return debug configuration register value. 602*072d7532SNicolas Le Bayon */ 603*072d7532SNicolas Le Bayon uint32_t bsec_read_debug_conf(void) 604*072d7532SNicolas Le Bayon { 605*072d7532SNicolas Le Bayon return mmio_read_32(bsec_base + BSEC_DEN_OFF); 606*072d7532SNicolas Le Bayon } 607*072d7532SNicolas Le Bayon 608*072d7532SNicolas Le Bayon /* 609*072d7532SNicolas Le Bayon * bsec_write_scratch: write value in scratch register. 610*072d7532SNicolas Le Bayon * val: value to write. 611*072d7532SNicolas Le Bayon * return value: none. 612*072d7532SNicolas Le Bayon */ 613*072d7532SNicolas Le Bayon void bsec_write_scratch(uint32_t val) 614*072d7532SNicolas Le Bayon { 615*072d7532SNicolas Le Bayon #if defined(IMAGE_BL32) 616*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 617*072d7532SNicolas Le Bayon return; 618*072d7532SNicolas Le Bayon } 619*072d7532SNicolas Le Bayon 620*072d7532SNicolas Le Bayon bsec_lock(); 621*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_SCRATCH_OFF, val); 622*072d7532SNicolas Le Bayon bsec_unlock(); 623*072d7532SNicolas Le Bayon #else 624*072d7532SNicolas Le Bayon mmio_write_32(BSEC_BASE + BSEC_SCRATCH_OFF, val); 625*072d7532SNicolas Le Bayon #endif 626*072d7532SNicolas Le Bayon } 627*072d7532SNicolas Le Bayon 628*072d7532SNicolas Le Bayon /* 629*072d7532SNicolas Le Bayon * bsec_read_scratch: return scratch register value. 630*072d7532SNicolas Le Bayon */ 631*072d7532SNicolas Le Bayon uint32_t bsec_read_scratch(void) 632*072d7532SNicolas Le Bayon { 633*072d7532SNicolas Le Bayon return mmio_read_32(bsec_base + BSEC_SCRATCH_OFF); 634*072d7532SNicolas Le Bayon } 635*072d7532SNicolas Le Bayon 636*072d7532SNicolas Le Bayon /* 637*072d7532SNicolas Le Bayon * bsec_get_status: return status register value. 638*072d7532SNicolas Le Bayon */ 639*072d7532SNicolas Le Bayon uint32_t bsec_get_status(void) 640*072d7532SNicolas Le Bayon { 641*072d7532SNicolas Le Bayon return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF); 642*072d7532SNicolas Le Bayon } 643*072d7532SNicolas Le Bayon 644*072d7532SNicolas Le Bayon /* 645*072d7532SNicolas Le Bayon * bsec_get_hw_conf: return hardware configuration register value. 646*072d7532SNicolas Le Bayon */ 647*072d7532SNicolas Le Bayon uint32_t bsec_get_hw_conf(void) 648*072d7532SNicolas Le Bayon { 649*072d7532SNicolas Le Bayon return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF); 650*072d7532SNicolas Le Bayon } 651*072d7532SNicolas Le Bayon 652*072d7532SNicolas Le Bayon /* 653*072d7532SNicolas Le Bayon * bsec_get_version: return BSEC version register value. 654*072d7532SNicolas Le Bayon */ 655*072d7532SNicolas Le Bayon uint32_t bsec_get_version(void) 656*072d7532SNicolas Le Bayon { 657*072d7532SNicolas Le Bayon return mmio_read_32(bsec_base + BSEC_IPVR_OFF); 658*072d7532SNicolas Le Bayon } 659*072d7532SNicolas Le Bayon 660*072d7532SNicolas Le Bayon /* 661*072d7532SNicolas Le Bayon * bsec_get_id: return BSEC ID register value. 662*072d7532SNicolas Le Bayon */ 663*072d7532SNicolas Le Bayon uint32_t bsec_get_id(void) 664*072d7532SNicolas Le Bayon { 665*072d7532SNicolas Le Bayon return mmio_read_32(bsec_base + BSEC_IP_ID_OFF); 666*072d7532SNicolas Le Bayon } 667*072d7532SNicolas Le Bayon 668*072d7532SNicolas Le Bayon /* 669*072d7532SNicolas Le Bayon * bsec_get_magic_id: return BSEC magic number register value. 670*072d7532SNicolas Le Bayon */ 671*072d7532SNicolas Le Bayon uint32_t bsec_get_magic_id(void) 672*072d7532SNicolas Le Bayon { 673*072d7532SNicolas Le Bayon return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF); 674*072d7532SNicolas Le Bayon } 675*072d7532SNicolas Le Bayon 676*072d7532SNicolas Le Bayon /* 677*072d7532SNicolas Le Bayon * bsec_set_sr_lock: set shadow-read lock. 678*072d7532SNicolas Le Bayon * otp: OTP number. 679*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 680*072d7532SNicolas Le Bayon */ 681*072d7532SNicolas Le Bayon uint32_t bsec_set_sr_lock(uint32_t otp) 682*072d7532SNicolas Le Bayon { 683*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 684*072d7532SNicolas Le Bayon uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); 685*072d7532SNicolas Le Bayon 686*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 687*072d7532SNicolas Le Bayon return BSEC_ERROR; 688*072d7532SNicolas Le Bayon } 689*072d7532SNicolas Le Bayon 690*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 691*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 692*072d7532SNicolas Le Bayon } 693*072d7532SNicolas Le Bayon 694*072d7532SNicolas Le Bayon bsec_lock(); 695*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, otp_mask); 696*072d7532SNicolas Le Bayon bsec_unlock(); 697*072d7532SNicolas Le Bayon 698*072d7532SNicolas Le Bayon return BSEC_OK; 699*072d7532SNicolas Le Bayon } 700*072d7532SNicolas Le Bayon 701*072d7532SNicolas Le Bayon /* 702*072d7532SNicolas Le Bayon * bsec_read_sr_lock: read shadow-read lock. 703*072d7532SNicolas Le Bayon * otp: OTP number. 704*072d7532SNicolas Le Bayon * value: read value (true or false). 705*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 706*072d7532SNicolas Le Bayon */ 707*072d7532SNicolas Le Bayon uint32_t bsec_read_sr_lock(uint32_t otp, bool *value) 708*072d7532SNicolas Le Bayon { 709*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 710*072d7532SNicolas Le Bayon uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); 711*072d7532SNicolas Le Bayon uint32_t bank_value; 712*072d7532SNicolas Le Bayon 713*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 714*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 715*072d7532SNicolas Le Bayon } 716*072d7532SNicolas Le Bayon 717*072d7532SNicolas Le Bayon bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); 718*072d7532SNicolas Le Bayon 719*072d7532SNicolas Le Bayon *value = ((bank_value & otp_mask) != 0U); 720*072d7532SNicolas Le Bayon 721*072d7532SNicolas Le Bayon return BSEC_OK; 722*072d7532SNicolas Le Bayon } 723*072d7532SNicolas Le Bayon 724*072d7532SNicolas Le Bayon /* 725*072d7532SNicolas Le Bayon * bsec_set_sw_lock: set shadow-write lock. 726*072d7532SNicolas Le Bayon * otp: OTP number. 727*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 728*072d7532SNicolas Le Bayon */ 729*072d7532SNicolas Le Bayon uint32_t bsec_set_sw_lock(uint32_t otp) 730*072d7532SNicolas Le Bayon { 731*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 732*072d7532SNicolas Le Bayon uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); 733*072d7532SNicolas Le Bayon 734*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 735*072d7532SNicolas Le Bayon return BSEC_ERROR; 736*072d7532SNicolas Le Bayon } 737*072d7532SNicolas Le Bayon 738*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 739*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 740*072d7532SNicolas Le Bayon } 741*072d7532SNicolas Le Bayon 742*072d7532SNicolas Le Bayon bsec_lock(); 743*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, otp_mask); 744*072d7532SNicolas Le Bayon bsec_unlock(); 745*072d7532SNicolas Le Bayon 746*072d7532SNicolas Le Bayon return BSEC_OK; 747*072d7532SNicolas Le Bayon } 748*072d7532SNicolas Le Bayon 749*072d7532SNicolas Le Bayon /* 750*072d7532SNicolas Le Bayon * bsec_read_sw_lock: read shadow-write lock. 751*072d7532SNicolas Le Bayon * otp: OTP number. 752*072d7532SNicolas Le Bayon * value: read value (true or false). 753*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 754*072d7532SNicolas Le Bayon */ 755*072d7532SNicolas Le Bayon uint32_t bsec_read_sw_lock(uint32_t otp, bool *value) 756*072d7532SNicolas Le Bayon { 757*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 758*072d7532SNicolas Le Bayon uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); 759*072d7532SNicolas Le Bayon uint32_t bank_value; 760*072d7532SNicolas Le Bayon 761*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 762*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 763*072d7532SNicolas Le Bayon } 764*072d7532SNicolas Le Bayon 765*072d7532SNicolas Le Bayon bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); 766*072d7532SNicolas Le Bayon 767*072d7532SNicolas Le Bayon *value = ((bank_value & otp_mask) != 0U); 768*072d7532SNicolas Le Bayon 769*072d7532SNicolas Le Bayon return BSEC_OK; 770*072d7532SNicolas Le Bayon } 771*072d7532SNicolas Le Bayon 772*072d7532SNicolas Le Bayon /* 773*072d7532SNicolas Le Bayon * bsec_set_sp_lock: set shadow-program lock. 774*072d7532SNicolas Le Bayon * otp: OTP number. 775*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 776*072d7532SNicolas Le Bayon */ 777*072d7532SNicolas Le Bayon uint32_t bsec_set_sp_lock(uint32_t otp) 778*072d7532SNicolas Le Bayon { 779*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 780*072d7532SNicolas Le Bayon uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); 781*072d7532SNicolas Le Bayon 782*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 783*072d7532SNicolas Le Bayon return BSEC_ERROR; 784*072d7532SNicolas Le Bayon } 785*072d7532SNicolas Le Bayon 786*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 787*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 788*072d7532SNicolas Le Bayon } 789*072d7532SNicolas Le Bayon 790*072d7532SNicolas Le Bayon bsec_lock(); 791*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, otp_mask); 792*072d7532SNicolas Le Bayon bsec_unlock(); 793*072d7532SNicolas Le Bayon 794*072d7532SNicolas Le Bayon return BSEC_OK; 795*072d7532SNicolas Le Bayon } 796*072d7532SNicolas Le Bayon 797*072d7532SNicolas Le Bayon /* 798*072d7532SNicolas Le Bayon * bsec_read_sp_lock: read shadow-program lock. 799*072d7532SNicolas Le Bayon * otp: OTP number. 800*072d7532SNicolas Le Bayon * value: read value (true or false). 801*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 802*072d7532SNicolas Le Bayon */ 803*072d7532SNicolas Le Bayon uint32_t bsec_read_sp_lock(uint32_t otp, bool *value) 804*072d7532SNicolas Le Bayon { 805*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 806*072d7532SNicolas Le Bayon uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); 807*072d7532SNicolas Le Bayon uint32_t bank_value; 808*072d7532SNicolas Le Bayon 809*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 810*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 811*072d7532SNicolas Le Bayon } 812*072d7532SNicolas Le Bayon 813*072d7532SNicolas Le Bayon bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); 814*072d7532SNicolas Le Bayon 815*072d7532SNicolas Le Bayon *value = ((bank_value & otp_mask) != 0U); 816*072d7532SNicolas Le Bayon 817*072d7532SNicolas Le Bayon return BSEC_OK; 818*072d7532SNicolas Le Bayon } 819*072d7532SNicolas Le Bayon 820*072d7532SNicolas Le Bayon /* 821*072d7532SNicolas Le Bayon * bsec_read_permanent_lock: Read permanent lock status. 822*072d7532SNicolas Le Bayon * otp: OTP number. 823*072d7532SNicolas Le Bayon * value: read value (true or false). 824*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 825*072d7532SNicolas Le Bayon */ 826*072d7532SNicolas Le Bayon uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value) 827*072d7532SNicolas Le Bayon { 828*072d7532SNicolas Le Bayon uint32_t bank = otp_bank_offset(otp); 829*072d7532SNicolas Le Bayon uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); 830*072d7532SNicolas Le Bayon uint32_t bank_value; 831*072d7532SNicolas Le Bayon 832*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 833*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 834*072d7532SNicolas Le Bayon } 835*072d7532SNicolas Le Bayon 836*072d7532SNicolas Le Bayon bank_value = mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank); 837*072d7532SNicolas Le Bayon 838*072d7532SNicolas Le Bayon *value = ((bank_value & otp_mask) != 0U); 839*072d7532SNicolas Le Bayon 840*072d7532SNicolas Le Bayon return BSEC_OK; 841*072d7532SNicolas Le Bayon } 842*072d7532SNicolas Le Bayon 843*072d7532SNicolas Le Bayon /* 844*072d7532SNicolas Le Bayon * bsec_otp_lock: Lock Upper OTP or Global Programming or Debug Enable. 845*072d7532SNicolas Le Bayon * service: Service to lock, see header file. 846*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 847*072d7532SNicolas Le Bayon */ 848*072d7532SNicolas Le Bayon uint32_t bsec_otp_lock(uint32_t service) 849*072d7532SNicolas Le Bayon { 850*072d7532SNicolas Le Bayon uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF; 851*072d7532SNicolas Le Bayon 852*072d7532SNicolas Le Bayon if (is_otp_invalid_mode()) { 853*072d7532SNicolas Le Bayon return BSEC_ERROR; 854*072d7532SNicolas Le Bayon } 855*072d7532SNicolas Le Bayon 856*072d7532SNicolas Le Bayon switch (service) { 857*072d7532SNicolas Le Bayon case BSEC_LOCK_UPPER_OTP: 858*072d7532SNicolas Le Bayon mmio_write_32(reg, BIT(BSEC_LOCK_UPPER_OTP)); 859*072d7532SNicolas Le Bayon break; 860*072d7532SNicolas Le Bayon case BSEC_LOCK_DEBUG: 861*072d7532SNicolas Le Bayon mmio_write_32(reg, BIT(BSEC_LOCK_DEBUG)); 862*072d7532SNicolas Le Bayon break; 863*072d7532SNicolas Le Bayon case BSEC_LOCK_PROGRAM: 864*072d7532SNicolas Le Bayon mmio_write_32(reg, BIT(BSEC_LOCK_PROGRAM)); 865*072d7532SNicolas Le Bayon break; 866*072d7532SNicolas Le Bayon default: 867*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 868*072d7532SNicolas Le Bayon } 869*072d7532SNicolas Le Bayon 870*072d7532SNicolas Le Bayon return BSEC_OK; 871*072d7532SNicolas Le Bayon } 872*072d7532SNicolas Le Bayon 873*072d7532SNicolas Le Bayon /* 874*072d7532SNicolas Le Bayon * bsec_power_safmem: Activate or deactivate SAFMEM power. 875*072d7532SNicolas Le Bayon * power: true to power up, false to power down. 876*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 877*072d7532SNicolas Le Bayon */ 878*072d7532SNicolas Le Bayon static uint32_t bsec_power_safmem(bool power) 879*072d7532SNicolas Le Bayon { 880*072d7532SNicolas Le Bayon uint32_t register_val; 881*072d7532SNicolas Le Bayon uint32_t timeout = BSEC_TIMEOUT_VALUE; 882*072d7532SNicolas Le Bayon 883*072d7532SNicolas Le Bayon bsec_lock(); 884*072d7532SNicolas Le Bayon 885*072d7532SNicolas Le Bayon register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); 886*072d7532SNicolas Le Bayon 887*072d7532SNicolas Le Bayon if (power) { 888*072d7532SNicolas Le Bayon register_val |= BSEC_CONF_POWER_UP_MASK; 889*072d7532SNicolas Le Bayon } else { 890*072d7532SNicolas Le Bayon register_val &= ~BSEC_CONF_POWER_UP_MASK; 891*072d7532SNicolas Le Bayon } 892*072d7532SNicolas Le Bayon 893*072d7532SNicolas Le Bayon mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val); 894*072d7532SNicolas Le Bayon 895*072d7532SNicolas Le Bayon if (power) { 896*072d7532SNicolas Le Bayon while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) && 897*072d7532SNicolas Le Bayon (timeout != 0U)) { 898*072d7532SNicolas Le Bayon timeout--; 899*072d7532SNicolas Le Bayon } 900*072d7532SNicolas Le Bayon } else { 901*072d7532SNicolas Le Bayon while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) && 902*072d7532SNicolas Le Bayon (timeout != 0U)) { 903*072d7532SNicolas Le Bayon timeout--; 904*072d7532SNicolas Le Bayon } 905*072d7532SNicolas Le Bayon } 906*072d7532SNicolas Le Bayon 907*072d7532SNicolas Le Bayon bsec_unlock(); 908*072d7532SNicolas Le Bayon 909*072d7532SNicolas Le Bayon if (timeout == 0U) { 910*072d7532SNicolas Le Bayon return BSEC_TIMEOUT; 911*072d7532SNicolas Le Bayon } 912*072d7532SNicolas Le Bayon 913*072d7532SNicolas Le Bayon return BSEC_OK; 914*072d7532SNicolas Le Bayon } 915*072d7532SNicolas Le Bayon 916*072d7532SNicolas Le Bayon /* 917*072d7532SNicolas Le Bayon * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value. 918*072d7532SNicolas Le Bayon * otp_value: read value. 919*072d7532SNicolas Le Bayon * word: OTP number. 920*072d7532SNicolas Le Bayon * return value: BSEC_OK if no error. 921*072d7532SNicolas Le Bayon */ 922*072d7532SNicolas Le Bayon uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) 923*072d7532SNicolas Le Bayon { 924*072d7532SNicolas Le Bayon uint32_t result; 925*072d7532SNicolas Le Bayon 926*072d7532SNicolas Le Bayon result = bsec_shadow_register(word); 927*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 928*072d7532SNicolas Le Bayon ERROR("BSEC: %u Shadowing Error %u\n", word, result); 929*072d7532SNicolas Le Bayon return result; 930*072d7532SNicolas Le Bayon } 931*072d7532SNicolas Le Bayon 932*072d7532SNicolas Le Bayon result = bsec_read_otp(otp_value, word); 933*072d7532SNicolas Le Bayon if (result != BSEC_OK) { 934*072d7532SNicolas Le Bayon ERROR("BSEC: %u Read Error %u\n", word, result); 935*072d7532SNicolas Le Bayon } 936*072d7532SNicolas Le Bayon 937*072d7532SNicolas Le Bayon return result; 938*072d7532SNicolas Le Bayon } 939*072d7532SNicolas Le Bayon 940*072d7532SNicolas Le Bayon /* 941*072d7532SNicolas Le Bayon * bsec_check_nsec_access_rights: check non-secure access rights to target OTP. 942*072d7532SNicolas Le Bayon * otp: OTP number. 943*072d7532SNicolas Le Bayon * return value: BSEC_OK if authorized access. 944*072d7532SNicolas Le Bayon */ 945*072d7532SNicolas Le Bayon uint32_t bsec_check_nsec_access_rights(uint32_t otp) 946*072d7532SNicolas Le Bayon { 947*072d7532SNicolas Le Bayon #if defined(IMAGE_BL32) 948*072d7532SNicolas Le Bayon if (otp > STM32MP1_OTP_MAX_ID) { 949*072d7532SNicolas Le Bayon return BSEC_INVALID_PARAM; 950*072d7532SNicolas Le Bayon } 951*072d7532SNicolas Le Bayon 952*072d7532SNicolas Le Bayon if (otp >= STM32MP1_UPPER_OTP_START) { 953*072d7532SNicolas Le Bayon if (!non_secure_can_access(otp)) { 954*072d7532SNicolas Le Bayon return BSEC_ERROR; 955*072d7532SNicolas Le Bayon } 956*072d7532SNicolas Le Bayon } 957*072d7532SNicolas Le Bayon #endif 958*072d7532SNicolas Le Bayon 959*072d7532SNicolas Le Bayon return BSEC_OK; 960*072d7532SNicolas Le Bayon } 961*072d7532SNicolas Le Bayon 962