
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- linux-2.6.11-rc1/include/linux/mmc/card.h~mmc_sd-r1.patch
+++ linux-2.6.11-rc1/include/linux/mmc/card.h
@@ -24,6 +24,7 @@
 };
 
 struct mmc_csd {
+	unsigned char		ver; /* CSD struct version */	
 	unsigned char		mmca_vsn;
 	unsigned short		cmdclass;
 	unsigned short		tacc_clks;
@@ -47,6 +48,7 @@
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
 #define MMC_STATE_DEAD		(1<<1)		/* device no longer in stack */
 #define MMC_STATE_BAD		(1<<2)		/* unrecognised device */
+#define MMC_STATE_IS_SD		(1<<3)		/* device is a SD card */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	struct mmc_cid		cid;		/* card identification */
--- linux-2.6.11-rc1/include/linux/mmc/host.h~mmc_sd-r1.patch
+++ linux-2.6.11-rc1/include/linux/mmc/host.h
@@ -61,6 +61,9 @@
 struct mmc_card;
 struct device;
 
+/* Flag Definitions */
+#define HOST_CAP_SD_4_BIT       (1 << 0)
+
 struct mmc_host {
 	struct device		*dev;
 	struct mmc_host_ops	*ops;
@@ -68,6 +71,7 @@
 	unsigned int		f_max;
 	u32			ocr_avail;
 	char			host_name[8];
+	unsigned long           flags;
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
--- linux-2.6.11-rc1/include/linux/mmc/protocol.h~mmc_sd-r1.patch
+++ linux-2.6.11-rc1/include/linux/mmc/protocol.h
@@ -31,6 +31,8 @@
 #define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
 #define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
 #define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
+/* The next entry is NOT a mistake - SD cards use a different CMD3 to MMC */
+#define MMC_SEND_RELATIVE_ADDR    3   /* ac                      R6  */
 #define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
 #define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
 #define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
@@ -76,6 +78,10 @@
 #define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
 #define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1b */
 
+/* Advanced Command (used by sd card) */
+#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
+#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
+
 /*
   MMC status in R1
   Type
--- linux-2.6.11-rc1/drivers/mmc/mmc.c~mmc_sd-r1.patch
+++ linux-2.6.11-rc1/drivers/mmc/mmc.c
@@ -3,6 +3,8 @@
  *
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
  *
+ *  SD support (c) 2004 Ian Molton.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -23,6 +25,8 @@
 
 #include "mmc.h"
 
+#define CONFIG_MMC_DEBUG 1
+
 #ifdef CONFIG_MMC_DEBUG
 #define DBG(x...)	printk(KERN_DEBUG x)
 #else
@@ -98,6 +102,7 @@
 void
 mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 {
+	
 	DBG("MMC: starting cmd %02x arg %08x flags %08x\n",
 	    mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
 
@@ -214,10 +219,33 @@
 		cmd.opcode = MMC_SELECT_CARD;
 		cmd.arg = card->rca << 16;
 		cmd.flags = MMC_RSP_R1;
-
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+
+		if(err != MMC_ERR_NONE)
+			goto out;
+
+		/* Select 4 bit mode on SD cards note: a 4 bit mmc standard is
+		 * on the table... watch this space.
+		 */
+		if(host->flags & HOST_CAP_SD_4_BIT &&
+		   card->state & MMC_STATE_IS_SD) {
+			cmd.opcode = MMC_APP_CMD;
+			cmd.arg = card->rca << 16;
+			cmd.flags = MMC_RSP_R1;
+			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+			if(err != MMC_ERR_NONE) {
+				goto out;
+			}
+			cmd.opcode = SD_APP_SET_BUS_WIDTH;
+			cmd.arg = 2;
+			cmd.flags = MMC_RSP_R1; //| MMC_FLAG_ACMD;
+			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+			if(err != MMC_ERR_NONE)
+				DBG("Error selecting 4 bit bus mode\n");
+		}
 	}
 
+out:
 	return err;
 }
 
@@ -321,7 +349,40 @@
 	u32 *resp = card->raw_cid;
 
 	memset(&card->cid, 0, sizeof(struct mmc_cid));
