diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/Kconfig linux-2.6.11-rc2-bk1-h1940/drivers/mmc/Kconfig
--- linux-2.6.11-rc2-bk1/drivers/mmc/Kconfig	2005-01-23 22:57:33.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/Kconfig	2005-01-26 20:43:20.000000000 +0100
@@ -60,4 +60,13 @@
 
 	  If unsure, say N.
 
+config MMC_S3C2410
+	tristate "Samsung S3C2410 Multimedia Card Interface support"
+	depends on ARCH_S3C2410 && MMC
+	help
+	  This selects the Samsung S3C2410 Multimedia Card Interface 
+	  support. 
+
+	  If unsure, say N.
+
 endmenu
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/Makefile linux-2.6.11-rc2-bk1-h1940/drivers/mmc/Makefile
--- linux-2.6.11-rc2-bk1/drivers/mmc/Makefile	2004-12-24 22:35:01.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/Makefile	2005-01-26 20:43:20.000000000 +0100
@@ -18,5 +18,6 @@
 obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
+obj-$(CONFIG_MMC_S3C2410)	+= s3c2410mci.o
 
 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/mmc_block.c linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc_block.c
--- linux-2.6.11-rc2-bk1/drivers/mmc/mmc_block.c	2005-01-23 22:57:33.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc_block.c	2005-01-26 20:48:49.000000000 +0100
@@ -3,6 +3,9 @@
  *
  * Copyright 2002 Hewlett-Packard Company
  *
+ *  SD-Card support:
+ *    Copyright (C) 2004 Thomas Kleffel, All Rights Reserved
+ *
  * Use consistent with the GNU GPL is permitted,
  * provided that this copyright notice is
  * preserved in its entirety in all copies and derived works.
@@ -30,11 +33,13 @@
 #include <linux/devfs_fs_kernel.h>
 
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#include "mmc.h"
 #include "mmc_queue.h"
 
 /*
@@ -165,11 +170,17 @@
 {
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
+	struct mmc_host *host = md->queue.card->host;
 	int ret;
 
 	if (mmc_card_claim_host(card))
 		goto cmd_err;
 
+	if((card->sd) && (host->flags & MMC_HOST_WIDEMODE) && (card->bus_width != 4)) {
+		if(sd_set_bus_width(host, card->rca, 4)) goto cmd_err;
+		card->bus_width=4;
+	}
+
 	do {
 		struct mmc_blk_request brq;
 		struct mmc_command cmd;
@@ -180,6 +191,7 @@
 
 		brq.cmd.arg = req->sector << 9;
 		brq.cmd.flags = MMC_RSP_R1;
+		brq.data.req = req;
 		brq.data.timeout_ns = card->csd.tacc_ns * 10;
 		brq.data.timeout_clks = card->csd.tacc_clks * 10;
 		brq.data.blksz_bits = md->block_bits;
@@ -188,6 +200,9 @@
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_R1B;
 
+		if(card->bus_width==4)
+			brq.data.flags |= MMC_DATA_WIDE;
+
 		if (rq_data_dir(req) == READ) {
 			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
 			brq.data.flags |= MMC_DATA_READ;
@@ -252,7 +267,7 @@
 			/*
 			 * The whole request completed successfully.
 			 */
-			add_disk_randomness(req->rq_disk);
+			//add_disk_randomness(req->rq_disk);
 			blkdev_dequeue_request(req);
 			end_that_request_last(req);
 		}
@@ -347,7 +362,7 @@
 		sprintf(md->disk->disk_name, "mmcblk%d", devidx);
 		sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
 
-		md->block_bits = card->csd.read_blkbits;
+		md->block_bits = card->csd.read_bl_len;
 
 		blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
 		set_capacity(md->disk, card->csd.capacity);
@@ -364,7 +379,7 @@
 
 	mmc_card_claim_host(card);
 	cmd.opcode = MMC_SET_BLOCKLEN;
-	cmd.arg = 1 << card->csd.read_blkbits;
+	cmd.arg = 1 << card->csd.read_bl_len;
 	cmd.flags = MMC_RSP_R1;
 	err = mmc_wait_for_cmd(card->host, &cmd, 5);
 	mmc_card_release_host(card);
@@ -383,12 +398,12 @@
 	struct mmc_blk_data *md;
 	int err;
 
-	if (card->csd.cmdclass & ~0x1ff)
+	if (card->csd.ccc & ~0x1ff)
 		return -ENODEV;
 
-	if (card->csd.read_blkbits < 9) {
+	if (card->csd.read_bl_len < 9) {
 		printk(KERN_WARNING "%s: read blocksize too small (%u)\n",
-			mmc_card_id(card), 1 << card->csd.read_blkbits);
+			mmc_card_id(card), 1 << card->csd.read_bl_len);
 		return -ENODEV;
 	}
 
@@ -402,7 +417,7 @@
 
 	printk(KERN_INFO "%s: %s %s %dKiB\n",
 		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
-		(card->csd.capacity << card->csd.read_blkbits) / 1024);
+		(card->csd.capacity << card->csd.read_bl_len) / 1024);
 
 	mmc_set_drvdata(card, md);
 	add_disk(md->disk);
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/mmc.c linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc.c
--- linux-2.6.11-rc2-bk1/drivers/mmc/mmc.c	2005-01-23 22:57:33.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc.c	2005-01-26 20:43:20.000000000 +0100
@@ -3,6 +3,9 @@
  *
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
  *
+ *  SD-Card support:
+ *    Copyright (C) 2004 Thomas Kleffel, All Rights Reserved
+ *
  * 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.
@@ -172,6 +175,34 @@
 
 EXPORT_SYMBOL(mmc_wait_for_cmd);
 
