#include "mmc_ops.h"
 #include "sd_ops.h"
 
-#define CMD_RETRIES    3
-
-/*
- * OCR Bit positions to 10s of Vdd mV.
- */
-static const unsigned short mmc_ocr_bit_to_vdd[] = {
-       150,    155,    160,    165,    170,    180,    190,    200,
-       210,    220,    230,    240,    250,    260,    270,    280,
-       290,    300,    310,    320,    330,    340,    350,    360
-};
-
-static const unsigned int tran_exp[] = {
-       10000,          100000,         1000000,        10000000,
-       0,              0,              0,              0
-};
-
-static const unsigned char tran_mant[] = {
-       0,      10,     12,     13,     15,     20,     25,     30,
-       35,     40,     45,     50,     55,     60,     70,     80,
-};
-
-static const unsigned int tacc_exp[] = {
-       1,      10,     100,    1000,   10000,  100000, 1000000, 10000000,
-};
-
-static const unsigned int tacc_mant[] = {
-       0,      10,     12,     13,     15,     20,     25,     30,
-       35,     40,     45,     50,     55,     60,     70,     80,
-};
-
+extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
 
 /**
  *     mmc_request_done - finish processing an MMC request
 
 EXPORT_SYMBOL(mmc_release_host);
 
+/*
+ * Internal function that does the actual ios call to the host driver,
+ * optionally printing some debug output.
+ */
 static inline void mmc_set_ios(struct mmc_host *host)
 {
        struct mmc_ios *ios = &host->ios;
        host->ops->set_ios(host, ios);
 }
 
+/*
+ * Control chip select pin on a host.
+ */
 void mmc_set_chip_select(struct mmc_host *host, int mode)
 {
        host->ios.chip_select = mode;
        mmc_set_ios(host);
 }
 
+/*
+ * Sets the host clock to the highest possible frequency that
+ * is below "hz".
+ */
+void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+{
+       WARN_ON(hz < host->f_min);
+
+       if (hz > host->f_max)
+               hz = host->f_max;
+
+       host->ios.clock = hz;
+       mmc_set_ios(host);
+}
+
+/*
+ * Change the bus mode (open drain/push-pull) of a host.
+ */
+void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
+{
+       host->ios.bus_mode = mode;
+       mmc_set_ios(host);
+}
+
+/*
+ * Change data bus width of a host.
+ */
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
+{
+       host->ios.bus_width = width;
+       mmc_set_ios(host);
+}
+
 /*
  * Mask off any voltages we don't support and select
  * the lowest voltage
  */
-static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
+u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
 {
        int bit;
 
        return ocr;
 }
 
