aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2007-02-17 16:15:27 -0500
committerPierre Ossman <drzeus@drzeus.cx>2007-05-01 07:04:15 -0400
commit85a18ad93ec66888d85758630019b10a84257f3c (patch)
tree46b1b7f72a8d4baac51916ca4ea09884ed043822
parentde85989511f3a0e15b04d18582b23d428d6ddbbd (diff)
mmc: MMC sector based cards
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>
-rw-r--r--drivers/mmc/mmc.c25
-rw-r--r--drivers/mmc/mmc_block.c19
-rw-r--r--include/linux/mmc/card.h1
-rw-r--r--include/linux/mmc/protocol.h1
4 files changed, 38 insertions, 8 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2ba46273496b..f772df93a398 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1106,11 +1106,29 @@ static void mmc_process_ext_csds(struct mmc_host *host)
1106 mmc_wait_for_req(host, &mrq); 1106 mmc_wait_for_req(host, &mrq);
1107 1107
1108 if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { 1108 if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
1109 printk("%s: unable to read EXT_CSD, performance " 1109 if (card->csd.capacity == (4096 * 512)) {
1110 "might suffer.\n", mmc_hostname(card->host)); 1110 printk(KERN_ERR "%s: unable to read EXT_CSD "
1111 "on a possible high capacity card. "
1112 "Card will be ignored.\n",
1113 mmc_hostname(card->host));
1114 mmc_card_set_dead(card);
1115 } else {
1116 printk(KERN_WARNING "%s: unable to read "
1117 "EXT_CSD, performance might "
1118 "suffer.\n",
1119 mmc_hostname(card->host));
1120 }
1111 continue; 1121 continue;
1112 } 1122 }
1113 1123
1124 card->ext_csd.sectors =
1125 ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
1126 ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
1127 ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
1128 ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
1129 if (card->ext_csd.sectors)
1130 mmc_card_set_blockaddr(card);
1131
1114 switch (ext_csd[EXT_CSD_CARD_TYPE]) { 1132 switch (ext_csd[EXT_CSD_CARD_TYPE]) {
1115 case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: 1133 case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
1116 card->ext_csd.hs_max_dtr = 52000000; 1134 card->ext_csd.hs_max_dtr = 52000000;
@@ -1499,7 +1517,8 @@ static void mmc_setup(struct mmc_host *host)
1499 mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL); 1517 mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
1500 } 1518 }
1501 } else { 1519 } else {
1502 mmc_send_op_cond(host, host->ocr, NULL); 1520 /* The extra bit indicates that we support high capacity */
1521 mmc_send_op_cond(host, host->ocr | (1 << 30), NULL);
1503 } 1522 }
1504 1523
1505 mmc_discover_cards(host); 1524 mmc_discover_cards(host);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 95b0da6abe87..63fbde8756ac 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -491,11 +491,20 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
491 491
492 blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); 492 blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
493 493
494 /* 494 if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
495 * The CSD capacity field is in units of read_blkbits. 495 /*
496 * set_capacity takes units of 512 bytes. 496 * The EXT_CSD sector count is in number or 512 byte
497 */ 497 * sectors.
498 set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9)); 498 */
499 set_capacity(md->disk, card->ext_csd.sectors);
500 } else {
501 /*
502 * The CSD capacity field is in units of read_blkbits.
503 * set_capacity takes units of 512 bytes.
504 */
505 set_capacity(md->disk,
506 card->csd.capacity << (card->csd.read_blkbits - 9));
507 }
499 return md; 508 return md;
500 509
501 err_putdisk: 510 err_putdisk:
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index e45712acfac5..5d9896c260a2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -41,6 +41,7 @@ struct mmc_csd {
41 41
42struct mmc_ext_csd { 42struct mmc_ext_csd {
43 unsigned int hs_max_dtr; 43 unsigned int hs_max_dtr;
44 unsigned int sectors;
44}; 45};
45 46
46struct sd_scr { 47struct sd_scr {
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index c90b6768329d..d740ab94fa25 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -284,6 +284,7 @@ struct _mmc_csd {
284#define EXT_CSD_BUS_WIDTH 183 /* R/W */ 284#define EXT_CSD_BUS_WIDTH 183 /* R/W */
285#define EXT_CSD_HS_TIMING 185 /* R/W */ 285#define EXT_CSD_HS_TIMING 185 /* R/W */
286#define EXT_CSD_CARD_TYPE 196 /* RO */ 286#define EXT_CSD_CARD_TYPE 196 /* RO */
287#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
287 288
288/* 289/*
289 * EXT_CSD field definitions 290 * EXT_CSD field definitions