aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-12-13 13:59:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-12-13 13:59:02 -0500
commite861e11c5900d21afe0c3a326d1303d6f92c9f6f (patch)
tree4fd8033b6e115389041c0512c818fa34dd0128ac
parent52a7dc28a7b01cdd9ec349a943944dc49d20fc26 (diff)
parentb704441e38f645dcfba1348ca3cc1ba43d1a9f31 (diff)
Merge tag 'mmc-v4.20-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull mmc fixes from Ulf Hansson: "MMC core: - Fixup RPMB requests to use mrq->sbc when sending CMD23 MMC host: - omap: Fix broken MMC/SD on OMAP15XX/OMAP5910/OMAP310 - sdhci-omap: Fix DCRC error handling during tuning - sdhci: Fixup the timeout check window for clock and reset" * tag 'mmc-v4.20-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: sdhci: fix the timeout check window for clock and reset mmc: sdhci-omap: Fix DCRC error handling during tuning MMC: OMAP: fix broken MMC on OMAP15XX/OMAP5910/OMAP310 mmc: core: use mrq->sbc when sending CMD23 for RPMB
-rw-r--r--drivers/mmc/core/block.c15
-rw-r--r--drivers/mmc/host/omap.c11
-rw-r--r--drivers/mmc/host/sdhci-omap.c12
-rw-r--r--drivers/mmc/host/sdhci.c18
4 files changed, 40 insertions, 16 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index c35b5b08bb33..111934838da2 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -472,7 +472,7 @@ out:
472static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, 472static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
473 struct mmc_blk_ioc_data *idata) 473 struct mmc_blk_ioc_data *idata)
474{ 474{
475 struct mmc_command cmd = {}; 475 struct mmc_command cmd = {}, sbc = {};
476 struct mmc_data data = {}; 476 struct mmc_data data = {};
477 struct mmc_request mrq = {}; 477 struct mmc_request mrq = {};
478 struct scatterlist sg; 478 struct scatterlist sg;
@@ -550,10 +550,15 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
550 } 550 }
551 551
552 if (idata->rpmb) { 552 if (idata->rpmb) {
553 err = mmc_set_blockcount(card, data.blocks, 553 sbc.opcode = MMC_SET_BLOCK_COUNT;
554 idata->ic.write_flag & (1 << 31)); 554 /*
555 if (err) 555 * We don't do any blockcount validation because the max size
556 return err; 556 * may be increased by a future standard. We just copy the
557 * 'Reliable Write' bit here.
558 */
559 sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31));
560 sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
561 mrq.sbc = &sbc;
557 } 562 }
558 563
559 if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && 564 if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
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;
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index 88347ce78f23..d264391616f9 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -288,9 +288,9 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
288 struct device *dev = omap_host->dev; 288 struct device *dev = omap_host->dev;
289 struct mmc_ios *ios = &mmc->ios; 289 struct mmc_ios *ios = &mmc->ios;
290 u32 start_window = 0, max_window = 0; 290 u32 start_window = 0, max_window = 0;
291 bool dcrc_was_enabled = false;
291 u8 cur_match, prev_match = 0; 292 u8 cur_match, prev_match = 0;
292 u32 length = 0, max_len = 0; 293 u32 length = 0, max_len = 0;
293 u32 ier = host->ier;
294 u32 phase_delay = 0; 294 u32 phase_delay = 0;
295 int ret = 0; 295 int ret = 0;
296 u32 reg; 296 u32 reg;
@@ -317,9 +317,10 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
317 * during the tuning procedure. So disable it during the 317 * during the tuning procedure. So disable it during the
318 * tuning procedure. 318 * tuning procedure.
319 */ 319 */
320 ier &= ~SDHCI_INT_DATA_CRC; 320 if (host->ier & SDHCI_INT_DATA_CRC) {
321 sdhci_writel(host, ier, SDHCI_INT_ENABLE); 321 host->ier &= ~SDHCI_INT_DATA_CRC;
322 sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); 322 dcrc_was_enabled = true;
323 }
323 324
324 while (phase_delay <= MAX_PHASE_DELAY) { 325 while (phase_delay <= MAX_PHASE_DELAY) {
325 sdhci_omap_set_dll(omap_host, phase_delay); 326 sdhci_omap_set_dll(omap_host, phase_delay);
@@ -366,6 +367,9 @@ tuning_error:
366 367
367ret: 368ret:
368 sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 369 sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
370 /* Reenable forbidden interrupt */
371 if (dcrc_was_enabled)
372 host->ier |= SDHCI_INT_DATA_CRC;
369 sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 373 sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
370 sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 374 sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
371 return ret; 375 return ret;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 99bdae53fa2e..451b08a818a9 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
216 timeout = ktime_add_ms(ktime_get(), 100); 216 timeout = ktime_add_ms(ktime_get(), 100);
217 217
218 /* hw clears the bit when it's done */ 218 /* hw clears the bit when it's done */
219 while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 219 while (1) {
220 if (ktime_after(ktime_get(), timeout)) { 220 bool timedout = ktime_after(ktime_get(), timeout);
221
222 if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask))
223 break;
224 if (timedout) {
221 pr_err("%s: Reset 0x%x never completed.\n", 225 pr_err("%s: Reset 0x%x never completed.\n",
222 mmc_hostname(host->mmc), (int)mask); 226 mmc_hostname(host->mmc), (int)mask);
223 sdhci_dumpregs(host); 227 sdhci_dumpregs(host);
@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
1608 1612
1609 /* Wait max 20 ms */ 1613 /* Wait max 20 ms */
1610 timeout = ktime_add_ms(ktime_get(), 20); 1614 timeout = ktime_add_ms(ktime_get(), 20);
1611 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 1615 while (1) {
1612 & SDHCI_CLOCK_INT_STABLE)) { 1616 bool timedout = ktime_after(ktime_get(), timeout);
1613 if (ktime_after(ktime_get(), timeout)) { 1617
1618 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
1619 if (clk & SDHCI_CLOCK_INT_STABLE)
1620 break;
1621 if (timedout) {
1614 pr_err("%s: Internal clock never stabilised.\n", 1622 pr_err("%s: Internal clock never stabilised.\n",
1615 mmc_hostname(host->mmc)); 1623 mmc_hostname(host->mmc));
1616 sdhci_dumpregs(host); 1624 sdhci_dumpregs(host);