All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
To: Pierre Ossman
	<drzeus-mmc-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Cc: Mikael Starvik <mikael.starvik-VrBV9hrLPhE@public.gmane.org>,
	Hans-Peter Nilsson
	<hans-peter.nilsson-VrBV9hrLPhE@public.gmane.org>,
	Mike Lavender
	<mike-UTnDXsALFwNjMdQLN6DIHgC/G2K4zDHf@public.gmane.org>
Subject: [patch 3/4] MMC-over-SPI core updates
Date: Sun, 10 Jun 2007 13:07:10 -0700	[thread overview]
Message-ID: <200706101307.11394.david-b@pacbell.net> (raw)
In-Reply-To: <200706101257.45278.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>

Teach the MMC/SD/SDIO core about using SPI mode.

 - Use mmc_host_is_spi() so enumeration works through SPI protocols,
   not just the native (and sometimes parallel) ones

 - Provide the SPI response type flags with each request issued,
   including rquests from the new lock/unlock code.  The model
   is that if no such flags are provided, it will be rejected 
   by the MMC-over-SPI host.

 - Understand that some commands act a bit differently ... notably the
   OP_COND command doesn't return the OCR, and does status differently.

Those changes required some new and updated primitives:

 - Provide utilities to access two SPI-only requests, and one
   request that wasn't previously needed:
     * mmc_spi_read_ocr() ... SPI only
     * mmc_spi_set_crc() ... SPI only
     * mmc_spi_send_cid() ... works without broadcast mode

 - Updated internal routines:
     * previous mmc_send_csd() modified into mmc_send_cxd_native();
       it uses native "R2" responses, which include 16 bytes of data.
     * previous mmc_send_ext_csd() becomes new mmc_send_cxd_data()
       helper for command-and-data access

 - Modified mmc_send_ext_csd() now uses mmc_send_cxd_data() helper

 - Modified mmc_send_csd(), and new mmc_spi_send_cid(), routines use
   those helper routines based on whether they're native or SPI

The current assumption is that nobody will want a controller driver
to handle both SPI *and* the faster "native" MMC/SD protocols, even
on hardware which can do that.

The SPI support hasn't been tested on the new MMC4 cards (they're not
widely available) or with the new card lock/unlock mechanism.  Likewise
SD cards with 4GB and up may have surprises lurking.

Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
---
 drivers/mmc/core/core.c    |   38 ++++++++-
 drivers/mmc/core/mmc.c     |   26 ++++--
 drivers/mmc/core/mmc_ops.c |  173 +++++++++++++++++++++++++++++++++++----------
 drivers/mmc/core/mmc_ops.h |    4 +
 drivers/mmc/core/sd.c      |   36 ++++++---
 drivers/mmc/core/sd_ops.c  |   17 +++-
 6 files changed, 226 insertions(+), 68 deletions(-)

