From d3434dca0b3acb902fe3a6cf39065ba917f69b1c Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 18 Aug 2021 15:03:40 +0200 Subject: [PATCH] feat(stm32mp1): manage second NAND OTP on STM32MP13 On STM32MP13, 2 OTP fuses can be used to configure NAND devices. By default OTP CFG9 is used for sNAND. A new OTP (CFG10) is used to configure raw NAND. Thanks to bit 0 of CFG10 OTP, this default configuration can be switched. For sNAND on STM32MP13, the NAND_PARAM_STORED_IN_OTP is not used. The sNAND parameters have to be taken from OTP bits. Change-Id: Ib95e0f9b9e66179a58b07f723ea01dce68b96475 Signed-off-by: Yann Gautier --- plat/st/stm32mp1/stm32mp1_boot_device.c | 28 +++++++++++++++++++++++++ plat/st/stm32mp1/stm32mp1_def.h | 16 +++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c index ba53c7a13..3a8a27ac9 100644 --- a/plat/st/stm32mp1/stm32mp1_boot_device.c +++ b/plat/st/stm32mp1/stm32mp1_boot_device.c @@ -30,6 +30,7 @@ void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size) static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) { uint32_t nand_param; + uint32_t nand2_param __maybe_unused; /* Check if NAND parameters are stored in OTP */ if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) { @@ -38,13 +39,40 @@ static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) } if (nand_param == 0U) { +#if STM32MP13 + if (is_slc) { + return 0; + } +#endif +#if STM32MP15 return 0; +#endif } if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) { +#if STM32MP13 + if (is_slc) { + goto ecc; + } +#endif +#if STM32MP15 goto ecc; +#endif } +#if STM32MP13 + if (stm32_get_otp_value(NAND2_OTP, &nand2_param) != 0) { + ERROR("BSEC: NAND_OTP Error\n"); + return -EACCES; + } + + /* Check OTP configuration for this device */ + if ((((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND1_SNAND_NAND2) && !is_slc) || + (((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND2_SNAND_NAND1) && is_slc)) { + nand_param = nand2_param << (NAND_PAGE_SIZE_SHIFT - NAND2_PAGE_SIZE_SHIFT); + } +#endif + /* NAND parameter shall be read from OTP */ if ((nand_param & NAND_WIDTH_MASK) != 0U) { nand_dev->buswidth = NAND_BUS_WIDTH_16; diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 06660ceb0..116bd5d86 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -442,7 +442,13 @@ enum ddr_type { #define PACKAGE_OTP "package_otp" #endif #define HW2_OTP "hw2_otp" +#if STM32MP13 +#define NAND_OTP "cfg9_otp" +#define NAND2_OTP "cfg10_otp" +#endif +#if STM32MP15 #define NAND_OTP "nand_otp" +#endif #define MONOTONIC_OTP "monotonic_otp" #define UID_OTP "uid_otp" #define BOARD_ID_OTP "board_id" @@ -502,7 +508,7 @@ enum ddr_type { #define NAND_BLOCK_SIZE_128_PAGES U(1) #define NAND_BLOCK_SIZE_256_PAGES U(2) -/* NAND number of block (in unit of 256 blocs) */ +/* NAND number of block (in unit of 256 blocks) */ #define NAND_BLOCK_NB_MASK GENMASK_32(26, 19) #define NAND_BLOCK_NB_SHIFT 19 #define NAND_BLOCK_NB_UNIT U(256) @@ -523,6 +529,14 @@ enum ddr_type { /* NAND number of planes */ #define NAND_PLANE_BIT_NB_MASK BIT(14) +/* NAND2 OTP */ +#define NAND2_PAGE_SIZE_SHIFT 16 + +/* NAND2 config distribution */ +#define NAND2_CONFIG_DISTRIB BIT(0) +#define NAND2_PNAND_NAND2_SNAND_NAND1 U(0) +#define NAND2_PNAND_NAND1_SNAND_NAND2 U(1) + /* MONOTONIC OTP */ #define MAX_MONOTONIC_VALUE 32