]> err.no Git - linux-2.6/commitdiff
mmc: MMC sector based cards
authorPierre Ossman <drzeus@drzeus.cx>
Sat, 17 Feb 2007 21:15:27 +0000 (22:15 +0100)
committerPierre Ossman <drzeus@drzeus.cx>
Tue, 1 May 2007 11:04:15 +0000 (13:04 +0200)
Support for MMC 4.2 sector based cards. This tweaks the init a
bit and reads a new field out of the EXT_CSD.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
drivers/mmc/mmc.c
drivers/mmc/mmc_block.c
include/linux/mmc/card.h
include/linux/mmc/protocol.h

index 2ba46273496bcf566ce6d271f320521b6ef570d8..f772df93a3989956a42f2a888aa8c862de1bc488 100644 (file)
@@ -1106,11 +1106,29 @@ static void mmc_process_ext_csds(struct mmc_host *host)
                mmc_wait_for_req(host, &mrq);
 
                if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       printk("%s: unable to read EXT_CSD, performance "
-                               "might suffer.\n", mmc_hostname(card->host));
+                       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));
+                               mmc_card_set_dead(card);
+                       } else {
+                               printk(KERN_WARNING "%s: unable to read "
+                                       "EXT_CSD, performance might "
+                                       "suffer.\n",
+                                       mmc_hostname(card->host));
+                       }
                        continue;
                }
 
+               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;
@@ -1499,7 +1517,8 @@ static void mmc_setup(struct mmc_host *host)
                        mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
                }
        } else {
-               mmc_send_op_cond(host, host->ocr, NULL);
+               /* The extra bit indicates that we support high capacity */
+               mmc_send_op_cond(host, host->ocr | (1 << 30), NULL);
        }
 
        mmc_discover_cards(host);
index 95b0da6abe870d87754bfcf6b3f48166f3b08aeb..63fbde8756acaeda6df14a8d86a9f5224d8c58a0 100644 (file)
@@ -491,11 +491,20 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 
        blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
 
-       /*
-        * The CSD capacity field is in units of read_blkbits.
-        * set_capacity takes units of 512 bytes.
-        */
-       set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
+       if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
+               /*
+                * The EXT_CSD sector count is in number or 512 byte
+                * sectors.
+                */
+               set_capacity(md->disk, card->ext_csd.sectors);
+       } else {
+               /*
+                * The CSD capacity field is in units of read_blkbits.
+                * set_capacity takes units of 512 bytes.
+                */
+               set_capacity(md->disk,
+                       card->csd.capacity << (card->csd.read_blkbits - 9));
+       }
        return md;
 
  err_putdisk:
index e45712acfac57901bab5e5d0e5708586300eb91d..5d9896c260a2accee04a4f5929a9f4eca144c915 100644 (file)
@@ -41,6 +41,7 @@ struct mmc_csd {
 
 struct mmc_ext_csd {
        unsigned int            hs_max_dtr;
+       unsigned int            sectors;
 };
 
 struct sd_scr {
index c90b6768329d51b024de636c5c8c56ba721ff3ec..d740ab94fa25f647e8a3d915c0864bed7a9b6f23 100644 (file)
@@ -284,6 +284,7 @@ struct _mmc_csd {
 #define EXT_CSD_BUS_WIDTH      183     /* R/W */
 #define EXT_CSD_HS_TIMING      185     /* R/W */
 #define EXT_CSD_CARD_TYPE      196     /* RO */
+#define EXT_CSD_SEC_CNT                212     /* RO, 4 bytes */
 
 /*
  * EXT_CSD field definitions