--- pxa.orig/drivers/mmc/core/mmc_ops.h	2007-06-10 13:00:21.000000000 -0700
+++ pxa/drivers/mmc/core/mmc_ops.h	2007-06-10 13:00:34.000000000 -0700
@@ -26,5 +26,9 @@ int mmc_switch(struct mmc_card *card, u8
 int mmc_send_status(struct mmc_card *card, u32 *status);
 int mmc_lock_unlock(struct mmc_card *card, struct key *key, int mode);
 
+int mmc_spi_send_cid(struct mmc_host *host, u32 *cid);
+int mmc_spi_read_ocr(struct mmc_host *host, u32 *ocrp);
+int mmc_spi_set_crc(struct mmc_host *host);
+
 #endif
 
--- pxa.orig/drivers/mmc/core/core.c	2007-06-10 13:00:21.000000000 -0700
+++ pxa/drivers/mmc/core/core.c	2007-06-10 13:00:34.000000000 -0700
@@ -386,8 +386,13 @@ static void mmc_power_up(struct mmc_host
 	int bit = fls(host->ocr_avail) - 1;
 
 	host->ios.vdd = bit;
-	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	host->ios.chip_select = MMC_CS_DONTCARE;
+	if (mmc_host_is_spi(host)) {
+		host->ios.chip_select = MMC_CS_HIGH;
+		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+	} else {
+		host->ios.chip_select = MMC_CS_DONTCARE;
+		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	}
 	host->ios.power_mode = MMC_POWER_UP;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
 	host->ios.timing = MMC_TIMING_LEGACY;
@@ -406,8 +411,10 @@ static void mmc_power_off(struct mmc_hos
 {
 	host->ios.clock = 0;
 	host->ios.vdd = 0;
-	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	host->ios.chip_select = MMC_CS_DONTCARE;
+	if (!mmc_host_is_spi(host)) {
+		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+		host->ios.chip_select = MMC_CS_DONTCARE;
+	}
 	host->ios.power_mode = MMC_POWER_OFF;
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
 	host->ios.timing = MMC_TIMING_LEGACY;
@@ -498,6 +505,19 @@ void mmc_detect_change(struct mmc_host *
 EXPORT_SYMBOL(mmc_detect_change);
 
 
+static int mmc_spi_fixup(struct mmc_host *host, u32 *ocrp)
+{
+	int err;
+
+	if (!mmc_host_is_spi(host))
+		return MMC_ERR_NONE;
+
+	err = mmc_spi_read_ocr(host, ocrp);
+	if (err == MMC_ERR_NONE);
+		err = mmc_spi_set_crc(host);
+	return err;
+}
+
 void mmc_rescan(struct work_struct *work)
 {
 	struct mmc_host *host =
@@ -519,11 +539,13 @@ void mmc_rescan(struct work_struct *work
 		mmc_power_up(host);
 		mmc_go_idle(host);
 
-		mmc_send_if_cond(host, host->ocr_avail);
+		if (!mmc_host_is_spi(host))
+			mmc_send_if_cond(host, host->ocr_avail);
 
 		err = mmc_send_app_op_cond(host, 0, &ocr);
 		if (err == MMC_ERR_NONE) {
-			if (mmc_attach_sd(host, ocr))
+			err = mmc_spi_fixup(host, &ocr);
+			if (err != MMC_ERR_NONE || mmc_attach_sd(host, ocr))
 				mmc_power_off(host);
 		} else {
 			/*
@@ -532,7 +554,9 @@ void mmc_rescan(struct work_struct *work
 			 */
 			err = mmc_send_op_cond(host, 0, &ocr);
 			if (err == MMC_ERR_NONE) {
-				if (mmc_attach_mmc(host, ocr))
+				err = mmc_spi_fixup(host, &ocr);
+				if (err != MMC_ERR_NONE
+						|| mmc_attach_mmc(host, ocr))
 					mmc_power_off(host);
 			} else {
 				mmc_power_off(host);
--- pxa.orig/drivers/mmc/core/mmc_ops.c	2007-06-10 13:00:21.000000000 -0700
+++ pxa/drivers/mmc/core/mmc_ops.c	2007-06-10 13:00:34.000000000 -0700
@@ -31,6 +31,10 @@ static int _mmc_select_card(struct mmc_h
 
 	BUG_ON(!host);
 
+	/* SPI doesn't multiplex; "select" is meaningless */
+	if (mmc_host_is_spi(host))
+		return MMC_ERR_NONE;
+
 	memset(&cmd, 0, sizeof(struct mmc_command));
 
 	cmd.opcode = MMC_SELECT_CARD;
@@ -67,23 +71,30 @@ int mmc_go_idle(struct mmc_host *host)
 	int err;
 	struct mmc_command cmd;
 
-	mmc_set_chip_select(host, MMC_CS_HIGH);
-
-	mmc_delay(1);
+	/*
+	 * Non-SPI hosts need to prevent chipselect going active
+	 * during GO_IDLE; that would put chips into SPI mode.
+	 * SPI hosts necessarily ignore host->chip_select.
+	 */
+	if (!mmc_host_is_spi(host)) {
+		mmc_set_chip_select(host, MMC_CS_HIGH);
+		mmc_delay(1);
+	}
 
 	memset(&cmd, 0, sizeof(struct mmc_command));
 
 	cmd.opcode = MMC_GO_IDLE_STATE;
 	cmd.arg = 0;
-	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_NONE | MMC_CMD_BC;
 
 	err = mmc_wait_for_cmd(host, &cmd, 0);
 
 	mmc_delay(1);
 
-	mmc_set_chip_select(host, MMC_CS_DONTCARE);
-
-	mmc_delay(1);
+	if (!mmc_host_is_spi(host)) {
+		mmc_set_chip_select(host, MMC_CS_DONTCARE);
+		mmc_delay(1);
+	}
 
 	return err;
 }
@@ -99,14 +110,18 @@ int mmc_send_op_cond(struct mmc_host *ho
 
 	cmd.opcode = MMC_SEND_OP_COND;
 	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
 
 	for (i = 100; i; i--) {
 		err = mmc_wait_for_cmd(host, &cmd, 0);
 		if (err != MMC_ERR_NONE)
 			break;
 
-		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+		if (mmc_host_is_spi(host)) {
+			/* wait until reset completes */
+			if (!(cmd.resp[2] & R1_SPI_IDLE))
+				break;
+		} else if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
 			break;
 
 		err = MMC_ERR_TIMEOUT;
@@ -114,7 +129,7 @@ int mmc_send_op_cond(struct mmc_host *ho
 		mmc_delay(10);
 	}
 
-	if (rocr)
+	if (rocr && !mmc_host_is_spi(host))
 		*rocr = cmd.resp[0];
 
 	return err;
@@ -164,41 +179,46 @@ int mmc_set_relative_addr(struct mmc_car
 	return MMC_ERR_NONE;
 }
 
-int mmc_send_csd(struct mmc_card *card, u32 *csd)
+static int
+mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
 {
 	int err;
 	struct mmc_command cmd;
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-	BUG_ON(!csd);
+	BUG_ON(!host);
+	BUG_ON(!cxd);
 
 	memset(&cmd, 0, sizeof(struct mmc_command));
 
-	cmd.opcode = MMC_SEND_CSD;
-	cmd.arg = card->rca << 16;
+	cmd.opcode = opcode;
+	cmd.arg = arg;
 	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
 
-	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
 	if (err != MMC_ERR_NONE)
 		return err;
 
-	memcpy(csd, cmd.resp, sizeof(u32) * 4);
+	memcpy(cxd, cmd.resp, sizeof(u32) * 4);
 
 	return MMC_ERR_NONE;
 }
 
-int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
+struct mmc_cxd {
+	struct mmc_card	*card;		/* optional */
+	void		*buf;
+	unsigned	len;
+	u32		opcode;
+	u32		arg;
+	unsigned	flags;
+};
+
+static int mmc_send_cxd_data(struct mmc_host *host, struct mmc_cxd *cxd)
 {
 	struct mmc_request mrq;
 	struct mmc_command cmd;
 	struct mmc_data data;
 	struct scatterlist sg;
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-	BUG_ON(!ext_csd);
-
 	memset(&mrq, 0, sizeof(struct mmc_request));
 	memset(&cmd, 0, sizeof(struct mmc_command));
 	memset(&data, 0, sizeof(struct mmc_data));
@@ -206,21 +226,22 @@ int mmc_send_ext_csd(struct mmc_card *ca
 	mrq.cmd = &cmd;
 	mrq.data = &data;
 
-	cmd.opcode = MMC_SEND_EXT_CSD;
-	cmd.arg = 0;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+	cmd.opcode = cxd->opcode;
+	cmd.arg = cxd->arg;
+	cmd.flags = cxd->flags;
 
-	data.blksz = 512;
+	data.blksz = cxd->len;
 	data.blocks = 1;
 	data.flags = MMC_DATA_READ;
 	data.sg = &sg;
 	data.sg_len = 1;
 
-	sg_init_one(&sg, ext_csd, 512);
+	sg_init_one(&sg, cxd->buf, cxd->len);
 
-	mmc_set_data_timeout(&data, card, 0);
+	if (cxd->card)
+		mmc_set_data_timeout(&data, cxd->card, 0);
 
-	mmc_wait_for_req(card->host, &mrq);
+	mmc_wait_for_req(host, &mrq);
 
 	if (cmd.error != MMC_ERR_NONE)
 		return cmd.error;
@@ -230,6 +251,85 @@ int mmc_send_ext_csd(struct mmc_card *ca
 	return MMC_ERR_NONE;
 }
 
+int mmc_spi_read_ocr(struct mmc_host *host, u32 *ocrp)
+{
+	struct mmc_command cmd;
+	int err;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SPI_READ_OCR;
+	cmd.flags = MMC_RSP_SPI_R3;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+
+	*ocrp = cmd.resp[1];
+	return err;
+}
+
+int mmc_spi_set_crc(struct mmc_host *host)
+{
+	struct mmc_command cmd;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SPI_CRC_ON_OFF;
+	cmd.flags = MMC_RSP_SPI_R1;
+	if (host->caps & MMC_CAP_SPI_CRC)
+		cmd.arg = 1;
+
+	return mmc_wait_for_cmd(host, &cmd, 0);
+}
+
+int mmc_send_csd(struct mmc_card *card, u32 *csd)
+{
+	struct mmc_cxd	cxd;
+
+	if (!mmc_host_is_spi(card->host))
+		return mmc_send_cxd_native(card->host, card->rca << 16,
+				csd, MMC_SEND_CSD);
+
+	cxd.card = card;
+	cxd.buf = csd;
+	cxd.len = 16;
+	cxd.opcode = MMC_SEND_CSD;
+	cxd.arg = 0;
+	cxd.flags = MMC_RSP_SPI_R1;
+
+	return mmc_send_cxd_data(card->host, &cxd);
+}
+
+int mmc_spi_send_cid(struct mmc_host *host, u32 *cid)
+{
+	struct mmc_cxd	cxd;
+
+	if (!mmc_host_is_spi(host))
+		return mmc_send_cxd_native(host, 0, cid, MMC_SEND_CID);
+
+	cxd.card = NULL;
+	cxd.buf = cid;
+	cxd.len = 16;
+	cxd.opcode = MMC_SEND_CID;
+	cxd.arg = 0;
+	cxd.flags = MMC_RSP_SPI_R1;
+
+	return mmc_send_cxd_data(host, &cxd);
+}
+
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
+{
+	struct mmc_cxd	cxd;
+
+	cxd.card = card;
+	cxd.buf = ext_csd;
+	cxd.len = 512;
+	cxd.opcode = MMC_SEND_EXT_CSD;
+	cxd.arg = 0;
+	cxd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	return mmc_send_cxd_data(card->host, &cxd);
+}
+
 int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
 {
 	int err;
@@ -245,7 +345,7 @@ int mmc_switch(struct mmc_card *card, u8
 		  (index << 16) |
 		  (value << 8) |
 		  set;
-	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err != MMC_ERR_NONE)
@@ -265,8 +365,9 @@ int mmc_send_status(struct mmc_card *car
 	memset(&cmd, 0, sizeof(struct mmc_command));
 
 	cmd.opcode = MMC_SEND_STATUS;
-	cmd.arg = card->rca << 16;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	if (!mmc_host_is_spi(card->host))
+		cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err != MMC_ERR_NONE)
@@ -316,7 +417,7 @@ int mmc_lock_unlock(struct mmc_card *car
 
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.arg = data_size;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err != MMC_ERR_NONE)
 		goto out;
@@ -325,7 +426,7 @@ int mmc_lock_unlock(struct mmc_card *car
 
 	cmd.opcode = MMC_LOCK_UNLOCK;
 	cmd.arg = 0;
-	cmd.flags = MMC_RSP_R1B | MMC_CMD_ADTC;
+	cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_ADTC;
 
 	memset(&data, 0, sizeof(struct mmc_data));
 
@@ -351,7 +452,7 @@ int mmc_lock_unlock(struct mmc_card *car
 
 	cmd.opcode = MMC_SEND_STATUS;
 	cmd.arg = card->rca << 16;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
 
 	/* set timeout for forced erase operation to 3 min. (see MMC spec) */
 	erase_timeout = jiffies + 180 * HZ;
--- pxa.orig/drivers/mmc/core/mmc.c	2007-06-10 13:00:21.000000000 -0700
+++ pxa/drivers/mmc/core/mmc.c	2007-06-10 13:00:34.000000000 -0700
@@ -320,9 +320,15 @@ static int mmc_init_card(struct mmc_host
 	/*
 	 * Fetch CID from card.
 	 */
-	err = mmc_all_send_cid(host, cid);
-	if (err != MMC_ERR_NONE)
-		goto err;
+	if (mmc_host_is_spi(host)) {
+		err = mmc_spi_send_cid(host, cid);
+		if (err != MMC_ERR_NONE)
+			goto err;
+	} else {
+		err = mmc_all_send_cid(host, cid);
+		if (err != MMC_ERR_NONE)
+			goto err;
+	}
 
 	if (oldcard) {
 		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
@@ -343,13 +349,15 @@ static int mmc_init_card(struct mmc_host
 	}
 
 	/*
-	 * Set card RCA.
+	 * For native busses:  set card RCA and leave open drain mode.
 	 */
-	err = mmc_set_relative_addr(card);
-	if (err != MMC_ERR_NONE)
-		goto free_card;
+	if (!mmc_host_is_spi(host)) {
+		err = mmc_set_relative_addr(card);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
 
-	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+	}
 
 	/*
 	 * Check if card is locked.
@@ -385,7 +393,7 @@ static int mmc_init_card(struct mmc_host
 
 	if (!oldcard) {
 		/*
-		 * Fetch and process extened CSD.
+		 * Fetch and process extended CSD.
 		 */
 		err = mmc_read_ext_csd(card);
 		if (err != MMC_ERR_NONE)
--- pxa.orig/drivers/mmc/core/sd.c	2007-06-10 13:00:21.000000000 -0700
+++ pxa/drivers/mmc/core/sd.c	2007-06-10 13:00:34.000000000 -0700
@@ -379,9 +379,19 @@ static int mmc_sd_init_card(struct mmc_h
 	/*
 	 * Fetch CID from card.
 	 */
-	err = mmc_all_send_cid(host, cid);
-	if (err != MMC_ERR_NONE)
-		goto err;
+	if (mmc_host_is_spi(host)) {
+		err = mmc_spi_set_crc(host);
+		if (err != MMC_ERR_NONE)
+			goto err;
+		err = mmc_spi_send_cid(host, cid);
+		if (err != MMC_ERR_NONE)
+			goto err;
+	} else {
+		err = mmc_all_send_cid(host, cid);
+		if (err != MMC_ERR_NONE)
+			goto err;
+	}
+
 
 	if (oldcard) {
 		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
@@ -401,13 +411,15 @@ static int mmc_sd_init_card(struct mmc_h
 	}
 
 	/*
-	 * Set card RCA.
+	 * For native busses:  set card RCA and leave open drain mode.
 	 */
-	err = mmc_send_relative_addr(host, &card->rca);
-	if (err != MMC_ERR_NONE)
-		goto free_card;
+	if (!mmc_host_is_spi(host)) {
+		err = mmc_send_relative_addr(host, &card->rca);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
 
-	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+	}
 
 	/*
 	 * Check if card is locked.
@@ -455,9 +467,11 @@ static int mmc_sd_init_card(struct mmc_h
 		/*
 		 * Fetch switch information from card.
 		 */
-		err = mmc_read_switch(card);
-		if (err != MMC_ERR_NONE)
-			goto free_card;
+		if (!mmc_host_is_spi(host)) {
+			err = mmc_read_switch(card);
+			if (err != MMC_ERR_NONE)
+				goto free_card;
+		}
 	}
 
 	/*
--- pxa.orig/drivers/mmc/core/sd_ops.c	2007-06-06 16:47:58.000000000 -0700
+++ pxa/drivers/mmc/core/sd_ops.c	2007-06-10 13:00:34.000000000 -0700
@@ -89,10 +89,10 @@ int mmc_app_cmd(struct mmc_host *host, s
 
 	if (card) {
 		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+		cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 	} else {
 		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR;
+		cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_BCR;
 	}
 
 	err = mmc_wait_for_cmd(host, &cmd, 0);
@@ -148,14 +148,18 @@ int mmc_send_app_op_cond(struct mmc_host
 
 	cmd.opcode = SD_APP_OP_COND;
 	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
 
 	for (i = 100; i; i--) {
 		err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES);
 		if (err != MMC_ERR_NONE)
 			break;
 
-		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+		if (mmc_host_is_spi(host)) {
+			/* wait until reset completes */
+			if (!(cmd.resp[2] & R1_SPI_IDLE))
+				break;
+		} else if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
 			break;
 
 		err = MMC_ERR_TIMEOUT;
@@ -175,6 +179,9 @@ int mmc_send_if_cond(struct mmc_host *ho
 	int err;
 	static const u8 test_pattern = 0xAA;
 
+	if (mmc_host_is_spi(host))
+		return MMC_ERR_FAILED;
+
 	/*
 	 * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
 	 * before SD_APP_OP_COND. This command will harmlessly fail for
@@ -242,7 +249,7 @@ int mmc_app_send_scr(struct mmc_card *ca
 
 	cmd.opcode = SD_APP_SEND_SCR;
 	cmd.arg = 0;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
 
 	data.blksz = 8;
 	data.blocks = 1;

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

  parent reply	other threads:[~2007-06-10 20:07 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-10 19:57 [patch 0/4] MMC-over-SPI for 2.6.22-rc4-mm David Brownell
     [not found] ` <200706101257.45278.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-10 20:05   ` [patch 1/4] MMC-over-SPI header updates David Brownell
     [not found]     ` <200706101305.53151.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-12 17:22       ` Pierre Ossman
     [not found]         ` <466ED661.1010407-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-12 18:06           ` David Brownell
     [not found]             ` <200706121106.42067.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-13  8:25               ` Pierre Ossman
     [not found]                 ` <466FAA0C.9020102-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-13 21:33                   ` David Brownell
     [not found]                     ` <200706131433.21238.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-15 17:53                       ` Pierre Ossman
     [not found]                         ` <4672D202.3000901-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-16 18:50                           ` David Brownell
     [not found]                             ` <200706161150.58273.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-20 15:52                               ` Pierre Ossman
     [not found]                                 ` <46794D3B.1060009-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-22 20:08                                   ` David Brownell
2007-06-10 20:06   ` [patch 2/4] MMC-over-SPI card driver update David Brownell
     [not found]     ` <200706101306.39081.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-12 17:28       ` Pierre Ossman
2007-06-10 20:07   ` David Brownell [this message]
     [not found]     ` <200706101307.11394.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-13  8:12       ` [patch 3/4] MMC-over-SPI core updates Pierre Ossman
     [not found]         ` <466FA700.2080009-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-14  0:53           ` David Brownell
     [not found]             ` <200706131753.47453.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-15 18:03               ` Pierre Ossman
     [not found]                 ` <4672D474.4060707-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-16 21:16                   ` David Brownell
     [not found]                     ` <200706161416.17802.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-20 15:56                       ` Pierre Ossman
     [not found]                         ` <46794E1B.6010907-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-22 20:42                           ` David Brownell
2007-06-10 20:08   ` [patch 4/4] MMC-over-SPI host driver David Brownell
     [not found]     ` <200706101308.07910.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-13 19:32       ` Pierre Ossman
     [not found]         ` <46704637.2090309-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-14  4:05           ` David Brownell
     [not found]             ` <200706132105.51711.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-15 18:26               ` Pierre Ossman
     [not found]                 ` <4672D9C5.9080707-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-17 20:29                   ` David Brownell
     [not found]                     ` <200706171329.12709.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-20 16:20                       ` Pierre Ossman
     [not found]                         ` <467953E0.8050408-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-20 17:05                           ` David Brownell
     [not found]                             ` <20070620170511.EC564F31CB-ZcXrCSuhvln6VZ3dlLfH/g4gEjPzgfUyLrfjE7I9kuVHxeISYlDBzl6hYfS7NtTn@public.gmane.org>
2007-06-20 17:51                               ` Pierre Ossman
     [not found]                                 ` <4679691C.2060803-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org>
2007-06-22 21:18                                   ` David Brownell
     [not found]                                     ` <200706221418.44214.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-06-30 18:46                                       ` Pierre Ossman
2007-07-12 18:14                                   ` David Brownell
2007-07-12 17:52                   ` David Brownell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200706101307.11394.david-b@pacbell.net \
    --to=david-b-ybekhbn/0ldr7s880joybq@public.gmane.org \
    --cc=drzeus-mmc-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org \
    --cc=hans-peter.nilsson-VrBV9hrLPhE@public.gmane.org \
    --cc=mikael.starvik-VrBV9hrLPhE@public.gmane.org \
    --cc=mike-UTnDXsALFwNjMdQLN6DIHgC/G2K4zDHf@public.gmane.org \
    --cc=spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.