mmc: fsl_esdhc: make sure delay chain locked for HS400
For eMMC HS400 mode, the DLL reset is a required step for mmc rescan. This step has not been documented in reference manual, but the RM will be fixed sooner or later. In previous commit to support eMMC HS400,db8f936mmc: fsl_esdhc: support eMMC HS400 mode the steps to configure DLL could be found in commit message, 13. Set DLLCFG0[DLL_ENABLE] and DLLCFG0[DLL_FREQ_SEL]. 14. Wait for delay chain to lock. these would be fixed as, 13. Set DLLCFG0[DLL_ENABLE] and DLLCFG0[DLL_FREQ_SEL]. 13.1 Write DLLCFG0[DLL_RESET] to 1 and wait for 1us, then write DLLCFG0[DLL_RESET] 14. Wait for delay chain to lock. This patch is to add the step of DLL reset, and make sure delay chain locked for HS400. Fixes:db8f93672b("mmc: fsl_esdhc: support eMMC HS400 mode") Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
This commit is contained in:
		
							parent
							
								
									263ddfc345
								
							
						
					
					
						commit
						8ee802f899
					
				|  | @ -70,7 +70,9 @@ struct fsl_esdhc { | |||
| 	uint	sdtimingctl;	/* SD timing control register */ | ||||
| 	char    reserved8[20];	/* reserved */ | ||||
| 	uint	dllcfg0;	/* DLL config 0 register */ | ||||
| 	char    reserved9[680];	/* reserved */ | ||||
| 	char	reserved9[12];	/* reserved */ | ||||
| 	uint	dllstat0;	/* DLL status 0 register */ | ||||
| 	char    reserved10[664];/* reserved */ | ||||
| 	uint    esdhcctl;	/* eSDHC control register */ | ||||
| }; | ||||
| 
 | ||||
|  | @ -617,9 +619,11 @@ static void esdhc_exit_hs400(struct fsl_esdhc_priv *priv) | |||
| 	esdhc_tuning_block_enable(priv, false); | ||||
| } | ||||
| 
 | ||||
| static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode) | ||||
| static int esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode) | ||||
| { | ||||
| 	struct fsl_esdhc *regs = priv->esdhc_regs; | ||||
| 	ulong start; | ||||
| 	u32 val; | ||||
| 
 | ||||
| 	/* Exit HS400 mode before setting any other mode */ | ||||
| 	if (esdhc_read32(®s->tbctl) & HS400_MODE && | ||||
|  | @ -640,17 +644,33 @@ static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode) | |||
| 			esdhc_setbits32(®s->dllcfg0, DLL_FREQ_SEL); | ||||
| 
 | ||||
| 		esdhc_setbits32(®s->dllcfg0, DLL_ENABLE); | ||||
| 
 | ||||
| 		esdhc_setbits32(®s->dllcfg0, DLL_RESET); | ||||
| 		udelay(1); | ||||
| 		esdhc_clrbits32(®s->dllcfg0, DLL_RESET); | ||||
| 
 | ||||
| 		start = get_timer(0); | ||||
| 		val = DLL_STS_SLV_LOCK; | ||||
| 		while (!(esdhc_read32(®s->dllstat0) & val)) { | ||||
| 			if (get_timer(start) > 1000) { | ||||
| 				printf("fsl_esdhc: delay chain lock timeout\n"); | ||||
| 				return -ETIMEDOUT; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		esdhc_setbits32(®s->tbctl, HS400_WNDW_ADJUST); | ||||
| 
 | ||||
| 		esdhc_clock_control(priv, false); | ||||
| 		esdhc_flush_async_fifo(priv); | ||||
| 	} | ||||
| 	esdhc_clock_control(priv, true); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) | ||||
| { | ||||
| 	struct fsl_esdhc *regs = priv->esdhc_regs; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (priv->is_sdhc_per_clk) { | ||||
| 		/* Select to use peripheral clock */ | ||||
|  | @ -667,7 +687,9 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) | |||
| 		set_sysctl(priv, mmc, mmc->clock); | ||||
| 
 | ||||
| 	/* Set timing */ | ||||
| 	esdhc_set_timing(priv, mmc->selected_mode); | ||||
| 	ret = esdhc_set_timing(priv, mmc->selected_mode); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	/* Set the bus width */ | ||||
| 	esdhc_clrbits32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); | ||||
|  |  | |||
|  | @ -187,8 +187,12 @@ | |||
| 
 | ||||
| /* DLL config 0 register */ | ||||
| #define DLL_ENABLE		0x80000000 | ||||
| #define DLL_RESET		0x40000000 | ||||
| #define DLL_FREQ_SEL		0x08000000 | ||||
| 
 | ||||
| /* DLL status 0 register */ | ||||
| #define DLL_STS_SLV_LOCK	0x08000000 | ||||
| 
 | ||||
| #define MAX_TUNING_LOOP		40 | ||||
| 
 | ||||
| #define HOSTVER_VENDOR(x)	(((x) >> 8) & 0xff) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue