diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c index e2629fa..d0bc605 100644 --- a/plat/st/common/bl2_io_storage.c +++ b/plat/st/common/bl2_io_storage.c @@ -19,9 +19,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -70,6 +72,17 @@ static const io_dev_connector_t *nand_dev_con; #endif +#if STM32MP_SPI_NAND +static io_mtd_dev_spec_t spi_nand_dev_spec = { + .ops = { + .init = spi_nand_init, + .read = nand_read, + }, +}; + +static const io_dev_connector_t *spi_dev_con; +#endif + #ifdef AARCH32_SP_OPTEE static const struct stm32image_part_info optee_header_partition_spec = { .name = OPTEE_HEADER_IMAGE_NAME, @@ -226,6 +239,9 @@ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: INFO("Using FMC NAND\n"); break; + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + INFO("Using SPI NAND\n"); + break; default: ERROR("Boot interface not found\n"); panic(); @@ -382,6 +398,60 @@ } #endif /* STM32MP_RAW_NAND */ +#if STM32MP_SPI_NAND +static void boot_spi_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + + io_result = stm32_qspi_init(); + assert(io_result == 0); + + io_result = register_io_dev_mtd(&spi_dev_con); + assert(io_result == 0); + + /* Open connections to device */ + io_result = io_dev_open(spi_dev_con, + (uintptr_t)&spi_nand_dev_spec, + &storage_dev_handle); + assert(io_result == 0); + + stm32image_dev_info_spec.device_size = + spi_nand_dev_spec.device_size; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_BL33_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEH_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEED_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_PAGER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEX_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; +#endif + + io_result = register_io_dev_stm32image(&stm32image_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(stm32image_dev_con, + (uintptr_t)&stm32image_dev_info_spec, + &image_dev_handle); + assert(io_result == 0); +} +#endif /* STM32MP_SPI_NAND */ + void stm32mp_io_setup(void) { int io_result __unused; @@ -422,6 +492,12 @@ boot_fmc2_nand(boot_context); break; #endif +#if STM32MP_SPI_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + dmbsy(); + boot_spi_nand(boot_context); + break; +#endif default: ERROR("Boot interface %d not supported\n", diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h index ba5d22f..1f05d0b 100644 --- a/plat/st/stm32mp1/include/boot_api.h +++ b/plat/st/stm32mp1/include/boot_api.h @@ -36,6 +36,9 @@ /* Boot occurred on FMC */ #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U +/* Boot occurred on QSPI NAND */ +#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U + /** * @brief Possible value of boot context field 'EmmcXferStatus' */ diff --git a/plat/st/stm32mp1/include/stm32mp1_boot_device.h b/plat/st/stm32mp1/include/stm32mp1_boot_device.h index ae6b02b..db80f93 100644 --- a/plat/st/stm32mp1/include/stm32mp1_boot_device.h +++ b/plat/st/stm32mp1/include/stm32mp1_boot_device.h @@ -8,7 +8,9 @@ #define STM32MP1_BOOT_DEVICE_H #include +#include int plat_get_raw_nand_data(struct rawnand_device *device); +int plat_get_spi_nand_data(struct spinand_device *device); #endif /* STM32MP1_BOOT_DEVICE_H */ diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index 71b3916..d25f3b3 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -28,17 +28,21 @@ STM32MP_EMMC ?= 0 STM32MP_SDMMC ?= 0 STM32MP_RAW_NAND ?= 0 +STM32MP_SPI_NAND ?= 0 -ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND}),) +ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND} \ + ${STM32MP_SPI_NAND}),) $(error "No boot device driver is enabled") endif $(eval $(call assert_boolean,STM32MP_EMMC)) $(eval $(call assert_boolean,STM32MP_SDMMC)) $(eval $(call assert_boolean,STM32MP_RAW_NAND)) +$(eval $(call assert_boolean,STM32MP_SPI_NAND)) $(eval $(call add_define,STM32MP_EMMC)) $(eval $(call add_define,STM32MP_SDMMC)) $(eval $(call add_define,STM32MP_RAW_NAND)) +$(eval $(call add_define,STM32MP_SPI_NAND)) PLAT_INCLUDES := -Iplat/st/common/include/ PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ @@ -108,7 +112,16 @@ drivers/st/fmc/stm32_fmc2_nand.c endif -ifneq ($(filter 1,${STM32MP_RAW_NAND}),) +ifeq (${STM32MP_SPI_NAND},1) +BL2_SOURCES += drivers/mtd/nand/spi_nand.c +endif + +ifeq (${STM32MP_SPI_NAND},1) +BL2_SOURCES += drivers/mtd/spi-mem/spi_mem.c \ + drivers/st/spi/stm32_qspi.c +endif + +ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),) BL2_SOURCES += drivers/mtd/nand/core.c \ plat/st/stm32mp1/stm32mp1_boot_device.c endif diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c index 8b1f07f..fa352f3 100644 --- a/plat/st/stm32mp1/stm32mp1_boot_device.c +++ b/plat/st/stm32mp1/stm32mp1_boot_device.c @@ -12,8 +12,8 @@ #define SZ_512 0x200U -#if STM32MP_RAW_NAND -static int get_data_from_otp(struct nand_device *nand_dev) +#if STM32MP_RAW_NAND || STM32MP_SPI_NAND +static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) { int result; uint32_t nand_param; @@ -81,28 +81,37 @@ NAND_BLOCK_NB_UNIT * nand_dev->block_size; ecc: - switch ((nand_param & NAND_ECC_BIT_NB_MASK) >> - NAND_ECC_BIT_NB_SHIFT) { - case NAND_ECC_BIT_NB_1_BITS: - nand_dev->ecc.max_bit_corr = 1U; - break; + if (is_slc) { + switch ((nand_param & NAND_ECC_BIT_NB_MASK) >> + NAND_ECC_BIT_NB_SHIFT) { + case NAND_ECC_BIT_NB_1_BITS: + nand_dev->ecc.max_bit_corr = 1U; + break; - case NAND_ECC_BIT_NB_4_BITS: - nand_dev->ecc.max_bit_corr = 4U; - break; + case NAND_ECC_BIT_NB_4_BITS: + nand_dev->ecc.max_bit_corr = 4U; + break; - case NAND_ECC_BIT_NB_8_BITS: - nand_dev->ecc.max_bit_corr = 8U; - break; + case NAND_ECC_BIT_NB_8_BITS: + nand_dev->ecc.max_bit_corr = 8U; + break; - case NAND_ECC_ON_DIE: - nand_dev->ecc.mode = NAND_ECC_ONDIE; - break; + case NAND_ECC_ON_DIE: + nand_dev->ecc.mode = NAND_ECC_ONDIE; + break; - default: - if (nand_dev->ecc.max_bit_corr == 0U) { - ERROR("No valid eccbit number\n"); - return -EINVAL; + default: + if (nand_dev->ecc.max_bit_corr == 0U) { + ERROR("No valid eccbit number\n"); + return -EINVAL; + } + } + } else { + /* Selected multiple plane NAND */ + if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) { + nand_dev->nb_planes = 2U; + } else { + nand_dev->nb_planes = 1U; } } @@ -111,7 +120,7 @@ return 0; } -#endif +#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */ #if STM32MP_RAW_NAND int plat_get_raw_nand_data(struct rawnand_device *device) @@ -119,7 +128,24 @@ device->nand_dev->ecc.mode = NAND_ECC_HW; device->nand_dev->ecc.size = SZ_512; - return get_data_from_otp(device->nand_dev); + return get_data_from_otp(device->nand_dev, true); +} +#endif + +#if STM32MP_SPI_NAND +int plat_get_spi_nand_data(struct spinand_device *device) +{ + zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op)); + device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X; + device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->spi_read_cache_op.addr.nbytes = 2U; + device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->spi_read_cache_op.dummy.nbytes = 1U; + device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE; + device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN; + + return get_data_from_otp(device->nand_dev, false); } #endif diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 7ac9b5f..a427dcf 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -340,6 +340,9 @@ #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(14) + /******************************************************************************* * STM32MP1 TAMP ******************************************************************************/