r1237 - trunk/src/target/kernel/patches

laforge at sita.openmoko.org laforge at sita.openmoko.org
Sun Mar 4 15:38:11 CET 2007


Author: laforge
Date: 2007-03-04 15:38:08 +0100 (Sun, 04 Mar 2007)
New Revision: 1237

Added:
   trunk/src/target/kernel/patches/sdhc-backport.patch
Modified:
   trunk/src/target/kernel/patches/series
Log:
add sdhc patch from 2.6.21-rc1 mainline (See: http://bugzilla.openmoko.org/cgi-bin/bugzilla/show_bug.cgi?id=93)


Added: trunk/src/target/kernel/patches/sdhc-backport.patch
===================================================================
--- trunk/src/target/kernel/patches/sdhc-backport.patch	2007-03-04 13:08:07 UTC (rev 1236)
+++ trunk/src/target/kernel/patches/sdhc-backport.patch	2007-03-04 14:38:08 UTC (rev 1237)
@@ -0,0 +1,323 @@
+From: Philip Langdale <philipl at overt.org>
+Date: Thu, 4 Jan 2007 14:57:32 +0000 (-0800)
+Subject: mmc: Add support for SDHC cards
+X-Git-Tag: v2.6.21-rc1^0~274^2~627^2~26
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=fba68bd2dab1ac99af3c5a963ec9581cfa9f1725
+
+mmc: Add support for SDHC cards
+
+Thanks to the generous donation of an SDHC card by John Gilmore, and
+the surprisingly enlightened decision by the SD Card Association to
+publish useful specs, I've been able to bash out support for SDHC. The
+changes are not too profound:
+
+i) Add a card flag indicating the card uses block level addressing and
+check it in the block driver. As we never took advantage of byte-level
+addressing, this simply involves skipping the block -> byte
+translation when sending commands.
+
+ii) The layout of the CSD is changed - a set of fields are discarded
+to make space for a larger C_SIZE. We did not reference any of the
+discarded fields except those related to the C_SIZE.
+
+iii) Read and write timeouts are fixed values and not calculated from
+CSD values.
+
+iv) Before invoking SEND_APP_OP_COND, we must invoke the new
+SEND_IF_COND to inform the card we support SDHC.
+
+Signed-off-by: Philipl Langdale <philipl at overt.org>
+Signed-off-by: Pierre Ossman <drzeus at drzeus.cx>
+---
+
+diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
+index 105f419..b48c277 100644
+--- a/drivers/mmc/mmc.c
++++ b/drivers/mmc/mmc.c
+@@ -289,7 +289,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
+ 		else
+ 			limit_us = 100000;
+ 
+-		if (timeout_us > limit_us) {
++		/*
++		 * SDHC cards always use these fixed values.
++		 */
++		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
+ 			data->timeout_ns = limit_us * 1000;
+ 			data->timeout_clks = 0;
+ 		}
+@@ -372,7 +375,7 @@ static inline void mmc_set_ios(struct mmc_host *host)
+ 		 mmc_hostname(host), ios->clock, ios->bus_mode,
+ 		 ios->power_mode, ios->chip_select, ios->vdd,
+ 		 ios->bus_width);
+-	
++
+ 	host->ops->set_ios(host, ios);
+ }
+ 
+@@ -588,34 +591,65 @@ static void mmc_decode_csd(struct mmc_card *card)
+ 
+ 	if (mmc_card_sd(card)) {
+ 		csd_struct = UNSTUFF_BITS(resp, 126, 2);
+-		if (csd_struct != 0) {
++
++		switch (csd_struct) {
++		case 0:
++			m = UNSTUFF_BITS(resp, 115, 4);
++			e = UNSTUFF_BITS(resp, 112, 3);
++			csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
++			csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
++
++			m = UNSTUFF_BITS(resp, 99, 4);
++			e = UNSTUFF_BITS(resp, 96, 3);
++			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
++			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
++
++			e = UNSTUFF_BITS(resp, 47, 3);
++			m = UNSTUFF_BITS(resp, 62, 12);
++			csd->capacity	  = (1 + m) << (e + 2);
++
++			csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
++			csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
++			csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
++			csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
++			csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
++			csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
++			csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
++			break;
++		case 1:
++			/*
++			 * This is a block-addressed SDHC card. Most
++			 * interesting fields are unused and have fixed
++			 * values. To avoid getting tripped by buggy cards,
++			 * we assume those fixed values ourselves.
++			 */
++			mmc_card_set_blockaddr(card);
++
++			csd->tacc_ns	 = 0; /* Unused */
++			csd->tacc_clks	 = 0; /* Unused */
++
++			m = UNSTUFF_BITS(resp, 99, 4);
++			e = UNSTUFF_BITS(resp, 96, 3);
++			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
++			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
++
++			m = UNSTUFF_BITS(resp, 48, 22);
++			csd->capacity     = (1 + m) << 10;
++
++			csd->read_blkbits = 9;
++			csd->read_partial = 0;
++			csd->write_misalign = 0;
++			csd->read_misalign = 0;
++			csd->r2w_factor = 4; /* Unused */
++			csd->write_blkbits = 9;
++			csd->write_partial = 0;
++			break;
++		default:
+ 			printk("%s: unrecognised CSD structure version %d\n",
+ 				mmc_hostname(card->host), csd_struct);
+ 			mmc_card_set_bad(card);
+ 			return;
+ 		}
+-
+-		m = UNSTUFF_BITS(resp, 115, 4);
+-		e = UNSTUFF_BITS(resp, 112, 3);
+-		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+-		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+-
+-		m = UNSTUFF_BITS(resp, 99, 4);
+-		e = UNSTUFF_BITS(resp, 96, 3);
+-		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+-		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+-
+-		e = UNSTUFF_BITS(resp, 47, 3);
+-		m = UNSTUFF_BITS(resp, 62, 12);
+-		csd->capacity	  = (1 + m) << (e + 2);
+-
+-		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+-		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+-		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+-		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+-		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+-		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+-		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+ 	} else {
+ 		/*
+ 		 * We only understand CSD structure v1.1 and v1.2.
+@@ -848,6 +882,41 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+ 	return err;
+ }
+ 
++static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
++{
++	struct mmc_command cmd;
++	int err, sd2;
++	static const u8 test_pattern = 0xAA;
++
++	/*
++	* 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
++	* SD 1.0 cards.
++	*/
++	cmd.opcode = SD_SEND_IF_COND;
++	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
++	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
++
++	err = mmc_wait_for_cmd(host, &cmd, 0);
++	if (err == MMC_ERR_NONE) {
++		if ((cmd.resp[0] & 0xFF) == test_pattern) {
++			sd2 = 1;
++		} else {
++			sd2 = 0;
++			err = MMC_ERR_FAILED;
++		}
++	} else {
++		/*
++		 * Treat errors as SD 1.0 card.
++		 */
++		sd2 = 0;
++		err = MMC_ERR_NONE;
++	}
++	if (rsd2)
++		*rsd2 = sd2;
++	return err;
++}
++
+ /*
+  * Discover cards by requesting their CID.  If this command
+  * times out, it is not an error; there are no further cards
+@@ -1334,6 +1403,10 @@ static void mmc_setup(struct mmc_host *host)
+ 		mmc_power_up(host);
+ 		mmc_idle_cards(host);
+ 
++		err = mmc_send_if_cond(host, host->ocr_avail, NULL);
++		if (err != MMC_ERR_NONE) {
++			return;
++		}
+ 		err = mmc_send_app_op_cond(host, 0, &ocr);
+ 
+ 		/*
+@@ -1386,10 +1459,21 @@ static void mmc_setup(struct mmc_host *host)
+ 	 * all get the idea that they should be ready for CMD2.
+ 	 * (My SanDisk card seems to need this.)
+ 	 */
+-	if (host->mode == MMC_MODE_SD)
+-		mmc_send_app_op_cond(host, host->ocr, NULL);
+-	else
++	if (host->mode == MMC_MODE_SD) {
++		int err, sd2;
++		err = mmc_send_if_cond(host, host->ocr, &sd2);
++		if (err == MMC_ERR_NONE) {
++			/*
++			* If SD_SEND_IF_COND indicates an SD 2.0
++			* compliant card and we should set bit 30
++			* of the ocr to indicate that we can handle
++			* block-addressed SDHC cards.
++			*/
++			mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
++		}
++	} else {
+ 		mmc_send_op_cond(host, host->ocr, NULL);
++	}
+ 
+ 	mmc_discover_cards(host);
+ 
+diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
+index 8771357..5a4eaca 100644
+--- a/drivers/mmc/mmc_block.c
++++ b/drivers/mmc/mmc_block.c
+@@ -237,7 +237,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
+ 		brq.mrq.cmd = &brq.cmd;
+ 		brq.mrq.data = &brq.data;
+ 
+-		brq.cmd.arg = req->sector << 9;
++		brq.cmd.arg = req->sector;
++		if (!mmc_card_blockaddr(card))
++			brq.cmd.arg <<= 9;
+ 		brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+ 		brq.data.blksz = 1 << md->block_bits;
+ 		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
+@@ -494,6 +496,10 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
+ 	struct mmc_command cmd;
+ 	int err;
+ 
++	/* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
++	if (mmc_card_blockaddr(card))
++		return 0;
++
+ 	mmc_card_claim_host(card);
+ 	cmd.opcode = MMC_SET_BLOCKLEN;
+ 	cmd.arg = 1 << md->block_bits;
+diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
+index d0e6a54..e45712a 100644
+--- a/include/linux/mmc/card.h
++++ b/include/linux/mmc/card.h
+@@ -71,6 +71,7 @@ struct mmc_card {
+ #define MMC_STATE_SDCARD	(1<<3)		/* is an SD card */
+ #define MMC_STATE_READONLY	(1<<4)		/* card is read-only */
+ #define MMC_STATE_HIGHSPEED	(1<<5)		/* card is in high speed mode */
++#define MMC_STATE_BLOCKADDR	(1<<6)		/* card uses block-addressing */
+ 	u32			raw_cid[4];	/* raw card CID */
+ 	u32			raw_csd[4];	/* raw card CSD */
+ 	u32			raw_scr[2];	/* raw card SCR */
+@@ -87,6 +88,7 @@ struct mmc_card {
+ #define mmc_card_sd(c)		((c)->state & MMC_STATE_SDCARD)
+ #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
+ #define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
++#define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
+ 
+ #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
+ #define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
+@@ -94,6 +96,7 @@ struct mmc_card {
+ #define mmc_card_set_sd(c)	((c)->state |= MMC_STATE_SDCARD)
+ #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+ #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
++#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
+ 
+ #define mmc_card_name(c)	((c)->cid.prod_name)
+ #define mmc_card_id(c)		((c)->dev.bus_id)
+diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
+index bcf2490..cdc54be 100644
+--- a/include/linux/mmc/mmc.h
++++ b/include/linux/mmc/mmc.h
+@@ -43,6 +43,7 @@ struct mmc_command {
+ #define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+ #define MMC_RSP_R3	(MMC_RSP_PRESENT)
+ #define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
++#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+ 
+ #define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
+ 
+diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
+index 2dce60c..c90b676 100644
+--- a/include/linux/mmc/protocol.h
++++ b/include/linux/mmc/protocol.h
+@@ -79,9 +79,12 @@
+ #define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
+ 
+ /* SD commands                           type  argument     response */
+-  /* class 8 */
++  /* class 0 */
+ /* This is basically the same command as for MMC with some quirks. */
+ #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
++#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
++
++  /* class 10 */
+ #define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
+ 
+   /* Application commands */
+@@ -115,6 +118,14 @@
+  */
+ 
+ /*
++ * SD_SEND_IF_COND argument format:
++ *
++ *	[31:12] Reserved (0)
++ *	[11:8] Host Voltage Supply Flags
++ *	[7:0] Check Pattern (0xAA)
++ */
++
++/*
+   MMC status in R1
+   Type
+   	e : error bit

Modified: trunk/src/target/kernel/patches/series
===================================================================
--- trunk/src/target/kernel/patches/series	2007-03-04 13:08:07 UTC (rev 1236)
+++ trunk/src/target/kernel/patches/series	2007-03-04 14:38:08 UTC (rev 1237)
@@ -33,3 +33,4 @@
 ts0710.patch
 s3c2410-qt2410-buttons.patch
 config-nr-tty-devices.patch
+sdhc-backport.patch





More information about the commitlog mailing list