]> err.no Git - linux-2.6/commitdiff
MMC: Fix handling of low-voltage cards
authorPhilip Langdale <philipl@overt.org>
Sat, 17 Mar 2007 02:39:00 +0000 (19:39 -0700)
committerPierre Ossman <drzeus@drzeus.cx>
Tue, 1 May 2007 12:14:50 +0000 (14:14 +0200)
Fix handling of low voltage MMC cards.

The latest MMC and SD specs both agree that support for
low-voltage operations is indicated by bit 7 in the OCR.
The MMC spec states that the low voltage range is
1.65-1.95V while the SD spec leaves the actual voltage
range undefined - meaning that there is still no such
thing as a low voltage SD card.

However, an old Sandisk spec implied that bits 7.0
represented voltages below 2.0V in 1V or 0.5V increments,
and the code was accordingly written with that expectation.

This confusion meant that host drivers attempting to support
the typical low voltage (1.8V) would set the wrong bits in
the host OCR mask (usually bits 5 and/or 6) resulting in the
the low voltage mode never being used.

This change corrects the low voltage range and adds sanity
checks on the reserved bits (0-6) and for SD cards that
claim to support low-voltage operations.

Signed-off-by: Philip Langdale <philipl@overt.org>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
drivers/mmc/core/mmc.c
drivers/mmc/core/sd.c
drivers/mmc/host/sdhci.c
include/linux/mmc/host.h

index c528017d6128b613f7acbcff5480c9eeac1f032c..c2e120b11bef7cebe71c5916fa866bf6f02bbfe0 100644 (file)
@@ -323,6 +323,17 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
 
        mmc_attach_bus(host, &mmc_ops);
 
+       /*
+        * Sanity check the voltages that the card claims to
+        * support.
+        */
+       if (ocr & 0x7F) {
+               printk(KERN_WARNING "%s: card claims to support voltages "
+                      "below the defined range. These will be ignored.\n",
+                      mmc_hostname(host));
+               ocr &= ~0x7F;
+       }
+
        host->ocr = mmc_select_voltage(host, ocr);
 
        /*
index 6c6beb48f3a8b2df582c6bd040fa6b8150d31877..fb18b301502e558b3b01d223a04ebb526cb6ed07 100644 (file)
@@ -297,6 +297,24 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
 
        mmc_attach_bus(host, &mmc_sd_ops);
 
+       /*
+        * Sanity check the voltages that the card claims to
+        * support.
+        */
+       if (ocr & 0x7F) {
+               printk(KERN_WARNING "%s: card claims to support voltages "
+                      "below the defined range. These will be ignored.\n",
+                      mmc_hostname(host));
+               ocr &= ~0x7F;
+       }
+
+       if (ocr & MMC_VDD_165_195) {
+               printk(KERN_WARNING "%s: SD card claims to support the "
+                      "incompletely defined 'low voltage range'. This "
+                      "will be ignored.\n", mmc_hostname(host));
+               ocr &= ~MMC_VDD_165_195;
+       }
+
        host->ocr = mmc_select_voltage(host, ocr);
 
        /*
index a57f6a3d48d340e94ad5e07ca6b6901ad4ff562f..ff5bf73cdd25656bcc41df6b1dc9e7e03e4d42f0 100644 (file)
@@ -659,8 +659,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
        pwr = SDHCI_POWER_ON;
 
        switch (1 << power) {
-       case MMC_VDD_17_18:
-       case MMC_VDD_18_19:
+       case MMC_VDD_165_195:
                pwr |= SDHCI_POWER_180;
                break;
        case MMC_VDD_29_30:
@@ -1280,7 +1279,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        if (caps & SDHCI_CAN_VDD_300)
                mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
        if (caps & SDHCI_CAN_VDD_180)
-               mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
+               mmc->ocr_avail |= MMC_VDD_165_195;
 
        if (mmc->ocr_avail == 0) {
                printk(KERN_ERR "%s: Hardware doesn't report any "
index 5a66d8a2bf17a8b6614ce29bebd38ddf4bdeca08..b1350dfd3e9108751b9fadd15dd8f1e61b77da2d 100644 (file)
@@ -65,14 +65,7 @@ struct mmc_host {
        unsigned int            f_max;
        u32                     ocr_avail;
 
-#define MMC_VDD_145_150                0x00000001      /* VDD voltage 1.45 - 1.50 */
-#define MMC_VDD_150_155                0x00000002      /* VDD voltage 1.50 - 1.55 */
-#define MMC_VDD_155_160                0x00000004      /* VDD voltage 1.55 - 1.60 */
-#define MMC_VDD_160_165                0x00000008      /* VDD voltage 1.60 - 1.65 */
-#define MMC_VDD_165_170                0x00000010      /* VDD voltage 1.65 - 1.70 */
-#define MMC_VDD_17_18          0x00000020      /* VDD voltage 1.7 - 1.8 */
-#define MMC_VDD_18_19          0x00000040      /* VDD voltage 1.8 - 1.9 */
-#define MMC_VDD_19_20          0x00000080      /* VDD voltage 1.9 - 2.0 */
+#define MMC_VDD_165_195                0x00000080      /* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21          0x00000100      /* VDD voltage 2.0 ~ 2.1 */
 #define MMC_VDD_21_22          0x00000200      /* VDD voltage 2.1 ~ 2.2 */
 #define MMC_VDD_22_23          0x00000400      /* VDD voltage 2.2 ~ 2.3 */