+static int mmc_send_app_cmd(struct mmc_host *host,  u16 rca)
+{
+	struct mmc_command cmd;
+
+	cmd.opcode = MMC_APP_CMD;
+	cmd.arg =((u32)rca)<<16;
+	cmd.flags = MMC_RSP_R1;
+
+	return mmc_wait_for_cmd(host, &cmd, 0);
+}
+
+int mmc_wait_for_acmd(struct mmc_host *host, u16 rca, struct mmc_command *cmd, int retries)
+{
+	int err;
+
+	do {
+		err = mmc_send_app_cmd(host, rca);
+		if(err != MMC_ERR_NONE) continue;
+
+		err = mmc_wait_for_cmd(host, cmd, 0);
+		if(err == MMC_ERR_NONE) break;
+
+	} while (retries--);
+
+	return err;
+}
+
+
 
 
 /**
@@ -274,6 +305,7 @@
 	}
 }
 
+#if 0 /* UNUSED */
 /*
  * Mask off any voltages we don't support and select
  * the lowest voltage
@@ -298,6 +330,7 @@
 
 	return ocr;
 }
+#endif
 
 #define UNSTUFF_BITS(resp,start,size)					\
 	({								\
@@ -322,48 +355,65 @@
 
 	memset(&card->cid, 0, sizeof(struct mmc_cid));
 
-	/*
-	 * The selection of the format here is guesswork based upon
-	 * information people have sent to date.
-	 */
-	switch (card->csd.mmca_vsn) {
-	case 0: /* MMC v1.? */
-	case 1: /* MMC v1.4 */
-		card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);
-		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.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
-		card->cid.prod_name[6]	= UNSTUFF_BITS(resp, 48, 8);
-		card->cid.hwrev		= UNSTUFF_BITS(resp, 44, 4);
-		card->cid.fwrev		= UNSTUFF_BITS(resp, 40, 4);
-		card->cid.serial	= UNSTUFF_BITS(resp, 16, 24);
-		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
-		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
-		break;
-
-	case 2: /* MMC v2.x ? */
-	case 3: /* MMC v3.x ? */
-		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.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
-		card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);
-		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
-		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
-		break;
-
-	default:
-		printk("%s: card has unknown MMCA version %d\n",
-			card->host->host_name, card->csd.mmca_vsn);
-		mmc_card_set_bad(card);
-		break;
+	if(card->sd) {
+		if(card->csd.csd_vers != SD_CSDV_1) {
+			DBG("%s: card has unknown SD-MMCA version %d\n", card->host->host_name, card->csd.spec_vers);
+			mmc_card_set_bad(card);
+		} else {
+			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.prod_name[5]  = 0;
+			card->cid.prod_name[6]  = 0;
+			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.month		= UNSTUFF_BITS(resp,  12,  4);
+			card->cid.year		= UNSTUFF_BITS(resp,   8,  4) + 2000;
+		}
+	} else {
+		switch (card->csd.csd_vers) {
+		case MMC_CSDV_1: /* MMC v1.? */
+		case MMC_CSDV_14: /* MMC v1.4 */
+			card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);
+			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.prod_name[5]	= UNSTUFF_BITS(resp,  56,  8);
+			card->cid.prod_name[6]	= UNSTUFF_BITS(resp,  48,  8);
+			card->cid.hwrev		= UNSTUFF_BITS(resp,  44,  4);
+			card->cid.fwrev		= UNSTUFF_BITS(resp,  40,  4);
+			card->cid.serial	= UNSTUFF_BITS(resp,  16, 24);
+			card->cid.month		= UNSTUFF_BITS(resp,  12,  4);
+			card->cid.year		= UNSTUFF_BITS(resp,   8,  4) + 1997;
+			break;
+
+		case MMC_CSDV_2: /* MMC v2.x ? */
+		case MMC_CSDV_3: /* MMC v3.x ? */
+			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.prod_name[5]	= UNSTUFF_BITS(resp,  56,  8);
+			card->cid.serial	= UNSTUFF_BITS(resp,  16, 32);
+			card->cid.month		= UNSTUFF_BITS(resp,  12,  4);
+			card->cid.year		= UNSTUFF_BITS(resp,   8,  4) + 1997;
+			break;
+
+		default:
+			printk(KERN_WARNING "%s: card has unknown MMC-MMCA version %d\n", card->host->host_name, card->csd.spec_vers);
+			mmc_card_set_bad(card);
+			break;
+		}
 	}
 }
 
@@ -373,37 +423,95 @@
 static void mmc_decode_csd(struct mmc_card *card)
 {
 	struct mmc_csd *csd = &card->csd;
-	unsigned int e, m, csd_struct;
+	unsigned int e, m;
 	u32 *resp = card->raw_csd;
 
-	/*
-	 * 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) {
-		printk("%s: unrecognised CSD structure version %d\n",
-			card->host->host_name, csd_struct);
-		mmc_card_set_bad(card);
-		return;
-	}
-
-	csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);
-	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);
+	if(card->sd) {
+		/*
+		* We only understand SD-CSD structure v1.0.
+		*/
+		csd->sd=1;
+		csd->csd_vers = UNSTUFF_BITS(resp, 126, 2);
+		if(csd->csd_vers != SD_CSDV_1) {
+			printk("%s: unrecognised SD-CSD structure version %d\n",
+				card->host->host_name, csd->csd_vers);
+			mmc_card_set_bad(card);
+			return;
+		}
+
+		csd->spec_vers 		= 0;
+		csd->taac		= UNSTUFF_BITS(resp, 112, 8);
+		csd->nsac		= UNSTUFF_BITS(resp, 104, 8);
+		csd->tran_speed		= UNSTUFF_BITS(resp,  96, 8);
+		csd->ccc		= UNSTUFF_BITS(resp,  84,12);
+		csd->read_bl_len	= UNSTUFF_BITS(resp,  80, 4);
+		csd->read_bl_partial	= UNSTUFF_BITS(resp,  79, 1);
+		csd->write_blk_misalign	= UNSTUFF_BITS(resp,  78, 1);
+		csd->read_blk_misalign	= UNSTUFF_BITS(resp,  77, 1);
+		csd->dsr_imp		= UNSTUFF_BITS(resp,  76, 1);
+		csd->c_size		= UNSTUFF_BITS(resp,  62,12);
+		csd->vdd_r_curr_min	= UNSTUFF_BITS(resp,  69, 3);
+		csd->vdd_r_curr_max	= UNSTUFF_BITS(resp,  56, 3);
+		csd->vdd_w_curr_min	= UNSTUFF_BITS(resp,  53, 3);
+		csd->vdd_w_curr_max	= UNSTUFF_BITS(resp,  50, 3);
+		csd->c_size_mult	= UNSTUFF_BITS(resp,  47, 3);
+		csd->erase.sd10.erase_blk_en	= UNSTUFF_BITS(resp,  46, 1);
+		csd->erase.sd10.erase_blk_size= UNSTUFF_BITS(resp,  39, 7);
+		csd->wp_grp_size	= UNSTUFF_BITS(resp,  32, 7);
+		csd->wp_grp_enable	= UNSTUFF_BITS(resp,  31, 1);
+		csd->r2w_factor		= UNSTUFF_BITS(resp,  26, 3);
+		csd->write_bl_len	= UNSTUFF_BITS(resp,  22, 4);
+		csd->write_bl_partial	= UNSTUFF_BITS(resp,  21, 1);
+		csd->file_format_grp	= UNSTUFF_BITS(resp,  15, 1);
+		csd->copy		= UNSTUFF_BITS(resp,  14, 1);
+		csd->perm_write_protect	= UNSTUFF_BITS(resp,  13, 1);
+		csd->tmp_write_protect	= UNSTUFF_BITS(resp,  12, 1);
+		csd->file_format	= UNSTUFF_BITS(resp,  10, 1);
+		csd->ecc		= UNSTUFF_BITS(resp,   1, 7);
+
+		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];
+
+		e = UNSTUFF_BITS(resp, 47, 3);
+		m = UNSTUFF_BITS(resp, 62, 12);
+		csd->capacity	  = (1 + m) << (e + 2);
+	} else {
+		/*
+		* We only understand MMC-CSD structure v1.1 and v2.
+		* v2 has extra information in bits 15, 11 and 10.
+		*/
+		csd->sd=0;
+		csd->csd_vers = UNSTUFF_BITS(resp, 126, 2);
+		if (csd->csd_vers != MMC_CSDV_14 && csd->csd_vers != MMC_CSDV_2) {
+			printk("%s: unrecognised MMC-CSD structure version %d\n",
+				card->host->host_name, csd->csd_vers);
+			mmc_card_set_bad(card);
+			return;
+		}
 
-	csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+		csd->spec_vers	 = UNSTUFF_BITS(resp, 122, 4);
+		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->ccc	  = 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_bl_len = UNSTUFF_BITS(resp, 80, 4);
+	}
 }
 
 /*
@@ -424,7 +532,7 @@
  * Allocate a new MMC card, and assign a unique RCA.
  */
 static struct mmc_card *
-mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca)
+mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, u8 sd, unsigned int *frca)
 {
 	struct mmc_card *card, *c;
 	unsigned int rca = *frca;
@@ -435,6 +543,7 @@
 
 	mmc_init_card(card, host);
 	memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid));
+	card->sd = sd;
 
  again:
 	list_for_each_entry(c, &host->cards, node)
