mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	mmc: sdhci-of-esdhc: workaround for unreliable pulse width detection
This was a SoC issue on LX2160A Rev1.0. eSDHC_DLLCFG1[DLL_PD_PULSE_STRETCH_SEL] must be set to 0 to get 4 delay cells in the pulse width detection logic for eMMC HS400 mode. Otherwise it would cause unexpected HS400 issue. This patch is to clear this bit always for affected SoC when reset for all, since this bit doesn't affect other speed modes. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
		
							parent
							
								
									58d0bf843b
								
							
						
					
					
						commit
						48e304cc19
					
				
					 2 changed files with 23 additions and 0 deletions
				
			
		| 
						 | 
					@ -78,6 +78,10 @@
 | 
				
			||||||
#define ESDHC_DLL_ENABLE		0x80000000
 | 
					#define ESDHC_DLL_ENABLE		0x80000000
 | 
				
			||||||
#define ESDHC_DLL_FREQ_SEL		0x08000000
 | 
					#define ESDHC_DLL_FREQ_SEL		0x08000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* DLL Config 1 Register */
 | 
				
			||||||
 | 
					#define ESDHC_DLLCFG1			0x164
 | 
				
			||||||
 | 
					#define ESDHC_DLL_PD_PULSE_STRETCH_SEL	0x80000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* DLL Status 0 Register */
 | 
					/* DLL Status 0 Register */
 | 
				
			||||||
#define ESDHC_DLLSTAT0			0x170
 | 
					#define ESDHC_DLLSTAT0			0x170
 | 
				
			||||||
#define ESDHC_DLL_STS_SLV_LOCK		0x08000000
 | 
					#define ESDHC_DLL_STS_SLV_LOCK		0x08000000
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,7 @@ struct sdhci_esdhc {
 | 
				
			||||||
	u8 spec_ver;
 | 
						u8 spec_ver;
 | 
				
			||||||
	bool quirk_incorrect_hostver;
 | 
						bool quirk_incorrect_hostver;
 | 
				
			||||||
	bool quirk_limited_clk_division;
 | 
						bool quirk_limited_clk_division;
 | 
				
			||||||
 | 
						bool quirk_unreliable_pulse_detection;
 | 
				
			||||||
	bool quirk_fixup_tuning;
 | 
						bool quirk_fixup_tuning;
 | 
				
			||||||
	unsigned int peripheral_clock;
 | 
						unsigned int peripheral_clock;
 | 
				
			||||||
	const struct esdhc_clk_fixup *clk_fixup;
 | 
						const struct esdhc_clk_fixup *clk_fixup;
 | 
				
			||||||
| 
						 | 
					@ -676,6 +677,8 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void esdhc_reset(struct sdhci_host *host, u8 mask)
 | 
					static void esdhc_reset(struct sdhci_host *host, u8 mask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 | 
				
			||||||
 | 
						struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 | 
				
			||||||
	u32 val;
 | 
						u32 val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdhci_reset(host, mask);
 | 
						sdhci_reset(host, mask);
 | 
				
			||||||
| 
						 | 
					@ -687,6 +690,12 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
 | 
				
			||||||
		val = sdhci_readl(host, ESDHC_TBCTL);
 | 
							val = sdhci_readl(host, ESDHC_TBCTL);
 | 
				
			||||||
		val &= ~ESDHC_TB_EN;
 | 
							val &= ~ESDHC_TB_EN;
 | 
				
			||||||
		sdhci_writel(host, val, ESDHC_TBCTL);
 | 
							sdhci_writel(host, val, ESDHC_TBCTL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (esdhc->quirk_unreliable_pulse_detection) {
 | 
				
			||||||
 | 
								val = sdhci_readl(host, ESDHC_DLLCFG1);
 | 
				
			||||||
 | 
								val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL;
 | 
				
			||||||
 | 
								sdhci_writel(host, val, ESDHC_DLLCFG1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -941,6 +950,11 @@ static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = {
 | 
				
			||||||
	{ },
 | 
						{ },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct soc_device_attribute soc_unreliable_pulse_detection[] = {
 | 
				
			||||||
 | 
						{ .family = "QorIQ LX2160A", .revision = "1.0", },
 | 
				
			||||||
 | 
						{ },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 | 
					static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct of_device_id *match;
 | 
						const struct of_device_id *match;
 | 
				
			||||||
| 
						 | 
					@ -968,6 +982,11 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		esdhc->quirk_limited_clk_division = false;
 | 
							esdhc->quirk_limited_clk_division = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (soc_device_match(soc_unreliable_pulse_detection))
 | 
				
			||||||
 | 
							esdhc->quirk_unreliable_pulse_detection = true;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							esdhc->quirk_unreliable_pulse_detection = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node);
 | 
						match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node);
 | 
				
			||||||
	if (match)
 | 
						if (match)
 | 
				
			||||||
		esdhc->clk_fixup = match->data;
 | 
							esdhc->clk_fixup = match->data;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue