mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-23 21:44:15 +00:00
feat(drivers/mmc): boot partition read support
Added a public function to read blocks from a current boot partition. switch between partitions has to respect eMMC partition switch timing. Signed-off-by: Vyacheslav Yurkov <uvv.mail@gmail.com> Change-Id: I55b0c910314253e5647486609583fd290dadd30a
This commit is contained in:
parent
0ef419b145
commit
5014b52dec
2 changed files with 84 additions and 3 deletions
|
@ -105,6 +105,36 @@ static int mmc_device_state(void)
|
||||||
return MMC_GET_STATE(resp_data[0]);
|
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)
|
static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -668,7 +698,7 @@ static inline void mmc_rpmb_enable(void)
|
||||||
{
|
{
|
||||||
mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
|
mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
|
||||||
PART_CFG_BOOT_PARTITION1_ENABLE |
|
PART_CFG_BOOT_PARTITION1_ENABLE |
|
||||||
PART_CFG_PARTITION1_ACCESS);
|
PART_CFG_BOOT_PARTITION1_ACCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mmc_rpmb_disable(void)
|
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;
|
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,
|
int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
|
||||||
unsigned int width, unsigned int flags,
|
unsigned int width, unsigned int flags,
|
||||||
struct mmc_device_info *device_info)
|
struct mmc_device_info *device_info)
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -60,10 +60,16 @@
|
||||||
#define CMD_EXTCSD_PARTITION_CONFIG 179
|
#define CMD_EXTCSD_PARTITION_CONFIG 179
|
||||||
#define CMD_EXTCSD_BUS_WIDTH 183
|
#define CMD_EXTCSD_BUS_WIDTH 183
|
||||||
#define CMD_EXTCSD_HS_TIMING 185
|
#define CMD_EXTCSD_HS_TIMING 185
|
||||||
|
#define CMD_EXTCSD_PART_SWITCH_TIME 199
|
||||||
#define CMD_EXTCSD_SEC_CNT 212
|
#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_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 */
|
/* Values in EXT CSD register */
|
||||||
#define MMC_BUS_WIDTH_1 U(0)
|
#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_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_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_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,
|
int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
|
||||||
unsigned int width, unsigned int flags,
|
unsigned int width, unsigned int flags,
|
||||||
struct mmc_device_info *device_info);
|
struct mmc_device_info *device_info);
|
||||||
|
|
Loading…
Add table
Reference in a new issue