@@ -456,6 +565,7 @@
 static void mmc_idle_cards(struct mmc_host *host)
 {
 	struct mmc_command cmd;
+	struct mmc_card *card;
 
 	cmd.opcode = MMC_GO_IDLE_STATE;
 	cmd.arg = 0;
@@ -463,9 +573,83 @@
 
 	mmc_wait_for_cmd(host, &cmd, 0);
 
-	mmc_delay(1);
+	//MMC_GO_IDLE_STATE resets all cards to bus width 1
+	list_for_each_entry(card, &host->cards, node) {
+		card->bus_width=1;
+	}
+
+
+	mmc_delay(100);
 }
 
+int sd_set_bus_width(struct mmc_host *host, u16 rca, u32 bus_width)
+{
+	struct mmc_command cmd;
+	int err;
+
+	cmd.opcode = MMC_ACMD_SD_SET_BUS_WIDTH;
+	cmd.flags  = MMC_RSP_R1;
+
+	switch(bus_width) {
+		case 1:	 cmd.arg = 00; break;
+		case 4:	 cmd.arg = 10; break;
+		default: return -EINVAL;
+	}
+
+	err = mmc_wait_for_acmd(host, rca, &cmd, 3);
+
+	if(err == MMC_ERR_TIMEOUT) {
+		printk(KERN_ERR "MMC: sd_set_bus_width timed out.\n");
+	} else if(err == MMC_ERR_BADCRC) {
+		printk(KERN_ERR "MMC: sd_set_bus_width yielded crc error.\n");
+	} else {
+		DBG("MMC: sd_app_op_cond done.\n");
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL(sd_set_bus_width);
+
+static int sd_app_op_cond(struct mmc_host *host, u16 rca, u32 parameter, u32 *response)
+{
+	struct mmc_command cmd;
+	int err;
+	int retries = 10;
+
+	cmd.opcode = MMC_ACMD_SD_APP_OP_COND;
+	cmd.arg = parameter;
+	cmd.flags = MMC_RSP_SHORT;
+
+	DBG("MMC: sd_app_op_cond to %08x\n",parameter);
+
+	while(retries--) {
+		err = mmc_wait_for_acmd(host, 0, &cmd, 0);
+		if(0 == (cmd.resp[0] & MMC_CARD_BUSY)) {
+			err=MMC_ERR_BUSY;
+			printk(KERN_ERR "MMC: sd_app_op_cond: at least one card is busy - trying again.\n");
+			mmc_delay(10);
+			continue;
+		}
+
+		if(err == MMC_ERR_NONE) {
+			if(response)*response = cmd.resp[0];
+			break;
+		}
+	}
+
+	if(err == MMC_ERR_TIMEOUT) {
+		printk(KERN_WARNING "MMC: sd_app_op_cond timed out. Probably no SD-Card here.\n");
+	} else if(err == MMC_ERR_BUSY) {
+		printk(KERN_ERR "MMC: sd_app_op_cond locked busy. Probably have broken SD-Card.\n");
+	} else {
+		DBG("MMC: sd_app_op_cond done. Results are: 0x%08x.\n",cmd.resp[0]);
+	}
+
+	return err;
+}
+
+
 /*
  * Apply power to the MMC stack.
  */
@@ -532,7 +716,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, u8 sd)
 {
 	struct mmc_card *card;
 	unsigned int first_rca = 1, err;
@@ -542,7 +726,7 @@
 
 		cmd.opcode = MMC_ALL_SEND_CID;
 		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R2;
+		cmd.flags = MMC_RSP_LONG; //HACK! CRC currently not implemented
 
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 		if (err == MMC_ERR_TIMEOUT) {
@@ -550,14 +734,13 @@
 			break;
 		}
 		if (err != MMC_ERR_NONE) {
-			printk(KERN_ERR "%s: error requesting CID: %d\n",
-				host->host_name, err);
+			printk(KERN_ERR "%s: error requesting CID: %d\n", host->host_name, err);
 			break;
 		}
 
 		card = mmc_find_card(host, cmd.resp);
 		if (!card) {
-			card = mmc_alloc_card(host, cmd.resp, &first_rca);
+			card = mmc_alloc_card(host, cmd.resp, sd, &first_rca);
 			if (IS_ERR(card)) {
 				err = PTR_ERR(card);
 				break;
@@ -574,6 +757,9 @@
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 		if (err != MMC_ERR_NONE)
 			mmc_card_set_dead(card);
+
+		//SD-Cards choose their adresses themselfes (yuck!)
+		if(card->sd) card->rca = (cmd.resp[0] >> 16);
 	}
 }
 
@@ -590,7 +776,7 @@
 
 		cmd.opcode = MMC_SEND_CSD;
 		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R2;
+		cmd.flags = MMC_RSP_LONG; 	//HACK: No CRC check as s3c-Core is broken
 
 		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
 		if (err != MMC_ERR_NONE) {
@@ -651,63 +837,22 @@
 	}
 }
 
+
 static void mmc_setup(struct mmc_host *host)
 {
-	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);
-		if (err != MMC_ERR_NONE)
-			return;
-
-		host->ocr = mmc_select_voltage(host, ocr);
-
-		/*
-		 * Since we're changing the OCR value, we seem to
-		 * need to tell some cards to go back to the idle
-		 * state.  We wait 1ms to give cards time to
-		 * respond.
-		 */
-		if (host->ocr)
-			mmc_idle_cards(host);
-	} else {
-		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-		host->ios.clock = host->f_min;
-		host->ops->set_ios(host, &host->ios);
-
-		/*
-		 * We should remember the OCR mask from the existing
-		 * cards, and detect the new cards OCR mask, combine
-		 * the two and re-select the VDD.  However, if we do
-		 * change VDD, we should do an idle, and then do a
-		 * full re-initialisation.  We would need to notify
-		 * drivers so that they can re-setup the cards as
-		 * well, while keeping their queues at bay.
-		 *
-		 * For the moment, we take the easy way out - if the
-		 * new cards don't like our currently selected VDD,
-		 * they drop off the bus.
-		 */
-	}
-
-	if (host->ocr == 0)
-		return;
-
-	/*
-	 * Send the selected OCR multiple times... until the cards
-	 * 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);
+	mmc_power_up(host);
+	mmc_idle_cards(host);
 
-	mmc_discover_cards(host);
+	// Wake and discover SD-Cards
+	sd_app_op_cond(host, 0, host->ocr_avail, NULL);
+	mmc_discover_cards(host, 1);
+
+	// Wake and discover MMC-Cards
+	mmc_send_op_cond(host, host->ocr_avail, NULL);
+	mmc_discover_cards(host, 0);
 
 	/*
-	 * Ok, now switch to push-pull mode.
+	 * switch to push-pull mode.
 	 */
 	host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
 	host->ops->set_ios(host, &host->ios);
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/mmc.h linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc.h
--- linux-2.6.11-rc2-bk1/drivers/mmc/mmc.h	2004-12-24 22:34:26.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc.h	2005-01-26 20:46:21.000000000 +0100
@@ -13,4 +13,5 @@
 void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
 int mmc_register_card(struct mmc_card *card);
 void mmc_remove_card(struct mmc_card *card);
+int sd_set_bus_width(struct mmc_host *host, u16 rca, u32 bus_width);
 #endif
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/mmc_sysfs.c linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc_sysfs.c
--- linux-2.6.11-rc2-bk1/drivers/mmc/mmc_sysfs.c	2004-12-24 22:35:01.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/mmc_sysfs.c	2005-01-26 20:43:20.000000000 +0100
@@ -3,6 +3,9 @@
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *
+ *  SD-Card support:
+ *    Copyright (C) 2004 Thomas Kleffel, All Rights Reserved
+ *
  * 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.
@@ -62,7 +65,7 @@
 	})
 
 	for (i = 0; i < 12; i++)
-		ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
+		ccc[i] = card->csd.ccc & (1 << i) ? '1' : '0';
 	ccc[12] = '\0';
 
 	i = 0;
