Commit e861e11c authored by Linus Torvalds's avatar Linus Torvalds

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
parents 52a7dc28 b704441e
...@@ -472,7 +472,7 @@ static int ioctl_do_sanitize(struct mmc_card *card) ...@@ -472,7 +472,7 @@ static int ioctl_do_sanitize(struct mmc_card *card)
static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
struct mmc_blk_ioc_data *idata) struct mmc_blk_ioc_data *idata)
{ {
struct mmc_command cmd = {}; struct mmc_command cmd = {}, sbc = {};
struct mmc_data data = {}; struct mmc_data data = {};
struct mmc_request mrq = {}; struct mmc_request mrq = {};
struct scatterlist sg; struct scatterlist sg;
...@@ -550,10 +550,15 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, ...@@ -550,10 +550,15 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
} }
if (idata->rpmb) { if (idata->rpmb) {
err = mmc_set_blockcount(card, data.blocks, sbc.opcode = MMC_SET_BLOCK_COUNT;
idata->ic.write_flag & (1 << 31)); /*
if (err) * We don't do any blockcount validation because the max size
return err; * may be increased by a future standard. We just copy the
* 'Reliable Write' bit here.
*/
sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31));
sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
mrq.sbc = &sbc;
} }
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
......
...@@ -104,6 +104,7 @@ struct mmc_omap_slot { ...@@ -104,6 +104,7 @@ struct mmc_omap_slot {
unsigned int vdd; unsigned int vdd;
u16 saved_con; u16 saved_con;
u16 bus_mode; u16 bus_mode;
u16 power_mode;
unsigned int fclk_freq; unsigned int fclk_freq;
struct tasklet_struct cover_tasklet; struct tasklet_struct cover_tasklet;
...@@ -1157,7 +1158,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1157,7 +1158,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct mmc_omap_slot *slot = mmc_priv(mmc); struct mmc_omap_slot *slot = mmc_priv(mmc);
struct mmc_omap_host *host = slot->host; struct mmc_omap_host *host = slot->host;
int i, dsor; int i, dsor;
int clk_enabled; int clk_enabled, init_stream;
mmc_omap_select_slot(slot, 0); mmc_omap_select_slot(slot, 0);
...@@ -1167,6 +1168,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1167,6 +1168,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
slot->vdd = ios->vdd; slot->vdd = ios->vdd;
clk_enabled = 0; clk_enabled = 0;
init_stream = 0;
switch (ios->power_mode) { switch (ios->power_mode) {
case MMC_POWER_OFF: case MMC_POWER_OFF:
mmc_omap_set_power(slot, 0, ios->vdd); 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,13 +1176,17 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_UP: case MMC_POWER_UP:
/* Cannot touch dsor yet, just power up MMC */ /* Cannot touch dsor yet, just power up MMC */
mmc_omap_set_power(slot, 1, ios->vdd); mmc_omap_set_power(slot, 1, ios->vdd);
slot->power_mode = ios->power_mode;
goto exit; goto exit;
case MMC_POWER_ON: case MMC_POWER_ON:
mmc_omap_fclk_enable(host, 1); mmc_omap_fclk_enable(host, 1);
clk_enabled = 1; clk_enabled = 1;
dsor |= 1 << 11; dsor |= 1 << 11;
if (slot->power_mode != MMC_POWER_ON)
init_stream = 1;
break; break;
} }
slot->power_mode = ios->power_mode;
if (slot->bus_mode != ios->bus_mode) { if (slot->bus_mode != ios->bus_mode) {
if (slot->pdata->set_bus_mode != NULL) 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,7 +1202,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
OMAP_MMC_WRITE(host, CON, dsor); OMAP_MMC_WRITE(host, CON, dsor);
slot->saved_con = dsor; slot->saved_con = dsor;
if (ios->power_mode == MMC_POWER_ON) { if (init_stream) {
/* worst case at 400kHz, 80 cycles makes 200 microsecs */ /* worst case at 400kHz, 80 cycles makes 200 microsecs */
int usecs = 250; int usecs = 250;
...@@ -1234,6 +1240,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) ...@@ -1234,6 +1240,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
slot->host = host; slot->host = host;
slot->mmc = mmc; slot->mmc = mmc;
slot->id = id; slot->id = id;
slot->power_mode = MMC_POWER_UNDEFINED;
slot->pdata = &host->pdata->slots[id]; slot->pdata = &host->pdata->slots[id];
host->slots[id] = slot; host->slots[id] = slot;
......
...@@ -288,9 +288,9 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -288,9 +288,9 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
struct device *dev = omap_host->dev; struct device *dev = omap_host->dev;
struct mmc_ios *ios = &mmc->ios; struct mmc_ios *ios = &mmc->ios;
u32 start_window = 0, max_window = 0; u32 start_window = 0, max_window = 0;
bool dcrc_was_enabled = false;
u8 cur_match, prev_match = 0; u8 cur_match, prev_match = 0;
u32 length = 0, max_len = 0; u32 length = 0, max_len = 0;
u32 ier = host->ier;
u32 phase_delay = 0; u32 phase_delay = 0;
int ret = 0; int ret = 0;
u32 reg; u32 reg;
...@@ -317,9 +317,10 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -317,9 +317,10 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
* during the tuning procedure. So disable it during the * during the tuning procedure. So disable it during the
* tuning procedure. * tuning procedure.
*/ */
ier &= ~SDHCI_INT_DATA_CRC; if (host->ier & SDHCI_INT_DATA_CRC) {
sdhci_writel(host, ier, SDHCI_INT_ENABLE); host->ier &= ~SDHCI_INT_DATA_CRC;
sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); dcrc_was_enabled = true;
}
while (phase_delay <= MAX_PHASE_DELAY) { while (phase_delay <= MAX_PHASE_DELAY) {
sdhci_omap_set_dll(omap_host, phase_delay); sdhci_omap_set_dll(omap_host, phase_delay);
...@@ -366,6 +367,9 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -366,6 +367,9 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
ret: ret:
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
/* Reenable forbidden interrupt */
if (dcrc_was_enabled)
host->ier |= SDHCI_INT_DATA_CRC;
sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
return ret; return ret;
......
...@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) ...@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
timeout = ktime_add_ms(ktime_get(), 100); timeout = ktime_add_ms(ktime_get(), 100);
/* hw clears the bit when it's done */ /* hw clears the bit when it's done */
while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { while (1) {
if (ktime_after(ktime_get(), timeout)) { bool timedout = ktime_after(ktime_get(), timeout);
if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask))
break;
if (timedout) {
pr_err("%s: Reset 0x%x never completed.\n", pr_err("%s: Reset 0x%x never completed.\n",
mmc_hostname(host->mmc), (int)mask); mmc_hostname(host->mmc), (int)mask);
sdhci_dumpregs(host); sdhci_dumpregs(host);
...@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) ...@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
/* Wait max 20 ms */ /* Wait max 20 ms */
timeout = ktime_add_ms(ktime_get(), 20); timeout = ktime_add_ms(ktime_get(), 20);
while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) while (1) {
& SDHCI_CLOCK_INT_STABLE)) { bool timedout = ktime_after(ktime_get(), timeout);
if (ktime_after(ktime_get(), timeout)) {
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
if (clk & SDHCI_CLOCK_INT_STABLE)
break;
if (timedout) {
pr_err("%s: Internal clock never stabilised.\n", pr_err("%s: Internal clock never stabilised.\n",
mmc_hostname(host->mmc)); mmc_hostname(host->mmc));
sdhci_dumpregs(host); sdhci_dumpregs(host);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment