diff --git a/drivers/emmc/emmc.c b/drivers/emmc/emmc.c index 5fe28ef..3fae2a1 100644 --- a/drivers/emmc/emmc.c +++ b/drivers/emmc/emmc.c @@ -40,6 +40,12 @@ static const emmc_ops_t *ops; static unsigned int emmc_ocr_value; static emmc_csd_t emmc_csd; +static unsigned int emmc_flags; + +static int is_cmd23_enabled(void) +{ + return (!!(emmc_flags & EMMC_FLAG_CMD23)); +} static int emmc_device_state(void) { @@ -174,11 +180,23 @@ ret = ops->prepare(lba, buf, size); assert(ret == 0); - memset(&cmd, 0, sizeof(emmc_cmd_t)); - if (size > EMMC_BLOCK_SIZE) + if (is_cmd23_enabled()) { + memset(&cmd, 0, sizeof(emmc_cmd_t)); + /* set block count */ + cmd.cmd_idx = EMMC_CMD23; + cmd.cmd_arg = size / EMMC_BLOCK_SIZE; + cmd.resp_type = EMMC_RESPONSE_R1; + ret = ops->send_cmd(&cmd); + assert(ret == 0); + + memset(&cmd, 0, sizeof(emmc_cmd_t)); cmd.cmd_idx = EMMC_CMD18; - else - cmd.cmd_idx = EMMC_CMD17; + } else { + if (size > EMMC_BLOCK_SIZE) + cmd.cmd_idx = EMMC_CMD18; + else + cmd.cmd_idx = EMMC_CMD17; + } if ((emmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) cmd.cmd_arg = lba * EMMC_BLOCK_SIZE; else @@ -193,11 +211,13 @@ /* wait buffer empty */ emmc_device_state(); - if (size > EMMC_BLOCK_SIZE) { - memset(&cmd, 0, sizeof(emmc_cmd_t)); - cmd.cmd_idx = EMMC_CMD12; - ret = ops->send_cmd(&cmd); - assert(ret == 0); + if (is_cmd23_enabled() == 0) { + if (size > EMMC_BLOCK_SIZE) { + memset(&cmd, 0, sizeof(emmc_cmd_t)); + cmd.cmd_idx = EMMC_CMD12; + ret = ops->send_cmd(&cmd); + assert(ret == 0); + } } /* Ignore improbable errors in release builds */ (void)ret; @@ -218,11 +238,24 @@ ret = ops->prepare(lba, buf, size); assert(ret == 0); - memset(&cmd, 0, sizeof(emmc_cmd_t)); - if (size > EMMC_BLOCK_SIZE) + if (is_cmd23_enabled()) { + /* set block count */ + memset(&cmd, 0, sizeof(emmc_cmd_t)); + cmd.cmd_idx = EMMC_CMD23; + cmd.cmd_arg = size / EMMC_BLOCK_SIZE; + cmd.resp_type = EMMC_RESPONSE_R1; + ret = ops->send_cmd(&cmd); + assert(ret == 0); + + memset(&cmd, 0, sizeof(emmc_cmd_t)); cmd.cmd_idx = EMMC_CMD25; - else - cmd.cmd_idx = EMMC_CMD24; + } else { + memset(&cmd, 0, sizeof(emmc_cmd_t)); + if (size > EMMC_BLOCK_SIZE) + cmd.cmd_idx = EMMC_CMD25; + else + cmd.cmd_idx = EMMC_CMD24; + } if ((emmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) cmd.cmd_arg = lba * EMMC_BLOCK_SIZE; else @@ -237,11 +270,13 @@ /* wait buffer empty */ emmc_device_state(); - if (size > EMMC_BLOCK_SIZE) { - memset(&cmd, 0, sizeof(emmc_cmd_t)); - cmd.cmd_idx = EMMC_CMD12; - ret = ops->send_cmd(&cmd); - assert(ret == 0); + if (is_cmd23_enabled() == 0) { + if (size > EMMC_BLOCK_SIZE) { + memset(&cmd, 0, sizeof(emmc_cmd_t)); + cmd.cmd_idx = EMMC_CMD12; + ret = ops->send_cmd(&cmd); + assert(ret == 0); + } } /* Ignore improbable errors in release builds */ (void)ret; @@ -328,7 +363,8 @@ return size_erased; } -void emmc_init(const emmc_ops_t *ops_ptr, int clk, int width) +void emmc_init(const emmc_ops_t *ops_ptr, int clk, int width, + unsigned int flags) { assert((ops_ptr != 0) && (ops_ptr->init != 0) && @@ -342,6 +378,7 @@ (width == EMMC_BUS_WIDTH_4) || (width == EMMC_BUS_WIDTH_8))); ops = ops_ptr; + emmc_flags = flags; emmc_enumerate(clk, width); } diff --git a/include/drivers/emmc.h b/include/drivers/emmc.h index 61d4495..5f78dce 100644 --- a/include/drivers/emmc.h +++ b/include/drivers/emmc.h @@ -49,6 +49,7 @@ #define EMMC_CMD13 13 #define EMMC_CMD17 17 #define EMMC_CMD18 18 +#define EMMC_CMD23 23 #define EMMC_CMD24 24 #define EMMC_CMD25 25 #define EMMC_CMD35 35 @@ -111,6 +112,8 @@ #define EMMC_STATE_BTST 9 #define EMMC_STATE_SLP 10 +#define EMMC_FLAG_CMD23 (1 << 0) + typedef struct emmc_cmd { unsigned int cmd_idx; unsigned int cmd_arg; @@ -177,6 +180,7 @@ size_t emmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size); size_t emmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size); size_t emmc_rpmb_erase_blocks(int lba, size_t size); -void emmc_init(const emmc_ops_t *ops, int clk, int bus_width); +void emmc_init(const emmc_ops_t *ops, int clk, int bus_width, + unsigned int flags); #endif /* __EMMC_H__ */