summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Christ <s.christ@phytec.de>2016-05-04 15:25:57 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-05-09 08:38:59 +0200
commitb66a106f3422b811f10e9b9dc987e2bc7f4fe449 (patch)
tree55a0213ca6d4d7d42d0857a9679e23be218b70d4
parent9d5cf8d42709763d2607cde991e024f36600eb07 (diff)
downloadbarebox-b66a106f3422b811f10e9b9dc987e2bc7f4fe449.tar.gz
barebox-b66a106f3422b811f10e9b9dc987e2bc7f4fe449.tar.xz
mci: imx-esdhc: implement reset quirks for i.MX6 DualLite/Solo
First of all the reset values of MMC interfaces are differently between Quad and DualLite/Solo SoM. Register VEND_SPEC2(0xC8) Quad: 0x0 DualLite: 0x00000006 default: 0x00000006 (from i.MX6 Reference Manual) Furthermore the ROM Code of Quad and DualLite uses the MMC interfaces differently when it loads the bootloader from that device: Register DLL_CTRL(0x60) Bit 25 FBCLK_SEL (0x48) Quad: 0x0 0 DualLite: 0x01000021 1 Since the linux kernel and barebox driver doesn't reset all registers, the MMC interface is in an inconsistent state, which leads to boot failures for some eMMC devices on the i.MX6 DualLite SoM. The errors look like: mmcblk3: error -110 sending stop command, original cmd response 0x900, card status 0x400900 mmcblk3: error -84 transferring data, sector 24578, nr 2, cmd response 0x900, card status 0x0 mmcblk3: retrying using single block read mmcblk3: error -84 transferring data, sector 24578, nr 2, cmd response 0x900, card status 0x0 blk_update_request: I/O error, dev mmcblk3, sector 24578 It's sufficient to reset register DLL_CTRL and bit FBCLK_SEL. Register VEND_SPEC2 has no effect. Signed-off-by: Stefan Christ <s.christ@phytec.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/mci/imx-esdhc.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 282887ba78..2e189fecad 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -41,6 +41,8 @@
#define IMX_SDHCI_WML 0x44
#define IMX_SDHCI_MIXCTRL 0x48
+#define IMX_SDHCI_DLL_CTRL 0x60
+#define IMX_SDHCI_MIX_CTRL_FBCLK_SEL (BIT(25))
struct fsl_esdhc_host {
struct mci_host mci;
@@ -516,11 +518,23 @@ static int esdhc_reset(struct fsl_esdhc_host *host)
{
void __iomem *regs = host->regs;
uint64_t start;
+ int val;
/* reset the controller */
esdhc_write32(regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
SYSCTL_RSTA);
+ /* extra register reset for i.MX6 Solo/DualLite */
+ if (cpu_is_mx6()) {
+ /* reset bit FBCLK_SEL */
+ val = esdhc_read32(regs + IMX_SDHCI_MIXCTRL);
+ val &= ~IMX_SDHCI_MIX_CTRL_FBCLK_SEL;
+ esdhc_write32(regs + IMX_SDHCI_MIXCTRL, val);
+
+ /* reset delay line settings in IMX_SDHCI_DLL_CTRL */
+ esdhc_write32(regs + IMX_SDHCI_DLL_CTRL, 0x0);
+ }
+
start = get_time_ns();
/* hardware clears the bit when it is done */
while (1) {