Commit e861e11c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -472,7 +472,7 @@ out:
static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
			       struct mmc_blk_ioc_data *idata)
{
	struct mmc_command cmd = {};
	struct mmc_command cmd = {}, sbc = {};
	struct mmc_data data = {};
	struct mmc_request mrq = {};
	struct scatterlist sg;
@@ -550,10 +550,15 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
	}

	if (idata->rpmb) {
		err = mmc_set_blockcount(card, data.blocks,
			idata->ic.write_flag & (1 << 31));
		if (err)
			return err;
		sbc.opcode = MMC_SET_BLOCK_COUNT;
		/*
		 * We don't do any blockcount validation because the max size
		 * 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) &&
+9 −2
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ struct mmc_omap_slot {
	unsigned int		vdd;
	u16			saved_con;
	u16			bus_mode;
	u16			power_mode;
	unsigned int		fclk_freq;

	struct tasklet_struct	cover_tasklet;
@@ -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_host *host = slot->host;
	int i, dsor;
	int clk_enabled;
	int clk_enabled, init_stream;

	mmc_omap_select_slot(slot, 0);

@@ -1167,6 +1168,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
		slot->vdd = ios->vdd;

	clk_enabled = 0;
	init_stream = 0;
	switch (ios->power_mode) {
	case MMC_POWER_OFF:
		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)
	case MMC_POWER_UP:
		/* Cannot touch dsor yet, just power up MMC */
		mmc_omap_set_power(slot, 1, ios->vdd);
		slot->power_mode = ios->power_mode;
		goto exit;
	case MMC_POWER_ON:
		mmc_omap_fclk_enable(host, 1);
		clk_enabled = 1;
		dsor |= 1 << 11;
		if (slot->power_mode != MMC_POWER_ON)
			init_stream = 1;
		break;
	}
	slot->power_mode = ios->power_mode;

	if (slot->bus_mode != ios->bus_mode) {
		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)
	for (i = 0; i < 2; i++)
		OMAP_MMC_WRITE(host, 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 */
		int usecs = 250;

@@ -1234,6 +1240,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
	slot->host = host;
	slot->mmc = mmc;
	slot->id = id;
	slot->power_mode = MMC_POWER_UNDEFINED;
	slot->pdata = &host->pdata->slots[id];

	host->slots[id] = slot;
+8 −4
Original line number Diff line number Diff line
@@ -288,9 +288,9 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
	struct device *dev = omap_host->dev;
	struct mmc_ios *ios = &mmc->ios;
	u32 start_window = 0, max_window = 0;
	bool dcrc_was_enabled = false;
	u8 cur_match, prev_match = 0;
	u32 length = 0, max_len = 0;
	u32 ier = host->ier;
	u32 phase_delay = 0;
	int ret = 0;
	u32 reg;
@@ -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
	 * tuning procedure.
	 */
	ier &= ~SDHCI_INT_DATA_CRC;
	sdhci_writel(host, ier, SDHCI_INT_ENABLE);
	sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
	if (host->ier & SDHCI_INT_DATA_CRC) {
		host->ier &= ~SDHCI_INT_DATA_CRC;
		dcrc_was_enabled = true;
	}

	while (phase_delay <= MAX_PHASE_DELAY) {
		sdhci_omap_set_dll(omap_host, phase_delay);
@@ -366,6 +367,9 @@ tuning_error:

ret:
	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_SIGNAL_ENABLE);
	return ret;
+13 −5
Original line number Diff line number Diff line
@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
	timeout = ktime_add_ms(ktime_get(), 100);

	/* hw clears the bit when it's done */
	while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
		if (ktime_after(ktime_get(), timeout)) {
	while (1) {
		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",
				mmc_hostname(host->mmc), (int)mask);
			sdhci_dumpregs(host);
@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)

	/* Wait max 20 ms */
	timeout = ktime_add_ms(ktime_get(), 20);
	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
		& SDHCI_CLOCK_INT_STABLE)) {
		if (ktime_after(ktime_get(), timeout)) {
	while (1) {
		bool timedout = 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",
			       mmc_hostname(host->mmc));
			sdhci_dumpregs(host);