Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Philip Rakity and committed by
Chris Ball
15ec4461 ed919b01

+44 -12
+3
arch/arm/plat-pxa/include/plat/sdhci.h
··· 17 17 /* Require clock free running */ 18 18 #define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0) 19 19 20 + /* Board design supports 8-bit data on SD/SDIO BUS */ 21 + #define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2) 22 + 20 23 /* 21 24 * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI 22 25 * @max_speed: the maximum speed supported
+4
drivers/mmc/host/sdhci-pxa.c
··· 141 141 if (pdata->quirks) 142 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 148 ret = sdhci_add_host(host); 145 149 if (ret) { 146 150 dev_err(&pdev->dev, "failed to add host\n");
+33 -11
drivers/mmc/host/sdhci.c
··· 1185 1185 if (host->ops->platform_send_init_74_clocks) 1186 1186 host->ops->platform_send_init_74_clocks(host, ios->power_mode); 1187 1187 1188 + /* 1189 + * If your platform has 8-bit width support but is not a v3 controller, 1190 + * or if it requires special setup code, you should implement that in 1191 + * platform_8bit_width(). 1192 + */ 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 + } 1211 + 1188 1212 ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 1189 - 1190 - if (ios->bus_width == MMC_BUS_WIDTH_8) 1191 - ctrl |= SDHCI_CTRL_8BITBUS; 1192 - else 1193 - ctrl &= ~SDHCI_CTRL_8BITBUS; 1194 - 1195 - if (ios->bus_width == MMC_BUS_WIDTH_4) 1196 - ctrl |= SDHCI_CTRL_4BITBUS; 1197 - else 1198 - ctrl &= ~SDHCI_CTRL_4BITBUS; 1199 1213 1200 1214 if ((ios->timing == MMC_TIMING_SD_HS || 1201 1215 ios->timing == MMC_TIMING_MMC_HS) ··· 1869 1855 mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; 1870 1856 else 1871 1857 mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; 1858 + 1872 1859 mmc->f_max = host->max_clk; 1873 1860 mmc->caps |= MMC_CAP_SDIO_IRQ; 1874 1861 1862 + /* 1863 + * A controller may support 8-bit width, but the board itself 1864 + * might not have the pins brought out. Boards that support 1865 + * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in 1866 + * their platform code before calling sdhci_add_host(), and we 1867 + * won't assume 8-bit width for hosts without that CAP. 1868 + */ 1875 1869 if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) 1876 - mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; 1870 + mmc->caps |= MMC_CAP_4_BIT_DATA; 1877 1871 1878 1872 if (caps & SDHCI_CAN_DO_HISPD) 1879 1873 mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
+4 -1
drivers/mmc/host/sdhci.h
··· 76 76 #define SDHCI_CTRL_ADMA1 0x08 77 77 #define SDHCI_CTRL_ADMA32 0x10 78 78 #define SDHCI_CTRL_ADMA64 0x18 79 - #define SDHCI_CTRL_8BITBUS 0x20 79 + #define SDHCI_CTRL_8BITBUS 0x20 80 80 81 81 #define SDHCI_POWER_CONTROL 0x29 82 82 #define SDHCI_POWER_ON 0x01 ··· 155 155 #define SDHCI_CLOCK_BASE_SHIFT 8 156 156 #define SDHCI_MAX_BLOCK_MASK 0x00030000 157 157 #define SDHCI_MAX_BLOCK_SHIFT 16 158 + #define SDHCI_CAN_DO_8BIT 0x00040000 158 159 #define SDHCI_CAN_DO_ADMA2 0x00080000 159 160 #define SDHCI_CAN_DO_ADMA1 0x00100000 160 161 #define SDHCI_CAN_DO_HISPD 0x00200000 ··· 216 215 unsigned int (*get_max_clock)(struct sdhci_host *host); 217 216 unsigned int (*get_min_clock)(struct sdhci_host *host); 218 217 unsigned int (*get_timeout_clock)(struct sdhci_host *host); 218 + int (*platform_8bit_width)(struct sdhci_host *host, 219 + int width); 219 220 void (*platform_send_init_74_clocks)(struct sdhci_host *host, 220 221 u8 power_mode); 221 222 unsigned int (*get_ro)(struct sdhci_host *host);