-
+	
+	if(card->csd.ver == 0) {
+		/*
+		 * Based on what I know, this is a SD card -Ian Molton
+		 * 
+		 * Unknown card (OEM card 'Traveller')
+		 * CID: 01504153 31323842 4134758d d0003400
+		 * CSD: 005d0132 135983d3 f6da4fff 16400000
+		 * Sandisk 32MB SD
+		 * CID: 03534453 44303332 318e01af 22002b00
+		 * CSD: 00260032 1f5981d2 ecb5cfff 92404000
+		 * Lexar 256MB SD (40x)
+		 * CID: 154d4353 4d492020 00120456 69003a00
+		 * CSD: 007f0032 1f5983cf f6dabf9f 96600000
+		 * Sandisk 128MB card:
+		 * CID: 03534453 44313238 31100b03 9e003500
+		 * CSD: 00260032 1f5983c0 ecb64fff 92404000
+		 */
+		card->cid.manfid       = UNSTUFF_BITS(resp, 120, 8);
+		card->cid.oemid	  = UNSTUFF_BITS(resp, 104, 16);
+		card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
+		card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
+		card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
+		card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
+		card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
+		card->cid.hwrev        = UNSTUFF_BITS(resp, 60, 4);
+		card->cid.fwrev        = UNSTUFF_BITS(resp, 56, 4);
+		card->cid.serial       = UNSTUFF_BITS(resp, 24, 32);
+		card->cid.year         = UNSTUFF_BITS(resp, 12, 8);
+		card->cid.month        = UNSTUFF_BITS(resp, 8, 4);
+	
+		card->cid.year += 2000; /* SD cards year offset */
+		return;
+	}
 	/*
 	 * The selection of the format here is guesswork based upon
 	 * information people have sent to date.
@@ -376,12 +437,20 @@
 	unsigned int e, m, csd_struct;
 	u32 *resp = card->raw_csd;
 
+	printk("CID dump: %08x %08x %08x %08x\n", card->raw_cid[0], card->raw_cid[1], card->raw_cid[2], card->raw_cid[3]);
+	printk("CSD dump: %08x %08x %08x %08x\n", resp[0], resp[1], resp[2], resp[3]);
+
+	/* ver 0 == SD CSD v 1.0   1 == MMC CSD v1.1 
+	 * 2 == MMC CSD v?.? 
+	 */
+	csd->ver = UNSTUFF_BITS(resp, 126, 2);
+
 	/*
 	 * We only understand CSD structure v1.1 and v2.
 	 * v2 has extra information in bits 15, 11 and 10.
 	 */
 	csd_struct = UNSTUFF_BITS(resp, 126, 2);
-	if (csd_struct != 1 && csd_struct != 2) {
+	if (csd_struct >= 3) {
 		printk("%s: unrecognised CSD structure version %d\n",
 			card->host->host_name, csd_struct);
 		mmc_card_set_bad(card);
@@ -392,6 +461,7 @@
 	m = UNSTUFF_BITS(resp, 115, 4);
 	e = UNSTUFF_BITS(resp, 112, 3);
 	csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+	/* FIXME - appears to be two ways of presenting tacc_ns in SD cards. */
 	csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
 
 	m = UNSTUFF_BITS(resp, 99, 4);
@@ -467,6 +537,23 @@
 }
 
 /*
+ * allocate a unique RCA
+ */
+static unsigned int mmc_alloc_rca(struct mmc_host *host, unsigned int *frca) {
+	unsigned int rca = *frca;
+	struct mmc_card *card;
+again:
+	list_for_each_entry(card, &host->cards, node) {
+		if (card->rca == rca) {
+			rca++;
+			goto again;
+		}
+	}
+	printk("Allocated rca: %04x\n", rca);
+	return rca;
+}
+
+/*
  * Apply power to the MMC stack.
  */
 static void mmc_power_up(struct mmc_host *host)
@@ -496,31 +583,49 @@
 	host->ops->set_ios(host, &host->ios);
 }
 
