diff options
author | Philip Rakity <prakity@marvell.com> | 2010-11-19 16:48:39 -0500 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2010-11-22 15:12:04 -0500 |
commit | 15ec44611904be0dcc97b84c29fbf964e5e2b36f (patch) | |
tree | d64384c6bf47beee40172419a29b09c2943e964e /drivers | |
parent | ed919b0125b26dcc052e44836f66e7e1f5c49c7e (diff) |
mmc: sdhci: 8-bit bus width changes
We now:
* check for a v3 controller before setting 8-bit bus width
* offer a callback for platform code to switch to 8-bit mode, which
allows non-v3 controllers to support it
* rely on mmc->caps |= MMC_CAP_8_BIT_DATA; in platform code to specify
that the board designers have indeed brought out all the pins for
8-bit to the slot.
We were previously relying only on whether the *controller* supported
8-bit, which doesn't tell us anything about the pin configuration in
the board design.
This fixes the MMC card regression reported by Maxim Levitsky here:
http://thread.gmane.org/gmane.linux.kernel.mmc/4336
by no longer assuming that 8-bit works by default.
Signed-off-by: Philip Rakity <prakity@marvell.com>
Tested-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/host/sdhci-pxa.c | 4 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 44 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 5 |
3 files changed, 41 insertions, 12 deletions
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c index fc406ac5d19..5a61208cbc6 100644 --- a/drivers/mmc/host/sdhci-pxa.c +++ b/drivers/mmc/host/sdhci-pxa.c | |||
@@ -141,6 +141,10 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev) | |||
141 | if (pdata->quirks) | 141 | if (pdata->quirks) |
142 | host->quirks |= pdata->quirks; | 142 | host->quirks |= pdata->quirks; |
143 | 143 | ||
144 | /* If slot design supports 8 bit data, indicate this to MMC. */ | ||
145 | if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) | ||
146 | host->mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
147 | |||
144 | ret = sdhci_add_host(host); | 148 | ret = sdhci_add_host(host); |
145 | if (ret) { | 149 | if (ret) { |
146 | dev_err(&pdev->dev, "failed to add host\n"); | 150 | dev_err(&pdev->dev, "failed to add host\n"); |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 154cbf83c1a..a25db426c91 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -1185,17 +1185,31 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1185 | if (host->ops->platform_send_init_74_clocks) | 1185 | if (host->ops->platform_send_init_74_clocks) |
1186 | host->ops->platform_send_init_74_clocks(host, ios->power_mode); | 1186 | host->ops->platform_send_init_74_clocks(host, ios->power_mode); |
1187 | 1187 | ||
1188 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | 1188 | /* |
1189 | 1189 | * If your platform has 8-bit width support but is not a v3 controller, | |
1190 | if (ios->bus_width == MMC_BUS_WIDTH_8) | 1190 | * or if it requires special setup code, you should implement that in |
1191 | ctrl |= SDHCI_CTRL_8BITBUS; | 1191 | * platform_8bit_width(). |
1192 | else | 1192 | */ |
1193 | ctrl &= ~SDHCI_CTRL_8BITBUS; | 1193 | if (host->ops->platform_8bit_width) |
1194 | host->ops->platform_8bit_width(host, ios->bus_width); | ||
1195 | else { | ||
1196 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | ||
1197 | if (ios->bus_width == MMC_BUS_WIDTH_8) { | ||
1198 | ctrl &= ~SDHCI_CTRL_4BITBUS; | ||
1199 | if (host->version >= SDHCI_SPEC_300) | ||
1200 | ctrl |= SDHCI_CTRL_8BITBUS; | ||
1201 | } else { | ||
1202 | if (host->version >= SDHCI_SPEC_300) | ||
1203 | ctrl &= ~SDHCI_CTRL_8BITBUS; | ||
1204 | if (ios->bus_width == MMC_BUS_WIDTH_4) | ||
1205 | ctrl |= SDHCI_CTRL_4BITBUS; | ||
1206 | else | ||
1207 | ctrl &= ~SDHCI_CTRL_4BITBUS; | ||
1208 | } | ||
1209 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | ||
1210 | } | ||
1194 | 1211 | ||
1195 | if (ios->bus_width == MMC_BUS_WIDTH_4) | 1212 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
1196 | ctrl |= SDHCI_CTRL_4BITBUS; | ||
1197 | else | ||
1198 | ctrl &= ~SDHCI_CTRL_4BITBUS; | ||
1199 | 1213 | ||
1200 | if ((ios->timing == MMC_TIMING_SD_HS || | 1214 | if ((ios->timing == MMC_TIMING_SD_HS || |
1201 | ios->timing == MMC_TIMING_MMC_HS) | 1215 | ios->timing == MMC_TIMING_MMC_HS) |
@@ -1855,11 +1869,19 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1855 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; | 1869 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; |
1856 | else | 1870 | else |
1857 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; | 1871 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; |
1872 | |||
1858 | mmc->f_max = host->max_clk; | 1873 | mmc->f_max = host->max_clk; |
1859 | mmc->caps |= MMC_CAP_SDIO_IRQ; | 1874 | mmc->caps |= MMC_CAP_SDIO_IRQ; |
1860 | 1875 | ||
1876 | /* | ||
1877 | * A controller may support 8-bit width, but the board itself | ||
1878 | * might not have the pins brought out. Boards that support | ||
1879 | * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in | ||
1880 | * their platform code before calling sdhci_add_host(), and we | ||
1881 | * won't assume 8-bit width for hosts without that CAP. | ||
1882 | */ | ||
1861 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) | 1883 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) |
1862 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; | 1884 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1863 | 1885 | ||
1864 | if (caps & SDHCI_CAN_DO_HISPD) | 1886 | if (caps & SDHCI_CAN_DO_HISPD) |
1865 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | 1887 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d52a7163b97..e42d7f00c06 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -76,7 +76,7 @@ | |||
76 | #define SDHCI_CTRL_ADMA1 0x08 | 76 | #define SDHCI_CTRL_ADMA1 0x08 |
77 | #define SDHCI_CTRL_ADMA32 0x10 | 77 | #define SDHCI_CTRL_ADMA32 0x10 |
78 | #define SDHCI_CTRL_ADMA64 0x18 | 78 | #define SDHCI_CTRL_ADMA64 0x18 |
79 | #define SDHCI_CTRL_8BITBUS 0x20 | 79 | #define SDHCI_CTRL_8BITBUS 0x20 |
80 | 80 | ||
81 | #define SDHCI_POWER_CONTROL 0x29 | 81 | #define SDHCI_POWER_CONTROL 0x29 |
82 | #define SDHCI_POWER_ON 0x01 | 82 | #define SDHCI_POWER_ON 0x01 |
@@ -155,6 +155,7 @@ | |||
155 | #define SDHCI_CLOCK_BASE_SHIFT 8 | 155 | #define SDHCI_CLOCK_BASE_SHIFT 8 |
156 | #define SDHCI_MAX_BLOCK_MASK 0x00030000 | 156 | #define SDHCI_MAX_BLOCK_MASK 0x00030000 |
157 | #define SDHCI_MAX_BLOCK_SHIFT 16 | 157 | #define SDHCI_MAX_BLOCK_SHIFT 16 |
158 | #define SDHCI_CAN_DO_8BIT 0x00040000 | ||
158 | #define SDHCI_CAN_DO_ADMA2 0x00080000 | 159 | #define SDHCI_CAN_DO_ADMA2 0x00080000 |
159 | #define SDHCI_CAN_DO_ADMA1 0x00100000 | 160 | #define SDHCI_CAN_DO_ADMA1 0x00100000 |
160 | #define SDHCI_CAN_DO_HISPD 0x00200000 | 161 | #define SDHCI_CAN_DO_HISPD 0x00200000 |
@@ -215,6 +216,8 @@ struct sdhci_ops { | |||
215 | unsigned int (*get_max_clock)(struct sdhci_host *host); | 216 | unsigned int (*get_max_clock)(struct sdhci_host *host); |
216 | unsigned int (*get_min_clock)(struct sdhci_host *host); | 217 | unsigned int (*get_min_clock)(struct sdhci_host *host); |
217 | unsigned int (*get_timeout_clock)(struct sdhci_host *host); | 218 | unsigned int (*get_timeout_clock)(struct sdhci_host *host); |
219 | int (*platform_8bit_width)(struct sdhci_host *host, | ||
220 | int width); | ||
218 | void (*platform_send_init_74_clocks)(struct sdhci_host *host, | 221 | void (*platform_send_init_74_clocks)(struct sdhci_host *host, |
219 | u8 power_mode); | 222 | u8 power_mode); |
220 | unsigned int (*get_ro)(struct sdhci_host *host); | 223 | unsigned int (*get_ro)(struct sdhci_host *host); |