[RFC 0/4] Support SDMA mode on RPI4 target - 32bit

RPI4's SDHCI controller is supported SDMA mode. (Checked on kernel side) But It doesn't use on u-boot side. Then it's too slow about read/write performance. This patchset is supported SDMA mode on RPI4 target(32bit). - I didn't test on RPI4 64bit.
Read/write time about 8MB file Before - Read : 1.472 seconds - Write : 4.690 seconds After - Read : 0.359 seconds - Write : 0.574 seconds
Jaehoon Chung (4): mmc: bcm2835_sdhci: use phys2bus macro when dma address is accessed mmc: sdhci: add quriks relevant to broken SDMA mmc: bcm2835_sdhci: set SDHCI_QUIRK_BROKEN_SDMA flag configs: rpi_4_32b_defconfig: enable SDHCI_SDMA config
configs/rpi_4_32b_defconfig | 1 + drivers/mmc/bcm2835_sdhci.c | 10 ++++++++-- drivers/mmc/sdhci.c | 10 ++++++++-- include/sdhci.h | 1 + 4 files changed, 18 insertions(+), 4 deletions(-)

Use phys2bus macro when dma address is accessed. After applied it, SDMA mode can be used.
When thor download is used, - Before : 1.8MB/s - After : 7.23MB/s
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com --- drivers/mmc/bcm2835_sdhci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 39c93db275..222ba22d66 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -46,6 +46,7 @@ #include <asm/arch/mbox.h> #include <mach/sdhci.h> #include <mach/timer.h> +#include <phys2bus.h>
/* 400KHz is max freq for card ID etc. Use that as min */ #define MIN_FREQ 400000 @@ -86,7 +87,11 @@ static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, ; }
- writel(val, host->ioaddr + reg); + if (reg == SDHCI_DMA_ADDRESS) + writel(phys_to_bus((unsigned long)val), host->ioaddr + reg); + else + writel(val, host->ioaddr + reg); + bcm_host->last_write = timer_get_us(); }

Hi Jaehoon,
On 20.01.2020 11:20, Jaehoon Chung wrote:
Use phys2bus macro when dma address is accessed. After applied it, SDMA mode can be used.
When thor download is used,
- Before : 1.8MB/s
- After : 7.23MB/s
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com
drivers/mmc/bcm2835_sdhci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 39c93db275..222ba22d66 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -46,6 +46,7 @@ #include <asm/arch/mbox.h> #include <mach/sdhci.h> #include <mach/timer.h> +#include <phys2bus.h>
/* 400KHz is max freq for card ID etc. Use that as min */ #define MIN_FREQ 400000 @@ -86,7 +87,11 @@ static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, ; }
- writel(val, host->ioaddr + reg);
- if (reg == SDHCI_DMA_ADDRESS)
writel(phys_to_bus((unsigned long)val), host->ioaddr + reg);
- else
writel(val, host->ioaddr + reg);
- bcm_host->last_write = timer_get_us(); }
It would be better to fix this directly in the place where writel with SDHCI_DMA_ADDRESS is called:
simply change sdhci_writel(host, host->start_addr, SDHCI_DMA_ADDRESS) to sdhci_writel(host, phys_to_bus(host->start_addr), SDHCI_DMA_ADDRESS);
In such case no if statement is the needed and phys_to_bus() is safe for non-rpi users (it is identity in such case).
# git grep SDHCI_DMA_ADDRESS
shows 2 places where writel to SDHCI_DMA_ADDRESS is being done.
Best regards

Hi Marek,
On 1/20/20 7:37 PM, Marek Szyprowski wrote:
Hi Jaehoon,
On 20.01.2020 11:20, Jaehoon Chung wrote:
Use phys2bus macro when dma address is accessed. After applied it, SDMA mode can be used.
When thor download is used,
- Before : 1.8MB/s
- After : 7.23MB/s
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com
drivers/mmc/bcm2835_sdhci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 39c93db275..222ba22d66 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -46,6 +46,7 @@ #include <asm/arch/mbox.h> #include <mach/sdhci.h> #include <mach/timer.h> +#include <phys2bus.h>
/* 400KHz is max freq for card ID etc. Use that as min */ #define MIN_FREQ 400000 @@ -86,7 +87,11 @@ static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, ; }
- writel(val, host->ioaddr + reg);
- if (reg == SDHCI_DMA_ADDRESS)
writel(phys_to_bus((unsigned long)val), host->ioaddr + reg);
- else
writel(val, host->ioaddr + reg);
- bcm_host->last_write = timer_get_us(); }
It would be better to fix this directly in the place where writel with SDHCI_DMA_ADDRESS is called:
simply change sdhci_writel(host, host->start_addr, SDHCI_DMA_ADDRESS) to sdhci_writel(host, phys_to_bus(host->start_addr), SDHCI_DMA_ADDRESS);
In such case no if statement is the needed and phys_to_bus() is safe for non-rpi users (it is identity in such case).
# git grep SDHCI_DMA_ADDRESS
shows 2 places where writel to SDHCI_DMA_ADDRESS is being done.
It's more reasonable than my patch. I will update it. Thanks.
Best Regards, Jaehoon Chung
Best regards

