
Hi,
-----Original Message----- From: U-Boot u-boot-bounces@lists.denx.de On Behalf Of Jaehoon Chung Sent: Wednesday, April 17, 2024 9:26 AM To: 'Greg Malysa' greg.malysa@timesys.com; u-boot@lists.denx.de; 'Peng Fan' peng.fan@nxp.com Cc: 'Ian Roberts' ian.roberts@timesys.com; 'Nathan Barrett-Morrison' nathan.morrison@timesys.com; 'Jonas Karlman' jonas@kwiboo.se; 'Kever Yang' kever.yang@rock-chips.com; 'Peter Geis' pgwipeout@gmail.com; 'Sean Anderson' sean.anderson@seco.com; 'Simon Glass' sjg@chromium.org; 'Tom Rini' trini@konsulko.com Subject: RE: [PATCH] mmc: sdhci: introduce adma_write_desc() hook to struct sdhci_ops
-----Original Message----- From: Greg Malysa greg.malysa@timesys.com Sent: Tuesday, March 26, 2024 11:18 AM To: u-boot@lists.denx.de; Peng Fan peng.fan@nxp.com; Jaehoon Chung jh80.chung@samsung.com Cc: Ian Roberts ian.roberts@timesys.com; Nathan Barrett-Morrison nathan.morrison@timesys.com;
Greg
Malysa greg.malysa@timesys.com; Jonas Karlman jonas@kwiboo.se; Kever Yang <kever.yang@rock- chips.com>; Peter Geis pgwipeout@gmail.com; Sean Anderson sean.anderson@seco.com; Simon Glass sjg@chromium.org; Tom Rini trini@konsulko.com Subject: [PATCH] mmc: sdhci: introduce adma_write_desc() hook to struct sdhci_ops
From: Ian Roberts ian.roberts@timesys.com
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 nathan.morrison@timesys.com Signed-off-by: Nathan Barrett-Morrison nathan.morrison@timesys.com Signed-off-by: Greg Malysa greg.malysa@timesys.com Signed-off-by: Ian Roberts ian.roberts@timesys.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Some target are failed to build. (e.g, j721e_beagleboneai64_r5)
+drivers/mmc/sdhci-adma.c: In function '__sdhci_adma_write_desc': +drivers/mmc/sdhci-adma.c:37:43: error: 'const struct sdhci_ops' has no member named 'adma_write_desc' + 37 | if (host && host->ops && host->ops->adma_write_desc) + | ^~ +drivers/mmc/sdhci-adma.c:38:26: error: 'const struct sdhci_ops' has no member named 'adma_write_desc' + 38 | host->ops->adma_write_desc(host, desc, addr, len, end); + | ^~ +make[3]: *** [scripts/Makefile.build:257: drivers/mmc/sdhci-adma.o] Error 1 +make[2]: *** [scripts/Makefile.build:397: drivers/mmc] Error 2
Best Regards, Jaehoon Chung
Best Regards, Jaehoon Chung
drivers/mmc/fsl_esdhc.c | 2 +- drivers/mmc/sdhci-adma.c | 41 +++++++++++++++++++++++++++------------- drivers/mmc/sdhci.c | 8 +++++--- include/sdhci.h | 12 ++++++++++-- 4 files changed, 44 insertions(+), 19 deletions(-)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index d506666669..bd0671cc52 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -252,7 +252,7 @@ static void esdhc_setup_dma(struct fsl_esdhc_priv *priv, struct mmc_data *data) priv->adma_desc_table) { debug("Using ADMA2\n"); /* prefer ADMA2 if it is available */
sdhci_prepare_adma_table(priv->adma_desc_table, data,
sdhci_prepare_adma_table(NULL, priv->adma_desc_table, data, priv->dma_addr);
adma_addr = virt_to_phys(priv->adma_desc_table);
diff --git a/drivers/mmc/sdhci-adma.c b/drivers/mmc/sdhci-adma.c index 8213223d3f..8c38448b6a 100644 --- a/drivers/mmc/sdhci-adma.c +++ b/drivers/mmc/sdhci-adma.c @@ -9,9 +9,10 @@ #include <malloc.h> #include <asm/cache.h>
-static void sdhci_adma_desc(struct sdhci_adma_desc *desc,
dma_addr_t addr, u16 len, bool end)
+void sdhci_adma_write_desc(struct sdhci_host *host, void **next_desc,
dma_addr_t addr, int len, bool end)
{
struct sdhci_adma_desc *desc = *next_desc; u8 attr;
attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA;
@@ -19,17 +20,30 @@ static void sdhci_adma_desc(struct sdhci_adma_desc *desc, attr |= ADMA_DESC_ATTR_END;
desc->attr = attr;
- desc->len = len;
- desc->len = len & 0xffff; desc->reserved = 0; desc->addr_lo = lower_32_bits(addr);
#ifdef CONFIG_DMA_ADDR_T_64BIT desc->addr_hi = upper_32_bits(addr); #endif
- *next_desc += ADMA_DESC_LEN;
+}
+static inline void __sdhci_adma_write_desc(struct sdhci_host *host,
void **desc, dma_addr_t addr,
int len, bool end)
+{
- if (host && host->ops && host->ops->adma_write_desc)
host->ops->adma_write_desc(host, desc, addr, len, end);
- else
sdhci_adma_write_desc(host, desc, addr, len, end);
}
/**
- sdhci_prepare_adma_table() - Populate the ADMA table
- @host: Pointer to the sdhci_host
- @table: Pointer to the ADMA table
- @data: Pointer to MMC data
- @addr: DMA address to write to or read from
@@ -39,25 +53,26 @@ static void sdhci_adma_desc(struct sdhci_adma_desc *desc,
- Please note, that the table size depends on CONFIG_SYS_MMC_MAX_BLK_COUNT and
- we don't have to check for overflow.
*/ -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)
{
- dma_addr_t addr = start_addr; uint trans_bytes = data->blocksize * data->blocks;
- uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN);
- struct sdhci_adma_desc *desc = table;
- int i = desc_count;
void *next_desc = table;
int i = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN);
while (--i) {
sdhci_adma_desc(desc, addr, ADMA_MAX_LEN, false);
__sdhci_adma_write_desc(host, &next_desc, addr,
addr += ADMA_MAX_LEN; trans_bytes -= ADMA_MAX_LEN;ADMA_MAX_LEN, false);
desc++;
}
sdhci_adma_desc(desc, addr, trans_bytes, true);
- __sdhci_adma_write_desc(host, &next_desc, addr, trans_bytes, true);
- flush_cache((dma_addr_t)table,
ROUND(desc_count * sizeof(struct sdhci_adma_desc),
- flush_cache((phys_addr_t)table,
ROUND(next_desc - (void *)table, ARCH_DMA_MINALIGN));
}
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 0178ed8a11..65090348ae 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -111,7 +111,7 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, } #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) else if (host->flags & (USE_ADMA | USE_ADMA64)) {
sdhci_prepare_adma_table(host->adma_desc_table, data,
sdhci_prepare_adma_table(host, host->adma_desc_table, data, host->start_addr);
sdhci_writel(host, lower_32_bits(host->adma_addr),
@@ -897,8 +897,10 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, __func__); return -EINVAL; }
- host->adma_desc_table = sdhci_adma_init();
- host->adma_addr = (dma_addr_t)host->adma_desc_table;
- if (!host->adma_desc_table) {
host->adma_desc_table = sdhci_adma_init();
host->adma_addr = virt_to_phys(host->adma_desc_table);
- }
#ifdef CONFIG_DMA_ADDR_T_64BIT host->flags |= USE_ADMA64; diff --git a/include/sdhci.h b/include/sdhci.h index a1b74e3bd7..4bde7db5c7 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);
+#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
- 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 */
2.43.2