Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: tmio: Add 64-bit read/write support for SD_BUF0 in polling mode

As per the RZ/{G2L,G3E} HW manual SD_BUF0 can be accessed by 16/32/64
bits. Most of the data transfer in SD/SDIO/eMMC mode is more than 8 bytes.
During testing it is found that, if the DMA buffer is not aligned to 128
bit it fallback to PIO mode. In such cases, 64-bit access is much more
efficient than the current 16-bit.

Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20250730164618.233117-2-biju.das.jz@bp.renesas.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Biju Das and committed by
Ulf Hansson
74f44ad0 9c174e4d

+51
+15
drivers/mmc/host/tmio_mmc.h
··· 16 16 17 17 #include <linux/dmaengine.h> 18 18 #include <linux/highmem.h> 19 + #include <linux/io.h> 19 20 #include <linux/mutex.h> 20 21 #include <linux/pagemap.h> 21 22 #include <linux/scatterlist.h> ··· 242 241 { 243 242 ioread32_rep(host->ctl + (addr << host->bus_shift), buf, count); 244 243 } 244 + 245 + #ifdef CONFIG_64BIT 246 + static inline void sd_ctrl_read64_rep(struct tmio_mmc_host *host, int addr, 247 + u64 *buf, int count) 248 + { 249 + readsq(host->ctl + (addr << host->bus_shift), buf, count); 250 + } 251 + 252 + static inline void sd_ctrl_write64_rep(struct tmio_mmc_host *host, int addr, 253 + const u64 *buf, int count) 254 + { 255 + writesq(host->ctl + (addr << host->bus_shift), buf, count); 256 + } 257 + #endif 245 258 246 259 static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, 247 260 u16 val)
+33
drivers/mmc/host/tmio_mmc_core.c
··· 349 349 /* 350 350 * Transfer the data 351 351 */ 352 + #ifdef CONFIG_64BIT 353 + if (host->pdata->flags & TMIO_MMC_64BIT_DATA_PORT) { 354 + u64 *buf64 = (u64 *)buf; 355 + u64 data = 0; 356 + 357 + if (count >= 8) { 358 + if (is_read) 359 + sd_ctrl_read64_rep(host, CTL_SD_DATA_PORT, 360 + buf64, count >> 3); 361 + else 362 + sd_ctrl_write64_rep(host, CTL_SD_DATA_PORT, 363 + buf64, count >> 3); 364 + } 365 + 366 + /* if count was multiple of 8 */ 367 + if (!(count & 0x7)) 368 + return; 369 + 370 + buf64 += count >> 3; 371 + count %= 8; 372 + 373 + if (is_read) { 374 + sd_ctrl_read64_rep(host, CTL_SD_DATA_PORT, &data, 1); 375 + memcpy(buf64, &data, count); 376 + } else { 377 + memcpy(&data, buf64, count); 378 + sd_ctrl_write64_rep(host, CTL_SD_DATA_PORT, &data, 1); 379 + } 380 + 381 + return; 382 + } 383 + #endif 384 + 352 385 if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) { 353 386 u32 data = 0; 354 387 u32 *buf32 = (u32 *)buf;
+3
include/linux/platform_data/tmio.h
··· 47 47 /* Some controllers have a CBSY bit */ 48 48 #define TMIO_MMC_HAVE_CBSY BIT(11) 49 49 50 + /* Some controllers have a 64-bit wide data port register */ 51 + #define TMIO_MMC_64BIT_DATA_PORT BIT(12) 52 + 50 53 struct tmio_mmc_data { 51 54 void *chan_priv_tx; 52 55 void *chan_priv_rx;