mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-26 06:50:10 +00:00
stm32mp1: Add support for raw NAND boot device
STM32MP1 platform is able to boot from raw NAND devices. These modifications add this support using the new raw NAND framework. Change-Id: I9e9c2b03930f98a5ac23f2b6b41945bef43e5043 Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
This commit is contained in:
parent
695f7df852
commit
12e21dfde2
7 changed files with 290 additions and 5 deletions
|
@ -14,11 +14,14 @@
|
|||
#include <drivers/io/io_block.h>
|
||||
#include <drivers/io/io_driver.h>
|
||||
#include <drivers/io/io_dummy.h>
|
||||
#include <drivers/io/io_mtd.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <drivers/mmc.h>
|
||||
#include <drivers/partition/partition.h>
|
||||
#include <drivers/raw_nand.h>
|
||||
#include <drivers/st/io_mmc.h>
|
||||
#include <drivers/st/io_stm32image.h>
|
||||
#include <drivers/st/stm32_fmc2_nand.h>
|
||||
#include <drivers/st/stm32_sdmmc2.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils.h>
|
||||
|
@ -56,6 +59,17 @@ static const io_block_dev_spec_t mmc_block_dev_spec = {
|
|||
static const io_dev_connector_t *mmc_dev_con;
|
||||
#endif /* STM32MP_SDMMC || STM32MP_EMMC */
|
||||
|
||||
#if STM32MP_RAW_NAND
|
||||
static io_mtd_dev_spec_t nand_dev_spec = {
|
||||
.ops = {
|
||||
.init = nand_raw_init,
|
||||
.read = nand_read,
|
||||
},
|
||||
};
|
||||
|
||||
static const io_dev_connector_t *nand_dev_con;
|
||||
#endif
|
||||
|
||||
#ifdef AARCH32_SP_OPTEE
|
||||
static const struct stm32image_part_info optee_header_partition_spec = {
|
||||
.name = OPTEE_HEADER_IMAGE_NAME,
|
||||
|
@ -209,6 +223,9 @@ static void print_boot_device(boot_api_context_t *boot_context)
|
|||
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
|
||||
INFO("Using EMMC\n");
|
||||
break;
|
||||
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
|
||||
INFO("Using FMC NAND\n");
|
||||
break;
|
||||
default:
|
||||
ERROR("Boot interface not found\n");
|
||||
panic();
|
||||
|
@ -312,6 +329,59 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type,
|
|||
}
|
||||
#endif /* STM32MP_SDMMC || STM32MP_EMMC */
|
||||
|
||||
#if STM32MP_RAW_NAND
|
||||
static void boot_fmc2_nand(boot_api_context_t *boot_context)
|
||||
{
|
||||
int io_result __unused;
|
||||
uint8_t idx;
|
||||
struct stm32image_part_info *part;
|
||||
|
||||
io_result = stm32_fmc2_init();
|
||||
assert(io_result == 0);
|
||||
|
||||
/* Register the IO device on this platform */
|
||||
io_result = register_io_dev_mtd(&nand_dev_con);
|
||||
assert(io_result == 0);
|
||||
|
||||
/* Open connections to device */
|
||||
io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
|
||||
&storage_dev_handle);
|
||||
assert(io_result == 0);
|
||||
|
||||
stm32image_dev_info_spec.device_size = 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 = 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 = 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 = 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 = 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_RAW_NAND */
|
||||
|
||||
void stm32mp_io_setup(void)
|
||||
{
|
||||
int io_result __unused;
|
||||
|
@ -346,6 +416,12 @@ void stm32mp_io_setup(void)
|
|||
boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
|
||||
break;
|
||||
#endif
|
||||
#if STM32MP_RAW_NAND
|
||||
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
|
||||
dmbsy();
|
||||
boot_fmc2_nand(boot_context);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ERROR("Boot interface %d not supported\n",
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
/* Boot occurred on EMMC */
|
||||
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U
|
||||
|
||||
/* Boot occurred on FMC */
|
||||
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U
|
||||
|
||||
/**
|
||||
* @brief Possible value of boot context field 'EmmcXferStatus'
|
||||
*/
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#define MAX_IO_DEVICES U(4)
|
||||
#define MAX_IO_HANDLES U(4)
|
||||
#define MAX_IO_BLOCK_DEVICES U(1)
|
||||
#define MAX_IO_MTD_DEVICES U(1)
|
||||
|
||||
/*******************************************************************************
|
||||
* BL2 specific defines.
|
||||
|
|
14
plat/st/stm32mp1/include/stm32mp1_boot_device.h
Normal file
14
plat/st/stm32mp1/include/stm32mp1_boot_device.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2019, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef STM32MP1_BOOT_DEVICE_H
|
||||
#define STM32MP1_BOOT_DEVICE_H
|
||||
|
||||
#include <drivers/raw_nand.h>
|
||||
|
||||
int plat_get_raw_nand_data(struct rawnand_device *device);
|
||||
|
||||
#endif /* STM32MP1_BOOT_DEVICE_H */
|
|
@ -27,15 +27,18 @@ $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
|
|||
# Boot devices
|
||||
STM32MP_EMMC ?= 0
|
||||
STM32MP_SDMMC ?= 0
|
||||
STM32MP_RAW_NAND ?= 0
|
||||
|
||||
ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
|
||||
ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_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 add_define,STM32MP_EMMC))
|
||||
$(eval $(call add_define,STM32MP_SDMMC))
|
||||
$(eval $(call add_define,STM32MP_RAW_NAND))
|
||||
|
||||
PLAT_INCLUDES := -Iplat/st/common/include/
|
||||
PLAT_INCLUDES += -Iplat/st/stm32mp1/include/
|
||||
|
@ -83,6 +86,7 @@ PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \
|
|||
|
||||
BL2_SOURCES += drivers/io/io_block.c \
|
||||
drivers/io/io_dummy.c \
|
||||
drivers/io/io_mtd.c \
|
||||
drivers/io/io_storage.c \
|
||||
drivers/st/crypto/stm32_hash.c \
|
||||
drivers/st/io/io_stm32image.c \
|
||||
|
@ -98,6 +102,17 @@ BL2_SOURCES += drivers/mmc/mmc.c \
|
|||
drivers/st/mmc/stm32_sdmmc2.c
|
||||
endif
|
||||
|
||||
ifeq (${STM32MP_RAW_NAND},1)
|
||||
$(eval $(call add_define_val,NAND_ONFI_DETECT,1))
|
||||
BL2_SOURCES += drivers/mtd/nand/raw_nand.c \
|
||||
drivers/st/fmc/stm32_fmc2_nand.c
|
||||
endif
|
||||
|
||||
ifneq ($(filter 1,${STM32MP_RAW_NAND}),)
|
||||
BL2_SOURCES += drivers/mtd/nand/core.c \
|
||||
plat/st/stm32mp1/stm32mp1_boot_device.c
|
||||
endif
|
||||
|
||||
BL2_SOURCES += drivers/st/ddr/stm32mp1_ddr.c \
|
||||
drivers/st/ddr/stm32mp1_ram.c
|
||||
|
||||
|
|
125
plat/st/stm32mp1/stm32mp1_boot_device.c
Normal file
125
plat/st/stm32mp1/stm32mp1_boot_device.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2019, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <drivers/nand.h>
|
||||
#include <lib/utils.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#define SZ_512 0x200U
|
||||
|
||||
#if STM32MP_RAW_NAND
|
||||
static int get_data_from_otp(struct nand_device *nand_dev)
|
||||
{
|
||||
int result;
|
||||
uint32_t nand_param;
|
||||
|
||||
/* Check if NAND parameters are stored in OTP */
|
||||
result = bsec_shadow_read_otp(&nand_param, NAND_OTP);
|
||||
if (result != BSEC_OK) {
|
||||
ERROR("BSEC: NAND_OTP Error %i\n", result);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (nand_param == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) {
|
||||
goto ecc;
|
||||
}
|
||||
|
||||
/* NAND parameter shall be read from OTP */
|
||||
if ((nand_param & NAND_WIDTH_MASK) != 0U) {
|
||||
nand_dev->buswidth = NAND_BUS_WIDTH_16;
|
||||
} else {
|
||||
nand_dev->buswidth = NAND_BUS_WIDTH_8;
|
||||
}
|
||||
|
||||
switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) {
|
||||
case NAND_PAGE_SIZE_2K:
|
||||
nand_dev->page_size = 0x800U;
|
||||
break;
|
||||
|
||||
case NAND_PAGE_SIZE_4K:
|
||||
nand_dev->page_size = 0x1000U;
|
||||
break;
|
||||
|
||||
case NAND_PAGE_SIZE_8K:
|
||||
nand_dev->page_size = 0x2000U;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR("Cannot read NAND page size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) {
|
||||
case NAND_BLOCK_SIZE_64_PAGES:
|
||||
nand_dev->block_size = 64U * nand_dev->page_size;
|
||||
break;
|
||||
|
||||
case NAND_BLOCK_SIZE_128_PAGES:
|
||||
nand_dev->block_size = 128U * nand_dev->page_size;
|
||||
break;
|
||||
|
||||
case NAND_BLOCK_SIZE_256_PAGES:
|
||||
nand_dev->block_size = 256U * nand_dev->page_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR("Cannot read NAND block size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >>
|
||||
NAND_BLOCK_NB_SHIFT) *
|
||||
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;
|
||||
|
||||
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_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;
|
||||
}
|
||||
}
|
||||
|
||||
VERBOSE("OTP: Block %i Page %i Size %lli\n", nand_dev->block_size,
|
||||
nand_dev->page_size, nand_dev->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if STM32MP_RAW_NAND
|
||||
int plat_get_raw_nand_data(struct rawnand_device *device)
|
||||
{
|
||||
device->nand_dev->ecc.mode = NAND_ECC_HW;
|
||||
device->nand_dev->ecc.size = SZ_512;
|
||||
|
||||
return get_data_from_otp(device->nand_dev);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include <stm32mp_common.h>
|
||||
#include <stm32mp_dt.h>
|
||||
#include <stm32mp_shres_helpers.h>
|
||||
#include <stm32mp1_boot_device.h>
|
||||
#include <stm32mp1_dbgmcu.h>
|
||||
#include <stm32mp1_private.h>
|
||||
#endif
|
||||
|
@ -107,15 +108,15 @@ enum ddr_type {
|
|||
|
||||
#ifdef AARCH32_SP_OPTEE
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
#define STM32MP_BL2_SIZE U(0x00019000) /* 100 KB for BL2 */
|
||||
#define STM32MP_BL2_SIZE U(0x0001A000) /* 100 KB for BL2 */
|
||||
#else
|
||||
#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */
|
||||
#define STM32MP_BL2_SIZE U(0x00018000) /* 92 KB for BL2 */
|
||||
#endif
|
||||
#else
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
#define STM32MP_BL2_SIZE U(0x00018000) /* 96 KB for BL2 */
|
||||
#define STM32MP_BL2_SIZE U(0x00019000) /* 96 KB for BL2 */
|
||||
#else
|
||||
#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */
|
||||
#define STM32MP_BL2_SIZE U(0x00017000) /* 88 KB for BL2 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -144,6 +145,19 @@ enum ddr_type {
|
|||
|
||||
#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000))
|
||||
|
||||
/* Define maximum page size for NAND devices */
|
||||
#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000)
|
||||
|
||||
/*******************************************************************************
|
||||
* STM32MP1 RAW partition offset for MTD devices
|
||||
******************************************************************************/
|
||||
#define STM32MP_NAND_BL33_OFFSET U(0x00200000)
|
||||
#ifdef AARCH32_SP_OPTEE
|
||||
#define STM32MP_NAND_TEEH_OFFSET U(0x00600000)
|
||||
#define STM32MP_NAND_TEED_OFFSET U(0x00680000)
|
||||
#define STM32MP_NAND_TEEX_OFFSET U(0x00700000)
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* STM32MP1 device/io map related constants (used for MMU)
|
||||
******************************************************************************/
|
||||
|
@ -266,6 +280,7 @@ enum ddr_type {
|
|||
/* OTP offsets */
|
||||
#define DATA0_OTP U(0)
|
||||
#define PART_NUMBER_OTP U(1)
|
||||
#define NAND_OTP U(9)
|
||||
#define PACKAGE_OTP U(16)
|
||||
#define HW2_OTP U(18)
|
||||
|
||||
|
@ -289,6 +304,42 @@ enum ddr_type {
|
|||
/* HW2 OTP */
|
||||
#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13)
|
||||
|
||||
/* NAND OTP */
|
||||
/* NAND parameter storage flag */
|
||||
#define NAND_PARAM_STORED_IN_OTP BIT(31)
|
||||
|
||||
/* NAND page size in bytes */
|
||||
#define NAND_PAGE_SIZE_MASK GENMASK_32(30, 29)
|
||||
#define NAND_PAGE_SIZE_SHIFT 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 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 blocs) */
|
||||
#define NAND_BLOCK_NB_MASK GENMASK_32(26, 19)
|
||||
#define NAND_BLOCK_NB_SHIFT 19
|
||||
#define NAND_BLOCK_NB_UNIT U(256)
|
||||
|
||||
/* NAND bus width in bits */
|
||||
#define NAND_WIDTH_MASK BIT(18)
|
||||
#define NAND_WIDTH_SHIFT 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 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)
|
||||
|
||||
/*******************************************************************************
|
||||
* STM32MP1 TAMP
|
||||
******************************************************************************/
|
||||
|
|
Loading…
Add table
Reference in a new issue