aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/mmc.c
diff options
context:
space:
mode:
authorPhilip Langdale <philipl@overt.org>2006-10-29 04:14:19 -0500
committerPierre Ossman <drzeus@drzeus.cx>2006-12-01 12:22:44 -0500
commite45a1bd20fa5b920901879e85cdf5eda21f78d7c (patch)
treed767af9df9ae4b39e9bd3675b1644fa5eaccd325 /drivers/mmc/mmc.c
parentbce40a36de574376f41f1ff3c4d212a7da2a3c90 (diff)
mmc: Add support for mmc v4 wide-bus modes
This change adds support for the mmc4 4-bit wide-bus mode. The mmc4 spec defines 8-bit and 4-bit transfer modes. As we do not support any 8-bit hardware, this patch only adds support for the 4-bit mode, but it can easily be built upon when the time comes. The 4-bit mode is electrically compatible with SD's 4-bit mode but the procedure for turning it on is different. This patch implements only the essential parts of the procedure as defined by the spec. Two additional steps are recommended but not compulsory. I am documenting them here so that there's a record. 1) A bus-test mechanism is implemented using dedicated mmc commands which allow for testing the functionality of the data bus at the electrical level. This is pretty paranoid and they way the commands work is not compatible with the mmc subsystem (they don't set valid CRC values). 2) MMC v4 cards can indicate they would like to draw more than the default amount of current in wide-bus modes. We currently will never switch the card into a higher draw mode. Supposedly, allowing the card to draw more current will let it perform better, but the specs seem to indicate that the card will function correctly without the mode change. Empirical testing supports this interpretation. Signed-off-by: Philip Langdale <philipl@overt.org> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/mmc.c')
-rw-r--r--drivers/mmc/mmc.c51
1 files changed, 37 insertions, 14 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2d5b93000dee..1593a6a632cf 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -397,23 +397,23 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
397 return err; 397 return err;
398 398
399 /* 399 /*
400 * Default bus width is 1 bit. 400 * We can only change the bus width of SD cards when
401 */ 401 * they are selected so we have to put the handling
402 host->ios.bus_width = MMC_BUS_WIDTH_1;
403
404 /*
405 * We can only change the bus width of the selected
406 * card so therefore we have to put the handling
407 * here. 402 * here.
403 *
404 * The card is in 1 bit mode by default so
405 * we only need to change if it supports the
406 * wider version.
408 */ 407 */
409 if (host->caps & MMC_CAP_4_BIT_DATA) { 408 if (mmc_card_sd(card) &&
409 (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
410
410 /* 411 /*
411 * The card is in 1 bit mode by default so 412 * Default bus width is 1 bit.
412 * we only need to change if it supports the 413 */
413 * wider version. 414 host->ios.bus_width = MMC_BUS_WIDTH_1;
414 */ 415
415 if (mmc_card_sd(card) && 416 if (host->caps & MMC_CAP_4_BIT_DATA) {
416 (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
417 struct mmc_command cmd; 417 struct mmc_command cmd;
418 cmd.opcode = SD_APP_SET_BUS_WIDTH; 418 cmd.opcode = SD_APP_SET_BUS_WIDTH;
419 cmd.arg = SD_BUS_WIDTH_4; 419 cmd.arg = SD_BUS_WIDTH_4;
@@ -1055,6 +1055,29 @@ static void mmc_process_ext_csds(struct mmc_host *host)
1055 } 1055 }
1056 1056
1057 mmc_card_set_highspeed(card); 1057 mmc_card_set_highspeed(card);
1058
1059 /* Check for host support for wide-bus modes. */
1060 if (!(host->caps & MMC_CAP_4_BIT_DATA)) {
1061 continue;
1062 }
1063
1064 /* Activate 4-bit support. */
1065 cmd.opcode = MMC_SWITCH;
1066 cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
1067 (EXT_CSD_BUS_WIDTH << 16) |
1068 (EXT_CSD_BUS_WIDTH_4 << 8) |
1069 EXT_CSD_CMD_SET_NORMAL;
1070 cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
1071
1072 err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
1073 if (err != MMC_ERR_NONE) {
1074 printk("%s: failed to switch card to "
1075 "mmc v4 4-bit bus mode.\n",
1076 mmc_hostname(card->host));
1077 continue;
1078 }
1079
1080 host->ios.bus_width = MMC_BUS_WIDTH_4;
1058 } 1081 }
1059 1082
1060 kfree(ext_csd); 1083 kfree(ext_csd);