@@ -170,8 +173,11 @@
 MMC_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_ATTR(bus_width, "%u\n", card->bus_width);
+MMC_ATTR(type, "%s\n", (card->sd?"SD":"MMC"));
 
 static struct device_attribute *mmc_dev_attributes[] = {
+	&dev_attr_bus_width,
 	&dev_attr_cid,
 	&dev_attr_csd,
 	&dev_attr_date,
@@ -181,6 +187,7 @@
 	&dev_attr_name,
 	&dev_attr_oemid,
 	&dev_attr_serial,
+	&dev_attr_type,
 };
 
 /*
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/s3c2410mci.c linux-2.6.11-rc2-bk1-h1940/drivers/mmc/s3c2410mci.c
--- linux-2.6.11-rc2-bk1/drivers/mmc/s3c2410mci.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/s3c2410mci.c	2005-01-26 20:49:40.000000000 +0100
@@ -0,0 +1,760 @@
+/*
+ *  linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver
+ *
+ *  Copyright (C) 2004 Thomas Kleffel, All Rights Reserved.
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/dma.h>
+#include <asm/dma-mapping.h>
+#include <asm/arch/dma.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware/amba.h>
+#include <asm/hardware/clock.h>
+#include <asm/mach/mmc.h>
+
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-gpio.h>
+
+//#define S3C2410SDI_DMA_BACKBUF
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(x...)       printk(KERN_DEBUG x)
+#else
+#define DBG(x...)       do { } while (0)
+#endif
+
+#include "s3c2410mci.h"
+
+#define DRIVER_NAME "mmci-s3c2410"
+#define PFX DRIVER_NAME ": "
+
+#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
+
+// #define KERN_DEBUG KERN_INFO
+
+typedef enum {
+	DMAP_READ,
+	DMAP_WRITE,
+} eDMAPurpose_t;
+
+static struct s3c2410_dma_client s3c2410sdi_dma_client = {
+	.name		= "s3c2410-sdi",
+};
+
+
+
+/*
+ * ISR for SDI Interface IRQ
+ * Communication between driver and ISR works as follows:
+ *   host->mrq 			points to current request
+ *   host->complete_what	tells the ISR when the request is considered done
+ *     COMPLETION_CMDSENT	  when the command was sent
+ *     COMPLETION_RSPFIN          when a response was received
+ *     COMPLETION_XFERFINISH	  when the data transfer is finished
+ *     COMPLETION_XFERFINISH_RSPFIN both of the above.
+ *   host->complete_request	is the completion-object the driver waits for
+ *
+ * 1) Driver sets up host->mrq and host->complete_what
+ * 2) Driver prepares the transfer
+ * 3) Driver enables interrupts
+ * 4) Driver starts transfer
+ * 5) Driver waits for host->complete_rquest
+ * 6) ISR checks for request status (errors and success)
+ * 6) ISR sets host->mrq->cmd->error and host->mrq->data->error
+ * 7) ISR completes host->complete_request
+ * 8) ISR disables interrupts
+ * 9) Driver wakes up and takes care of the request
+*/
+
+static irqreturn_t s3c2410sdi_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct s3c2410sdi_host *host;
+	u32 sdi_csta, sdi_dsta, sdi_dcnt;
+	u32 sdi_cclear, sdi_dclear;
+	unsigned long iflags;
+
+	host = (struct s3c2410sdi_host *)dev_id;
+
+	//Check for things not supposed to happen
+	if(!host) return IRQ_HANDLED;
+	
+	sdi_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
+	sdi_dsta 	= readl(host->base + S3C2410_SDIDSTA);
+	sdi_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
+	
+	DBG(PFX "IRQ csta=0x%08x dsta=0x%08x dcnt:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt);
+		
+	spin_lock_irqsave( &host->complete_lock, iflags);
+	
+	if( host->complete_what==COMPLETION_NONE ) {
+		goto clear_imask;
+	}
+	
+	if(!host->mrq) { 
+		goto clear_imask;
+	}
+
+	
+	sdi_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
+	sdi_dsta 	= readl(host->base + S3C2410_SDIDSTA);
+	sdi_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
+	sdi_cclear	= 0;
+	sdi_dclear	= 0;
+	
+	
+	if(sdi_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
+		host->mrq->cmd->error = MMC_ERR_TIMEOUT;
+		goto transfer_closed;
+	}
+
+	if(sdi_csta & S3C2410_SDICMDSTAT_CMDSENT) {
+		if(host->complete_what == COMPLETION_CMDSENT) {
+			host->mrq->cmd->error = MMC_ERR_NONE;
+			goto transfer_closed;
+		}
+
+		sdi_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
+	}
+
+	if(sdi_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
+		if(host->mrq->cmd->flags & MMC_RSP_CRC) {
+			host->mrq->cmd->error = MMC_ERR_BADCRC;
+			goto transfer_closed;
+		}
+
+		sdi_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
+	}
+
+	if(sdi_csta & S3C2410_SDICMDSTAT_RSPFIN) {
+		if(host->complete_what == COMPLETION_RSPFIN) {
+			host->mrq->cmd->error = MMC_ERR_NONE;
+			goto transfer_closed;
+		}
+
+		if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
+			host->mrq->cmd->error = MMC_ERR_NONE;
+			host->complete_what = COMPLETION_XFERFINISH;
+		}
+
+		sdi_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
+	}
+
+	if(sdi_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
+		host->mrq->cmd->error = MMC_ERR_NONE;
+		host->mrq->data->error = MMC_ERR_FIFO;
+		goto transfer_closed;
+	}
+
+	if(sdi_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
+		host->mrq->cmd->error = MMC_ERR_NONE;
+		host->mrq->data->error = MMC_ERR_BADCRC;
+		goto transfer_closed;
+	}
+
+	if(sdi_dsta & S3C2410_SDIDSTA_CRCFAIL) {
+		host->mrq->cmd->error = MMC_ERR_NONE;
+		host->mrq->data->error = MMC_ERR_BADCRC;
+		goto transfer_closed;
+	}
+
+	if(sdi_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
+		host->mrq->cmd->error = MMC_ERR_NONE;
+		host->mrq->data->error = MMC_ERR_TIMEOUT;
+		goto transfer_closed;
+	}
+
+	if(sdi_dsta & S3C2410_SDIDSTA_XFERFINISH) {
+		if(host->complete_what == COMPLETION_XFERFINISH) {
+			host->mrq->cmd->error = MMC_ERR_NONE;
+			host->mrq->data->error = MMC_ERR_NONE;
+			goto transfer_closed;
+		}
+
+		if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
+			host->mrq->data->error = MMC_ERR_NONE;
+			host->complete_what = COMPLETION_RSPFIN;
+		}
+
+		sdi_dclear |= S3C2410_SDIDSTA_XFERFINISH;
+	}
+
+	writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);
+	writel(sdi_dclear, host->base + S3C2410_SDIDSTA);
+
+	spin_unlock_irqrestore( &host->complete_lock, iflags);
+	DBG(PFX "IRQ still waiting.\n");
+	return IRQ_HANDLED;
+
+
+transfer_closed:
+	host->complete_what = COMPLETION_NONE;
+	complete(&host->complete_request);
+	writel(0, host->base + S3C2410_SDIIMSK);
+	spin_unlock_irqrestore( &host->complete_lock, iflags);
+	DBG(PFX "IRQ transfer closed.\n");
+	return IRQ_HANDLED;
+	
+clear_imask:
+	writel(0, host->base + S3C2410_SDIIMSK);
+	spin_unlock_irqrestore( &host->complete_lock, iflags);
+	DBG(PFX "IRQ clear imask.\n");
+	return IRQ_HANDLED;
+
+}
+
+
+/*
+ * ISR for the CardDetect Pin
+*/
+
+static irqreturn_t s3c2410sdi_irq_cd(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)dev_id;
+	mmc_detect_change(host->mmc);
+
+	return IRQ_HANDLED;
+}
+
+
+
+void s3c2410sdi_dma_done_callback(s3c2410_dma_chan_t *dma_ch, void *buf_id,
+	int size, s3c2410_dma_buffresult_t result)
+{	unsigned long iflags;
+	u32 sdi_csta, sdi_dsta,sdi_dcnt;
+	struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)buf_id;
+	
+	sdi_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
+	sdi_dsta 	= readl(host->base + S3C2410_SDIDSTA);
+	sdi_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
+	
+	DBG(PFX "DMAD csta=0x%08x dsta=0x%08x dcnt:0x%08x result:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt, result);
+	
+	spin_lock_irqsave( &host->complete_lock, iflags);
+	
+	if(!host->mrq) goto out;
+	if(!host->mrq->data) goto out;
+	
+	
+	sdi_csta 	= readl(host->base + S3C2410_SDICMDSTAT);
+	sdi_dsta 	= readl(host->base + S3C2410_SDIDSTA);
+	sdi_dcnt 	= readl(host->base + S3C2410_SDIDCNT);
+		
+	if( result!=S3C2410_RES_OK ) {
+		goto fail_request;
+	}
+	
+	
+	if(host->mrq->data->flags & MMC_DATA_READ) {
+		if( sdi_dcnt>0 ) {
+			goto fail_request;
+		}
+	}
+	
+out:	
+	complete(&host->complete_dma);
+	spin_unlock_irqrestore( &host->complete_lock, iflags);
+	return;
+
+
+fail_request:
+	host->mrq->data->error = MMC_ERR_DMA;
+	host->complete_what = COMPLETION_NONE;
+	complete(&host->complete_dma);
+	complete(&host->complete_request);
+	writel(0, host->base + S3C2410_SDIIMSK);
+	goto out;
+
+}
+
+
+void s3c2410sdi_dma_setup(struct s3c2410sdi_host *host, eDMAPurpose_t purpose) {
+	s3c2410_dmasrc_t source;
+
+	switch(purpose) {
+		default:
+		case DMAP_READ:
+			source  = S3C2410_DMASRC_HW;
+			break;
+
+		case DMAP_WRITE:
+			source  = S3C2410_DMASRC_MEM;
+			break;
+	}
+
+	s3c2410_dma_devconfig(host->dma, source, 3, host->mem->start + S3C2410_SDIDATA);
+	s3c2410_dma_config(host->dma, 4, (1<<23) | (2<<24));
+	s3c2410_dma_set_buffdone_fn(host->dma, s3c2410sdi_dma_done_callback);
+	s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
+}
+
+static void s3c2410sdi_request(struct mmc_host *mmc, struct mmc_request *mrq) {
+ 	struct s3c2410sdi_host *host = mmc_priv(mmc);
+	u32 sdi_carg, sdi_ccon, sdi_timer;
+	u32 sdi_bsize, sdi_dcon, sdi_imsk;
+
+	DBG(KERN_DEBUG PFX "request: [CMD] opcode:0x%02x arg:0x%08x flags:%x retries:%u\n",
+		mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags, mrq->cmd->retries);
+
+
+	sdi_ccon = mrq->cmd->opcode & S3C2410_SDICMDCON_INDEX;
+	sdi_ccon|= S3C2410_SDICMDCON_SENDERHOST;
+	sdi_ccon|= S3C2410_SDICMDCON_CMDSTART;
+
+	sdi_carg = mrq->cmd->arg;
+
+	//FIXME: Timer value ?!
+	sdi_timer= 0xF000;
+
+	sdi_bsize= 0;
+	sdi_dcon = 0;
+	sdi_imsk = 0;
+
+	//enable interrupts for transmission errors
+	sdi_imsk |= S3C2410_SDIIMSK_RESPONSEND;
+	sdi_imsk |= S3C2410_SDIIMSK_CRCSTATUS;
+
+
+	host->complete_what = COMPLETION_CMDSENT;
+
+	if (mrq->cmd->flags & MMC_RSP_MASK) {
+		host->complete_what = COMPLETION_RSPFIN;
+
+		sdi_ccon |= S3C2410_SDICMDCON_WAITRSP;
+		sdi_imsk |= S3C2410_SDIIMSK_CMDTIMEOUT;
+
+	} else {
+		//We need the CMDSENT-Interrupt only if we want are not waiting
+		//for a response
+		sdi_imsk |= S3C2410_SDIIMSK_CMDSENT;
+	}
+
+	if(mrq->cmd->flags & MMC_RSP_LONG) {
+		sdi_ccon|= S3C2410_SDICMDCON_LONGRSP;
+	}
+
+	if(mrq->cmd->flags & MMC_RSP_CRC) {
+		sdi_imsk |= S3C2410_SDIIMSK_RESPONSECRC;
+	}
+
+
+	if (mrq->data) {
+		host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
+
+
+
+		sdi_bsize = (1 << mrq->data->blksz_bits);
+
+		sdi_dcon  = (mrq->data->blocks & S3C2410_SDIDCON_BLKNUM_MASK);
+		sdi_dcon |= S3C2410_SDIDCON_DMAEN;
+
+		sdi_imsk |= S3C2410_SDIIMSK_FIFOFAIL;
+		sdi_imsk |= S3C2410_SDIIMSK_DATACRC;
+		sdi_imsk |= S3C2410_SDIIMSK_DATATIMEOUT;
+		sdi_imsk |= S3C2410_SDIIMSK_DATAFINISH;
+		sdi_imsk |= 0xFFFFFFE0;
+
+		DBG(PFX "request: [DAT] bsize:%u blocks:%u bytes:%u\n",
+			sdi_bsize, mrq->data->blocks, mrq->data->blocks * sdi_bsize);
+
+		if(mrq->data->flags & MMC_DATA_WIDE) {
+			sdi_dcon |= S3C2410_SDIDCON_WIDEBUS;
+		}
+
+		if(!(mrq->data->flags & MMC_DATA_STREAM)) {
+			sdi_dcon |= S3C2410_SDIDCON_BLOCKMODE;
+		}
+
+		if(mrq->data->flags & MMC_DATA_WRITE) {
+			sdi_dcon |= S3C2410_SDIDCON_TXAFTERRESP;
+			sdi_dcon |= S3C2410_SDIDCON_XFER_TXSTART;
+			s3c2410sdi_dma_setup(host, DMAP_WRITE);
+#ifdef S3C2410SDI_DMA_BACKBUF			
+			memcpy(host->dmabuf_log, mrq->data->req->buffer, mrq->data->blocks * sdi_bsize);
+#endif
+		}
+
+		if(mrq->data->flags & MMC_DATA_READ) {
+			sdi_dcon |= S3C2410_SDIDCON_RXAFTERCMD;
+			sdi_dcon |= S3C2410_SDIDCON_XFER_RXSTART;
+			s3c2410sdi_dma_setup(host, DMAP_READ);
+		}
+		
+		
+
+		//start DMA
+#ifdef S3C2410SDI_DMA_BACKBUF
+		s3c2410_dma_enqueue(host->dma, (void *) host,
+			host->dmabuf_phys,
+			(mrq->data->blocks << mrq->data->blksz_bits) );
+#else
+		s3c2410_dma_enqueue(host->dma, (void *) host,
+			virt_to_phys(mrq->data->req->buffer),
+			(mrq->data->blocks << mrq->data->blksz_bits) );
+#endif
+	}
+
+	host->mrq = mrq;
+
+	init_completion(&host->complete_request);
+	init_completion(&host->complete_dma);
+
+	//Clear command and data status registers
+	writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
+	writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
+
+	// Setup SDI controller
+	writel(sdi_bsize,host->base + S3C2410_SDIBSIZE);
+	writel(sdi_timer,host->base + S3C2410_SDITIMER);
+	writel(sdi_imsk,host->base + S3C2410_SDIIMSK);
+
+	// Setup SDI command argument and data control
+	writel(sdi_carg, host->base + S3C2410_SDICMDARG);
+	writel(sdi_dcon, host->base + S3C2410_SDIDCON);
+
+	// This initiates transfer
+	writel(sdi_ccon, host->base + S3C2410_SDICMDCON);
+
+	// Wait for transfer to complete
+	wait_for_completion(&host->complete_request);
+	DBG("[CMD] request complete.\n");
+	if(mrq->data) {
+		wait_for_completion(&host->complete_dma);
+		DBG("[DAT] DMA complete.\n");
+	}
+	
+	// Wait for DMA to complete
+//	if(mrq->data) wait_for_completion(&host->complete_dma);
+
+	//Cleanup controller
+	writel(0, host->base + S3C2410_SDICMDARG);
+	writel(0, host->base + S3C2410_SDIDCON);
+	writel(0, host->base + S3C2410_SDICMDCON);
+	writel(0, host->base + S3C2410_SDIIMSK);
+
+	// Read response
+	mrq->cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
+	mrq->cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
+	mrq->cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
+	mrq->cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
+
+	host->mrq = NULL;
+
+	DBG(PFX "request done.\n");
+
+	// If we have no data transfer we are finished here
+	if (!mrq->data) goto request_done;
+
+	// Calulate the amout of bytes transfer, but only if there was
+	// no error
+	if(mrq->data->error == MMC_ERR_NONE) {
+		mrq->data->bytes_xfered = (mrq->data->blocks << mrq->data->blksz_bits);
+		if(mrq->data->flags & MMC_DATA_READ);
+#ifdef S3C2410SDI_DMA_BACKBUF
+		memcpy(mrq->data->req->buffer, host->dmabuf_log, mrq->data->bytes_xfered);
+#endif
+	} else {
+		mrq->data->bytes_xfered = 0;
+	}
+
+	// If we had an error while transfering data we flush the
+	// DMA channel to clear out any garbage
+	if(mrq->data->error != MMC_ERR_NONE) {
+		s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+		DBG(PFX "flushing DMA.\n");		
+	}
+	// Issue stop command
+	if(mrq->data->stop) mmc_wait_for_cmd(mmc, mrq->data->stop, 3);
+
+
+request_done:
+
+	mrq->done(mrq);
+}
+
+static void s3c2410sdi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) {
+	struct s3c2410sdi_host *host = mmc_priv(mmc);
+	u32 sdi_psc, sdi_con;
+
+	//Set power
+	sdi_con = readl(host->base + S3C2410_SDICON);
+	switch(ios->power_mode) {
+		case MMC_POWER_ON:
+		case MMC_POWER_UP:
+			s3c2410_gpio_setpin(S3C2410_GPA17, 1); // card power on
+
+			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
+			s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
+			s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
+			s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+			s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
+			s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
+
+			sdi_con|= S3C2410_SDICON_FIFORESET;
+			break;
+
+		case MMC_POWER_OFF:
+		default:
+			s3c2410_gpio_setpin(S3C2410_GPA17, 0); // card power off
+
+			s3c2410_gpio_setpin(S3C2410_GPE5, 0);
+			s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);
+			break;
+	}
+
+	//Set clock
+	for(sdi_psc=0;sdi_psc<255;sdi_psc++) {
+		if( (clk_get_rate(host->clk) / (2*(sdi_psc+1))) <= ios->clock) break;
+	}
+
+	if(sdi_psc > 255) sdi_psc = 255;
+	writel(sdi_psc, host->base + S3C2410_SDIPRE);
+
+	//Set CLOCK_ENABLE
+	if(ios->clock) 	sdi_con |= S3C2410_SDICON_CLOCKTYPE;
+	else		sdi_con &=~S3C2410_SDICON_CLOCKTYPE;
+
+	writel(sdi_con, host->base + S3C2410_SDICON);
+}
+
+static struct mmc_host_ops s3c2410sdi_ops = {
+	.request	= s3c2410sdi_request,
+	.set_ios	= s3c2410sdi_set_ios,
+};
+
+static int s3c2410sdi_probe(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct mmc_host 	*mmc;
+	struct s3c2410sdi_host 	*host;
+
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct s3c2410sdi_host), dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto probe_out;
+	}
+
+	host = mmc_priv(mmc);
+
+	spin_lock_init( &host->complete_lock );
+	host->complete_what 	= COMPLETION_NONE;
+	host->mmc 		= mmc;
+	host->dma		= S3C2410SDI_DMA;
+	host->irq_cd		= IRQ_EINT2;
+
+
+	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!host->mem) {
+		printk(KERN_INFO PFX "failed to get io memory region resouce.\n");
+		ret = -ENOENT;
+		goto probe_free_host;
+	}
+
+	host->mem = request_mem_region(host->mem->start,
+		RESSIZE(host->mem), pdev->name);
+
+	if (!host->mem) {
+		printk(KERN_INFO PFX "failed to request io memory region.\n");
+		ret = -ENOENT;
+		goto probe_free_host;
+	}
+
+	host->base = ioremap(host->mem->start, RESSIZE(host->mem));
+	if (host->base == 0) {
+		printk(KERN_INFO PFX "failed to ioremap() io memory region.\n");
+		ret = -EINVAL;
+		goto probe_free_mem_region;
+	}
+
+	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq == 0) {
+		printk(KERN_INFO PFX "failed to get interrupt resouce.\n");
+		ret = -EINVAL;
+		goto probe_iounmap;
+	}
+
+	if(request_irq(host->irq, s3c2410sdi_irq, 0, DRIVER_NAME, host)) {
+		printk(KERN_INFO PFX "failed to request sdi interrupt.\n");
+		ret = -ENOENT;
+		goto probe_iounmap;
+	}
+
+	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);
+	set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
+
+	if(request_irq(host->irq_cd, s3c2410sdi_irq_cd, 0, DRIVER_NAME, host)) {
+		printk(KERN_WARNING PFX "failed to request card detect interrupt.\n" );
+		ret = -ENOENT;
+		goto probe_free_irq;
+	}
+
+	if(s3c2410_dma_request(S3C2410SDI_DMA, &s3c2410sdi_dma_client, NULL)) {
+		printk(KERN_WARNING PFX "unable to get DMA channel.\n" );
+		ret = -EBUSY;
+		goto probe_free_irq_cd;
+	}
+
+	host->clk = clk_get(dev, "sdi");
+	if (IS_ERR(host->clk)) {
+		printk(KERN_INFO PFX "failed to find clock source.\n");
+		ret = PTR_ERR(host->clk);
+		host->clk = NULL;
+		goto probe_free_host;
+	}
+
+	if((ret = clk_use(host->clk))) {
+		printk(KERN_INFO PFX "failed to use clock source.\n");
+		goto clk_free;
+	}
+
+	if((ret = clk_enable(host->clk))) {
+		printk(KERN_INFO PFX "failed to enable clock source.\n");
+		goto clk_unuse;
+	}
+
+
+	mmc->ops 	= &s3c2410sdi_ops;
+	mmc->ocr_avail	= MMC_VDD_32_33;
+	mmc->flags      = MMC_HOST_WIDEMODE;
+	mmc->f_min 	= clk_get_rate(host->clk) / 512;
+	mmc->f_max 	= clk_get_rate(host->clk) / 2;
+
+
+	//HACK: There seems to be a hardware bug in TomTom GO.
+	if(mmc->f_max>3000000) mmc->f_max=3000000;
+
+
+	/*
+	 * Since we only have a 16-bit data length register, we must
+	 * ensure that we don't exceed 2^16-1 bytes in a single request.
+	 * Choose 64 (512-byte) sectors as the limit.
+	 */
+	mmc->max_sectors = 64;
+
+	/*
+	 * Set the maximum segment size.  Since we aren't doing DMA
+	 * (yet) we are only limited by the data length register.
+	 */
+
+	mmc->max_seg_size = mmc->max_sectors << 9;
+#ifdef S3C2410SDI_DMA_BACKBUF	
+	host->dmabuf_log = dma_alloc_coherent(NULL, mmc->max_seg_size ,&host->dmabuf_phys, GFP_KERNEL|GFP_DMA);
+	
+	if(!host->dmabuf_log) {
+		printk(KERN_INFO PFX "failed to allocate DMA buffer.\n");
+		goto clk_disable;
+	}
+	
+	host->dmabuf_size = mmc->max_seg_size;
+	
+	printk(KERN_INFO PFX "probe: mapped sdi_base=%p irq=%u irq_cd=%u dma=%u dmabuf_l=%p dmabuf_p=%p.\n", 
+		host->base, host->irq, host->irq_cd, host->dma, host->dmabuf_log, host->dmabuf_phys);
+#else
+	printk(KERN_INFO PFX "probe: mapped sdi_base=%p irq=%u irq_cd=%u dma=%u.\n", 
+		host->base, host->irq, host->irq_cd, host->dma);
+#endif	
+	if((ret = mmc_add_host(mmc))) {
+		printk(KERN_INFO PFX "failed to add mmc host.\n");
+		goto free_dmabuf;
+	}
+
+	dev_set_drvdata(dev, mmc);
+
+	printk(KERN_INFO PFX "initialisation done.\n");
+	return 0;
+	
+ free_dmabuf:
+#ifdef S3C2410SDI_DMA_BACKBUF
+ 	dma_free_coherent(NULL, host->dmabuf_size, host->dmabuf_log, host->dmabuf_phys);
+#endif
+
+	clk_disable(host->clk);
+
+ clk_unuse:
+	clk_unuse(host->clk);
+
+ clk_free:
+	clk_put(host->clk);
+
+ probe_free_irq_cd:
+ 	free_irq(host->irq_cd, host);
+
+ probe_free_irq:
+ 	free_irq(host->irq, host);
+
+ probe_iounmap:
+	iounmap(host->base);
+
+ probe_free_mem_region:
+	release_mem_region(host->mem->start, RESSIZE(host->mem));
+
+ probe_free_host:
+	mmc_free_host(mmc);
+ probe_out:
+	return ret;
+}
+
+static int s3c2410sdi_remove(struct device *dev)
+{
+	struct mmc_host 	*mmc  = dev_get_drvdata(dev);
+	struct s3c2410sdi_host 	*host = mmc_priv(mmc);
+
+	mmc_remove_host(mmc);
+#ifdef S3C2410SDI_DMA_BACKBUF
+ 	dma_free_coherent(NULL, host->dmabuf_size, host->dmabuf_log, host->dmabuf_phys);
+#endif
+	clk_disable(host->clk);
+	clk_unuse(host->clk);
+	clk_put(host->clk);
+ 	free_irq(host->irq_cd, host);
+ 	free_irq(host->irq, host);
+	iounmap(host->base);
+	release_mem_region(host->mem->start, RESSIZE(host->mem));
+	mmc_free_host(mmc);
+
+	return 0;
+}
+
+static struct device_driver s3c2410sdi_driver =
+{
+        .name           = "s3c2410-sdi",
+        .bus            = &platform_bus_type,
+        .probe          = s3c2410sdi_probe,
+        .remove         = s3c2410sdi_remove,
+};
+
+static int __init s3c2410sdi_init(void)
+{
+	return driver_register(&s3c2410sdi_driver);
+}
+
+static void __exit s3c2410sdi_exit(void)
+{
+	driver_unregister(&s3c2410sdi_driver);
+}
+
+module_init(s3c2410sdi_init);
+module_exit(s3c2410sdi_exit);
+
+MODULE_DESCRIPTION("Samsung S3C2410 Multimedia Card Interface driver");
+MODULE_LICENSE("GPL");
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/drivers/mmc/s3c2410mci.h linux-2.6.11-rc2-bk1-h1940/drivers/mmc/s3c2410mci.h
--- linux-2.6.11-rc2-bk1/drivers/mmc/s3c2410mci.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/drivers/mmc/s3c2410mci.h	2005-01-26 20:43:20.000000000 +0100
@@ -0,0 +1,45 @@
+/*
+ *  linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver
+ *
+ *  Copyright (C) 2004 Thomas Kleffel, All Rights Reserved.
+ *
+ * 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.
+ */
+
+struct clk;
+
+//FIXME: DMA Resource management ?!
+#define S3C2410SDI_DMA 0
+
+enum s3c2410sdi_waitfor {
+	COMPLETION_NONE,
+	COMPLETION_CMDSENT,
+	COMPLETION_RSPFIN,
+	COMPLETION_XFERFINISH,
+	COMPLETION_XFERFINISH_RSPFIN,
+};
+
+struct s3c2410sdi_host {
+	struct mmc_host		*mmc;
+
+	struct resource		*mem;
+	struct clk		*clk;
+	void __iomem		*base;
+	int			irq;
+	int			irq_cd;
+	int			dma;
+#ifdef S3C2410SDI_DMA_BACKBUF
+	dma_addr_t		 dmabuf_phys;
+	void			*dmabuf_log;
+	unsigned int		 dmabuf_size;
+#endif
+	
+	struct mmc_request	*mrq;
+
+	spinlock_t		complete_lock;
+	struct completion	complete_request;
+	struct completion	complete_dma;
+	enum s3c2410sdi_waitfor	complete_what;
+};
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/include/linux/mmc/card.h linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/card.h
--- linux-2.6.11-rc2-bk1/include/linux/mmc/card.h	2004-12-24 22:35:24.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/card.h	2005-01-25 22:54:58.000000000 +0100
@@ -24,12 +24,55 @@
 };
 
 struct mmc_csd {
-	unsigned char		mmca_vsn;
-	unsigned short		cmdclass;
+	u8  sd;
+	u8  csd_vers;
+	u8  spec_vers;
+	u8  taac;
+	u8  nsac;
+	u16 ccc;
+	u8  tran_speed;
+	u8  read_bl_len;
+	u8  read_bl_partial;
+	u8  write_blk_misalign;
+	u8  read_blk_misalign;
+	u8  dsr_imp;
+	u16 c_size;
+	u8  vdd_r_curr_min;
+	u8  vdd_r_curr_max;
+	u8  vdd_w_curr_min;
+	u8  vdd_w_curr_max;
+	u8  c_size_mult;
+	union {
+		struct { /* MMC system specification version 3.1 */
+			u8  erase_grp_size;
+			u8  erase_grp_mult;
+		} mmc31;
+		struct { /* MMC system specification version 2.2 */
+			u8  sector_size;
+			u8  erase_grp_size;
+		} mmc22;
+		struct { /* SD Version 1.0 */
+			u8  erase_blk_en;
+			u8  erase_blk_size;
+		} sd10;
+	} erase;
+
+	u8  wp_grp_size;
+	u8  wp_grp_enable;
+	u8  default_ecc;
+	u8  r2w_factor;
+	u8  write_bl_len;
+	u8  write_bl_partial;
+	u8  file_format_grp;
+	u8  copy;
+	u8  perm_write_protect;
+	u8  tmp_write_protect;
+	u8  file_format;
+	u8  ecc;
+
 	unsigned short		tacc_clks;
 	unsigned int		tacc_ns;
 	unsigned int		max_dtr;
-	unsigned int		read_blkbits;
 	unsigned int		capacity;
 };
 
