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

Commit e89d456f authored by Andrei Warkentin's avatar Andrei Warkentin Committed by Chris Ball
Browse files

mmc: sdhci: Implement MMC_CAP_CMD23 for SDHCI.



Implements support for multiblock transfers bounded
by SET_BLOCK_COUNT (CMD23).

Signed-off-by: default avatarAndrei Warkentin <andreiw@motorola.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent d0c97cfb
Loading
Loading
Loading
Loading
+47 −16
Original line number Diff line number Diff line
@@ -838,9 +838,10 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
}

static void sdhci_set_transfer_mode(struct sdhci_host *host,
	struct mmc_data *data)
	struct mmc_command *cmd)
{
	u16 mode;
	struct mmc_data *data = cmd->data;

	if (data == NULL)
		return;
@@ -848,11 +849,14 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
	WARN_ON(!host->data);

	mode = SDHCI_TRNS_BLK_CNT_EN;
	if (data->blocks > 1) {
		if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
			mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12;
		else
	if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {
		mode |= SDHCI_TRNS_MULTI;
		/*
		 * If we are sending CMD23, CMD12 never gets sent
		 * on successful completion (so no Auto-CMD12).
		 */
		if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12))
			mode |= SDHCI_TRNS_AUTO_CMD12;
	}
	if (data->flags & MMC_DATA_READ)
		mode |= SDHCI_TRNS_READ;
@@ -893,7 +897,15 @@ static void sdhci_finish_data(struct sdhci_host *host)
	else
		data->bytes_xfered = data->blksz * data->blocks;

	if (data->stop) {
	/*
	 * Need to send CMD12 if -
	 * a) open-ended multiblock transfer (no CMD23)
	 * b) error in multiblock transfer
	 */
	if (data->stop &&
	    (data->error ||
	     !host->mrq->sbc)) {

		/*
		 * The controller needs a reset of internal state machines
		 * upon error conditions.
@@ -949,7 +961,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)

	sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);

	sdhci_set_transfer_mode(host, cmd->data);
	sdhci_set_transfer_mode(host, cmd);

	if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
		printk(KERN_ERR "%s: Unsupported response type!\n",
@@ -1004,6 +1016,13 @@ static void sdhci_finish_command(struct sdhci_host *host)

	host->cmd->error = 0;

	/* Finished CMD23, now send actual command. */
	if (host->cmd == host->mrq->sbc) {
		host->cmd = NULL;
		sdhci_send_command(host, host->mrq->cmd);
	} else {

		/* Processed actual command. */
		if (host->data && host->data_early)
			sdhci_finish_data(host);

@@ -1012,6 +1031,7 @@ static void sdhci_finish_command(struct sdhci_host *host)

		host->cmd = NULL;
	}
}

static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
@@ -1189,7 +1209,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
#ifndef SDHCI_USE_LEDS_CLASS
	sdhci_activate_led(host);
#endif
	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) {

	/*
	 * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED
	 * requests if Auto-CMD12 is enabled.
	 */
	if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) {
		if (mrq->stop) {
			mrq->data->stop = NULL;
			mrq->stop = NULL;
@@ -1227,6 +1252,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
			host->mrq = mrq;
		}

		if (mrq->sbc)
			sdhci_send_command(host, mrq->sbc);
		else
			sdhci_send_command(host, mrq->cmd);
	}

@@ -2455,7 +2483,10 @@ int sdhci_add_host(struct sdhci_host *host)
	} else
		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;

	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE;
	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;

	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
		host->flags |= SDHCI_AUTO_CMD12;

	/*
	 * A controller may support 8-bit width, but the board itself
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@
#define SDHCI_TRANSFER_MODE	0x0C
#define  SDHCI_TRNS_DMA		0x01
#define  SDHCI_TRNS_BLK_CNT_EN	0x02
#define  SDHCI_TRNS_ACMD12	0x04
#define  SDHCI_TRNS_AUTO_CMD12	0x04
#define  SDHCI_TRNS_READ	0x10
#define  SDHCI_TRNS_MULTI	0x20

+1 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ struct sdhci_host {
#define SDHCI_DEVICE_DEAD	(1<<3)	/* Device unresponsive */
#define SDHCI_SDR50_NEEDS_TUNING (1<<4)	/* SDR50 needs tuning */
#define SDHCI_NEEDS_RETUNING	(1<<5)	/* Host needs retuning */
#define SDHCI_AUTO_CMD12	(1<<6)	/* Auto CMD12 support */

	unsigned int version;	/* SDHCI spec. version */