Add support for multi-block reads (performance improvements)

pull/655/head
David Garske 2025-12-23 17:13:42 -08:00 committed by Daniele Lacamera
parent 963cdadeaf
commit d3ff5783b3
5 changed files with 62 additions and 31 deletions

View File

@ -586,6 +586,7 @@ ifeq ($(ARCH),RISCV64)
endif
ifneq ($(NO_ASM),1)
CFLAGS+=-DWOLFSSL_RISCV_ASM
MATH_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha256.o \
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha512.o \
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/riscv/riscv-64-sha3.o \

View File

@ -46,6 +46,8 @@ WOLFBOOT_LOAD_ADDRESS?=0x8E000000
WOLFBOOT_NO_PARTITIONS=1
CFLAGS_EXTRA+=-DBOOT_PART_A=1
CFLAGS_EXTRA+=-DBOOT_PART_B=2
# Speed up disk partition read (1MB chunks)
CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x100000
# DTS (Device Tree)
WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000

View File

@ -936,7 +936,10 @@ See:
Building mchp-base-image Yocto Linux:
```sh
cd yocto-dev-polarfire/
mkdir ../yocto-dev-polarfire
cd ../yocto-dev-polarfire
repo init -u https://github.com/linux4microchip/meta-mchp-manifest.git -b refs/tags/linux4microchip+fpga-2025.10 -m polarfire-soc/default.xml
repo sync
export TEMPLATECONF=${TEMPLATECONF:-../meta-mchp/meta-mchp-polarfire-soc/meta-mchp-polarfire-soc-bsp/conf/templates/default}
source openembedded-core/oe-init-build-env
# A Microchip base image with standard Linux utilities, as well as some Microchip apps and examples
@ -1077,7 +1080,7 @@ Booting at 80200000
### PolarFire TODO
* Add eMMC/SD features:
- Multi-block read (CMD18 support)
- Improve mmc_delay and timeout handling
- DMA read support
- Write support
- eMMC support (not just SD)

View File

@ -456,7 +456,8 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
uint32_t sz)
{
int status;
uint32_t reg;
uint32_t block_count;
uint32_t reg, cmd_reg;
/* wait for idle */
status = mmc_wait_busy(0);
@ -468,46 +469,66 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
/* wait for command and data line busy to clear */
while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0);
/* get block count (round up) */
block_count = (sz + (EMMC_SD_BLOCK_SIZE - 1)) / EMMC_SD_BLOCK_SIZE;
/* set transfer block count */
EMMC_SD_SRS01 = (1 << EMMC_SD_SRS01_BCCT_SHIFT) | sz;
EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) | sz;
cmd_reg = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) |
EMMC_SD_SRS03_DPS | EMMC_SD_SRS03_DTDS |
EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID |
EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE);
if (cmd_index == SD_ACMD51_SEND_SCR) {
status = mmc_send_cmd(SD_CMD_16, sz, EMMC_SD_RESP_R1);
status = mmc_send_cmd(SD_CMD16, sz, EMMC_SD_RESP_R1);
if (status == 0) {
status = mmc_send_cmd(SD_CMD55_APP_CMD, (g_rca << SD_RCA_SHIFT),
EMMC_SD_RESP_R1);
}
status = 0; /* ignore error */
}
else if (cmd_index == MMC_CMD18_READ_MULTIPLE) {
cmd_reg |= EMMC_SD_SRS03_MSBS; /* enable multi-block select */
EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) |
EMMC_SD_BLOCK_SIZE;
}
#ifdef DEBUG_MMC
wolfBoot_printf("mmc_read: cmd_index: %d, block_addr: %08X, dst %p, sz: %d\n",
cmd_index, block_addr, dst, sz);
wolfBoot_printf("mmc_read: cmd_index: %d, block_addr: %08X, dst %p, sz: %d (%d blocks)\n",
cmd_index, block_addr, dst, sz, block_count);
#endif
EMMC_SD_SRS02 = block_addr; /* cmd argument */
/* execute command */
EMMC_SD_SRS03 = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) |
EMMC_SD_SRS03_DPS | EMMC_SD_SRS03_DTDS |
EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID |
EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE);
EMMC_SD_SRS03 = cmd_reg; /* execute command */
while (sz > 0) {
/* wait for buffer read ready */
while (((reg = EMMC_SD_SRS12) &
(EMMC_SD_SRS12_BRR | EMMC_SD_SRS12_EINT)) == 0);
/* wait for buffer read ready */
while (((reg = EMMC_SD_SRS12) & (EMMC_SD_SRS12_BRR | EMMC_SD_SRS12_EINT)) == 0);
/* read in buffer - read 4 bytes at a time */
if (reg & EMMC_SD_SRS12_BRR) {
uint32_t i;
for (i=0; i<sz; i+=4) {
*dst = EMMC_SD_SRS08;
dst++;
/* read in buffer - read 4 bytes at a time */
if (reg & EMMC_SD_SRS12_BRR) {
uint32_t i, read_sz = sz;
if (read_sz > EMMC_SD_BLOCK_SIZE) {
read_sz = EMMC_SD_BLOCK_SIZE;
}
for (i=0; i<read_sz; i+=4) {
*dst = EMMC_SD_SRS08;
dst++;
}
sz -= read_sz;
}
}
if (cmd_index == MMC_CMD18_READ_MULTIPLE) {
/* send CMD12 to stop transfer - ignore response */
(void)mmc_send_cmd(MMC_CMD12_STOP_TRANS, (g_rca << SD_RCA_SHIFT),
EMMC_SD_RESP_R1);
}
/* check for any errors and wait for idle */
reg = EMMC_SD_SRS12;
if ((reg & EMMC_SD_SRS12_ERR_STAT) == 0) {
mmc_delay(0xFF);
mmc_delay(0xFFF);
status = mmc_wait_busy(0);
}
else {
@ -585,7 +606,7 @@ int mmc_send_switch_function(uint32_t mode, uint32_t function_number,
cmd_arg = (function_number << ((group_number - 1) * 4));
do {
/* first run check to see if function is supported */
status = mmc_read(SD_CMD_6_SWITCH_FUNC,
status = mmc_read(SD_CMD6_SWITCH_FUNC,
(mode | cmd_arg),
func_status, sizeof(func_status));
if (status == 0) {
@ -904,7 +925,7 @@ int disk_read(int drv, uint64_t start, uint32_t count, uint8_t *buf)
}
if (read_sz < EMMC_SD_BLOCK_SIZE || /* last partial */
start_offset != 0 || /* start not block aligned */
((uintptr_t)buf % 4) != 0) /* buf not 4-byte aligned */
((uintptr_t)buf % 4) != 0) /* buf not 4-byte aligned */
{
/* block read to temporary buffer */
status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr,
@ -916,9 +937,13 @@ int disk_read(int drv, uint64_t start, uint32_t count, uint8_t *buf)
}
}
else {
/* direct full block read */
status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr,
(uint32_t*)buf, read_sz);
/* direct full block(s) read */
uint32_t blocks = (count / EMMC_SD_BLOCK_SIZE);
read_sz = (blocks * EMMC_SD_BLOCK_SIZE);
status = mmc_read(blocks > 1 ?
MMC_CMD18_READ_MULTIPLE :
MMC_CMD17_READ_SINGLE,
block_addr, (uint32_t*)buf, read_sz);
}
if (status != 0) {
break;

View File

@ -837,8 +837,8 @@
#define MMC_CMD1_SEND_OP_COND 1 /* MMC: Send operating conditions */
#define MMC_CMD2_ALL_SEND_CID 2 /* Get card identification */
#define MMC_CMD3_SET_REL_ADDR 3 /* Set relative address */
#define MMC_CMD_4_SET_DSR 4
#define SD_CMD_6_SWITCH_FUNC 6 /* SD: Switch function */
#define MMC_CMD4_SET_DSR 4
#define SD_CMD6_SWITCH_FUNC 6 /* SD: Switch function */
#define MMC_CMD7_SELECT_CARD 7 /* Select/deselect card */
#define MMC_CMD8_SEND_EXT_CSD 8 /* MMC: Get EXT_CSD */
#define SD_CMD8_SEND_IF_COND 8 /* SD: Send interface condition */
@ -846,8 +846,8 @@
#define SD_CMD11_VOLAGE_SWITCH 11 /* R1 Rsp */
#define MMC_CMD12_STOP_TRANS 12 /* Stop transmission */
#define MMC_CMD13_SEND_STATUS 13 /* Get card status */
#define MMC_CMD_15_GOTO_INACT_ST 15
#define SD_CMD_16 16 /* R1 Rsp */
#define MMC_CMD15_GOTO_INACT_ST 15
#define SD_CMD16 16 /* R1 Rsp */
#define MMC_CMD17_READ_SINGLE 17 /* Read single block */
#define MMC_CMD18_READ_MULTIPLE 18 /* Read multiple blocks */
#define MMC_CMD24_WRITE_SINGLE 24 /* Write single block */