]> err.no Git - linux-2.6/commitdiff
mmc: sdhci high speed support
authorPierre Ossman <drzeus@drzeus.cx>
Wed, 8 Nov 2006 22:06:35 +0000 (23:06 +0100)
committerPierre Ossman <drzeus@drzeus.cx>
Fri, 1 Dec 2006 17:54:10 +0000 (18:54 +0100)
The SDHCI spec implies that is is incorrect to set a clock
frequency above 25 MHz without setting the high speed bit.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
drivers/mmc/sdhci.c
drivers/mmc/sdhci.h

index 54990ed26770277fff3b84726bf632f71bacf4c5..cd98117632d38e66687ad8aa91185c5dccf9a067 100644 (file)
@@ -616,6 +616,7 @@ static void sdhci_finish_command(struct sdhci_host *host)
 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        int div;
+       u8 ctrl;
        u16 clk;
        unsigned long timeout;
 
@@ -624,6 +625,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 
        writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
 
+       ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+       if (clock > 25000000)
+               ctrl |= SDHCI_CTRL_HISPD;
+       else
+               ctrl &= ~SDHCI_CTRL_HISPD;
+       writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+
        if (clock == 0)
                goto out;
 
@@ -1291,6 +1299,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        else if (caps & SDHCI_CAN_VDD_180)
                mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
 
+       if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
+               printk(KERN_ERR "%s: Controller reports > 25 MHz base clock,"
+                       " but no high speed support.\n",
+                       host->slot_descr);
+               mmc->f_max = 25000000;
+       }
+
        if (mmc->ocr_avail == 0) {
                printk(KERN_ERR "%s: Hardware doesn't report any "
                        "support voltages.\n", host->slot_descr);
index 72a67937afe0edc83fe8289116c1e61304367b3f..f9d1a0a6f03a97fae3e0b1ebd7a129999877c42a 100644 (file)
@@ -71,6 +71,7 @@
 #define SDHCI_HOST_CONTROL     0x28
 #define  SDHCI_CTRL_LED                0x01
 #define  SDHCI_CTRL_4BITBUS    0x02
+#define  SDHCI_CTRL_HISPD      0x04
 
 #define SDHCI_POWER_CONTROL    0x29
 #define  SDHCI_POWER_ON                0x01
 #define  SDHCI_CLOCK_BASE_SHIFT        8
 #define  SDHCI_MAX_BLOCK_MASK  0x00030000
 #define  SDHCI_MAX_BLOCK_SHIFT  16
+#define  SDHCI_CAN_DO_HISPD    0x00200000
 #define  SDHCI_CAN_DO_DMA      0x00400000
 #define  SDHCI_CAN_VDD_330     0x01000000
 #define  SDHCI_CAN_VDD_300     0x02000000