diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2006-11-08 17:06:35 -0500 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2006-12-01 12:54:10 -0500 |
commit | 077df884835ebf2b5db16aacd9a24691d89902a0 (patch) | |
tree | 6d812005b3f5c9062ccd8dd2157a558a9bb1f0ed /drivers | |
parent | 7ccd266e676a3f0c6f8f897f58b684cac3dd1650 (diff) |
mmc: sdhci high speed support
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/sdhci.c | 15 | ||||
-rw-r--r-- | drivers/mmc/sdhci.h | 2 |
2 files changed, 17 insertions, 0 deletions
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 54990ed26770..cd98117632d3 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c | |||
@@ -616,6 +616,7 @@ static void sdhci_finish_command(struct sdhci_host *host) | |||
616 | static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | 616 | static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) |
617 | { | 617 | { |
618 | int div; | 618 | int div; |
619 | u8 ctrl; | ||
619 | u16 clk; | 620 | u16 clk; |
620 | unsigned long timeout; | 621 | unsigned long timeout; |
621 | 622 | ||
@@ -624,6 +625,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
624 | 625 | ||
625 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | 626 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); |
626 | 627 | ||
628 | ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); | ||
629 | if (clock > 25000000) | ||
630 | ctrl |= SDHCI_CTRL_HISPD; | ||
631 | else | ||
632 | ctrl &= ~SDHCI_CTRL_HISPD; | ||
633 | writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); | ||
634 | |||
627 | if (clock == 0) | 635 | if (clock == 0) |
628 | goto out; | 636 | goto out; |
629 | 637 | ||
@@ -1291,6 +1299,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1291 | else if (caps & SDHCI_CAN_VDD_180) | 1299 | else if (caps & SDHCI_CAN_VDD_180) |
1292 | mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; | 1300 | mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; |
1293 | 1301 | ||
1302 | if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) { | ||
1303 | printk(KERN_ERR "%s: Controller reports > 25 MHz base clock," | ||
1304 | " but no high speed support.\n", | ||
1305 | host->slot_descr); | ||
1306 | mmc->f_max = 25000000; | ||
1307 | } | ||
1308 | |||
1294 | if (mmc->ocr_avail == 0) { | 1309 | if (mmc->ocr_avail == 0) { |
1295 | printk(KERN_ERR "%s: Hardware doesn't report any " | 1310 | printk(KERN_ERR "%s: Hardware doesn't report any " |
1296 | "support voltages.\n", host->slot_descr); | 1311 | "support voltages.\n", host->slot_descr); |
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h index 72a67937afe0..f9d1a0a6f03a 100644 --- a/drivers/mmc/sdhci.h +++ b/drivers/mmc/sdhci.h | |||
@@ -71,6 +71,7 @@ | |||
71 | #define SDHCI_HOST_CONTROL 0x28 | 71 | #define SDHCI_HOST_CONTROL 0x28 |
72 | #define SDHCI_CTRL_LED 0x01 | 72 | #define SDHCI_CTRL_LED 0x01 |
73 | #define SDHCI_CTRL_4BITBUS 0x02 | 73 | #define SDHCI_CTRL_4BITBUS 0x02 |
74 | #define SDHCI_CTRL_HISPD 0x04 | ||
74 | 75 | ||
75 | #define SDHCI_POWER_CONTROL 0x29 | 76 | #define SDHCI_POWER_CONTROL 0x29 |
76 | #define SDHCI_POWER_ON 0x01 | 77 | #define SDHCI_POWER_ON 0x01 |
@@ -138,6 +139,7 @@ | |||
138 | #define SDHCI_CLOCK_BASE_SHIFT 8 | 139 | #define SDHCI_CLOCK_BASE_SHIFT 8 |
139 | #define SDHCI_MAX_BLOCK_MASK 0x00030000 | 140 | #define SDHCI_MAX_BLOCK_MASK 0x00030000 |
140 | #define SDHCI_MAX_BLOCK_SHIFT 16 | 141 | #define SDHCI_MAX_BLOCK_SHIFT 16 |
142 | #define SDHCI_CAN_DO_HISPD 0x00200000 | ||
141 | #define SDHCI_CAN_DO_DMA 0x00400000 | 143 | #define SDHCI_CAN_DO_DMA 0x00400000 |
142 | #define SDHCI_CAN_VDD_330 0x01000000 | 144 | #define SDHCI_CAN_VDD_330 0x01000000 |
143 | #define SDHCI_CAN_VDD_300 0x02000000 | 145 | #define SDHCI_CAN_VDD_300 0x02000000 |