diff -NurbBpP linux-2.6.11.11-h1940-2/arch/arm/mach-s3c2410/mach-h1940.c linux-2.6.11.11-h1940-3.3/arch/arm/mach-s3c2410/mach-h1940.c
--- linux-2.6.11.11-h1940-2/arch/arm/mach-s3c2410/mach-h1940.c    2005-06-03 12:13:42.000000000 +0200
+++ linux-2.6.11.11-h1940-3.3/arch/arm/mach-s3c2410/mach-h1940.c    2005-06-03 19:11:47.000000000 +0200
@@ -167,6 +167,7 @@ static struct platform_device *h1940_dev
     &s3c_device_wdt,
     &s3c_device_i2c,
     &s3c_device_iis,
+    &s3c_device_sdi,
     &s3c_device_usbgadget,
 };
 
diff -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/Kconfig linux-2.6.11.11-h1940-3.3/drivers/mmc/Kconfig
--- linux-2.6.11.11-h1940-2/drivers/mmc/Kconfig    2005-03-29 06:05:33.000000000 +0200
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/Kconfig    2005-06-03 19:11:47.000000000 +0200
@@ -39,6 +39,15 @@ config MMC_ARMMMCI
 
       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.
+
 config MMC_PXA
     tristate "Intel PXA255 Multimedia Card Interface support"
     depends on ARCH_PXA && MMC
diff -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/Makefile linux-2.6.11.11-h1940-3.3/drivers/mmc/Makefile
--- linux-2.6.11.11-h1940-2/drivers/mmc/Makefile    2005-03-29 06:04:22.000000000 +0200
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/Makefile    2005-06-03 19:11:47.000000000 +0200
@@ -18,5 +18,6 @@ obj-$(CONFIG_MMC_BLOCK)        += mmc_block.o
 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 -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/mmc_block.c linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc_block.c
--- linux-2.6.11.11-h1940-2/drivers/mmc/mmc_block.c    2005-03-29 06:05:33.000000000 +0200
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc_block.c    2005-06-03 19:45:15.000000000 +0200
@@ -3,6 +3,9 @@
  *
  * Copyright 2002 Hewlett-Packard Company
  *