@@ -42,8 +85,10 @@
 	struct list_head	node;		/* node in hosts devices list */
 	struct mmc_host		*host;		/* the host this device belongs to */
 	struct device		dev;		/* the device */
+	unsigned char		sd;
 	unsigned int		rca;		/* relative card address of device */
 	unsigned int		state;		/* (our) card state */
+	u8			bus_width;	/* bus_width the card is set to */
 #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 */
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/include/linux/mmc/host.h linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/host.h
--- linux-2.6.11-rc2-bk1/include/linux/mmc/host.h	2004-12-24 22:34:58.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/host.h	2005-01-25 23:00:14.000000000 +0100
@@ -61,12 +61,17 @@
 struct mmc_card;
 struct device;
 
+#define MMC_HOST_WIDEMODE	1
+
+#define MMC_HOST_WIDEMODE	1
+
 struct mmc_host {
 	struct device		*dev;
 	struct mmc_host_ops	*ops;
 	unsigned int		f_min;
 	unsigned int		f_max;
 	u32			ocr_avail;
+	u32			flags;
 	char			host_name[8];
 
 	/* host specific block data */
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/include/linux/mmc/mmc.h linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/mmc.h
--- linux-2.6.11-rc2-bk1/include/linux/mmc/mmc.h	2005-01-23 22:57:45.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/mmc.h	2005-01-24 00:43:42.000000000 +0100
@@ -47,6 +47,8 @@
 #define MMC_ERR_FIFO	3
 #define MMC_ERR_FAILED	4
 #define MMC_ERR_INVALID	5
+#define MMC_ERR_BUSY	6
+#define MMC_ERR_DMA	7
 
 	struct mmc_data		*data;		/* data segment associated with cmd */
 	struct mmc_request	*mrq;		/* assoicated request */
@@ -63,6 +65,7 @@
 #define MMC_DATA_WRITE	(1 << 8)
 #define MMC_DATA_READ	(1 << 9)
 #define MMC_DATA_STREAM	(1 << 10)
+#define MMC_DATA_WIDE	(1 << 11)
 
 	unsigned int		bytes_xfered;
 
@@ -71,6 +74,8 @@
 
 	unsigned int		sg_len;		/* size of scatter list */
 	struct scatterlist	*sg;		/* I/O scatter list */
+
+	struct request		*req;
 };
 
 struct mmc_request {
diff -X dontdiff -Nur linux-2.6.11-rc2-bk1/include/linux/mmc/protocol.h linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/protocol.h
--- linux-2.6.11-rc2-bk1/include/linux/mmc/protocol.h	2004-12-24 22:35:50.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/include/linux/mmc/protocol.h	2005-01-25 22:54:58.000000000 +0100
@@ -76,6 +76,9 @@
 #define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
 #define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1b */
 
+#define MMC_ACMD_SD_APP_OP_COND  41   /* ????  op conds		 ??? */
+#define MMC_ACMD_SD_SET_BUS_WIDTH 6   /* ????  00=1 10=4	 ??? */
+
 /*
   MMC status in R1
   Type
@@ -118,7 +121,8 @@
 /* These are unpacked versions of the actual responses */
 
 struct _mmc_csd {
-	u8  csd_structure;
+	u8  sd;
+	u8  csd_vers;
 	u8  spec_vers;
 	u8  taac;
 	u8  nsac;
@@ -139,11 +143,15 @@
 		struct { /* MMC system specification version 3.1 */
 			u8  erase_grp_size;
 			u8  erase_grp_mult;
-		} v31;
+		} mmc31;
 		struct { /* MMC system specification version 2.2 */
 			u8  sector_size;
 			u8  erase_grp_size;
-		} v22;
+		} mmc22;
+		struct { /* SD Version 1.0 */
+			u8  erase_blk_en;
+			u8  erase_blk_size;
+		} sd10;
 	} erase;
 	u8  wp_grp_size;
 	u8  wp_grp_enable;
