Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33fa108e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  sdhci-of: Fix the wrong accessor to HOSTVER register
  mvsdio: fix config failure with some high speed SDHC cards
  mvsdio: ignore high speed timing requests from the core
  mmc/omap: Use disable_irq_nosync() from within irq handlers.
  sdhci-of: Add fsl,esdhc as a valid compatible to bind against
  mvsdio: allow automatic loading when modular
  mxcmmc: Fix missing return value checking in DMA setup code.
  mxcmmc : Reset the SDHC hardware if software timeout occurs.
  omap_hsmmc: Trivial fix for a typo in comment
  mxcmmc: decrease minimum frequency to make MMC cards work
parents ccc0d38e fbf6a5fc
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -64,6 +64,31 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
	unsigned int tmout;
	int tmout_index;

	/*
	 * Hardware weirdness.  The FIFO_EMPTY bit of the HW_STATE
	 * register is sometimes not set before a while when some
	 * "unusual" data block sizes are used (such as with the SWITCH
	 * command), even despite the fact that the XFER_DONE interrupt
	 * was raised.  And if another data transfer starts before
	 * this bit comes to good sense (which eventually happens by
	 * itself) then the new transfer simply fails with a timeout.
	 */
	if (!(mvsd_read(MVSD_HW_STATE) & (1 << 13))) {
		unsigned long t = jiffies + HZ;
		unsigned int hw_state,  count = 0;
		do {
			if (time_after(jiffies, t)) {
				dev_warn(host->dev, "FIFO_EMPTY bit missing\n");
				break;
			}
			hw_state = mvsd_read(MVSD_HW_STATE);
			count++;
		} while (!(hw_state & (1 << 13)));
		dev_dbg(host->dev, "*** wait for FIFO_EMPTY bit "
				   "(hw=0x%04x, count=%d, jiffies=%ld)\n",
				   hw_state, count, jiffies - (t - HZ));
	}

	/* If timeout=0 then maximum timeout index is used. */
	tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk);
	tmout += data->timeout_clks;
@@ -620,9 +645,18 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
	if (ios->bus_width == MMC_BUS_WIDTH_4)
		ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS;

	/*
	 * The HI_SPEED_EN bit is causing trouble with many (but not all)
	 * high speed SD, SDHC and SDIO cards.  Not enabling that bit
	 * makes all cards work.  So let's just ignore that bit for now
	 * and revisit this issue if problems for not enabling this bit
	 * are ever reported.
	 */
#if 0
	if (ios->timing == MMC_TIMING_MMC_HS ||
	    ios->timing == MMC_TIMING_SD_HS)
		ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN;
#endif

	host->ctrl = ctrl_reg;
	mvsd_write(MVSD_HOST_CTRL, ctrl_reg);
@@ -882,3 +916,4 @@ module_param(nodma, int, 0);
MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre");
MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:mvsdio");
+35 −12
Original line number Diff line number Diff line
@@ -140,6 +140,8 @@ struct mxcmci_host {
	struct work_struct	datawork;
};

static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);

static inline int mxcmci_use_dma(struct mxcmci_host *host)
{
	return host->do_dma;
@@ -160,7 +162,7 @@ static void mxcmci_softreset(struct mxcmci_host *host)
	writew(0xff, host->base + MMC_REG_RES_TO);
}

static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
{
	unsigned int nob = data->blocks;
	unsigned int blksz = data->blksz;
@@ -168,6 +170,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
#ifdef HAS_DMA
	struct scatterlist *sg;
	int i;
	int ret;
#endif
	if (data->flags & MMC_DATA_STREAM)
		nob = 0xffff;
@@ -183,7 +186,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
	for_each_sg(data->sg, sg, data->sg_len, i) {
		if (sg->offset & 3 || sg->length & 3) {
			host->do_dma = 0;
			return;
			return 0;
		}
	}

@@ -192,7 +195,8 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
					     data->sg_len,  host->dma_dir);

		imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize,
		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
				datasize,
				host->res->start + MMC_REG_BUFFER_ACCESS,
				DMA_MODE_READ);
	} else {
@@ -200,15 +204,21 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
					     data->sg_len,  host->dma_dir);

		imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize,
		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
				datasize,
				host->res->start + MMC_REG_BUFFER_ACCESS,
				DMA_MODE_WRITE);
	}

	if (ret) {
		dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret);
		return ret;
	}
	wmb();

	imx_dma_enable(host->dma);