-static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr, int init_opcode, int *is_sd)
 {
 	struct mmc_command cmd;
 	int i, err = 0;
 
-	cmd.opcode = MMC_SEND_OP_COND;
-	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3;
-
 	for (i = 100; i; i--) {
+		if(init_opcode == SD_APP_OP_COND) {
+			cmd.opcode = MMC_APP_CMD;
+			cmd.arg = 0;
+			cmd.flags = MMC_RSP_R1;
+			err = mmc_wait_for_cmd(host, &cmd, 0);
+
+			if(err != MMC_ERR_NONE)
+				init_opcode = MMC_SEND_OP_COND; // fallback to MMC
+		}
+
+		cmd.opcode = init_opcode;
+		cmd.arg = ocr;
+		cmd.flags = MMC_RSP_R3;
 		err = mmc_wait_for_cmd(host, &cmd, 0);
+
 		if (err != MMC_ERR_NONE)
 			break;
+		
+		mdelay(3);
+		// 4 works
+		// 2 is too short
 
-		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0) {
+			if(rocr)
+				*rocr = cmd.resp[0];
+			if(is_sd) {
+				if(init_opcode == SD_APP_OP_COND)
+					*is_sd = 1;
+				else
+					*is_sd = 0;
+			}
 			break;
+		}
 
 		err = MMC_ERR_TIMEOUT;
-
-		mmc_delay(10);
 	}
 
-	if (rocr)
-		*rocr = cmd.resp[0];
-
 	return err;
 }
 
@@ -532,7 +637,7 @@
  * Create a mmc_card entry for each discovered card, assigning
  * it an RCA, and save the raw CID for decoding later.
  */
-static void mmc_discover_cards(struct mmc_host *host)
+static void mmc_discover_cards(struct mmc_host *host, int is_sd)
 {
 	struct mmc_card *card;
 	unsigned int first_rca = 1, err;
@@ -565,15 +670,37 @@
 			list_add(&card->node, &host->cards);
 		}
 
+		/* SD cards allocate their own RCA. MMC cards have one allocated
+		 * for them by us.
+		 */
 		card->state &= ~MMC_STATE_DEAD;
+		if(is_sd){
+			cmd.opcode = MMC_SEND_RELATIVE_ADDR;
+			cmd.arg = 0; // ignored
+			cmd.flags = MMC_RSP_R1;
+			card->state |= MMC_STATE_IS_SD;
+		}
+		else{
+			card->rca = mmc_alloc_rca(host, &first_rca);
+			cmd.opcode = MMC_SET_RELATIVE_ADDR;
+			cmd.arg = card->rca << 16;
+			cmd.flags = MMC_RSP_R1;
+		}
 
-		cmd.opcode = MMC_SET_RELATIVE_ADDR;
-		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1;
-
+		/* Sandisk say: should ignore ILLEGAL_COMMAND errors
+		 * as CMD{0,1,2} dont clear status and an SD probe can
+		 * upset MMC cards.
+		 */
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 		if (err != MMC_ERR_NONE)
-			mmc_card_set_dead(card);
+			if(err != MMC_ERR_INVALID)
+				mmc_card_set_dead(card);
+
+		if(is_sd){
+			card->rca = cmd.resp[0] >> 16;
+			printk("Card wants rca: %08x\n", cmd.resp[0]);
+			first_rca = card->rca;
+		}
 	}
 }
 
@@ -653,14 +780,16 @@
 
 static void mmc_setup(struct mmc_host *host)
 {
+	int err, is_sd;	
+	
 	if (host->ios.power_mode != MMC_POWER_ON) {
-		int err;
 		u32 ocr;
 
 		mmc_power_up(host);
 		mmc_idle_cards(host);
 
-		err = mmc_send_op_cond(host, 0, &ocr);
+		err = mmc_send_op_cond(host, 0, &ocr, SD_APP_OP_COND, &is_sd);
+
 		if (err != MMC_ERR_NONE)
 			return;
 
@@ -702,9 +831,18 @@
 	 * all get the idea that they should be ready for CMD2.
 	 * (My SanDisk card seems to need this.)
 	 */
-	mmc_send_op_cond(host, host->ocr, NULL);
+	 
+	/* Try SD cards first */
+	if(is_sd){
+		err = mmc_send_op_cond(host, host->ocr, NULL, SD_APP_OP_COND, NULL);
 
-	mmc_discover_cards(host);
+		if(err == MMC_ERR_NONE)
+			mmc_discover_cards(host, 1);
+	}
+		 
+	err = mmc_send_op_cond(host, host->ocr, NULL, MMC_SEND_OP_COND, NULL);
+	if(err == MMC_ERR_NONE)
+		mmc_discover_cards(host, 0);
 
 	/*
 	 * Ok, now switch to push-pull mode.

