diff options
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 76bb621e9aa9..1d8409fcf155 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -534,39 +534,57 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
534 | */ | 534 | */ |
535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && | 535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && |
536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { | 536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { |
537 | unsigned ext_csd_bit, bus_width; | 537 | static unsigned ext_csd_bits[][2] = { |
538 | 538 | { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 }, | |
539 | if (host->caps & MMC_CAP_8_BIT_DATA) { | 539 | { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 }, |
540 | if (ddr) | 540 | { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 }, |
541 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; | 541 | }; |
542 | else | 542 | static unsigned bus_widths[] = { |
543 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | 543 | MMC_BUS_WIDTH_8, |
544 | bus_width = MMC_BUS_WIDTH_8; | 544 | MMC_BUS_WIDTH_4, |
545 | } else { | 545 | MMC_BUS_WIDTH_1 |
546 | if (ddr) | 546 | }; |
547 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; | 547 | unsigned idx, bus_width = 0; |
548 | else | 548 | |
549 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | 549 | if (host->caps & MMC_CAP_8_BIT_DATA) |
550 | bus_width = MMC_BUS_WIDTH_4; | 550 | idx = 0; |
551 | else | ||
552 | idx = 1; | ||
553 | for (; idx < ARRAY_SIZE(bus_widths); idx++) { | ||
554 | bus_width = bus_widths[idx]; | ||
555 | if (bus_width == MMC_BUS_WIDTH_1) | ||
556 | ddr = 0; /* no DDR for 1-bit width */ | ||
557 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
558 | EXT_CSD_BUS_WIDTH, | ||
559 | ext_csd_bits[idx][0]); | ||
560 | if (!err) { | ||
561 | /* | ||
562 | * If controller can't handle bus width test, | ||
563 | * use the highest bus width to maintain | ||
564 | * compatibility with previous MMC behavior. | ||
565 | */ | ||
566 | if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) | ||
567 | break; | ||
568 | mmc_set_bus_width_ddr(card->host, | ||
569 | bus_width, MMC_SDR_MODE); | ||
570 | err = mmc_bus_test(card, bus_width); | ||
571 | if (!err) | ||
572 | break; | ||
573 | } | ||
551 | } | 574 | } |
552 | 575 | ||
553 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 576 | if (!err && ddr) { |
554 | EXT_CSD_BUS_WIDTH, ext_csd_bit); | 577 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
555 | 578 | EXT_CSD_BUS_WIDTH, | |
556 | if (err && err != -EBADMSG) | 579 | ext_csd_bits[idx][1]); |
557 | goto free_card; | 580 | } |
558 | |||
559 | if (err) { | 581 | if (err) { |
560 | printk(KERN_WARNING "%s: switch to bus width %d ddr %d " | 582 | printk(KERN_WARNING "%s: switch to bus width %d ddr %d " |
561 | "failed\n", mmc_hostname(card->host), | 583 | "failed\n", mmc_hostname(card->host), |
562 | 1 << bus_width, ddr); | 584 | 1 << bus_width, ddr); |
563 | err = 0; | 585 | goto free_card; |
564 | } else { | 586 | } else if (ddr) { |
565 | if (ddr) | 587 | mmc_card_set_ddr_mode(card); |
566 | mmc_card_set_ddr_mode(card); | ||
567 | else | ||
568 | ddr = MMC_SDR_MODE; | ||
569 | |||
570 | mmc_set_bus_width_ddr(card->host, bus_width, ddr); | 588 | mmc_set_bus_width_ddr(card->host, bus_width, ddr); |
571 | } | 589 | } |
572 | } | 590 | } |