+ * SD-Card support based on the work of:
+ *    Thomas Kleffel, Ian Molton, and Pierre Ossman
+ *
  * 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,19 @@ static int mmc_blk_issue_rq(struct mmc_q
 {
     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 (mmc_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 +193,7 @@ static int mmc_blk_issue_rq(struct mmc_q
 
         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 +202,9 @@ static int mmc_blk_issue_rq(struct mmc_q
         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;
diff -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/mmc.c linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc.c
--- linux-2.6.11.11-h1940-2/drivers/mmc/mmc.c    2005-03-29 06:05:33.000000000 +0200
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc.c    2005-06-03 21:47:26.000000000 +0200
@@ -3,6 +3,9 @@
  *
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
  *
+ * SD-Card support based on the work of:
+ *    Thomas Kleffel, Ian Molton, and Pierre Ossman
+ *
  * 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.
@@ -173,6 +176,48 @@ int mmc_wait_for_cmd(struct mmc_host *ho
 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, CMD_RETRIES);
+}
+
+/**
+ *    mmc_wait_for_app_cmd - start an application command and wait
+ *                            for completion
+ *    @host: MMC host to start command
+ *    @rca: RCA to send MMC_APP_CMD to
+ *    @cmd: MMC command to start
+ *    @retries: maximum number of retries
+ *
+ *    Sends a MMC_APP_CMD, checks the card response, sends the command
+ *    in the parameter and waits for it to complete. Return any error
+ *    that occurred while the command was executing.
+ *    Do not attempt to parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
+    struct mmc_command *cmd, int retries)
+{
+    int err;
+
+    BUG_ON(host->card_busy == NULL);
+    BUG_ON(retries < 0);
+
+    err = mmc_send_app_cmd(host, rca);
+    if (err != MMC_ERR_NONE)
+        goto fail;
+
+    err = mmc_wait_for_cmd(host, cmd, retries);
+fail:
+    return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
 
 /**
  *    __mmc_claim_host - exclusively claim a host
@@ -322,13 +367,30 @@ static void mmc_decode_cid(struct mmc_ca
 
     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 */
+    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);
@@ -344,8 +406,8 @@ static void mmc_decode_cid(struct mmc_ca
         card->cid.year        = UNSTUFF_BITS(resp, 8, 4) + 1997;
         break;
 
-    case 2: /* MMC v2.x ? */
-    case 3: /* MMC v3.x ? */
+        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);
@@ -360,11 +422,11 @@ static void mmc_decode_cid(struct mmc_ca
         break;
 
     default:
-        printk("%s: card has unknown MMCA version %d\n",
-            card->host->host_name, card->csd.mmca_vsn);
+            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,22 +435,79 @@ static void mmc_decode_cid(struct mmc_ca
 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;
 
+    if (card->sd) {
     /*
-     * We only understand CSD structure v1.1 and v2.
+        * 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->cmdclass        = UNSTUFF_BITS(resp,  84,12);
+        csd->read_blkbits    = 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_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);
+        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->mmca_vsn     = UNSTUFF_BITS(resp, 122, 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;
@@ -404,6 +523,7 @@ static void mmc_decode_csd(struct mmc_ca
     csd->capacity      = (1 + m) << (e + 2);
 
     csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+    }
 }
 
 /*
@@ -456,6 +576,7 @@ mmc_alloc_card(struct mmc_host *host, u3
 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 +584,95 @@ static void mmc_idle_cards(struct mmc_ho
 
     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 mmc_sd_set_bus_width(struct mmc_host *host, u16 rca, u32 bus_width)
+{
+    struct mmc_command cmd;
+    int err;
+
+    cmd.opcode = MMC_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_app_cmd(host, rca, &cmd, CMD_RETRIES);
+    if (err != MMC_ERR_NONE)
+        goto fail;
+
+    DBG("MMC: sd_set_bus_width done.\n");
+    return err;
+
+fail:
+    switch (err) {
+    case MMC_ERR_TIMEOUT:
+        printk(KERN_ERR "MMC: sd_set_bus_width timed out.\n");
+        break;
+    case MMC_ERR_BADCRC:
+        printk(KERN_ERR "MMC: sd_set_bus_width yielded crc error.\n");
+        break;
+    default:
+        printk(KERN_ERR "MMC: sd_set_bus_width error %d.\n", err);
+    }
+    return err;
+}
+
+EXPORT_SYMBOL(mmc_sd_set_bus_width);
+
+
+static int mmc_send_app_op_cond(struct mmc_host *host, u16 rca, u32 parameter, u32 *response)
+{
+    struct mmc_command cmd;
+    int err;
+    int retries = 100;
+
+    cmd.opcode = MMC_SD_APP_OP_COND;
+    cmd.arg = parameter;
+    cmd.flags = MMC_RSP_R3;
+
+    DBG("MMC: send_app_op_cond to %08x\n",parameter);
+
+    while (retries--) {
+        err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
+        if (err != MMC_ERR_NONE)
+            goto retry; // was break;
+
+        if (cmd.resp[0] & MMC_CARD_BUSY || parameter == 0)
+            break;
+
+    retry:
+        err = MMC_ERR_TIMEOUT;
+        mmc_delay(10);
+    }
+
+    if (response)
+        *response = cmd.resp[0];
+
+    switch (err) {
+    case MMC_ERR_TIMEOUT:
+        printk(KERN_WARNING "MMC: send_app_op_cond timed out. Probably no SD-Card here.\n");
+        break;
+    case MMC_ERR_BUSY:
+        printk(KERN_ERR "MMC: send_app_op_cond locked busy. Probably have broken SD-Card.\n");
+        break;
+    default:
+        DBG("MMC: send_app_op_cond done. Results are: 0x%08x.\n",cmd.resp[0]);
+    }
+    return err;
 }
 
+
 /*
  * Apply power to the MMC stack.
  */
@@ -532,7 +739,7 @@ static int mmc_send_op_cond(struct mmc_h
  * 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 +749,7 @@ static void mmc_discover_cards(struct mm
 
         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,8 +757,7 @@ static void mmc_discover_cards(struct mm
             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;
         }
 
@@ -562,6 +768,7 @@ static void mmc_discover_cards(struct mm
                 err = PTR_ERR(card);
                 break;
             }
+            card->sd = sd;
             list_add(&card->node, &host->cards);
         }
 
@@ -574,6 +781,15 @@ static void mmc_discover_cards(struct mm
         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);
+            if (!card->rca) {
+                mmc_card_set_dead(card);
+                break;
+            }
+        }
     }
 }
 
@@ -590,7 +806,7 @@ static void mmc_read_csds(struct mmc_hos
 
         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 +867,23 @@ static void mmc_check_cards(struct mmc_h
     }
 }
 
+
 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_discover_cards(host);
+    // Wake and discover SD-Cards
+    mmc_send_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 -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/mmc.h linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc.h
--- linux-2.6.11.11-h1940-2/drivers/mmc/mmc.h    2004-11-21 14:46:06.000000000 +0100
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc.h    2005-06-03 19:46:38.000000000 +0200
@@ -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 mmc_sd_set_bus_width(struct mmc_host *host, u16 rca, u32 bus_width);
 #endif
diff -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/mmc_sysfs.c linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc_sysfs.c
--- linux-2.6.11.11-h1940-2/drivers/mmc/mmc_sysfs.c    2004-11-21 14:46:06.000000000 +0100
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/mmc_sysfs.c    2005-06-03 19:13:27.000000000 +0200
@@ -3,6 +3,9 @@
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *
+ * SD-Card support based on the work of:
+ *    Thomas Kleffel, Ian Molton, and Pierre Ossman
+ *
  * 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.
@@ -201,17 +204,10 @@ void mmc_init_card(struct mmc_card *card
  */
 int mmc_register_card(struct mmc_card *card)
 {
-    int ret, i;
-
     snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
          "%s:%04x", card->host->host_name, card->rca);
 
-    ret = device_add(&card->dev);
-    if (ret == 0)
-        for (i = 0; i < ARRAY_SIZE(mmc_dev_attributes); i++)
-            device_create_file(&card->dev, mmc_dev_attributes[i]);
-
-    return ret;
+    return device_add(&card->dev);
 }
 
 /*
diff -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/s3c2410mci.c linux-2.6.11.11-h1940-3.3/drivers/mmc/s3c2410mci.c
--- linux-2.6.11.11-h1940-2/drivers/mmc/s3c2410mci.c    1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/s3c2410mci.c    2005-06-03 21:59:13.000000000 +0200
@@ -0,0 +1,748 @@
+/*
+ *  linux/drivers/mmc/s3c2410mci.c - 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;
+
+    printk("s3c2410sdi_irq_cd: irq=%d, host=%d\n", irq, host);
+    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 = 0;
+
+    switch (purpose) {
+        case DMAP_READ:
+            source  = S3C2410_DMASRC_HW;
+            break;
+
+        case DMAP_WRITE:
+            source  = S3C2410_DMASRC_MEM;
+            break;
+
+        default:
+            BUG();
+    }
+
+    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_EINT5;
+
+    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_GPF5, S3C2410_GPF5_EINT5);
+    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 -NurbBpP linux-2.6.11.11-h1940-2/drivers/mmc/s3c2410mci.h linux-2.6.11.11-h1940-3.3/drivers/mmc/s3c2410mci.h
--- linux-2.6.11.11-h1940-2/drivers/mmc/s3c2410mci.h    1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.11-h1940-3.3/drivers/mmc/s3c2410mci.h    2005-06-03 18:53:54.000000000 +0200
@@ -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 -NurbBpP linux-2.6.11.11-h1940-2/include/asm-arm/arch-s3c2410/regs-sdi.h linux-2.6.11.11-h1940-3.3/include/asm-arm/arch-s3c2410/regs-sdi.h
--- linux-2.6.11.11-h1940-2/include/asm-arm/arch-s3c2410/regs-sdi.h    2005-03-29 06:04:40.000000000 +0200
+++ linux-2.6.11.11-h1940-3.3/include/asm-arm/arch-s3c2410/regs-sdi.h    2005-06-03 19:11:47.000000000 +0200
@@ -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)
diff -NurbBpP linux-2.6.11.11-h1940-2/include/linux/mmc/card.h linux-2.6.11.11-h1940-3.3/include/linux/mmc/card.h
--- linux-2.6.11.11-h1940-2/include/linux/mmc/card.h    2004-11-21 14:46:21.000000000 +0100
+++ linux-2.6.11.11-h1940-3.3/include/linux/mmc/card.h    2005-06-03 19:11:47.000000000 +0200
@@ -24,12 +24,55 @@ struct mmc_cid {
 };
 
 struct mmc_csd {
-    unsigned char        mmca_vsn;
-    unsigned short        cmdclass;
+    u8  sd;
+    u8  csd_vers;
+    u8  spec_vers;
+    u8  taac;
+    u8  nsac;
+    u16 cmdclass;
+    u8  tran_speed;
+    u8  read_blkbits;
+    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 mmc_card {
     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 -NurbBpP linux-2.6.11.11-h1940-2/include/linux/mmc/host.h linux-2.6.11.11-h1940-3.3/include/linux/mmc/host.h
--- linux-2.6.11.11-h1940-2/include/linux/mmc/host.h    2004-11-21 14:46:21.000000000 +0100
+++ linux-2.6.11.11-h1940-3.3/include/linux/mmc/host.h    2005-06-03 19:11:47.000000000 +0200
@@ -61,12 +61,15 @@ struct mmc_host_ops {
 struct mmc_card;
 struct device;
 
+#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 -NurbBpP linux-2.6.11.11-h1940-2/include/linux/mmc/mmc.h linux-2.6.11.11-h1940-3.3/include/linux/mmc/mmc.h
--- linux-2.6.11.11-h1940-2/include/linux/mmc/mmc.h    2005-03-29 06:05:49.000000000 +0200
+++ linux-2.6.11.11-h1940-3.3/include/linux/mmc/mmc.h    2005-06-03 19:11:47.000000000 +0200
@@ -47,6 +47,8 @@ struct mmc_command {
 #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 @@ struct mmc_data {
 #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 @@ struct mmc_data {
 
     unsigned int        sg_len;        /* size of scatter list */
     struct scatterlist    *sg;        /* I/O scatter list */
+
+    struct request        *req;
 };
 
 struct mmc_request {
diff -NurbBpP linux-2.6.11.11-h1940-2/include/linux/mmc/protocol.h linux-2.6.11.11-h1940-3.3/include/linux/mmc/protocol.h
--- linux-2.6.11.11-h1940-2/include/linux/mmc/protocol.h    2004-11-21 14:46:21.000000000 +0100
+++ linux-2.6.11.11-h1940-3.3/include/linux/mmc/protocol.h    2005-06-03 19:39:23.000000000 +0200
@@ -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_SD_APP_OP_COND     41   /* ????  op conds         ??? */
+#define MMC_SD_SET_BUS_WIDTH      6   /* ????  00=1 10=4     ??? */
+
 /*
   MMC status in R1
   Type
@@ -118,13 +121,14 @@
 /* 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;
     u8  tran_speed;
-    u16 ccc;
-    u8  read_bl_len;
+    u16 cmdclass;
+    u8  read_blkbits;
     u8  read_bl_partial;
     u8  write_blk_misalign;
     u8  read_blk_misalign;
@@ -139,11 +143,15 @@ struct _mmc_csd {
         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 @@ struct _mmc_csd {
     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 */