mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-08 08:16:59 +02:00
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 <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>
This commit is contained in:
parent
d097f9e129
commit
74755c1fed
@ -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);
|
||||
|
@ -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,
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
if (!host->adma_desc_table) {
|
||||
host->adma_desc_table = sdhci_adma_init();
|
||||
host->adma_addr = (dma_addr_t)host->adma_desc_table;
|
||||
host->adma_addr = virt_to_phys(host->adma_desc_table);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DMA_ADDR_T_64BIT
|
||||
host->flags |= USE_ADMA64;
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user