mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 10:26:10 +01: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:
		
				
					committed by
					
						 Jaehoon Chung
						Jaehoon Chung
					
				
			
			
				
	
			
			
			
						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 */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user