aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2011-11-10 03:39:32 -0500
committerSascha Hauer <s.hauer@pengutronix.de>2011-11-11 10:53:35 -0500
commitf750ba9b8db2a926c315ccfa9e95d12fe4590a22 (patch)
tree1bdd2ce107b6a39b4797dab955a003e7a9c1e0ba
parent1b929995ebc0f00cc56ddc14cf75a875f4d565d6 (diff)
arm/imx: fix imx6q mmc error when mounting rootfs
The following error is seen in some case when mounting rootfs from SD/MMC cards. Waiting for root device /dev/mmcblk0p1... mmc1: host does not support reading read-only switch. assuming write-enable. mmc1: new high speed SDHC card at address b368 mmcblk0: mmc1:b368 SDC 3.74 GiB mmcblk0: p1 mmc1: Timeout waiting for hardware interrupt. mmcblk0: error -110 transferring data, sector 3678224, nr 40, cmd response 0x900, card status 0xc00 end_request: I/O error, dev mmcblk0, sector 3678225 Buffer I/O error on device mmcblk0p1, logical block 458754 lost page write due to I/O error on mmcblk0p1 This patch fixes the problem by lowering the usdhc clock and correcting watermark configuration. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Cc: Chris Ball <cjb@laptop.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/arm/mach-imx/clock-imx6q.c17
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c8
2 files changed, 24 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
index e0b926dfeced..613a1b993bff 100644
--- a/arch/arm/mach-imx/clock-imx6q.c
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -1139,7 +1139,7 @@ static int _clk_set_rate(struct clk *clk, unsigned long rate)
1139 return -EINVAL; 1139 return -EINVAL;
1140 1140
1141 max_div = ((d->bm_pred >> d->bp_pred) + 1) * 1141 max_div = ((d->bm_pred >> d->bp_pred) + 1) *
1142 ((d->bm_pred >> d->bp_pred) + 1); 1142 ((d->bm_podf >> d->bp_podf) + 1);
1143 1143
1144 div = parent_rate / rate; 1144 div = parent_rate / rate;
1145 if (div == 0) 1145 if (div == 0)
@@ -2002,6 +2002,21 @@ int __init mx6q_clocks_init(void)
2002 clk_set_rate(&asrc_serial_clk, 1500000); 2002 clk_set_rate(&asrc_serial_clk, 1500000);
2003 clk_set_rate(&enfc_clk, 11000000); 2003 clk_set_rate(&enfc_clk, 11000000);
2004 2004
2005 /*
2006 * Before pinctrl API is available, we have to rely on the pad
2007 * configuration set up by bootloader. For usdhc example here,
2008 * u-boot sets up the pads for 49.5 MHz case, and we have to lower
2009 * the usdhc clock from 198 to 49.5 MHz to match the pad configuration.
2010 *
2011 * FIXME: This is should be removed after pinctrl API is available.
2012 * At that time, usdhc driver can call pinctrl API to change pad
2013 * configuration dynamically per different usdhc clock settings.
2014 */
2015 clk_set_rate(&usdhc1_clk, 49500000);
2016 clk_set_rate(&usdhc2_clk, 49500000);
2017 clk_set_rate(&usdhc3_clk, 49500000);
2018 clk_set_rate(&usdhc4_clk, 49500000);
2019
2005 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); 2020 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
2006 base = of_iomap(np, 0); 2021 base = of_iomap(np, 0);
2007 WARN_ON(!base); 2022 WARN_ON(!base);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index ae57769ba50d..4b976f00ea85 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -32,6 +32,7 @@
32/* VENDOR SPEC register */ 32/* VENDOR SPEC register */
33#define SDHCI_VENDOR_SPEC 0xC0 33#define SDHCI_VENDOR_SPEC 0xC0
34#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 34#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
35#define SDHCI_WTMK_LVL 0x44
35#define SDHCI_MIX_CTRL 0x48 36#define SDHCI_MIX_CTRL 0x48
36 37
37/* 38/*
@@ -476,6 +477,13 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
476 if (is_imx53_esdhc(imx_data)) 477 if (is_imx53_esdhc(imx_data))
477 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; 478 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
478 479
480 /*
481 * The imx6q ROM code will change the default watermark level setting
482 * to something insane. Change it back here.
483 */
484 if (is_imx6q_usdhc(imx_data))
485 writel(0x08100810, host->ioaddr + SDHCI_WTMK_LVL);
486
479 boarddata = &imx_data->boarddata; 487 boarddata = &imx_data->boarddata;
480 if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { 488 if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
481 if (!host->mmc->parent->platform_data) { 489 if (!host->mmc->parent->platform_data) {