aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaro Koskinen <aaro.koskinen@iki.fi>2018-11-19 18:14:00 -0500
committerUlf Hansson <ulf.hansson@linaro.org>2018-12-04 08:34:51 -0500
commite8cde625bfe8a714a856e1366bcbb259d7346095 (patch)
tree89fa1f842fab24dbb780e05b46186f37401ab1aa
parenta44f7cb937321d4961bfc8f28912126b06e701c5 (diff)
MMC: OMAP: fix broken MMC on OMAP15XX/OMAP5910/OMAP310
Since v2.6.22 or so there has been reports [1] about OMAP MMC being broken on OMAP15XX based hardware (OMAP5910 and OMAP310). The breakage seems to have been caused by commit 46a6730e3ff9 ("mmc-omap: Fix omap to use MMC_POWER_ON") that changed clock enabling to be done on MMC_POWER_ON. This can happen multiple times in a row, and on 15XX the hardware doesn't seem to like it and the MMC just stops responding. Fix by memorizing the power mode and do the init only when necessary. Before the patch (on Palm TE): mmc0: new SD card at address b368 mmcblk0: mmc0:b368 SDC 977 MiB mmci-omap mmci-omap.0: command timeout (CMD18) mmci-omap mmci-omap.0: command timeout (CMD13) mmci-omap mmci-omap.0: command timeout (CMD13) mmci-omap mmci-omap.0: command timeout (CMD12) [x 6] mmci-omap mmci-omap.0: command timeout (CMD13) [x 6] mmcblk0: error -110 requesting status mmci-omap mmci-omap.0: command timeout (CMD8) mmci-omap mmci-omap.0: command timeout (CMD18) mmci-omap mmci-omap.0: command timeout (CMD13) mmci-omap mmci-omap.0: command timeout (CMD13) mmci-omap mmci-omap.0: command timeout (CMD12) [x 6] mmci-omap mmci-omap.0: command timeout (CMD13) [x 6] mmcblk0: error -110 requesting status mmcblk0: recovery failed! print_req_error: I/O error, dev mmcblk0, sector 0 Buffer I/O error on dev mmcblk0, logical block 0, async page read mmcblk0: unable to read partition table After the patch: mmc0: new SD card at address b368 mmcblk0: mmc0:b368 SDC 977 MiB mmcblk0: p1 The patch is based on a fix and analysis done by Ladislav Michl. Tested on OMAP15XX/OMAP310 (Palm TE), OMAP1710 (Nokia 770) and OMAP2420 (Nokia N810). [1] https://marc.info/?t=123175197000003&r=1&w=2 Fixes: 46a6730e3ff9 ("mmc-omap: Fix omap to use MMC_POWER_ON") Reported-by: Ladislav Michl <ladis@linux-mips.org> Reported-by: Andrzej Zaborowski <balrogg@gmail.com> Tested-by: Ladislav Michl <ladis@linux-mips.org> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/omap.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index adf32682f27a..c60a7625b1fa 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -104,6 +104,7 @@ struct mmc_omap_slot {
104 unsigned int vdd; 104 unsigned int vdd;
105 u16 saved_con; 105 u16 saved_con;
106 u16 bus_mode; 106 u16 bus_mode;
107 u16 power_mode;
107 unsigned int fclk_freq; 108 unsigned int fclk_freq;
108 109
109 struct tasklet_struct cover_tasklet; 110 struct tasklet_struct cover_tasklet;
@@ -1157,7 +1158,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1157 struct mmc_omap_slot *slot = mmc_priv(mmc); 1158 struct mmc_omap_slot *slot = mmc_priv(mmc);
1158 struct mmc_omap_host *host = slot->host; 1159 struct mmc_omap_host *host = slot->host;
1159 int i, dsor; 1160 int i, dsor;
1160 int clk_enabled; 1161 int clk_enabled, init_stream;
1161 1162
1162 mmc_omap_select_slot(slot, 0); 1163 mmc_omap_select_slot(slot, 0);
1163 1164
@@ -1167,6 +1168,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1167 slot->vdd = ios->vdd; 1168 slot->vdd = ios->vdd;
1168 1169
1169 clk_enabled = 0; 1170 clk_enabled = 0;
1171 init_stream = 0;
1170 switch (ios->power_mode) { 1172 switch (ios->power_mode) {
1171 case MMC_POWER_OFF: 1173 case MMC_POWER_OFF:
1172 mmc_omap_set_power(slot, 0, ios->vdd); 1174 mmc_omap_set_power(slot, 0, ios->vdd);
@@ -1174,13 +1176,17 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1174 case MMC_POWER_UP: 1176 case MMC_POWER_UP:
1175 /* Cannot touch dsor yet, just power up MMC */ 1177 /* Cannot touch dsor yet, just power up MMC */
1176 mmc_omap_set_power(slot, 1, ios->vdd); 1178 mmc_omap_set_power(slot, 1, ios->vdd);
1179 slot->power_mode = ios->power_mode;
1177 goto exit; 1180 goto exit;
1178 case MMC_POWER_ON: 1181 case MMC_POWER_ON:
1179 mmc_omap_fclk_enable(host, 1); 1182 mmc_omap_fclk_enable(host, 1);
1180 clk_enabled = 1; 1183 clk_enabled = 1;
1181 dsor |= 1 << 11; 1184 dsor |= 1 << 11;
1185 if (slot->power_mode != MMC_POWER_ON)
1186 init_stream = 1;
1182 break; 1187 break;
1183 } 1188 }
1189 slot->power_mode = ios->power_mode;
1184 1190
1185 if (slot->bus_mode != ios->bus_mode) { 1191 if (slot->bus_mode != ios->bus_mode) {
1186 if (slot->pdata->set_bus_mode != NULL) 1192 if (slot->pdata->set_bus_mode != NULL)
@@ -1196,7 +1202,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1196 for (i = 0; i < 2; i++) 1202 for (i = 0; i < 2; i++)
1197 OMAP_MMC_WRITE(host, CON, dsor); 1203 OMAP_MMC_WRITE(host, CON, dsor);
1198 slot->saved_con = dsor; 1204 slot->saved_con = dsor;
1199 if (ios->power_mode == MMC_POWER_ON) { 1205 if (init_stream) {
1200 /* worst case at 400kHz, 80 cycles makes 200 microsecs */ 1206 /* worst case at 400kHz, 80 cycles makes 200 microsecs */
1201 int usecs = 250; 1207 int usecs = 250;
1202 1208
@@ -1234,6 +1240,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
1234 slot->host = host; 1240 slot->host = host;
1235 slot->mmc = mmc; 1241 slot->mmc = mmc;
1236 slot->id = id; 1242 slot->id = id;
1243 slot->power_mode = MMC_POWER_UNDEFINED;
1237 slot->pdata = &host->pdata->slots[id]; 1244 slot->pdata = &host->pdata->slots[id];
1238 1245
1239 host->slots[id] = slot; 1246 host->slots[id] = slot;