Commit 5014b52d authored by Vyacheslav Yurkov's avatar Vyacheslav Yurkov
Browse files

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: default avatarVyacheslav Yurkov <uvv.mail@gmail.com>
Change-Id: I55b0c910314253e5647486609583fd290dadd30a
parent 0ef419b1
...@@ -105,6 +105,36 @@ static int mmc_device_state(void) ...@@ -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) ...@@ -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) ...@@ -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)
......
/* /*
* 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 @@ ...@@ -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); ...@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment