Merge changes I85a87dc9,If75df769,I55b0c910 into integration

* changes:
  feat(plat/st): add STM32MP_EMMC_BOOT option
  feat(drivers/st): manage boot part in io_mmc
  feat(drivers/mmc): boot partition read support
This commit is contained in:
Madhukar Pappireddy 2021-06-07 18:21:16 +02:00 committed by TrustedFirmware Code Review
commit b39a1308ab
7 changed files with 191 additions and 12 deletions

View File

@ -105,6 +105,36 @@ static int mmc_device_state(void)
return MMC_GET_STATE(resp_data[0]);
}
static int mmc_send_part_switch_cmd(unsigned int part_config)
{
int ret;
unsigned int part_time = 0;
ret = mmc_send_cmd(MMC_CMD(6),
EXTCSD_WRITE_BYTES |
EXTCSD_CMD(CMD_EXTCSD_PARTITION_CONFIG) |
EXTCSD_VALUE(part_config) |
EXTCSD_CMD_SET_NORMAL,
MMC_RESPONSE_R1B, NULL);
if (ret != 0) {
return ret;
}
/* Partition switch timing is in 10ms units */
part_time = mmc_ext_csd[CMD_EXTCSD_PART_SWITCH_TIME] * 10;
mdelay(part_time);
do {
ret = mmc_device_state();
if (ret < 0) {
return ret;
}
} while (ret == MMC_STATE_PRG);
return 0;
}
static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value)
{
int ret;
@ -668,7 +698,7 @@ static inline void mmc_rpmb_enable(void)
{
mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
PART_CFG_BOOT_PARTITION1_ENABLE |
PART_CFG_PARTITION1_ACCESS);
PART_CFG_BOOT_PARTITION1_ACCESS);
}
static inline void mmc_rpmb_disable(void)
@ -710,6 +740,50 @@ size_t mmc_rpmb_erase_blocks(int lba, size_t size)
return size_erased;
}
static int mmc_part_switch(unsigned int part_type)
{
uint8_t part_config = mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG];
part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
part_config |= part_type;
return mmc_send_part_switch_cmd(part_config);
}
static unsigned char mmc_current_boot_part(void)
{
return PART_CFG_CURRENT_BOOT_PARTITION(mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]);
}
size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size)
{
size_t size_read;
int ret;
unsigned char current_boot_part = mmc_current_boot_part();
if (current_boot_part != 1U &&
current_boot_part != 2U) {
ERROR("Got unexpected value for active boot partition, %u\n", current_boot_part);
return 0;
}
ret = mmc_part_switch(current_boot_part);
if (ret < 0) {
ERROR("Failed to switch to boot partition, %d\n", ret);
return 0;
}
size_read = mmc_read_blocks(lba, buf, size);
ret = mmc_part_switch(0);
if (ret < 0) {
ERROR("Failed to switch back to user partition, %d\n", ret);
return 0;
}
return size_read;
}
int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
unsigned int width, unsigned int flags,
struct mmc_device_info *device_info)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -29,6 +29,7 @@ static int mmc_dev_close(io_dev_info_t *dev_info);
static io_type_t device_type_mmc(void);
static signed long long seek_offset;
static size_t (*_read_blocks)(int lba, uintptr_t buf, size_t size);
static const io_dev_connector_t mmc_dev_connector = {
.dev_open = mmc_dev_open
@ -60,9 +61,15 @@ static io_type_t device_type_mmc(void)
/* Open a connection to the mmc device */
static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
{
struct io_mmc_dev_spec *device_spec =
(struct io_mmc_dev_spec *)init_params;
assert(dev_info != NULL);
*dev_info = (io_dev_info_t *)&mmc_dev_info;
_read_blocks = !device_spec->use_boot_part ?
mmc_read_blocks : mmc_boot_part_read_blocks;
return 0;
}
@ -100,8 +107,8 @@ static int mmc_block_read(io_entity_t *entity, uintptr_t buffer,
uint8_t retries;
for (retries = 0U; retries < 3U; retries++) {
*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
buffer, length);
*length_read = _read_blocks(seek_offset / MMC_BLOCK_SIZE,
buffer, length);
if (*length_read == length) {
return 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -60,10 +60,16 @@
#define CMD_EXTCSD_PARTITION_CONFIG 179
#define CMD_EXTCSD_BUS_WIDTH 183
#define CMD_EXTCSD_HS_TIMING 185
#define CMD_EXTCSD_PART_SWITCH_TIME 199
#define CMD_EXTCSD_SEC_CNT 212
#define EXT_CSD_PART_CONFIG_ACC_MASK GENMASK(2, 0)
#define PART_CFG_BOOT_PARTITION1_ENABLE (U(1) << 3)
#define PART_CFG_PARTITION1_ACCESS (U(1) << 0)
#define PART_CFG_BOOT_PARTITION1_ACCESS (U(1) << 0)
#define PART_CFG_BOOT_PART_EN_MASK GENMASK(5, 3)
#define PART_CFG_BOOT_PART_EN_SHIFT 3
#define PART_CFG_CURRENT_BOOT_PARTITION(x) (((x) & PART_CFG_BOOT_PART_EN_MASK) >> \
PART_CFG_BOOT_PART_EN_SHIFT)
/* Values in EXT CSD register */
#define MMC_BUS_WIDTH_1 U(0)
@ -230,6 +236,7 @@ size_t mmc_erase_blocks(int lba, size_t size);
size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size);
size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size);
size_t mmc_rpmb_erase_blocks(int lba, size_t size);
size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size);
int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
unsigned int width, unsigned int flags,
struct mmc_device_info *device_info);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -9,6 +9,10 @@
#include <drivers/io/io_driver.h>
struct io_mmc_dev_spec {
bool use_boot_part;
};
int register_io_dev_mmc(const io_dev_connector_t **dev_con);
#endif /* IO_MMC_H */

