aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPhilip Rakity <prakity@marvell.com>2010-11-19 16:48:39 -0500
committerChris Ball <cjb@laptop.org>2010-11-22 15:12:04 -0500
commit15ec44611904be0dcc97b84c29fbf964e5e2b36f (patch)
treed64384c6bf47beee40172419a29b09c2943e964e /drivers
parented919b0125b26dcc052e44836f66e7e1f5c49c7e (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.c4
-rw-r--r--drivers/mmc/host/sdhci.c44
-rw-r--r--drivers/mmc/host/sdhci.h5
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);