Skip to content

Commit

Permalink
mmc: sdhci: introduce adma_write_desc() hook to struct sdhci_ops
Browse files Browse the repository at this point in the history
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>
Co-developed-by: Greg Malysa <greg.malysa@timesys.com>
Signed-off-by: Greg Malysa <greg.malysa@timesys.com>
Signed-off-by: Ian Roberts <ian.roberts@timesys.com>
  • Loading branch information
iroberts-timesys authored and Jaehoon Chung committed Apr 26, 2024
1 parent d097f9e commit 74755c1
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 19 deletions.
2 changes: 1 addition & 1 deletion drivers/mmc/fsl_esdhc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
41 changes: 28 additions & 13 deletions drivers/mmc/sdhci-adma.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,41 @@
#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;
if (end)
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
Expand All @@ -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,
ADMA_MAX_LEN, false);
addr += ADMA_MAX_LEN;
trans_bytes -= ADMA_MAX_LEN;
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));
}

Expand Down
8 changes: 5 additions & 3 deletions drivers/mmc/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down
12 changes: 10 additions & 2 deletions include/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

0 comments on commit 74755c1

Please sign in to comment.