View File

@ -62,6 +62,30 @@ static const io_block_dev_spec_t mmc_block_dev_spec = {
.block_size = MMC_BLOCK_SIZE,
};
#if STM32MP_EMMC_BOOT
static io_block_spec_t emmc_boot_ssbl_block_spec = {
.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
};
static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
/* It's used as temp buffer in block driver */
.buffer = {
.offset = (size_t)&block_buffer,
.length = MMC_BLOCK_SIZE,
},
.ops = {
.read = mmc_boot_part_read_blocks,
.write = NULL,
},
.block_size = MMC_BLOCK_SIZE,
};
#endif
static struct io_mmc_dev_spec mmc_device_spec = {
.use_boot_part = false,
};
static const io_dev_connector_t *mmc_dev_con;
#endif /* STM32MP_SDMMC || STM32MP_EMMC */
@ -236,6 +260,38 @@ static int open_storage(const uintptr_t spec)
return io_dev_init(storage_dev_handle, 0);
}
#if STM32MP_EMMC_BOOT
static uint32_t get_boot_part_ssbl_header(void)
{
uint32_t magic = 0;
int io_result;
size_t bytes_read;
io_result = register_io_dev_block(&mmc_dev_con);
if (io_result != 0) {
panic();
}
io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
&storage_dev_handle);
assert(io_result == 0);
io_result = io_open(storage_dev_handle, (uintptr_t) &emmc_boot_ssbl_block_spec,
&image_dev_handle);
assert(io_result == 0);
io_result = io_read(image_dev_handle, (uintptr_t) &magic, sizeof(magic),
&bytes_read);
assert(io_result == 0);
assert(bytes_read == sizeof(magic));
io_result = io_dev_close(storage_dev_handle);
assert(io_result == 0);
return magic;
}
#endif
static void print_boot_device(boot_api_context_t *boot_context)
{
switch (boot_context->boot_interface_selected) {
@ -273,7 +329,8 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type,
uint8_t idx;
struct stm32image_part_info *part;
struct stm32_sdmmc2_params params;
const partition_entry_t *entry;
const partition_entry_t *entry __unused;
uint32_t magic __unused;
zeromem(&params, sizeof(struct stm32_sdmmc2_params));
@ -305,6 +362,26 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type,
panic();
}
stm32image_dev_info_spec.device_size =
stm32_sdmmc2_mmc_get_device_size();
#if STM32MP_EMMC_BOOT
magic = get_boot_part_ssbl_header();
if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
VERBOSE("%s, header found, jump to emmc load\n", __func__);
idx = IMG_IDX_BL33;
part = &stm32image_dev_info_spec.part_info[idx];
part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
part->bkp_offset = 0U;
mmc_device_spec.use_boot_part = true;
goto emmc_boot;
} else {
WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
}
#endif
/* Open MMC as a block device to read GPT table */
io_result = register_io_dev_block(&mmc_dev_con);
if (io_result != 0) {
@ -320,9 +397,6 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type,
io_result = io_dev_close(storage_dev_handle);
assert(io_result == 0);
stm32image_dev_info_spec.device_size =
stm32_sdmmc2_mmc_get_device_size();
for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
part = &stm32image_dev_info_spec.part_info[idx];
entry = get_partition_entry(part->name);
@ -335,6 +409,9 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type,
part->bkp_offset = 0U;
}
#if STM32MP_EMMC_BOOT
emmc_boot:
#endif
/*
* Re-open MMC with io_mmc, for better perfs compared to
* io_block.
@ -342,7 +419,8 @@ static void boot_mmc(enum mmc_device_type mmc_dev_type,
io_result = register_io_dev_mmc(&mmc_dev_con);
assert(io_result == 0);
io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
&storage_dev_handle);
assert(io_result == 0);
io_result = register_io_dev_stm32image(&stm32image_dev_con);

View File

@ -88,6 +88,12 @@
*/
#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE
/*
* SSBL offset in case it's stored in eMMC boot partition.
* We can fix it to 256K because TF-A size can't be bigger than SRAM
*/
#define PLAT_EMMC_BOOT_SSBL_OFFSET U(0x40000)
/*******************************************************************************
* DTB specific defines.
******************************************************************************/

View File

@ -42,6 +42,7 @@ STM32MP_SDMMC ?= 0
STM32MP_RAW_NAND ?= 0
STM32MP_SPI_NAND ?= 0
STM32MP_SPI_NOR ?= 0
STM32MP_EMMC_BOOT ?= 0
ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND} \
${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
@ -77,6 +78,7 @@ $(eval $(call assert_booleans,\
STM32MP_RAW_NAND \
STM32MP_SPI_NAND \
STM32MP_SPI_NOR \
STM32MP_EMMC_BOOT \
PLAT_XLAT_TABLES_DYNAMIC \
)))
@ -93,6 +95,7 @@ $(eval $(call add_defines,\
STM32MP_RAW_NAND \
STM32MP_SPI_NAND \
STM32MP_SPI_NOR \
STM32MP_EMMC_BOOT \
PLAT_XLAT_TABLES_DYNAMIC \
STM32_TF_A_COPIES \
PLAT_PARTITION_MAX_ENTRIES \