ADd quirks relevant to broken SDMA. If set to SDHCI_QUIRK_BROKEN_SDMA, it should be run the pio mode.
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com --- drivers/mmc/sdhci.c | 10 ++++++++-- include/sdhci.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 01fa5a9d4d..acda997fbc 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -728,12 +728,18 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
#ifdef CONFIG_MMC_SDHCI_SDMA if (!(caps & SDHCI_CAN_DO_SDMA)) { - printf("%s: Your controller doesn't support SDMA!!\n", + if (host->quirks & SDHCI_QUIRK_BROKEN_SDMA) { + caps &= ~SDHCI_CAN_DO_SDMA; + goto skip; + } else { + printf("%s: Your controller doesn't support SDMA!!\n", __func__); - return -EINVAL; + return -EINVAL; + } }
host->flags |= USE_SDMA; +skip: #endif #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) if (!(caps & SDHCI_CAN_DO_ADMA2)) { diff --git a/include/sdhci.h b/include/sdhci.h index 01addb7a60..9865a9d6c8 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -243,6 +243,7 @@ #define SDHCI_QUIRK_WAIT_SEND_CMD (1 << 6) #define SDHCI_QUIRK_USE_WIDE8 (1 << 8) #define SDHCI_QUIRK_NO_1_8_V (1 << 9) +#define SDHCI_QUIRK_BROKEN_SDMA (1 << 10)
/* to make gcc happy */ struct sdhci_host;

RPI4 is used device-tree that taken from firmware. mmcnr@73e00000 is enabled on device-tree, so it's probed on u-boot side. Because it's for SDIO interface, it doesn't need to probe. When SDMA is enabled, mmcnr's probe is always failed.
Below log is unnecessary : sdhci_setup_cfg: Your controller doesn't support SDMA!! mmcnr@7e30000 - probe failed: -22
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com --- drivers/mmc/bcm2835_sdhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 222ba22d66..f763c9a36e 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -216,7 +216,8 @@ static int bcm2835_sdhci_probe(struct udevice *dev) host->name = dev->name; host->ioaddr = (void *)base; host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | - SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT; + SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT | + SDHCI_QUIRK_BROKEN_SDMA; host->max_clk = emmc_freq; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; host->ops = &bcm2835_ops;

Enable SDHCI_SDMA configuration.
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com --- configs/rpi_4_32b_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig index 00f80f71ad..8fbadc0bc8 100644 --- a/configs/rpi_4_32b_defconfig +++ b/configs/rpi_4_32b_defconfig @@ -23,6 +23,7 @@ CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_DM_KEYBOARD=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_BCM2835=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set

RPI4's SDHCI controller is supported SDMA mode. (Checked on kernel side) But It doesn't use on u-boot side. Then it's too slow about read/write performance. This patchset is supported SDMA mode on RPI4 target(32bit).
- I didn't test on RPI4 64bit.
What about on other models of the rpi given they all use the same sdhci controller?
Read/write time about 8MB file Before
- Read : 1.472 seconds
- Write : 4.690 seconds
After
- Read : 0.359 seconds
- Write : 0.574 seconds
Jaehoon Chung (4): mmc: bcm2835_sdhci: use phys2bus macro when dma address is accessed mmc: sdhci: add quriks relevant to broken SDMA mmc: bcm2835_sdhci: set SDHCI_QUIRK_BROKEN_SDMA flag configs: rpi_4_32b_defconfig: enable SDHCI_SDMA config
configs/rpi_4_32b_defconfig | 1 + drivers/mmc/bcm2835_sdhci.c | 10 ++++++++-- drivers/mmc/sdhci.c | 10 ++++++++-- include/sdhci.h | 1 + 4 files changed, 18 insertions(+), 4 deletions(-)
-- 2.25.0

On 1/20/20 8:50 PM, Peter Robinson wrote:
RPI4's SDHCI controller is supported SDMA mode. (Checked on kernel side) But It doesn't use on u-boot side. Then it's too slow about read/write performance. This patchset is supported SDMA mode on RPI4 target(32bit).
- I didn't test on RPI4 64bit.
What about on other models of the rpi given they all use the same sdhci controller?
Well, i didn't check other models. As i know, in RPI3's case, SDHCI controller is used for WiFi. So it doesn't need to check on u-boot side. I had checked RPI4 target. (1/2/4GB model) If other RPI models are using same SDHCI controller(assume that provides same functionality), it can be used SDMA mode.
Best Regards, Jaehoon Chung
Read/write time about 8MB file Before
- Read : 1.472 seconds
- Write : 4.690 seconds
After
- Read : 0.359 seconds
- Write : 0.574 seconds
Jaehoon Chung (4): mmc: bcm2835_sdhci: use phys2bus macro when dma address is accessed mmc: sdhci: add quriks relevant to broken SDMA mmc: bcm2835_sdhci: set SDHCI_QUIRK_BROKEN_SDMA flag configs: rpi_4_32b_defconfig: enable SDHCI_SDMA config
configs/rpi_4_32b_defconfig | 1 + drivers/mmc/bcm2835_sdhci.c | 10 ++++++++-- drivers/mmc/sdhci.c | 10 ++++++++-- include/sdhci.h | 1 + 4 files changed, 18 insertions(+), 4 deletions(-)
-- 2.25.0
participants (3)
-
Jaehoon Chung
-
Marek Szyprowski
-
Peter Robinson