From 85a18ad93ec66888d85758630019b10a84257f3c Mon Sep 17 00:00:00 2001
From: Pierre Ossman <drzeus@drzeus.cx>
Date: Sat, 17 Feb 2007 22:15:27 +0100
Subject: mmc: MMC sector based cards

Support for MMC 4.2 sector based cards. This tweaks the init a
bit and reads a new field out of the EXT_CSD.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
---
 drivers/mmc/mmc.c       | 25 ++++++++++++++++++++++---
 drivers/mmc/mmc_block.c | 19 ++++++++++++++-----
 2 files changed, 36 insertions(+), 8 deletions(-)

(limited to 'drivers/mmc')

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2ba46273496..f772df93a39 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1106,11 +1106,29 @@ static void mmc_process_ext_csds(struct mmc_host *host)
 		mmc_wait_for_req(host, &mrq);
 
 		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			printk("%s: unable to read EXT_CSD, performance "
-				"might suffer.\n", mmc_hostname(card->host));
+			if (card->csd.capacity == (4096 * 512)) {
+				printk(KERN_ERR "%s: unable to read EXT_CSD "
+					"on a possible high capacity card. "
+					"Card will be ignored.\n",
+					mmc_hostname(card->host));
+				mmc_card_set_dead(card);
+			} else {
+				printk(KERN_WARNING "%s: unable to read "
+					"EXT_CSD, performance might "
+					"suffer.\n",
+					mmc_hostname(card->host));
+			}
 			continue;
 		}
 
+		card->ext_csd.sectors =
+			ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+			ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
+			ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
+			ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+		if (card->ext_csd.sectors)
+			mmc_card_set_blockaddr(card);
+
 		switch (ext_csd[EXT_CSD_CARD_TYPE]) {
 		case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
 			card->ext_csd.hs_max_dtr = 52000000;
@@ -1499,7 +1517,8 @@ static void mmc_setup(struct mmc_host *host)
 			mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
 		}
 	} else {
-		mmc_send_op_cond(host, host->ocr, NULL);
+		/* The extra bit indicates that we support high capacity */
+		mmc_send_op_cond(host, host->ocr | (1 << 30), NULL);
 	}
 
 	mmc_discover_cards(host);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 95b0da6abe8..63fbde8756a 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -491,11 +491,20 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 
 	blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
 
-	/*
-	 * The CSD capacity field is in units of read_blkbits.
-	 * set_capacity takes units of 512 bytes.
-	 */
-	set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
+	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
+		/*
+		 * The EXT_CSD sector count is in number or 512 byte
+		 * sectors.
+		 */
+		set_capacity(md->disk, card->ext_csd.sectors);
+	} else {
+		/*
+		 * The CSD capacity field is in units of read_blkbits.
+		 * set_capacity takes units of 512 bytes.
+		 */
+		set_capacity(md->disk,
+			card->csd.capacity << (card->csd.read_blkbits - 9));
+	}
 	return md;
 
  err_putdisk:
-- 
cgit v1.2.3-18-g5258