diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-01-12 00:37:42 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-12 00:37:42 -0500 |
commit | 83eb95b852902f952ba594447a796ad8146b9462 (patch) | |
tree | 33c199aeeae58b69ad8d6d2a33c2d96ba2b98ddf /drivers/mmc/core/mmc.c | |
parent | efb3e34b6176d30c4fe8635fa8e1beb6280cc2cd (diff) | |
parent | 9bbe7b984096ac45586da2adf26c14069ecb79b2 (diff) |
Merge branch 'sh/sdio' into sh-latest
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 91 |
1 files changed, 58 insertions, 33 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 77f93c3b8808..16006ef153fe 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 | mmc_set_bus_width_ddr(card->host, | ||
562 | bus_width, MMC_SDR_MODE); | ||
563 | /* | ||
564 | * If controller can't handle bus width test, | ||
565 | * use the highest bus width to maintain | ||
566 | * compatibility with previous MMC behavior. | ||
567 | */ | ||
568 | if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) | ||
569 | break; | ||
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 | } |
@@ -737,14 +755,21 @@ static void mmc_attach_bus_ops(struct mmc_host *host) | |||
737 | /* | 755 | /* |
738 | * Starting point for MMC card init. | 756 | * Starting point for MMC card init. |
739 | */ | 757 | */ |
740 | int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | 758 | int mmc_attach_mmc(struct mmc_host *host) |
741 | { | 759 | { |
742 | int err; | 760 | int err; |
761 | u32 ocr; | ||
743 | 762 | ||
744 | BUG_ON(!host); | 763 | BUG_ON(!host); |
745 | WARN_ON(!host->claimed); | 764 | WARN_ON(!host->claimed); |
746 | 765 | ||
766 | err = mmc_send_op_cond(host, 0, &ocr); | ||
767 | if (err) | ||
768 | return err; | ||
769 | |||
747 | mmc_attach_bus_ops(host); | 770 | mmc_attach_bus_ops(host); |
771 | if (host->ocr_avail_mmc) | ||
772 | host->ocr_avail = host->ocr_avail_mmc; | ||
748 | 773 | ||
749 | /* | 774 | /* |
750 | * We need to get OCR a different way for SPI. | 775 | * We need to get OCR a different way for SPI. |
@@ -784,20 +809,20 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
784 | goto err; | 809 | goto err; |
785 | 810 | ||
786 | mmc_release_host(host); | 811 | mmc_release_host(host); |
787 | |||
788 | err = mmc_add_card(host->card); | 812 | err = mmc_add_card(host->card); |
813 | mmc_claim_host(host); | ||
789 | if (err) | 814 | if (err) |
790 | goto remove_card; | 815 | goto remove_card; |
791 | 816 | ||
792 | return 0; | 817 | return 0; |
793 | 818 | ||
794 | remove_card: | 819 | remove_card: |
820 | mmc_release_host(host); | ||
795 | mmc_remove_card(host->card); | 821 | mmc_remove_card(host->card); |
796 | host->card = NULL; | ||
797 | mmc_claim_host(host); | 822 | mmc_claim_host(host); |
823 | host->card = NULL; | ||
798 | err: | 824 | err: |
799 | mmc_detach_bus(host); | 825 | mmc_detach_bus(host); |
800 | mmc_release_host(host); | ||
801 | 826 | ||
802 | printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", | 827 | printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", |
803 | mmc_hostname(host), err); | 828 | mmc_hostname(host), err); |