#endif /* HAS_DMA */
	return 0;
}

static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
@@ -345,8 +355,11 @@ static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask)
		stat = readl(host->base + MMC_REG_STATUS);
		if (stat & STATUS_ERR_MASK)
			return stat;
		if (time_after(jiffies, timeout))
		if (time_after(jiffies, timeout)) {
			mxcmci_softreset(host);
			mxcmci_set_clk_rate(host, host->clock);
			return STATUS_TIME_OUT_READ;
		}
		if (stat & mask)
			return 0;
		cpu_relax();
@@ -531,6 +544,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
{
	struct mxcmci_host *host = mmc_priv(mmc);
	unsigned int cmdat = host->cmdat;
	int error;

	WARN_ON(host->req != NULL);

@@ -540,7 +554,12 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
	host->do_dma = 1;
#endif
	if (req->data) {
		mxcmci_setup_data(host, req->data);
		error = mxcmci_setup_data(host, req->data);
		if (error) {
			req->cmd->error = error;
			goto out;
		}


		cmdat |= CMD_DAT_CONT_DATA_ENABLE;

@@ -548,7 +567,9 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
			cmdat |= CMD_DAT_CONT_WRITE;
	}

	if (mxcmci_start_cmd(host, req->cmd, cmdat))
	error = mxcmci_start_cmd(host, req->cmd, cmdat);
out:
	if (error)
		mxcmci_finish_request(host, req);
}

@@ -724,7 +745,9 @@ static int mxcmci_probe(struct platform_device *pdev)
		goto out_clk_put;
	}

	mmc->f_min = clk_get_rate(host->clk) >> 7;
	mmc->f_min = clk_get_rate(host->clk) >> 16;
	if (mmc->f_min < 400000)
		mmc->f_min = 400000;
	mmc->f_max = clk_get_rate(host->clk) >> 1;

	/* recommended in data sheet */
+1 −1
Original line number Diff line number Diff line
@@ -822,7 +822,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
		del_timer(&host->cmd_abort_timer);
		host->abort = 1;
		OMAP_MMC_WRITE(host, IE, 0);
		disable_irq(host->irq);
		disable_irq_nosync(host->irq);
		schedule_work(&host->cmd_abort_work);
		return IRQ_HANDLED;
	}
+1 −1
Original line number Diff line number Diff line
@@ -680,7 +680,7 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
	host->dma_ch = -1;
	/*
	 * DMA Callback: run in interrupt context.
	 * mutex_unlock will through a kernel warning if used.
	 * mutex_unlock will throw a kernel warning if used.
	 */
	up(&host->sem);
}
+8 −1
Original line number Diff line number Diff line
@@ -55,7 +55,13 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)

static u16 esdhc_readw(struct sdhci_host *host, int reg)
{
	return in_be16(host->ioaddr + (reg ^ 0x2));
	u16 ret;

	if (unlikely(reg == SDHCI_HOST_VERSION))
		ret = in_be16(host->ioaddr + reg);
	else
		ret = in_be16(host->ioaddr + (reg ^ 0x2));
	return ret;
}

static u8 esdhc_readb(struct sdhci_host *host, int reg)
@@ -277,6 +283,7 @@ static int __devexit sdhci_of_remove(struct of_device *ofdev)
static const struct of_device_id sdhci_of_match[] = {
	{ .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },
	{ .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, },
	{ .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },
	{ .compatible = "generic-sdhci", },
	{},
};