Browse Source

ARM: imx: fsl_esdhc: fix usage of low 4 bits of sysctl register

The low four bits of the SYSCTL register are reserved on the USDHC
controller on i.MX6 and i.MX7 processors, but are used for clocking
operations on earlier models.

Guard against their usage by hiding the bit mask macros on those
processors.

These bits are used to prevent glitches when changing clocks on
i.MX35 et al. Use the RSTA bit instead for i.MX6 and i.MX7.

>From the i.MX6DQ RM:
	To prevent possible glitch on the card clock, clear the
	FRC_SDCLK_ON bit when changing clock divisor value(SDCLKFS
	or DVS in System Control Register) or setting RSTA bit.

Signed-off-by: Eric Nelson <eric@nelint.com>
Reviewed-by: Fabio Estevam <fabio.estevam@freescale.com>
Reviewed-by: Stefano Babic <sbabic@denx.de>
Reviewed-by: Hector Palacios <hector.palacios@digi.com>
Eric Nelson 8 years ago
parent
commit
f0b5f23f32
2 changed files with 15 additions and 2 deletions
  1. 13 2
      drivers/mmc/fsl_esdhc.c
  2. 2 0
      include/fsl_esdhc.h

+ 13 - 2
drivers/mmc/fsl_esdhc.c

@@ -502,15 +502,22 @@ static void set_sysctl(struct mmc *mmc, uint clock)
 
 	clk = (pre_div << 8) | (div << 4);
 
+#ifdef CONFIG_FSL_USDHC
+	esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
+#else
 	esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
+#endif
 
 	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
 
 	udelay(10000);
 
-	clk = SYSCTL_PEREN | SYSCTL_CKEN;
+#ifdef CONFIG_FSL_USDHC
+	esdhc_clrbits32(&regs->sysctl, SYSCTL_RSTA);
+#else
+	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
+#endif
 
-	esdhc_setbits32(&regs->sysctl, clk);
 }
 
 #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
@@ -585,7 +592,9 @@ static int esdhc_init(struct mmc *mmc)
 	esdhc_write32(&regs->scr, 0x00000040);
 #endif
 
+#ifndef CONFIG_FSL_USDHC
 	esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
+#endif
 
 	/* Set the initial clock speed */
 	mmc_set_clock(mmc, 400000);
@@ -657,8 +666,10 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 	/* First reset the eSDHC controller */
 	esdhc_reset(regs);
 
+#ifndef CONFIG_FSL_USDHC
 	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
 				| SYSCTL_IPGEN | SYSCTL_CKEN);
+#endif
 
 	writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
 	memset(&cfg->cfg, 0, sizeof(cfg->cfg));

+ 2 - 0
include/fsl_esdhc.h

@@ -25,10 +25,12 @@
 #define SYSCTL_INITA		0x08000000
 #define SYSCTL_TIMEOUT_MASK	0x000f0000
 #define SYSCTL_CLOCK_MASK	0x0000fff0
+#if !defined(CONFIG_FSL_USDHC)
 #define SYSCTL_CKEN		0x00000008
 #define SYSCTL_PEREN		0x00000004
 #define SYSCTL_HCKEN		0x00000002
 #define SYSCTL_IPGEN		0x00000001
+#endif
 #define SYSCTL_RSTA		0x01000000
 #define SYSCTL_RSTC		0x02000000
 #define SYSCTL_RSTD		0x04000000