diff --git a/drivers/st/bsec/bsec3.c b/drivers/st/bsec/bsec3.c new file mode 100644 index 000000000..a803a3a9c --- /dev/null +++ b/drivers/st/bsec/bsec3.c @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2024, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BSEC_IP_VERSION_1_0 U(0x10) +#define BSEC_IP_ID_3 U(0x100033) + +#define MAX_NB_TRIES U(3) + +/* + * IP configuration + */ +#define BSEC_OTP_MASK GENMASK_32(4, 0) +#define BSEC_OTP_BANK_SHIFT U(5) +#define BSEC_TIMEOUT_VALUE U(0x800000) /* ~7sec @1.2GHz */ + +/* Magic use to indicated valid SHADOW = 'B' 'S' 'E' 'C' */ +#define BSEC_MAGIC U(0x42534543) + +#define OTP_MAX_SIZE (STM32MP2_OTP_MAX_ID + U(1)) + +struct bsec_shadow { + uint32_t magic; + uint32_t state; + uint32_t value[OTP_MAX_SIZE]; + uint32_t status[OTP_MAX_SIZE]; +}; + +static uint32_t otp_bank(uint32_t otp) +{ + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + return (otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT; +} + +static uint32_t otp_bit_mask(uint32_t otp) +{ + return BIT(otp & BSEC_OTP_MASK); +} + +/* + * bsec_get_status: return status register value. + */ +static uint32_t bsec_get_status(void) +{ + return mmio_read_32(BSEC_BASE + BSEC_OTPSR); +} + +/* + * bsec_get_version: return BSEC version. + */ +static uint32_t bsec_get_version(void) +{ + return mmio_read_32(BSEC_BASE + BSEC_VERR) & BSEC_VERR_MASK; +} + +/* + * bsec_get_id: return BSEC ID. + */ +static uint32_t bsec_get_id(void) +{ + return mmio_read_32(BSEC_BASE + BSEC_IPIDR); +} + +static bool is_fuse_shadowed(uint32_t otp) +{ + uint32_t bank = otp_bank(otp); + uint32_t otp_mask = otp_bit_mask(otp); + uint32_t bank_value; + + bank_value = mmio_read_32(BSEC_BASE + BSEC_SFSR(bank)); + + if ((bank_value & otp_mask) != 0U) { + return true; + } + + return false; +} + +static void poll_otp_status_busy(void) +{ + uint32_t timeout = BSEC_TIMEOUT_VALUE; + + while (((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) && (timeout != 0U)) { + timeout--; + } + + if ((bsec_get_status() & BSEC_OTPSR_BUSY) != 0U) { + ERROR("BSEC timeout\n"); + panic(); + } +} + +static uint32_t check_read_error(uint32_t otp) +{ + uint32_t status = bsec_get_status(); + + if ((status & BSEC_OTPSR_SECF) != 0U) { + VERBOSE("BSEC read %u single error correction detected\n", otp); + } + + if ((status & BSEC_OTPSR_PPLF) != 0U) { + VERBOSE("BSEC read %u permanent programming lock detected.\n", otp); + } + + if ((status & BSEC_OTPSR_PPLMF) != 0U) { + ERROR("BSEC read %u error 0x%x\n", otp, status); + return BSEC_ERROR; + } + + if ((status & (BSEC_OTPSR_DISTURBF | BSEC_OTPSR_DEDF | BSEC_OTPSR_AMEF)) != 0U) { + ERROR("BSEC read %u error 0x%x with invalid FVR\n", otp, status); + return BSEC_RETRY; + } + + return BSEC_OK; +} + +static uint32_t check_program_error(uint32_t otp) +{ + uint32_t status = bsec_get_status(); + + if ((status & BSEC_OTPSR_PROGFAIL) != 0U) { + ERROR("BSEC program %u error 0x%x\n", otp, status); + return BSEC_RETRY; + } + + return BSEC_OK; +} + +static void check_reset_error(void) +{ + uint32_t status = bsec_get_status(); + + /* check initial status reporting */ + if ((status & BSEC_OTPSR_BUSY) != 0U) { + VERBOSE("BSEC reset and busy when OTPSR read\n"); + } + if ((status & BSEC_OTPSR_HIDEUP) != 0U) { + VERBOSE("BSEC upper fuse are not accessible (HIDEUP)\n"); + } + if ((status & BSEC_OTPSR_OTPSEC) != 0U) { + VERBOSE("BSEC reset single error correction detected\n"); + } + if ((status & BSEC_OTPSR_OTPNVIR) == 0U) { + VERBOSE("BSEC reset first fuse word 0 is detected zero\n"); + } + if ((status & BSEC_OTPSR_OTPERR) != 0U) { + ERROR("BSEC reset critical error 0x%x\n", status); + panic(); + } + if ((status & BSEC_OTPSR_FUSEOK) != BSEC_OTPSR_FUSEOK) { + ERROR("BSEC reset critical error 0x%x\n", status); + panic(); + } +} + +static bool is_bsec_write_locked(void) +{ + return (mmio_read_32(BSEC_BASE + BSEC_LOCKR) & BSEC_LOCKR_GWLOCK_MASK) != 0U; +} + +/* + * bsec_probe: initialize BSEC driver. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_probe(void) +{ + uint32_t version = bsec_get_version(); + uint32_t id = bsec_get_id(); + + if ((version != BSEC_IP_VERSION_1_0) || (id != BSEC_IP_ID_3)) { + ERROR("%s: version = 0x%x, id = 0x%x\n", __func__, version, id); + panic(); + } + + check_reset_error(); + + return BSEC_OK; +} + +/* + * bsec_shadow_register: copy SAFMEM OTP to BSEC data. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +static uint32_t bsec_shadow_register(uint32_t otp) +{ + uint32_t result; + uint32_t i; + bool value; + + result = bsec_read_sr_lock(otp, &value); + if (result != BSEC_OK) { + WARN("BSEC: %u Sticky-read bit read Error %u\n", otp, result); + } else if (value) { + VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", otp); + } + + for (i = 0U; i < MAX_NB_TRIES; i++) { + mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp); + + poll_otp_status_busy(); + + result = check_read_error(otp); + if (result != BSEC_RETRY) { + break; + } + } + + return result; +} + +/* + * bsec_write_otp: write a value in shadow OTP. + * val: value to program. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_write_otp(uint32_t val, uint32_t otp) +{ + bool state; + uint32_t result; + + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + if (!is_fuse_shadowed(otp)) { + return BSEC_ERROR; + } + + if (is_bsec_write_locked()) { + return BSEC_WRITE_LOCKED; + } + + result = bsec_read_sw_lock(otp, &state); + if (result != BSEC_OK) { + WARN("Shadow register is SW locked\n"); + return result; + } + + mmio_write_32(BSEC_BASE + BSEC_FVR(otp), val); + + return BSEC_OK; +} + +/* + * bsec_program_otp: program a bit in SAFMEM after the prog. + * The OTP data is not refreshed. + * val: value to program. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_program_otp(uint32_t val, uint32_t otp) +{ + uint32_t result; + uint32_t i; + bool value; + + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + if (is_bsec_write_locked() == true) { + return BSEC_WRITE_LOCKED; + } + + result = bsec_read_sp_lock(otp, &value); + if (result != BSEC_OK) { + WARN("BSEC: %u Sticky-prog bit read Error %u\n", otp, result); + } else if (value) { + WARN("BSEC: OTP locked, prog will be ignored\n"); + return BSEC_WRITE_LOCKED; + } + + mmio_write_32(BSEC_BASE + BSEC_WDR, val); + + for (i = 0U; i < MAX_NB_TRIES; i++) { + mmio_write_32(BSEC_BASE + BSEC_OTPCR, otp | BSEC_OTPCR_PROG); + + poll_otp_status_busy(); + + result = check_program_error(otp); + if (result != BSEC_RETRY) { + break; + } + } + + return result; +} + +/* + * bsec_read_debug_conf: read debug configuration. + */ +uint32_t bsec_read_debug_conf(void) +{ + return mmio_read_32(BSEC_BASE + BSEC_DENR); +} + +static uint32_t bsec_lock_register_set(uint32_t offset, uint32_t mask) +{ + uint32_t value = mmio_read_32(BSEC_BASE + offset); + + /* The lock is already set */ + if ((value & mask) != 0U) { + return BSEC_OK; + } + + if (is_bsec_write_locked()) { + return BSEC_WRITE_LOCKED; + } + + value |= mask; + + mmio_write_32(BSEC_BASE + offset, value); + + return BSEC_OK; +} + +static bool bsec_lock_register_get(uint32_t offset, uint32_t mask) +{ + uint32_t value = mmio_read_32(BSEC_BASE + offset); + + return (value & mask) != 0U; +} + +/* + * bsec_set_sr_lock: set shadow-read lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sr_lock(uint32_t otp) +{ + uint32_t bank = otp_bank(otp); + uint32_t otp_mask = otp_bit_mask(otp); + + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + return bsec_lock_register_set(BSEC_SRLOCK(bank), otp_mask); +} + +/* + * bsec_read_sr_lock: read shadow-read lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sr_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank(otp); + uint32_t otp_mask = otp_bit_mask(otp); + + assert(value != NULL); + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + *value = bsec_lock_register_get(BSEC_SRLOCK(bank), otp_mask); + + return BSEC_OK; +} + +/* + * bsec_set_sw_lock: set shadow-write lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sw_lock(uint32_t otp) +{ + uint32_t bank = otp_bank(otp); + uint32_t otp_mask = otp_bit_mask(otp); + + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + return bsec_lock_register_set(BSEC_SWLOCK(bank), otp_mask); +} + +/* + * bsec_read_sw_lock: read shadow-write lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sw_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank(otp); + uint32_t otp_mask = otp_bit_mask(otp); + + assert(value != NULL); + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + *value = bsec_lock_register_get(BSEC_SWLOCK(bank), otp_mask); + + return BSEC_OK; +} + +/* + * bsec_set_sp_lock: set shadow-program lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sp_lock(uint32_t otp) +{ + uint32_t bank = otp_bank(otp); + uint32_t otp_mask = otp_bit_mask(otp); + + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + return bsec_lock_register_set(BSEC_SPLOCK(bank), otp_mask); +} + +/* + * bsec_read_sp_lock: read shadow-program lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sp_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank(otp); + uint32_t otp_mask = otp_bit_mask(otp); + + assert(value != NULL); + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + *value = bsec_lock_register_get(BSEC_SPLOCK(bank), otp_mask); + + return BSEC_OK; +} + +/* + * bsec_get_secure_state: read state in BSEC status register. + * return: secure state + */ +uint32_t bsec_get_secure_state(void) +{ + uint32_t state = BSEC_STATE_INVALID; + uint32_t status = bsec_get_status(); + uint32_t bsec_sr = mmio_read_32(BSEC_BASE + BSEC_SR); + + if ((status & BSEC_OTPSR_FUSEOK) == BSEC_OTPSR_FUSEOK) { + /* NVSTATE is only valid if FUSEOK */ + uint32_t nvstates = (bsec_sr & BSEC_SR_NVSTATE_MASK) >> BSEC_SR_NVSTATE_SHIFT; + + if (nvstates == BSEC_SR_NVSTATE_OPEN) { + state = BSEC_STATE_SEC_OPEN; + } else if (nvstates == BSEC_SR_NVSTATE_CLOSED) { + state = BSEC_STATE_SEC_CLOSED; + } else { + VERBOSE("%s nvstates = %u\n", __func__, nvstates); + } + } + + return state; +} + +/* + * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value + * val: read value. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_shadow_read_otp(uint32_t *val, uint32_t otp) +{ + assert(val != NULL); + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + *val = 0U; + + if (is_bsec_write_locked()) { + return BSEC_WRITE_LOCKED; + } + + if (!is_fuse_shadowed(otp)) { + uint32_t result = bsec_shadow_register(otp); + + if (result != BSEC_OK) { + ERROR("BSEC: %u Shadowing Error %u\n", otp, result); + return result; + } + } + + *val = mmio_read_32(BSEC_BASE + BSEC_FVR(otp)); + + return BSEC_OK; +} + +/* + * bsec_read_otp: read an OTP data value. + * val: read value. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) +{ + assert(val != NULL); + if (otp > STM32MP2_OTP_MAX_ID) { + panic(); + } + + return bsec_shadow_read_otp(val, otp); +} diff --git a/include/drivers/st/bsec3_reg.h b/include/drivers/st/bsec3_reg.h new file mode 100644 index 000000000..177e30ba5 --- /dev/null +++ b/include/drivers/st/bsec3_reg.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC3_REG_H +#define BSEC3_REG_H + +#include + +/* BSEC REGISTER OFFSET (base relative) */ +#define BSEC_FVR(x) (U(0x000) + 4U * (x)) +#define BSEC_SPLOCK(x) (U(0x800) + 4U * (x)) +#define BSEC_SWLOCK(x) (U(0x840) + 4U * (x)) +#define BSEC_SRLOCK(x) (U(0x880) + 4U * (x)) +#define BSEC_OTPVLDR(x) (U(0x8C0) + 4U * (x)) +#define BSEC_SFSR(x) (U(0x940) + 4U * (x)) +#define BSEC_OTPCR U(0xC04) +#define BSEC_WDR U(0xC08) +#define BSEC_SCRATCHR0 U(0xE00) +#define BSEC_SCRATCHR1 U(0xE04) +#define BSEC_SCRATCHR2 U(0xE08) +#define BSEC_SCRATCHR3 U(0xE0C) +#define BSEC_LOCKR U(0xE10) +#define BSEC_JTAGINR U(0xE14) +#define BSEC_JTAGOUTR U(0xE18) +#define BSEC_DENR U(0xE20) +#define BSEC_UNMAPR U(0xE24) +#define BSEC_SR U(0xE40) +#define BSEC_OTPSR U(0xE44) +#define BSEC_WRCR U(0xF00) +#define BSEC_HWCFGR U(0xFF0) +#define BSEC_VERR U(0xFF4) +#define BSEC_IPIDR U(0xFF8) +#define BSEC_SIDR U(0xFFC) + +/* BSEC_OTPCR register fields */ +#define BSEC_OTPCR_ADDR_MASK GENMASK_32(8, 0) +#define BSEC_OTPCR_ADDR_SHIFT U(0) +#define BSEC_OTPCR_PROG BIT_32(13) +#define BSEC_OTPCR_PPLOCK BIT_32(14) +#define BSEC_OTPCR_LASTCID_MASK GENMASK_32(21, 19) +#define BSEC_OTPCR_LASTCID_SHIFT U(19) + +/* BSEC_LOCKR register fields */ +#define BSEC_LOCKR_GWLOCK_MASK BIT_32(0) +#define BSEC_LOCKR_GWLOCK_SHIFT U(0) +#define BSEC_LOCKR_DENLOCK_MASK BIT_32(1) +#define BSEC_LOCKR_DENLOCK_SHIFT U(1) +#define BSEC_LOCKR_HKLOCK_MASK BIT_32(2) +#define BSEC_LOCKR_HKLOCK_SHIFT U(2) + +/* BSEC_DENR register fields */ +#define BSEC_DENR_LPDBGEN BIT_32(0) +#define BSEC_DENR_DBGENA BIT_32(1) +#define BSEC_DENR_NIDENA BIT_32(2) +#define BSEC_DENR_DEVICEEN BIT_32(3) +#define BSEC_DENR_HDPEN BIT_32(4) +#define BSEC_DENR_SPIDENA BIT_32(5) +#define BSEC_DENR_SPNIDENA BIT_32(6) +#define BSEC_DENR_DBGSWEN BIT_32(7) +#define BSEC_DENR_DBGENM BIT_32(8) +#define BSEC_DENR_NIDENM BIT_32(9) +#define BSEC_DENR_SPIDENM BIT_32(10) +#define BSEC_DENR_SPNIDENM BIT_32(11) +#define BSEC_DENR_CFGSDIS BIT_32(12) +#define BSEC_DENR_CP15SDIS_MASK GENMASK_32(14, 13) +#define BSEC_DENR_CP15SDIS_SHIFT U(13) +#define BSEC_DENR_LPDBGDIS BIT_32(15) +#define BSEC_DENR_ALL_MSK GENMASK_32(15, 0) + +/* BSEC_SR register fields */ +#define BSEC_SR_BUSY BIT_32(0) +#define BSEC_SR_HVALID BIT_32(1) +#define BSEC_SR_RNGERR BIT_32(2) +#define BSEC_SR_HKWW_MASK GENMASK_32(15, 8) +#define BSEC_SR_HKWW_SHIFT U(8) +#define BSEC_SR_NVSTATE_MASK GENMASK_32(31, 26) +#define BSEC_SR_NVSTATE_SHIFT U(26) +#define BSEC_SR_NVSTATE_OPEN U(0x16) +#define BSEC_SR_NVSTATE_CLOSED U(0x0D) +#define BSEC_SR_NVSTATE_OTP_LOCKED U(0x23) + +/* BSEC_OTPSR register fields */ +#define BSEC_OTPSR_BUSY BIT_32(0) +#define BSEC_OTPSR_FUSEOK BIT_32(1) +#define BSEC_OTPSR_HIDEUP BIT_32(2) +#define BSEC_OTPSR_OTPNVIR BIT_32(4) +#define BSEC_OTPSR_OTPERR BIT_32(5) +#define BSEC_OTPSR_OTPSEC BIT_32(6) +#define BSEC_OTPSR_PROGFAIL BIT_32(16) +#define BSEC_OTPSR_DISTURBF BIT_32(17) +#define BSEC_OTPSR_DEDF BIT_32(18) +#define BSEC_OTPSR_SECF BIT_32(19) +#define BSEC_OTPSR_PPLF BIT_32(20) +#define BSEC_OTPSR_PPLMF BIT_32(21) +#define BSEC_OTPSR_AMEF BIT_32(22) + +/* BSEC_VERR register fields */ +#define BSEC_VERR_MASK GENMASK_32(7, 0) + +#endif /* BSEC3_REG_H */ diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c index 5f05f637e..a7cce627c 100644 --- a/plat/st/stm32mp2/bl2_plat_setup.c +++ b/plat/st/stm32mp2/bl2_plat_setup.c @@ -7,8 +7,10 @@ #include #include +#include #include +#include #include void bl2_el3_early_platform_setup(u_register_t arg0 __unused, @@ -25,4 +27,8 @@ void bl2_platform_setup(void) void bl2_el3_plat_arch_setup(void) { + if (stm32_otp_probe() != 0U) { + ERROR("OTP probe failed\n"); + panic(); + } } diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk index 6ea4638cc..0519b164d 100644 --- a/plat/st/stm32mp2/platform.mk +++ b/plat/st/stm32mp2/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2023, STMicroelectronics - All Rights Reserved +# Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved # # SPDX-License-Identifier: BSD-3-Clause # @@ -46,6 +46,8 @@ PLAT_BL_COMMON_SOURCES += lib/cpus/${ARCH}/cortex_a35.S PLAT_BL_COMMON_SOURCES += drivers/st/uart/${ARCH}/stm32_console.S PLAT_BL_COMMON_SOURCES += plat/st/stm32mp2/${ARCH}/stm32mp2_helper.S +PLAT_BL_COMMON_SOURCES += drivers/st/bsec/bsec3.c + BL2_SOURCES += plat/st/stm32mp2/plat_bl2_mem_params_desc.c BL2_SOURCES += plat/st/stm32mp2/bl2_plat_setup.c diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h index ee105de66..56c62e12b 100644 --- a/plat/st/stm32mp2/stm32mp2_def.h +++ b/plat/st/stm32mp2/stm32mp2_def.h @@ -157,6 +157,96 @@ enum ddr_type { #define STM32MP_SDMMC2_BASE U(0x48230000) #define STM32MP_SDMMC3_BASE U(0x48240000) +/******************************************************************************* + * STM32MP2 BSEC / OTP + ******************************************************************************/ +/* + * 367 available OTPs, the other are masked + * - ECIES key: 368 to 375 (only readable by bootrom) + * - HWKEY: 376 to 383 (never reloadable or readable) + */ +#define STM32MP2_OTP_MAX_ID U(0x16F) +#define STM32MP2_MID_OTP_START U(0x80) +#define STM32MP2_UPPER_OTP_START U(0x100) + +/* OTP labels */ +#define PART_NUMBER_OTP "part-number-otp" +#define PACKAGE_OTP "package-otp" +#define HCONF1_OTP "otp124" +#define NAND_OTP "otp16" +#define NAND2_OTP "otp20" +#define BOARD_ID_OTP "board-id" +#define UID_OTP "uid-otp" +#define LIFECYCLE2_OTP "otp18" +#define PKH_OTP "otp144" +#define ENCKEY_OTP "otp260" + +/* OTP mask */ +/* PACKAGE */ +#define PACKAGE_OTP_PKG_MASK GENMASK_32(2, 0) +#define PACKAGE_OTP_PKG_SHIFT U(0) + +/* IWDG OTP */ +#define HCONF1_OTP_IWDG_HW_POS U(0) +#define HCONF1_OTP_IWDG_FZ_STOP_POS U(1) +#define HCONF1_OTP_IWDG_FZ_STANDBY_POS U(2) + +/* NAND OTP */ +/* NAND parameter storage flag */ +#define NAND_PARAM_STORED_IN_OTP BIT_32(31) + +/* NAND page size in bytes */ +#define NAND_PAGE_SIZE_MASK GENMASK_32(30, 29) +#define NAND_PAGE_SIZE_SHIFT U(29) +#define NAND_PAGE_SIZE_2K U(0) +#define NAND_PAGE_SIZE_4K U(1) +#define NAND_PAGE_SIZE_8K U(2) + +/* NAND block size in pages */ +#define NAND_BLOCK_SIZE_MASK GENMASK_32(28, 27) +#define NAND_BLOCK_SIZE_SHIFT U(27) +#define NAND_BLOCK_SIZE_64_PAGES U(0) +#define NAND_BLOCK_SIZE_128_PAGES U(1) +#define NAND_BLOCK_SIZE_256_PAGES U(2) + +/* NAND number of block (in unit of 256 blocks) */ +#define NAND_BLOCK_NB_MASK GENMASK_32(26, 19) +#define NAND_BLOCK_NB_SHIFT U(19) +#define NAND_BLOCK_NB_UNIT U(256) + +/* NAND bus width in bits */ +#define NAND_WIDTH_MASK BIT_32(18) +#define NAND_WIDTH_SHIFT U(18) + +/* NAND number of ECC bits per 512 bytes */ +#define NAND_ECC_BIT_NB_MASK GENMASK_32(17, 15) +#define NAND_ECC_BIT_NB_SHIFT U(15) +#define NAND_ECC_BIT_NB_UNSET U(0) +#define NAND_ECC_BIT_NB_1_BITS U(1) +#define NAND_ECC_BIT_NB_4_BITS U(2) +#define NAND_ECC_BIT_NB_8_BITS U(3) +#define NAND_ECC_ON_DIE U(4) + +/* NAND number of planes */ +#define NAND_PLANE_BIT_NB_MASK BIT_32(14) + +/* NAND2 OTP */ +#define NAND2_PAGE_SIZE_SHIFT U(16) + +/* NAND2 config distribution */ +#define NAND2_CONFIG_DISTRIB BIT_32(0) +#define NAND2_PNAND_NAND2_SNAND_NAND1 U(0) +#define NAND2_PNAND_NAND1_SNAND_NAND2 U(1) + +/* MONOTONIC OTP */ +#define MAX_MONOTONIC_VALUE U(32) + +/* UID OTP */ +#define UID_WORD_NB U(3) + +/* Lifecycle OTP */ +#define SECURE_BOOT_CLOSED_SECURE GENMASK_32(3, 0) + /******************************************************************************* * STM32MP2 TAMP ******************************************************************************/