-#define UNSTUFF_BITS(resp,start,size)                                  \
-       ({                                                              \
-               const int __size = size;                                \
-               const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
-               const int __off = 3 - ((start) / 32);                   \
-               const int __shft = (start) & 31;                        \
-               u32 __res;                                              \
-                                                                       \
-               __res = resp[__off] >> __shft;                          \
-               if (__size + __shft > 32)                               \
-                       __res |= resp[__off-1] << ((32 - __shft) % 32); \
-               __res & __mask;                                         \
-       })
-
-/*
- * Given the decoded CSD structure, decode the raw CID to our CID structure.
- */
-static void mmc_decode_cid(struct mmc_card *card)
-{
-       u32 *resp = card->raw_cid;
-
-       memset(&card->cid, 0, sizeof(struct mmc_cid));
-
-       if (mmc_card_sd(card)) {
-               /*
-                * SD doesn't currently have a version field so we will
-                * have to assume we can parse this.
-                */
-               card->cid.manfid                = UNSTUFF_BITS(resp, 120, 8);
-               card->cid.oemid                 = UNSTUFF_BITS(resp, 104, 16);
-               card->cid.prod_name[0]          = UNSTUFF_BITS(resp, 96, 8);
-               card->cid.prod_name[1]          = UNSTUFF_BITS(resp, 88, 8);
-               card->cid.prod_name[2]          = UNSTUFF_BITS(resp, 80, 8);
-               card->cid.prod_name[3]          = UNSTUFF_BITS(resp, 72, 8);
-               card->cid.prod_name[4]          = UNSTUFF_BITS(resp, 64, 8);
-               card->cid.hwrev                 = UNSTUFF_BITS(resp, 60, 4);
-               card->cid.fwrev                 = UNSTUFF_BITS(resp, 56, 4);
-               card->cid.serial                = UNSTUFF_BITS(resp, 24, 32);
-               card->cid.year                  = UNSTUFF_BITS(resp, 12, 8);
-               card->cid.month                 = UNSTUFF_BITS(resp, 8, 4);
-
-               card->cid.year += 2000; /* SD cards year offset */
-       } else {
-               /*
-                * The selection of the format here is based upon published
-                * specs from sandisk and from what people have reported.
-                */
-               switch (card->csd.mmca_vsn) {
-               case 0: /* MMC v1.0 - v1.2 */
-               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.0 - v2.2 */
-               case 3: /* MMC v3.1 - v3.3 */
-               case 4: /* MMC v4 */
-                       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",
-                               mmc_hostname(card->host), card->csd.mmca_vsn);
-                       mmc_card_set_bad(card);
-                       break;
-               }
-       }
-}
-
-/*
- * Given a 128-bit response, decode to our card CSD structure.
- */
-static void mmc_decode_csd(struct mmc_card *card)
-{
-       struct mmc_csd *csd = &card->csd;
-       unsigned int e, m, csd_struct;
-       u32 *resp = card->raw_csd;
-
-       if (mmc_card_sd(card)) {
-               csd_struct = UNSTUFF_BITS(resp, 126, 2);
-
-               switch (csd_struct) {
-               case 0:
-                       m = UNSTUFF_BITS(resp, 115, 4);
-                       e = UNSTUFF_BITS(resp, 112, 3);
-                       csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-                       csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-                       m = UNSTUFF_BITS(resp, 99, 4);
-                       e = UNSTUFF_BITS(resp, 96, 3);
-                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
-                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
-
-                       e = UNSTUFF_BITS(resp, 47, 3);
-                       m = UNSTUFF_BITS(resp, 62, 12);
-                       csd->capacity     = (1 + m) << (e + 2);
-
-                       csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-                       csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-                       csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-                       csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-                       csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-                       csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-                       csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-                       break;
-               case 1:
-                       /*
-                        * This is a block-addressed SDHC card. Most
-                        * interesting fields are unused and have fixed
-                        * values. To avoid getting tripped by buggy cards,
-                        * we assume those fixed values ourselves.
-                        */
-                       mmc_card_set_blockaddr(card);
-
-                       csd->tacc_ns     = 0; /* Unused */
-                       csd->tacc_clks   = 0; /* Unused */
-
-                       m = UNSTUFF_BITS(resp, 99, 4);
-                       e = UNSTUFF_BITS(resp, 96, 3);
-                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
-                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
-
-                       m = UNSTUFF_BITS(resp, 48, 22);
-                       csd->capacity     = (1 + m) << 10;
-
-                       csd->read_blkbits = 9;
-                       csd->read_partial = 0;
-                       csd->write_misalign = 0;
-                       csd->read_misalign = 0;
-                       csd->r2w_factor = 4; /* Unused */
-                       csd->write_blkbits = 9;
-                       csd->write_partial = 0;
-                       break;
-               default:
-                       printk("%s: unrecognised CSD structure version %d\n",
-                               mmc_hostname(card->host), csd_struct);
-                       mmc_card_set_bad(card);
-                       return;
-               }
-       } else {
-               /*
-                * We only understand CSD structure v1.1 and v1.2.
-                * v1.2 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",
-                               mmc_hostname(card->host), 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);
-
-               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-               csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-               csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-               csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-               csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-               csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-               csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-       }
-}
-
 /*
- * Given a 64-bit response, decode to our card SCR structure.
+ * Select timing parameters for host.
  */
-static void mmc_decode_scr(struct mmc_card *card)
+void mmc_set_timing(struct mmc_host *host, unsigned int timing)
 {
-       struct sd_scr *scr = &card->scr;
-       unsigned int scr_struct;
-       u32 resp[4];
-
-       BUG_ON(!mmc_card_sd(card));
-
-       resp[3] = card->raw_scr[1];
-       resp[2] = card->raw_scr[0];
-
-       scr_struct = UNSTUFF_BITS(resp, 60, 4);
-       if (scr_struct != 0) {
-               printk("%s: unrecognised SCR structure version %d\n",
-                       mmc_hostname(card->host), scr_struct);
-               mmc_card_set_bad(card);
-               return;
-       }
-
-       scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
-       scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
+       host->ios.timing = timing;
+       mmc_set_ios(host);
 }
 
 /*
  * Allocate a new MMC card
  */
-static struct mmc_card *
-mmc_alloc_card(struct mmc_host *host, u32 *raw_cid)
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
 {
        struct mmc_card *card;
 
                return ERR_PTR(-ENOMEM);
 
        mmc_init_card(card, host);
-       memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid));
 
        return card;
 }
 }
 
 /*
- * Discover the card by requesting its CID.
- *
- * Create a mmc_card entry for the discovered card, assigning
- * it an RCA, and save the raw CID for decoding later.
+ * Assign a mmc bus handler to a host. Only one bus handler may control a
+ * host at any given time.
  */