@@ -159,6 +167,13 @@
 	u8  ecc;
 };
 
+#define SD_CSDV_1	0
+
+#define MMC_CSDV_1	0
+#define MMC_CSDV_14	1
+#define MMC_CSDV_2	2
+#define MMC_CSDV_3	3
+
 #define MMC_VDD_145_150	0x00000001	/* VDD voltage 1.45 - 1.50 */
 #define MMC_VDD_150_155	0x00000002	/* VDD voltage 1.50 - 1.55 */
 #define MMC_VDD_155_160	0x00000004	/* VDD voltage 1.55 - 1.60 */
--- linux-2.6.11-rc2-bk1/arch/arm/mach-s3c2410/mach-h1940.c		2005-01-26 21:16:48.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/arch/arm/mach-s3c2410/mach-h1940.c	2005-01-25 23:46:51.000000000 +0100
@@ -221,6 +221,7 @@
 	&s3c_device_wdt,
 	&s3c_device_i2c,
 	&s3c_device_iis,
+	&s3c_device_sdi,
 	&s3c_device_usbgadget,
 };
 
--- linux-2.6.11-rc2-bk1/include/asm-arm/arch-s3c2410/regs-sdi.h	2004-12-24 22:33:49.000000000 +0100
+++ linux-2.6.11-rc2-bk1-h1940/include/asm-arm/arch-s3c2410/regs-sdi.h	2005-01-25 22:54:58.000000000 +0100
@@ -47,7 +47,8 @@
 #define S3C2410_SDICMDCON_LONGRSP     (1<<10)
 #define S3C2410_SDICMDCON_WAITRSP     (1<<9)
 #define S3C2410_SDICMDCON_CMDSTART    (1<<8)
