Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+40 -16
+10 -5
drivers/mmc/core/block.c
··· 472 472 static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, 473 473 struct mmc_blk_ioc_data *idata) 474 474 { 475 - struct mmc_command cmd = {}; 475 + struct mmc_command cmd = {}, sbc = {}; 476 476 struct mmc_data data = {}; 477 477 struct mmc_request mrq = {}; 478 478 struct scatterlist sg; ··· 550 550 } 551 551 552 552 if (idata->rpmb) { 553 - err = mmc_set_blockcount(card, data.blocks, 554 - idata->ic.write_flag & (1 << 31)); 555 - if (err) 556 - return err; 553 + sbc.opcode = MMC_SET_BLOCK_COUNT; 554 + /* 555 + * We don't do any blockcount validation because the max size 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 564 if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
+9 -2
drivers/mmc/host/omap.c
··· 104 104 unsigned int vdd; 105 105 u16 saved_con; 106 106 u16 bus_mode; 107 + u16 power_mode; 107 108 unsigned int fclk_freq; 108 109 109 110 struct tasklet_struct cover_tasklet; ··· 1158 1157 struct mmc_omap_slot *slot = mmc_priv(mmc); 1159 1158 struct mmc_omap_host *host = slot->host; 1160 1159 int i, dsor; 1161 - int clk_enabled; 1160 + int clk_enabled, init_stream; 1162 1161 1163 1162 mmc_omap_select_slot(slot, 0); 1164 1163 ··· 1168 1167 slot->vdd = ios->vdd; 1169 1168 1170 1169 clk_enabled = 0; 1170 + init_stream = 0; 1171 1171 switch (ios->power_mode) { 1172 1172 case MMC_POWER_OFF: 1173 1173 mmc_omap_set_power(slot, 0, ios->vdd); ··· 1176 1174 case MMC_POWER_UP: 1177 1175 /* Cannot touch dsor yet, just power up MMC */ 1178 1176 mmc_omap_set_power(slot, 1, ios->vdd); 1177 + slot->power_mode = ios->power_mode; 1179 1178 goto exit; 1180 1179 case MMC_POWER_ON: 1181 1180 mmc_omap_fclk_enable(host, 1); 1182 1181 clk_enabled = 1; 1183 1182 dsor |= 1 << 11; 1183 + if (slot->power_mode != MMC_POWER_ON) 1184 + init_stream = 1; 1184 1185 break; 1185 1186 } 1187 + slot->power_mode = ios->power_mode; 1186 1188 1187 1189 if (slot->bus_mode != ios->bus_mode) { 1188 1190 if (slot->pdata->set_bus_mode != NULL) ··· 1202 1196 for (i = 0; i < 2; i++) 1203 1197 OMAP_MMC_WRITE(host, CON, dsor); 1204 1198 slot->saved_con = dsor; 1205 - if (ios->power_mode == MMC_POWER_ON) { 1199 + if (init_stream) { 1206 1200 /* worst case at 400kHz, 80 cycles makes 200 microsecs */ 1207 1201 int usecs = 250; 1208 1202 ··· 1240 1234 slot->host = host; 1241 1235 slot->mmc = mmc; 1242 1236 slot->id = id; 1237 + slot->power_mode = MMC_POWER_UNDEFINED; 1243 1238 slot->pdata = &host->pdata->slots[id]; 1244 1239 1245 1240 host->slots[id] = slot;
+8 -4
drivers/mmc/host/sdhci-omap.c
··· 288 288 struct device *dev = omap_host->dev; 289 289 struct mmc_ios *ios = &mmc->ios; 290 290 u32 start_window = 0, max_window = 0; 291 + bool dcrc_was_enabled = false; 291 292 u8 cur_match, prev_match = 0; 292 293 u32 length = 0, max_len = 0; 293 - u32 ier = host->ier; 294 294 u32 phase_delay = 0; 295 295 int ret = 0; 296 296 u32 reg; ··· 317 317 * during the tuning procedure. So disable it during the 318 318 * tuning procedure. 319 319 */ 320 - ier &= ~SDHCI_INT_DATA_CRC; 321 - sdhci_writel(host, ier, SDHCI_INT_ENABLE); 322 - sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); 320 + if (host->ier & SDHCI_INT_DATA_CRC) { 321 + host->ier &= ~SDHCI_INT_DATA_CRC; 322 + dcrc_was_enabled = true; 323 + } 323 324 324 325 while (phase_delay <= MAX_PHASE_DELAY) { 325 326 sdhci_omap_set_dll(omap_host, phase_delay); ··· 367 366 368 367 ret: 369 368 sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); 369 + /* Reenable forbidden interrupt */ 370 + if (dcrc_was_enabled) 371 + host->ier |= SDHCI_INT_DATA_CRC; 370 372 sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 371 373 sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); 372 374 return ret;
+13 -5
drivers/mmc/host/sdhci.c
··· 216 216 timeout = ktime_add_ms(ktime_get(), 100); 217 217 218 218 /* hw clears the bit when it's done */ 219 - while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { 220 - if (ktime_after(ktime_get(), timeout)) { 219 + while (1) { 220 + bool timedout = ktime_after(ktime_get(), timeout); 221 + 222 + if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask)) 223 + break; 224 + if (timedout) { 221 225 pr_err("%s: Reset 0x%x never completed.\n", 222 226 mmc_hostname(host->mmc), (int)mask); 223 227 sdhci_dumpregs(host); ··· 1612 1608 1613 1609 /* Wait max 20 ms */ 1614 1610 timeout = ktime_add_ms(ktime_get(), 20); 1615 - while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 1616 - & SDHCI_CLOCK_INT_STABLE)) { 1617 - if (ktime_after(ktime_get(), timeout)) { 1611 + while (1) { 1612 + bool timedout = ktime_after(ktime_get(), timeout); 1613 + 1614 + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1615 + if (clk & SDHCI_CLOCK_INT_STABLE) 1616 + break; 1617 + if (timedout) { 1618 1618 pr_err("%s: Internal clock never stabilised.\n", 1619 1619 mmc_hostname(host->mmc)); 1620 1620 sdhci_dumpregs(host);