-static void mmc_discover_card(struct mmc_host *host)
+void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
 {
-       unsigned int err;
-       u32 cid[4];
-
-       BUG_ON(host->card);
-
-       err = mmc_all_send_cid(host, cid);
-       if (err != MMC_ERR_NONE) {
-               printk(KERN_ERR "%s: error requesting CID: %d\n",
-                       mmc_hostname(host), err);
-               return;
-       }
-
-       host->card = mmc_alloc_card(host, cid);
-       if (IS_ERR(host->card)) {
-               err = PTR_ERR(host->card);
-               host->card = NULL;
-               return;
-       }
-
-       if (host->mode == MMC_MODE_SD) {
-               host->card->type = MMC_TYPE_SD;
-
-               err = mmc_send_relative_addr(host, &host->card->rca);
-               if (err != MMC_ERR_NONE)
-                       mmc_card_set_dead(host->card);
-               else {
-                       if (!host->ops->get_ro) {
-                               printk(KERN_WARNING "%s: host does not "
-                                       "support reading read-only "
-                                       "switch. assuming write-enable.\n",
-                                       mmc_hostname(host));
-                       } else {
-                               if (host->ops->get_ro(host))
-                                       mmc_card_set_readonly(host->card);
-                       }
-               }
-       } else {
-               host->card->type = MMC_TYPE_MMC;
-               host->card->rca = 1;
-
-               err = mmc_set_relative_addr(host->card);
-               if (err != MMC_ERR_NONE)
-                       mmc_card_set_dead(host->card);
-       }
-}
-
-static void mmc_read_csd(struct mmc_host *host)
-{
-       int err;
-
-       if (!host->card)
-               return;
-       if (mmc_card_dead(host->card))
-               return;
-
-       err = mmc_send_csd(host->card, host->card->raw_csd);
-       if (err != MMC_ERR_NONE) {
-               mmc_card_set_dead(host->card);
-               return;
-       }
-
-       mmc_decode_csd(host->card);
-       mmc_decode_cid(host->card);
-}
-
-static void mmc_process_ext_csd(struct mmc_host *host)
-{
-       int err;
-       u8 *ext_csd;
-
-       if (!host->card)
-               return;
-       if (mmc_card_dead(host->card))
-               return;
-       if (mmc_card_sd(host->card))
-               return;
-       if (host->card->csd.mmca_vsn < CSD_SPEC_VER_4)
-               return;
-
-       /*
-        * As the ext_csd is so large and mostly unused, we don't store the
-        * raw block in mmc_card.
-        */
-       ext_csd = kmalloc(512, GFP_KERNEL);
-       if (!ext_csd) {
-               printk("%s: could not allocate a buffer to receive the ext_csd."
-                      "mmc v4 cards will be treated as v3.\n",
-                       mmc_hostname(host));
-               return;
-       }
-
-       err = mmc_send_ext_csd(host->card, ext_csd);
-       if (err != MMC_ERR_NONE) {
-               if (host->card->csd.capacity == (4096 * 512)) {
-                       printk(KERN_ERR "%s: unable to read EXT_CSD "
-                               "on a possible high capacity card. "
-                               "Card will be ignored.\n",
-                               mmc_hostname(host));
-                       mmc_card_set_dead(host->card);
-               } else {
-                       printk(KERN_WARNING "%s: unable to read "
-                               "EXT_CSD, performance might "
-                               "suffer.\n",
-                               mmc_hostname(host));
-               }
-               goto out;
-       }
-
-       host->card->ext_csd.sectors =
-               ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
-               ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
-               ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
-               ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
-       if (host->card->ext_csd.sectors)
-               mmc_card_set_blockaddr(host->card);
-
-       switch (ext_csd[EXT_CSD_CARD_TYPE]) {
-       case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
-               host->card->ext_csd.hs_max_dtr = 52000000;
-               break;
-       case EXT_CSD_CARD_TYPE_26:
-               host->card->ext_csd.hs_max_dtr = 26000000;
-               break;
-       default:
-               /* MMC v4 spec says this cannot happen */
-               printk("%s: card is mmc v4 but doesn't support "
-                      "any high-speed modes.\n",
-                       mmc_hostname(host));
-               goto out;
-       }
-
-       if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
-               /* Activate highspeed support. */
-               err = mmc_switch(host->card, MMC_SWITCH_MODE_WRITE_BYTE,
-                       EXT_CSD_HS_TIMING, 1);
-               if (err != MMC_ERR_NONE) {
-                       printk("%s: failed to switch card to mmc v4 "
-                              "high-speed mode.\n",
-                              mmc_hostname(host));
-                       goto out;
-               }
-
-               mmc_card_set_highspeed(host->card);
-
-               host->ios.timing = MMC_TIMING_MMC_HS;
-               mmc_set_ios(host);
-       }
+       unsigned long flags;
 
-       /* Check for host support for wide-bus modes. */
-       if (host->caps & MMC_CAP_4_BIT_DATA) {
-               /* Activate 4-bit support. */
-               err = mmc_switch(host->card, MMC_SWITCH_MODE_WRITE_BYTE,
-                       EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4 |
-                       EXT_CSD_CMD_SET_NORMAL);
-               if (err != MMC_ERR_NONE) {
-                       printk("%s: failed to switch card to "
-                              "mmc v4 4-bit bus mode.\n",
-                              mmc_hostname(host));
-                       goto out;
-               }
+       BUG_ON(!host);
+       BUG_ON(!ops);
 
-               host->ios.bus_width = MMC_BUS_WIDTH_4;
-               mmc_set_ios(host);
-       }
+       BUG_ON(!host->claimed);
 
-out:
-       kfree(ext_csd);
-}
+       spin_lock_irqsave(&host->lock, flags);
 