-#define S3C2410_SDICMDCON_INDEX       (0xff)
+#define S3C2410_SDICMDCON_SENDERHOST  (1<<6)
+#define S3C2410_SDICMDCON_INDEX       (0x3f)
 
 #define S3C2410_SDICMDSTAT_CRCFAIL    (1<<12)
 #define S3C2410_SDICMDSTAT_CMDSENT    (1<<11)
@@ -73,6 +74,7 @@
 #define S3C2410_SDIDCON_XFER_RXSTART  (2<<12)
 #define S3C2410_SDIDCON_XFER_TXSTART  (3<<12)
 
+#define S3C2410_SDIDCON_BLKNUM_MASK   (0xFFF)
 #define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
 
 #define S3C2410_SDIDSTA_RDYWAITREQ    (1<<10)
@@ -115,4 +117,14 @@
 #define S3C2410_SDIIMSK_RXFIFOFULL     (1<<1)
 #define S3C2410_SDIIMSK_RXFIFOHALF     (1<<0)
 
+#define S3C2410_SDICMDCON_ABORT       (1<<12)
+#define S3C2410_SDICMDCON_WITHDATA    (1<<11)
+#define S3C2410_SDICMDCON_LONGRSP     (1<<10)
+#define S3C2410_SDICMDCON_WAITRSP     (1<<9)
+#define S3C2410_SDICMDCON_CMDSTART    (1<<8)
+#define S3C2410_SDICMDCON_SENDERHOST  (1<<6)
+
+#define S3C2410_SDIDCON_BLKNUM_MASK   (0xFFF)
+#define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
+
 #endif /* __ASM_ARM_REGS_SDI */
