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) { | 	    priv->adma_desc_table) { | ||||||
| 		debug("Using ADMA2\n"); | 		debug("Using ADMA2\n"); | ||||||
| 		/* prefer ADMA2 if it is available */ | 		/* 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); | 					 priv->dma_addr); | ||||||
|  |  | ||||||
| 		adma_addr = virt_to_phys(priv->adma_desc_table); | 		adma_addr = virt_to_phys(priv->adma_desc_table); | ||||||
|   | |||||||
| @@ -9,9 +9,10 @@ | |||||||
| #include <malloc.h> | #include <malloc.h> | ||||||
| #include <asm/cache.h> | #include <asm/cache.h> | ||||||
|  |  | ||||||
| static void sdhci_adma_desc(struct sdhci_adma_desc *desc, | void sdhci_adma_write_desc(struct sdhci_host *host, void **next_desc, | ||||||
| 			    dma_addr_t addr, u16 len, bool end) | 			   dma_addr_t addr, int len, bool end) | ||||||
| { | { | ||||||
|  | 	struct sdhci_adma_desc *desc = *next_desc; | ||||||
| 	u8 attr; | 	u8 attr; | ||||||
|  |  | ||||||
| 	attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA; | 	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; | 		attr |= ADMA_DESC_ATTR_END; | ||||||
|  |  | ||||||
| 	desc->attr = attr; | 	desc->attr = attr; | ||||||
| 	desc->len = len; | 	desc->len = len & 0xffff; | ||||||
| 	desc->reserved = 0; | 	desc->reserved = 0; | ||||||
| 	desc->addr_lo = lower_32_bits(addr); | 	desc->addr_lo = lower_32_bits(addr); | ||||||
| #ifdef CONFIG_DMA_ADDR_T_64BIT | #ifdef CONFIG_DMA_ADDR_T_64BIT | ||||||
| 	desc->addr_hi = upper_32_bits(addr); | 	desc->addr_hi = upper_32_bits(addr); | ||||||
| #endif | #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 |  * sdhci_prepare_adma_table() - Populate the ADMA table | ||||||
|  * |  * | ||||||
|  |  * @host:	Pointer to the sdhci_host | ||||||
|  * @table:	Pointer to the ADMA table |  * @table:	Pointer to the ADMA table | ||||||
|  * @data:	Pointer to MMC data |  * @data:	Pointer to MMC data | ||||||
|  * @addr:	DMA address to write to or read from |  * @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 |  * Please note, that the table size depends on CONFIG_SYS_MMC_MAX_BLK_COUNT and | ||||||
|  * we don't have to check for overflow. |  * we don't have to check for overflow. | ||||||
|  */ |  */ | ||||||
| void sdhci_prepare_adma_table(struct sdhci_adma_desc *table, | void sdhci_prepare_adma_table(struct sdhci_host *host, | ||||||
| 			      struct mmc_data *data, dma_addr_t addr) | 			      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 trans_bytes = data->blocksize * data->blocks; | ||||||
| 	uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN); | 	void *next_desc = table; | ||||||
| 	struct sdhci_adma_desc *desc = table; | 	int i = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN); | ||||||
| 	int i = desc_count; |  | ||||||
|  |  | ||||||
| 	while (--i) { | 	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; | 		addr += ADMA_MAX_LEN; | ||||||
| 		trans_bytes -= 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, | 	flush_cache((phys_addr_t)table, | ||||||
| 		    ROUND(desc_count * sizeof(struct sdhci_adma_desc), | 		    ROUND(next_desc - (void *)table, | ||||||
| 			  ARCH_DMA_MINALIGN)); | 			  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) | #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) | ||||||
| 	else if (host->flags & (USE_ADMA | USE_ADMA64)) { | 	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); | 					 host->start_addr); | ||||||
|  |  | ||||||
| 		sdhci_writel(host, lower_32_bits(host->adma_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__); | 		       __func__); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 	host->adma_desc_table = sdhci_adma_init(); | 	if (!host->adma_desc_table) { | ||||||
| 	host->adma_addr = (dma_addr_t)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 | #ifdef CONFIG_DMA_ADDR_T_64BIT | ||||||
| 	host->flags |= USE_ADMA64; | 	host->flags |= USE_ADMA64; | ||||||
|   | |||||||
| @@ -291,6 +291,11 @@ struct sdhci_ops { | |||||||
| 	 * Return: 0 if successful, -ve on error | 	 * Return: 0 if successful, -ve on error | ||||||
| 	 */ | 	 */ | ||||||
| 	int	(*set_enhanced_strobe)(struct sdhci_host *host); | 	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 | #define ADMA_MAX_LEN	65532 | ||||||
| @@ -526,8 +531,11 @@ extern const struct dm_mmc_ops sdhci_ops; | |||||||
| #else | #else | ||||||
| #endif | #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); | struct sdhci_adma_desc *sdhci_adma_init(void); | ||||||
| void sdhci_prepare_adma_table(struct sdhci_adma_desc *table, | void sdhci_prepare_adma_table(struct sdhci_host *host, | ||||||
| 			      struct mmc_data *data, dma_addr_t addr); | 			      struct sdhci_adma_desc *table, | ||||||
|  | 			      struct mmc_data *data, dma_addr_t start_addr); | ||||||
|  |  | ||||||
| #endif /* __SDHCI_HW_H */ | #endif /* __SDHCI_HW_H */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user