-static void mmc_read_scr(struct mmc_host *host)
-{
-       int err;
+       BUG_ON(host->bus_ops);
+       BUG_ON(host->bus_refs);
 
-       if (!host->card)
-               return;
-       if (mmc_card_dead(host->card))
-               return;
-       if (!mmc_card_sd(host->card))
-               return;
-
-       err = mmc_app_send_scr(host->card, host->card->raw_scr);
-       if (err != MMC_ERR_NONE) {
-               mmc_card_set_dead(host->card);
-               return;
-       }
+       host->bus_ops = ops;
+       host->bus_refs = 1;
+       host->bus_dead = 0;
 
-       mmc_decode_scr(host->card);
+       spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static void mmc_read_switch_caps(struct mmc_host *host)
+/*
+ * Remove the current bus handler from a host. Assumes that there are
+ * no interesting cards left, so the bus is powered down.
+ */
+void mmc_detach_bus(struct mmc_host *host)
 {
-       int err;
-       unsigned char *status;
-
-       if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
-               return;
-
-       if (!host->card)
-               return;
-       if (mmc_card_dead(host->card))
-               return;
-       if (!mmc_card_sd(host->card))
-               return;
-       if (host->card->scr.sda_vsn < SCR_SPEC_VER_1)
-               return;
-
-       status = kmalloc(64, GFP_KERNEL);
-       if (!status) {
-               printk(KERN_WARNING "%s: Unable to allocate buffer for "
-                       "reading switch capabilities.\n",
-                       mmc_hostname(host));
-               return;
-       }
-
-       err = mmc_sd_switch(host->card, SD_SWITCH_CHECK,
-               SD_SWITCH_GRP_ACCESS, SD_SWITCH_ACCESS_HS, status);
-       if (err != MMC_ERR_NONE) {
-               printk("%s: unable to read switch capabilities, "
-                       "performance might suffer.\n",
-                       mmc_hostname(host));
-               goto out;
-       }
-
-       if (status[13] & 0x02)
-               host->card->sw_caps.hs_max_dtr = 50000000;
+       unsigned long flags;
 
-       err = mmc_sd_switch(host->card, SD_SWITCH_SET,
-               SD_SWITCH_GRP_ACCESS, SD_SWITCH_ACCESS_HS, status);
-       if (err != MMC_ERR_NONE || (status[16] & 0xF) != 1) {
-               printk(KERN_WARNING "%s: Problem switching card "
-                       "into high-speed mode!\n",
-                       mmc_hostname(host));
-               goto out;
-       }
+       BUG_ON(!host);
 
-       mmc_card_set_highspeed(host->card);
+       BUG_ON(!host->claimed);
+       BUG_ON(!host->bus_ops);
 
-       host->ios.timing = MMC_TIMING_SD_HS;
-       mmc_set_ios(host);
+       spin_lock_irqsave(&host->lock, flags);
 
-out:
-       kfree(status);
-}
+       host->bus_dead = 1;
 
-static unsigned int mmc_calculate_clock(struct mmc_host *host)
-{
-       unsigned int max_dtr = host->f_max;
-
-       if (host->card && !mmc_card_dead(host->card)) {
-               if (mmc_card_highspeed(host->card) && mmc_card_sd(host->card)) {
-                       if (max_dtr > host->card->sw_caps.hs_max_dtr)
-                               max_dtr = host->card->sw_caps.hs_max_dtr;
-               } else if (mmc_card_highspeed(host->card) && !mmc_card_sd(host->card)) {
-                       if (max_dtr > host->card->ext_csd.hs_max_dtr)
-                               max_dtr = host->card->ext_csd.hs_max_dtr;
-               } else if (max_dtr > host->card->csd.max_dtr) {
-                       max_dtr = host->card->csd.max_dtr;
-               }
-       }
+       spin_unlock_irqrestore(&host->lock, flags);
 
-       pr_debug("%s: selected %d.%03dMHz transfer rate\n",
-                mmc_hostname(host),
-                max_dtr / 1000000, (max_dtr / 1000) % 1000);
+       mmc_power_off(host);
 
-       return max_dtr;
+       mmc_bus_put(host);
 }
 
 /*
- * Check whether cards we already know about are still present.
- * We do this by requesting status, and checking whether a card
- * responds.
- *
- * A request for status does not cause a state change in data
- * transfer mode.
+ * Cleanup when the last reference to the bus operator is dropped.
  */
-static void mmc_check_card(struct mmc_card *card)
+void __mmc_release_bus(struct mmc_host *host)
 {
-       int err;
-
-       BUG_ON(!card);
+       BUG_ON(!host);
+       BUG_ON(host->bus_refs);
+       BUG_ON(!host->bus_dead);
 
-       err = mmc_send_status(card, NULL);
-       if (err == MMC_ERR_NONE)
-               return;
-
-       mmc_card_set_dead(card);
+       host->bus_ops = NULL;
 }
 
-static void mmc_setup(struct mmc_host *host)
-{
-       int err;
-       u32 ocr;
-
-       host->mode = MMC_MODE_SD;
-
-       mmc_power_up(host);
-       mmc_go_idle(host);
-
-       err = mmc_send_if_cond(host, host->ocr_avail);
-       if (err != MMC_ERR_NONE) {
-               return;
-       }
-       err = mmc_send_app_op_cond(host, 0, &ocr);
-
-       /*
-        * If we fail to detect any SD cards then try
-        * searching for MMC cards.
-        */
-       if (err != MMC_ERR_NONE) {
-               host->mode = MMC_MODE_MMC;
-
-               err = mmc_send_op_cond(host, 0, &ocr);
-               if (err != MMC_ERR_NONE)
-                       return;
-       }
-
-       host->ocr = mmc_select_voltage(host, ocr);
-
-       if (host->ocr == 0)
-               return;
-
-       /*
-        * 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.
-        */
-       mmc_go_idle(host);
-
-       /*
-        * 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.)
-        */
-       if (host->mode == MMC_MODE_SD) {
-               /*
-                * If SD_SEND_IF_COND indicates an SD 2.0
-                * compliant card and we should set bit 30
-                * of the ocr to indicate that we can handle
-                * block-addressed SDHC cards.
-                */
-               err = mmc_send_if_cond(host, host->ocr);
-               if (err == MMC_ERR_NONE)
-                       ocr = host->ocr | (1 << 30);
-
-               mmc_send_app_op_cond(host, ocr, NULL);
-       } else {
-               /* The extra bit indicates that we support high capacity */
-               mmc_send_op_cond(host, host->ocr | (1 << 30), NULL);
-       }
-
-       mmc_discover_card(host);
-
-       /*
-        * Ok, now switch to push-pull mode.
-        */
-       host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-       mmc_set_ios(host);
-
-       mmc_read_csd(host);
-
-       if (host->card && !mmc_card_dead(host->card)) {
-               err = mmc_select_card(host->card);
-               if (err != MMC_ERR_NONE)
-                       mmc_card_set_dead(host->card);
-       }
-
-       /*
-        * The card is in 1 bit mode by default so
-        * we only need to change if it supports the
-        * wider version.
-        */
-       if (host->card && !mmc_card_dead(host->card) && 
-               mmc_card_sd(host->card) &&
-               (host->card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) &&
-               (host->card->host->caps & MMC_CAP_4_BIT_DATA)) {
-               err = mmc_app_set_bus_width(host->card, SD_BUS_WIDTH_4);
-               if (err != MMC_ERR_NONE)
-                       mmc_card_set_dead(host->card);
-               else {
-                       host->ios.bus_width = MMC_BUS_WIDTH_4;
-                       mmc_set_ios(host);
-               }
-       }
-
-       if (host->mode == MMC_MODE_SD) {
-               mmc_read_scr(host);
-               mmc_read_switch_caps(host);
-       } else
-               mmc_process_ext_csd(host);
-}
-
-
 /**
  *     mmc_detect_change - process change of state on a MMC socket
  *     @host: host which changed state.
 {
        struct mmc_host *host =
                container_of(work, struct mmc_host, detect.work);
+       u32 ocr;
+       int err;
 
-       mmc_claim_host(host);
-
-       /*
-        * Check for removed card and newly inserted ones. We check for
-        * removed cards first so we can intelligently re-select the VDD.
-        */
-       if (host->card) {
-               mmc_check_card(host->card);
-
-               mmc_release_host(host);
-
-               if (mmc_card_dead(host->card)) {
-                       mmc_remove_card(host->card);
-                       host->card = NULL;
-               }
-
-               goto out;
-       }
-
-       mmc_setup(host);
+       mmc_bus_get(host);
 
-       if (host->card && !mmc_card_dead(host->card)) {
+       if (host->bus_ops == NULL) {
                /*
-                * (Re-)calculate the fastest clock rate which the
-                * attached cards and the host support.
+                * Only we can add a new handler, so it's safe to
+                * release the lock here.
                 */
-               host->ios.clock = mmc_calculate_clock(host);
-               mmc_set_ios(host);
-       }
+               mmc_bus_put(host);
 
-       mmc_release_host(host);
+               mmc_claim_host(host);
 
-       /*
-        * If this is a new and good card, register it.
-        */
-       if (host->card && !mmc_card_dead(host->card)) {
-               if (mmc_register_card(host->card))
-                       mmc_card_set_dead(host->card);
-       }
+               mmc_power_up(host);
+               mmc_go_idle(host);
 
-       /*
-        * If this card is dead, destroy it.
-        */
-       if (host->card && mmc_card_dead(host->card)) {
-               mmc_remove_card(host->card);
-               host->card = NULL;
-       }
+               mmc_send_if_cond(host, host->ocr_avail);
 
-out:
-       /*
-        * If we discover that there are no cards on the
-        * bus, turn off the clock and power down.
-        */
-       if (!host->card)
-               mmc_power_off(host);
+               err = mmc_send_app_op_cond(host, 0, &ocr);
+               if (err == MMC_ERR_NONE) {
+                       if (mmc_attach_sd(host, ocr))
+                               mmc_power_off(host);
+               } else {
+                       /*
+                        * If we fail to detect any SD cards then try
+                        * searching for MMC cards.
+                        */
+                       err = mmc_send_op_cond(host, 0, &ocr);
+                       if (err == MMC_ERR_NONE) {
+                               if (mmc_attach_mmc(host, ocr))
+                                       mmc_power_off(host);
+                       } else {
+                               mmc_power_off(host);
+                               mmc_release_host(host);
+                       }
+               }
+       } else {
+               if (host->bus_ops->detect && !host->bus_dead)
+                       host->bus_ops->detect(host);
+
+               mmc_bus_put(host);
+       }
 }
 
 
 
        mmc_flush_scheduled_work();
 
