]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
mmc: sdhci: introduce adma_write_desc() hook to struct sdhci_ops
authorIan Roberts <ian.roberts@timesys.com>
Mon, 22 Apr 2024 19:00:02 +0000 (15:00 -0400)
committerJaehoon Chung <jh80.chung@samsung.com>
Fri, 26 Apr 2024 06:30:48 +0000 (15:30 +0900)
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>
drivers/mmc/fsl_esdhc.c
drivers/mmc/sdhci-adma.c
drivers/mmc/sdhci.c
include/sdhci.h

index d44dfa5d06f678e6f76e6d680499a49a93a0d3d9..595d88bd56253f256a8bb1022f7feac6584e8ce7 100644 (file)
@@ -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);
index 8213223d3f9f85fe5cebf0579de84de2b57263ff..8c38448b6a383662f7283d315ead7f7f2825c1e7 100644 (file)
@@ -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));
 }
 
index 0178ed8a11e1235b45a5b3ec49a7fee2a32c75c7..65090348aeeddf4933e6ed6c92c155cda1d16265 100644 (file)
@@ -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;
index a1b74e3bd79905e165a2c55421a516c9a7ebce34..d73a725609be359cd4bce1077f1e165011dd3070 100644 (file)
@@ -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 */