diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-02-17 17:49:01 -0500 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2009-02-18 16:09:56 -0500 |
commit | eb25082657be3e7639e349fc926afdcbb0a4dc65 (patch) | |
tree | d311c5c0d95c9837e2a7b8b54bf0aa256df5bd7f /drivers/mmc/host/omap_hsmmc.c | |
parent | 249d0fa9d59b6165ecc224720d9ce9b7267cf1b8 (diff) |
omap_hsmmc: only MMC1 allows HCTL.SDVS != 1.8V
Based on a patch from Tony Lindgren ... after initialization,
never change HCTL.SDVS except for MMC1. The other controller
instances only support 1.8V in that field, although they can
suport other card/SDIO/eMMC/... voltages with level shifting
solutions such as external transceivers.
MMC2 behavior sanity tested on Overo/WLAN, OMAP3430 SDP, and
custom hardware. MMC1 also sanity tested on those platforms
plus Beagle. This also fixes a bug preventing MMC2 (and also
presumably MMC3) from powering down when requested.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4dba48642e60..3bfd0facb794 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #define VS30 (1 << 25) | 55 | #define VS30 (1 << 25) |
56 | #define SDVS18 (0x5 << 9) | 56 | #define SDVS18 (0x5 << 9) |
57 | #define SDVS30 (0x6 << 9) | 57 | #define SDVS30 (0x6 << 9) |
58 | #define SDVS33 (0x7 << 9) | ||
58 | #define SDVSCLR 0xFFFFF1FF | 59 | #define SDVSCLR 0xFFFFF1FF |
59 | #define SDVSDET 0x00000400 | 60 | #define SDVSDET 0x00000400 |
60 | #define AUTOIDLE 0x1 | 61 | #define AUTOIDLE 0x1 |
@@ -456,13 +457,20 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
456 | } | 457 | } |
457 | 458 | ||
458 | /* | 459 | /* |
459 | * Switch MMC operating voltage | 460 | * Switch MMC interface voltage ... only relevant for MMC1. |
461 | * | ||
462 | * MMC2 and MMC3 use fixed 1.8V levels, and maybe a transceiver. | ||
463 | * The MMC2 transceiver controls are used instead of DAT4..DAT7. | ||
464 | * Some chips, like eMMC ones, use internal transceivers. | ||
460 | */ | 465 | */ |
461 | static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) | 466 | static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) |
462 | { | 467 | { |
463 | u32 reg_val = 0; | 468 | u32 reg_val = 0; |
464 | int ret; | 469 | int ret; |
465 | 470 | ||
471 | if (host->id != OMAP_MMC1_DEVID) | ||
472 | return 0; | ||
473 | |||
466 | /* Disable the clocks */ | 474 | /* Disable the clocks */ |
467 | clk_disable(host->fclk); | 475 | clk_disable(host->fclk); |
468 | clk_disable(host->iclk); | 476 | clk_disable(host->iclk); |
@@ -485,19 +493,26 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) | |||
485 | OMAP_HSMMC_WRITE(host->base, HCTL, | 493 | OMAP_HSMMC_WRITE(host->base, HCTL, |
486 | OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR); | 494 | OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR); |
487 | reg_val = OMAP_HSMMC_READ(host->base, HCTL); | 495 | reg_val = OMAP_HSMMC_READ(host->base, HCTL); |
496 | |||
488 | /* | 497 | /* |
489 | * If a MMC dual voltage card is detected, the set_ios fn calls | 498 | * If a MMC dual voltage card is detected, the set_ios fn calls |
490 | * this fn with VDD bit set for 1.8V. Upon card removal from the | 499 | * this fn with VDD bit set for 1.8V. Upon card removal from the |
491 | * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF. | 500 | * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF. |
492 | * | 501 | * |
493 | * Only MMC1 supports 3.0V. MMC2 will not function if SDVS30 is | 502 | * Cope with a bit of slop in the range ... per data sheets: |
494 | * set in HCTL. | 503 | * - "1.8V" for vdds_mmc1/vdds_mmc1a can be up to 2.45V max, |
504 | * but recommended values are 1.71V to 1.89V | ||
505 | * - "3.0V" for vdds_mmc1/vdds_mmc1a can be up to 3.5V max, | ||
506 | * but recommended values are 2.7V to 3.3V | ||
507 | * | ||
508 | * Board setup code shouldn't permit anything very out-of-range. | ||
509 | * TWL4030-family VMMC1 and VSIM regulators are fine (avoiding the | ||
510 | * middle range) but VSIM can't power DAT4..DAT7 at more than 3V. | ||
495 | */ | 511 | */ |
496 | if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) || | 512 | if ((1 << vdd) <= MMC_VDD_23_24) |
497 | ((1 << vdd) == MMC_VDD_33_34))) | ||
498 | reg_val |= SDVS30; | ||
499 | if ((1 << vdd) == MMC_VDD_165_195) | ||
500 | reg_val |= SDVS18; | 513 | reg_val |= SDVS18; |
514 | else | ||
515 | reg_val |= SDVS30; | ||
501 | 516 | ||
502 | OMAP_HSMMC_WRITE(host->base, HCTL, reg_val); | 517 | OMAP_HSMMC_WRITE(host->base, HCTL, reg_val); |
503 | 518 | ||
@@ -759,10 +774,14 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
759 | case MMC_POWER_OFF: | 774 | case MMC_POWER_OFF: |
760 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); | 775 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); |
761 | /* | 776 | /* |
762 | * Reset bus voltage to 3V if it got set to 1.8V earlier. | 777 | * Reset interface voltage to 3V if it's 1.8V now; |
778 | * only relevant on MMC-1, the others always use 1.8V. | ||
779 | * | ||
763 | * REVISIT: If we are able to detect cards after unplugging | 780 | * REVISIT: If we are able to detect cards after unplugging |
764 | * a 1.8V card, this code should not be needed. | 781 | * a 1.8V card, this code should not be needed. |
765 | */ | 782 | */ |
783 | if (host->id != OMAP_MMC1_DEVID) | ||
784 | break; | ||
766 | if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) { | 785 | if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) { |
767 | int vdd = fls(host->mmc->ocr_avail) - 1; | 786 | int vdd = fls(host->mmc->ocr_avail) - 1; |
768 | if (omap_mmc_switch_opcond(host, vdd) != 0) | 787 | if (omap_mmc_switch_opcond(host, vdd) != 0) |
@@ -786,7 +805,9 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
786 | } | 805 | } |
787 | 806 | ||
788 | if (host->id == OMAP_MMC1_DEVID) { | 807 | if (host->id == OMAP_MMC1_DEVID) { |
789 | /* Only MMC1 can operate at 3V/1.8V */ | 808 | /* Only MMC1 can interface at 3V without some flavor |
809 | * of external transceiver; but they all handle 1.8V. | ||
810 | */ | ||
790 | if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) && | 811 | if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) && |
791 | (ios->vdd == DUAL_VOLT_OCR_BIT)) { | 812 | (ios->vdd == DUAL_VOLT_OCR_BIT)) { |
792 | /* | 813 | /* |
@@ -1139,7 +1160,9 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
1139 | " level suspend\n"); | 1160 | " level suspend\n"); |
1140 | } | 1161 | } |
1141 | 1162 | ||
1142 | if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) { | 1163 | if (host->id == OMAP_MMC1_DEVID |
1164 | && !(OMAP_HSMMC_READ(host->base, HCTL) | ||
1165 | & SDVSDET)) { | ||
1143 | OMAP_HSMMC_WRITE(host->base, HCTL, | 1166 | OMAP_HSMMC_WRITE(host->base, HCTL, |
1144 | OMAP_HSMMC_READ(host->base, HCTL) | 1167 | OMAP_HSMMC_READ(host->base, HCTL) |
1145 | & SDVSCLR); | 1168 | & SDVSCLR); |