-       if (host->card) {
-               mmc_remove_card(host->card);
-               host->card = NULL;
+       mmc_bus_get(host);
+       if (host->bus_ops && !host->bus_dead) {
+               if (host->bus_ops->remove)
+                       host->bus_ops->remove(host);
+
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+               mmc_release_host(host);
        }
+       mmc_bus_put(host);
+
+       BUG_ON(host->card);
 
        mmc_power_off(host);
        mmc_remove_host_sysfs(host);
 {
        mmc_flush_scheduled_work();
 
-       if (host->card) {
-               mmc_remove_card(host->card);
-               host->card = NULL;
+       mmc_bus_get(host);
+       if (host->bus_ops && !host->bus_dead) {
+               if (host->bus_ops->remove)
+                       host->bus_ops->remove(host);
+               mmc_detach_bus(host);
        }
+       mmc_bus_put(host);
+
+       BUG_ON(host->card);
 
        mmc_power_off(host);
 
 
--- /dev/null
+/*
+ *  linux/drivers/mmc/mmc.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+
+static const unsigned int tran_exp[] = {
+       10000,          100000,         1000000,        10000000,
+       0,              0,              0,              0
+};
+
+static const unsigned char tran_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+static const unsigned int tacc_exp[] = {
+       1,      10,     100,    1000,   10000,  100000, 1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)                                  \
+       ({                                                              \
+               const int __size = size;                                \
+               const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
+               const int __off = 3 - ((start) / 32);                   \
+               const int __shft = (start) & 31;                        \
+               u32 __res;                                              \
+                                                                       \
+               __res = resp[__off] >> __shft;                          \
+               if (__size + __shft > 32)                               \
+                       __res |= resp[__off-1] << ((32 - __shft) % 32); \
+               __res & __mask;                                         \
+       })
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static void mmc_decode_cid(struct mmc_card *card)
+{
+       u32 *resp = card->raw_cid;
+
+       /*
+        * The selection of the format here is based upon published
+        * specs from sandisk and from what people have reported.
+        */
+       switch (card->csd.mmca_vsn) {
+       case 0: /* MMC v1.0 - v1.2 */
+       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.0 - v2.2 */
+       case 3: /* MMC v3.1 - v3.3 */
+       case 4: /* MMC v4 */
+               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",
+                       mmc_hostname(card->host), card->csd.mmca_vsn);
+               mmc_card_set_bad(card);
+               break;
+       }
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static void mmc_decode_csd(struct mmc_card *card)
+{
+       struct mmc_csd *csd = &card->csd;
+       unsigned int e, m, csd_struct;
+       u32 *resp = card->raw_csd;
+
+       /*
+        * We only understand CSD structure v1.1 and v1.2.
+        * v1.2 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",
+                       mmc_hostname(card->host), 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);
+
+       csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+       csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+       csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+       csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+       csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+       csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+       csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+}
+
+/*
+ * Read and decode extended CSD. Switch to high-speed and wide bus
+ * if supported.
+ */
+static int mmc_process_ext_csd(struct mmc_card *card)
+{
+       int err;
+       u8 *ext_csd;
+
+       BUG_ON(!card);
+
+       err = MMC_ERR_FAILED;
+
+       if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+               return MMC_ERR_NONE;
+
+       /*
+        * As the ext_csd is so large and mostly unused, we don't store the
+        * raw block in mmc_card.
+        */
+       ext_csd = kmalloc(512, GFP_KERNEL);
+       if (!ext_csd) {
+               printk(KERN_ERR "%s: could not allocate a buffer to "
+                       "receive the ext_csd. mmc v4 cards will be "
+                       "treated as v3.\n", mmc_hostname(card->host));
+               return MMC_ERR_FAILED;
+       }
+
+       err = mmc_send_ext_csd(card, ext_csd);
+       if (err != MMC_ERR_NONE) {
+               /*
+                * High capacity cards should have this "magic" size
+                * stored in their CSD.
+                */
+               if (card->csd.capacity == (4096 * 512)) {
+                       printk(KERN_ERR "%s: unable to read EXT_CSD "
+                               "on a possible high capacity card. "
+                               "Card will be ignored.\n",
+                               mmc_hostname(card->host));
+               } else {
+                       printk(KERN_WARNING "%s: unable to read "
+                               "EXT_CSD, performance might "
+                               "suffer.\n",
+                               mmc_hostname(card->host));
+                       err = MMC_ERR_NONE;
+               }
+               goto out;
+       }
+
+       card->ext_csd.sectors =
+               ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+               ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
+               ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
+               ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+       if (card->ext_csd.sectors)
+               mmc_card_set_blockaddr(card);
+
+       switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+       case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+               card->ext_csd.hs_max_dtr = 52000000;
+               break;
+       case EXT_CSD_CARD_TYPE_26:
+               card->ext_csd.hs_max_dtr = 26000000;
+               break;
+       default:
+               /* MMC v4 spec says this cannot happen */
+               printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
+                       "support any high-speed modes.\n",
+                       mmc_hostname(card->host));
+               goto out;
+       }
+
+       if (card->host->caps & MMC_CAP_MMC_HIGHSPEED) {
+               /* Activate highspeed support. */
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                       EXT_CSD_HS_TIMING, 1);
+               if (err != MMC_ERR_NONE) {
+                       printk(KERN_WARNING "%s: failed to switch "
+                               "card to mmc v4 high-speed mode.\n",
+                              mmc_hostname(card->host));
+                       err = MMC_ERR_NONE;
+                       goto out;
+               }
+
+               mmc_card_set_highspeed(card);
+
+               mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+       }
+
+       /* Check for host support for wide-bus modes. */
+       if (card->host->caps & MMC_CAP_4_BIT_DATA) {
+               /* Activate 4-bit support. */
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                       EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
+               if (err != MMC_ERR_NONE) {
+                       printk(KERN_WARNING "%s: failed to switch "
+                               "card to mmc v4 4-bit bus mode.\n",
+                              mmc_hostname(card->host));
+                       err = MMC_ERR_NONE;
+                       goto out;
+               }
+
+               mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+       }
+
+out:
+       kfree(ext_csd);
+
+       return err;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_remove(struct mmc_host *host)
+{
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_remove_card(host->card);
+       host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_detect(struct mmc_host *host)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+
+       /*
+        * Just check if our card has been removed.
+        */
+       err = mmc_send_status(host->card, NULL);
+
+       mmc_release_host(host);
+
+       if (err != MMC_ERR_NONE) {
+               mmc_remove_card(host->card);
+               host->card = NULL;
+
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+               mmc_release_host(host);
+       }
+}
+
+static const struct mmc_bus_ops mmc_ops = {
+       .remove = mmc_remove,
+       .detect = mmc_detect,
+};
+
+/*
+ * Starting point for MMC card init.
+ */
+int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
+{
+       struct mmc_card *card;
+       int err;
+       u32 cid[4];
+       unsigned int max_dtr;
+
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+
+       mmc_attach_bus(host, &mmc_ops);
+
+       host->ocr = mmc_select_voltage(host, ocr);
+
+       /*
+        * Can we support the voltage of the card?
+        */
+       if (!host->ocr)
+               goto err;
+
+       /*
+        * 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.
+        */
+       mmc_go_idle(host);
+
+       /* The extra bit indicates that we support high capacity */
+       mmc_send_op_cond(host, host->ocr | (1 << 30), NULL);
+
+       /*
+        * Fetch CID from card.
+        */
+       err = mmc_all_send_cid(host, cid);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       /*
+        * Allocate card structure.
+        */
+       card = mmc_alloc_card(host);
+       if (IS_ERR(card))
+               goto err;
+
+       card->type = MMC_TYPE_MMC;
+       card->rca = 1;
+       memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+
+       /*
+        * Set card RCA.
+        */
+       err = mmc_set_relative_addr(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+       /*
+        * Fetch CSD from card.
+        */
+       err = mmc_send_csd(card, card->raw_csd);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       mmc_decode_csd(card);
+       mmc_decode_cid(card);
+
+       /*
+        * Fetch and process extened CSD.
+        * This will switch into high-speed and wide bus modes,
+        * as available.
+        */
+       err = mmc_select_card(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       err = mmc_process_ext_csd(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       /*
+        * Compute bus speed.
+        */
+       max_dtr = (unsigned int)-1;
+
+       if (mmc_card_highspeed(card)) {
+               if (max_dtr > card->ext_csd.hs_max_dtr)
+                       max_dtr = card->ext_csd.hs_max_dtr;
+       } else if (max_dtr > card->csd.max_dtr) {
+               max_dtr = card->csd.max_dtr;
+       }
+
+       mmc_set_clock(host, max_dtr);
+
+       host->card = card;
+
+       mmc_release_host(host);
+
+       err = mmc_register_card(card);
+       if (err)
+               goto reclaim_host;
+
+       return 0;
+
+reclaim_host:
+       mmc_claim_host(host);
+free_card:
+       mmc_remove_card(card);
+       host->card = NULL;
+err:
+       mmc_detach_bus(host);
+       mmc_release_host(host);
+
+       return 0;
+}
+
 
--- /dev/null
+/*
+ *  linux/drivers/mmc/sd.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+#include "sd_ops.h"
+
+#include "core.h"
+
+static const unsigned int tran_exp[] = {
+       10000,          100000,         1000000,        10000000,
+       0,              0,              0,              0
+};
+
+static const unsigned char tran_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+static const unsigned int tacc_exp[] = {
+       1,      10,     100,    1000,   10000,  100000, 1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)                                  \
+       ({                                                              \
+               const int __size = size;                                \
+               const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
+               const int __off = 3 - ((start) / 32);                   \
+               const int __shft = (start) & 31;                        \
+               u32 __res;                                              \
+                                                                       \
+               __res = resp[__off] >> __shft;                          \
+               if (__size + __shft > 32)                               \
+                       __res |= resp[__off-1] << ((32 - __shft) % 32); \
+               __res & __mask;                                         \
+       })
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static void mmc_decode_cid(struct mmc_card *card)
+{
+       u32 *resp = card->raw_cid;
+
+       memset(&card->cid, 0, sizeof(struct mmc_cid));
+
+       /*
+        * SD doesn't currently have a version field so we will
+        * have to assume we can parse this.
+        */
+       card->cid.manfid                = UNSTUFF_BITS(resp, 120, 8);
+       card->cid.oemid                 = UNSTUFF_BITS(resp, 104, 16);
+       card->cid.prod_name[0]          = UNSTUFF_BITS(resp, 96, 8);
+       card->cid.prod_name[1]          = UNSTUFF_BITS(resp, 88, 8);
+       card->cid.prod_name[2]          = UNSTUFF_BITS(resp, 80, 8);
+       card->cid.prod_name[3]          = UNSTUFF_BITS(resp, 72, 8);
+       card->cid.prod_name[4]          = UNSTUFF_BITS(resp, 64, 8);
+       card->cid.hwrev                 = UNSTUFF_BITS(resp, 60, 4);
+       card->cid.fwrev                 = UNSTUFF_BITS(resp, 56, 4);
+       card->cid.serial                = UNSTUFF_BITS(resp, 24, 32);
+       card->cid.year                  = UNSTUFF_BITS(resp, 12, 8);
+       card->cid.month                 = UNSTUFF_BITS(resp, 8, 4);
+
+       card->cid.year += 2000; /* SD cards year offset */
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static void mmc_decode_csd(struct mmc_card *card)
+{
+       struct mmc_csd *csd = &card->csd;
+       unsigned int e, m, csd_struct;
+       u32 *resp = card->raw_csd;
+
+       csd_struct = UNSTUFF_BITS(resp, 126, 2);
+
+       switch (csd_struct) {
+       case 0:
+               m = UNSTUFF_BITS(resp, 115, 4);
+               e = UNSTUFF_BITS(resp, 112, 3);
+               csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+               csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+               m = UNSTUFF_BITS(resp, 99, 4);
+               e = UNSTUFF_BITS(resp, 96, 3);
+               csd->max_dtr      = tran_exp[e] * tran_mant[m];
+               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+               e = UNSTUFF_BITS(resp, 47, 3);
+               m = UNSTUFF_BITS(resp, 62, 12);
+               csd->capacity     = (1 + m) << (e + 2);
+
+               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+               csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+               csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+               csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+               csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+               csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+               csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+               break;
+       case 1:
+               /*
+                * This is a block-addressed SDHC card. Most
+                * interesting fields are unused and have fixed
+                * values. To avoid getting tripped by buggy cards,
+                * we assume those fixed values ourselves.
+                */
+               mmc_card_set_blockaddr(card);
+
+               csd->tacc_ns     = 0; /* Unused */
+               csd->tacc_clks   = 0; /* Unused */
+
+               m = UNSTUFF_BITS(resp, 99, 4);
+               e = UNSTUFF_BITS(resp, 96, 3);
+               csd->max_dtr      = tran_exp[e] * tran_mant[m];
+               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+               m = UNSTUFF_BITS(resp, 48, 22);
+               csd->capacity     = (1 + m) << 10;
+
+               csd->read_blkbits = 9;
+               csd->read_partial = 0;
+               csd->write_misalign = 0;
+               csd->read_misalign = 0;
+               csd->r2w_factor = 4; /* Unused */
+               csd->write_blkbits = 9;
+               csd->write_partial = 0;
+               break;
+       default:
+               printk("%s: unrecognised CSD structure version %d\n",
+                       mmc_hostname(card->host), csd_struct);
+               mmc_card_set_bad(card);
+               return;
+       }
+}
+
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static void mmc_decode_scr(struct mmc_card *card)
+{
+       struct sd_scr *scr = &card->scr;
+       unsigned int scr_struct;
+       u32 resp[4];
+
+       BUG_ON(!mmc_card_sd(card));
+
+       resp[3] = card->raw_scr[1];
+       resp[2] = card->raw_scr[0];
+
+       scr_struct = UNSTUFF_BITS(resp, 60, 4);
+       if (scr_struct != 0) {
+               printk("%s: unrecognised SCR structure version %d\n",
+                       mmc_hostname(card->host), scr_struct);
+               mmc_card_set_bad(card);
+               return;
+       }
+
+       scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+       scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
+}
+
+/*
+ * Test if the card supports high-speed mode and, if so, switch to it.
+ */
+static int mmc_switch_hs(struct mmc_card *card)
+{
+       int err;
+       u8 *status;
+
+       if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+               return MMC_ERR_NONE;
+
+       err = MMC_ERR_FAILED;
+
+       status = kmalloc(64, GFP_KERNEL);
+       if (!status) {
+               printk("%s: could not allocate a buffer for switch "
+                      "capabilities.\n",
+                       mmc_hostname(card->host));
+               return err;
+       }
+
+       err = mmc_sd_switch(card, 0, 0, 1, status);
+       if (err != MMC_ERR_NONE) {
+               /*
+                * Card not supporting high-speed will ignore the
+                * command.
+                */
+               if (err == MMC_ERR_TIMEOUT)
+                       err = MMC_ERR_NONE;
+               goto out;
+       }
+
+       if (status[13] & 0x02)
+               card->sw_caps.hs_max_dtr = 50000000;
+
+       err = mmc_sd_switch(card, 1, 0, 1, status);
+       if (err != MMC_ERR_NONE)
+               goto out;
+
+       if ((status[16] & 0xF) != 1) {
+               printk(KERN_WARNING "%s: Problem switching card "
+                       "into high-speed mode!\n",
+                       mmc_hostname(card->host));
+       } else {
+               mmc_card_set_highspeed(card);
+               mmc_set_timing(card->host, MMC_TIMING_SD_HS);
+       }
+
+out:
+       kfree(status);
+
+       return err;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_sd_remove(struct mmc_host *host)
+{
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_remove_card(host->card);
+       host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_sd_detect(struct mmc_host *host)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+
+       /*
+        * Just check if our card has been removed.
+        */
+       err = mmc_send_status(host->card, NULL);
+
+       mmc_release_host(host);
+
+       if (err != MMC_ERR_NONE) {
+               mmc_remove_card(host->card);
+               host->card = NULL;
+
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+               mmc_release_host(host);
+       }
+}
+
+static const struct mmc_bus_ops mmc_sd_ops = {
+       .remove = mmc_sd_remove,
+       .detect = mmc_sd_detect,
+};
+
+/*
+ * Starting point for SD card init.
+ */
+int mmc_attach_sd(struct mmc_host *host, u32 ocr)
+{
+       struct mmc_card *card;
+       int err;
+       u32 cid[4];
+       unsigned int max_dtr;
+
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+
+       mmc_attach_bus(host, &mmc_sd_ops);
+
+       host->ocr = mmc_select_voltage(host, ocr);
+
+       /*
+        * Can we support the voltage(s) of the card(s)?
+        */
+       if (!host->ocr)
+               goto err;
+
+       /*
+        * 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.
+        */
+       mmc_go_idle(host);
+
+       /*
+        * If SD_SEND_IF_COND indicates an SD 2.0
+        * compliant card and we should set bit 30
+        * of the ocr to indicate that we can handle
+        * block-addressed SDHC cards.
+        */
+       err = mmc_send_if_cond(host, host->ocr);
+       if (err == MMC_ERR_NONE)
+               ocr = host->ocr | (1 << 30);
+
+       mmc_send_app_op_cond(host, ocr, NULL);
+
+       /*
+        * Fetch CID from card.
+        */
+       err = mmc_all_send_cid(host, cid);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       /*
+        * Allocate card structure.
+        */
+       card = mmc_alloc_card(host);
+       if (IS_ERR(card))
+               goto err;
+
+       card->type = MMC_TYPE_SD;
+       memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+
+       /*
+        * Set card RCA.
+        */
+       err = mmc_send_relative_addr(host, &card->rca);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+       /*
+        * Fetch CSD from card.
+        */
+       err = mmc_send_csd(card, card->raw_csd);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       mmc_decode_csd(card);
+       mmc_decode_cid(card);
+
+       /*
+        * Fetch SCR from card.
+        */
+       err = mmc_select_card(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       err = mmc_app_send_scr(card, card->raw_scr);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       mmc_decode_scr(card);
+
+       /*
+        * Check if card can be switched into high-speed mode.
+        */
+       err = mmc_switch_hs(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       /*
+        * Compute bus speed.
+        */
+       max_dtr = (unsigned int)-1;
+
+       if (mmc_card_highspeed(card)) {
+               if (max_dtr > card->sw_caps.hs_max_dtr)
+                       max_dtr = card->sw_caps.hs_max_dtr;
+       } else if (max_dtr > card->csd.max_dtr) {
+               max_dtr = card->csd.max_dtr;
+       }
+
+       mmc_set_clock(host, max_dtr);
+
+       /*
+        * Switch to wider bus (if supported).
+        */
+       if ((host->caps && MMC_CAP_4_BIT_DATA) &&
+               (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+               err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+
+               mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
+       }
+
+       host->card = card;
+
+       mmc_release_host(host);
+
+       err = mmc_register_card(card);
+       if (err)
+               goto reclaim_host;
+
+       return 0;
+
+reclaim_host:
+       mmc_claim_host(host);
+free_card:
+       mmc_remove_card(card);
+       host->card = NULL;
+err:
+       mmc_detach_bus(host);
+       mmc_release_host(host);
+
+       return 0;
+}
+