From 74755c1fed1b09526b0993c729fe3ae909752fbd Mon Sep 17 00:00:00 2001 From: Ian Roberts Date: Mon, 22 Apr 2024 15:00:02 -0400 Subject: mmc: sdhci: introduce adma_write_desc() hook to struct sdhci_ops Add this hook so that it can be overridden with driver specific implementations. We also let the original sdhci_adma_write_desc() accept &desc so that the function can set its new value. Then export the function so that it could be reused by driver's specific implementations. The above is a port of Linux kernel commit 54552e4948cbf In addition, allow drivers to allocate their own ADMA descriptor tables if additional space is required. Finally, fix the assignment of adma_addr to fix compiler warning on 64-bit platforms that still use 32-bit DMA addressing. Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa Signed-off-by: Ian Roberts --- include/sdhci.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sdhci.h b/include/sdhci.h index a1b74e3bd79..d73a725609b 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -291,6 +291,11 @@ struct sdhci_ops { * Return: 0 if successful, -ve on error */ int (*set_enhanced_strobe)(struct sdhci_host *host); + +#ifdef CONFIG_MMC_SDHCI_ADMA_HELPERS + void (*adma_write_desc)(struct sdhci_host *host, void **desc, + dma_addr_t addr, int len, bool end); +#endif }; #define ADMA_MAX_LEN 65532 @@ -526,8 +531,11 @@ extern const struct dm_mmc_ops sdhci_ops; #else #endif +void sdhci_adma_write_desc(struct sdhci_host *host, void **next_desc, + dma_addr_t addr, int len, bool end); struct sdhci_adma_desc *sdhci_adma_init(void); -void sdhci_prepare_adma_table(struct sdhci_adma_desc *table, - struct mmc_data *data, dma_addr_t addr); +void sdhci_prepare_adma_table(struct sdhci_host *host, + struct sdhci_adma_desc *table, + struct mmc_data *data, dma_addr_t start_addr); #endif /* __SDHCI_HW_H */ -- cgit v1.2.3 From 5f0714496869b95e57a8b72192089e7df18c94cf Mon Sep 17 00:00:00 2001 From: Ian Roberts Date: Mon, 25 Mar 2024 22:22:37 -0400 Subject: mmc: sdhci: Fix potential ADMA descriptor table overflow Change ADMA_TABLE_NO_ENTRIES to round the division up to fully contain CONFIG_SYS_MMC_MAX_BLK_COUNT, fixing potential buffer overflow of the ADMA descriptor table. sdhci_prepare_adma_table() expecitily states it does _not_ check for overflow as the descriptor table size is dependent on CONFIG_SYS_MMC_MAX_BLK_COUNT. However, the ADMA_TABLE_NO_ENTRIES calculation does not round up the divison, so with the current u-boot defaults: max_mmc_transfer = (CONFIG_SYS_MMC_MAX_BLK_COUNT * MMC_MAX_BLOCK_LEN) = 65535 * 512 = 33553920 bytes. ADMA_TABLE_NO_ENTRIES = max_mmc_transfer / ADMA_MAX_LEN = 33553920 / 65532, which does not divide cleanly. actual_max_transfer = ADMA_TABLE_NO_ENTRIES * ADMA_MAX_LEN = 512 * 65532 = 33552384, which is smaller than max_mmc_transfer. This can cause sdhci_prepare_adma_table() to write one extra descriptor, overflowing the table when a transaction larger than actual_max_transfer is issued. Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Signed-off-by: Greg Malysa Signed-off-by: Ian Roberts Reviewed-by: Jaehoon Chung --- include/sdhci.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sdhci.h b/include/sdhci.h index d73a725609b..2dd13b4c714 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -304,8 +305,8 @@ struct sdhci_ops { #else #define ADMA_DESC_LEN 8 #endif -#define ADMA_TABLE_NO_ENTRIES (CONFIG_SYS_MMC_MAX_BLK_COUNT * \ - MMC_MAX_BLOCK_LEN) / ADMA_MAX_LEN +#define ADMA_TABLE_NO_ENTRIES DIV_ROUND_UP(CONFIG_SYS_MMC_MAX_BLK_COUNT * \ + MMC_MAX_BLOCK_LEN, ADMA_MAX_LEN) #define ADMA_TABLE_SZ (ADMA_TABLE_NO_ENTRIES * ADMA_DESC_LEN) -- cgit v1.2.3 From 5359cd1135d069a3033bda65d3e72a3c4a76160d Mon Sep 17 00:00:00 2001 From: Greg Malysa Date: Mon, 25 Mar 2024 22:28:08 -0400 Subject: mmc: Support 32-bit only ADMA on 64-bit platforms Some arm64 platforms may include SDIO host controllers that only support 32-bit ADMA. While the Linux kernel detects which size is supported and adjusts the descriptor size used dynamically, the previous u-boot implementation statically selected between the two depending on whether DMA_ADDR_T_64BIT was defined. Because the static selection is already in place and effective for most platforms, this patch logically separates "64 bit addresses are used for DMA on this platform" and "64 bit addresses are used by the SDIO host controller for ADMA" in order to support the small number of platforms where these statements are not equivalent. Using 32 bits is opt-in and existing 64 bit platforms should be unaffected by this change. Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Ian Roberts Signed-off-by: Ian Roberts Signed-off-by: Greg Malysa Reviewed-by: Jaehoon Chung --- include/sdhci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sdhci.h b/include/sdhci.h index 2dd13b4c714..78ef0d1c088 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -300,7 +300,7 @@ struct sdhci_ops { }; #define ADMA_MAX_LEN 65532 -#ifdef CONFIG_DMA_ADDR_T_64BIT +#ifdef CONFIG_MMC_SDHCI_ADMA_64BIT #define ADMA_DESC_LEN 16 #else #define ADMA_DESC_LEN 8 @@ -325,7 +325,7 @@ struct sdhci_adma_desc { u8 reserved; u16 len; u32 addr_lo; -#ifdef CONFIG_DMA_ADDR_T_64BIT +#ifdef CONFIG_MMC_SDHCI_ADMA_64BIT u32 addr_hi; #endif } __packed; -- cgit v1.2.3