8 bit width is a new feature in the sd 3.0 spec. Add checks to ensure HOST_CONTROL register set 8 bit mode only if sd 3.0 add quirk to indicate that board design supports 8 data lines. The controller can support 8 data bits but the board design may only bring out 4 data bits. Signed-off-by: Philip Rakity <prakity@xxxxxxxxxxx> --- drivers/mmc/host/sdhci.c | 24 ++++++++++++++++++++++-- drivers/mmc/host/sdhci.h | 3 ++- include/linux/mmc/sdhci.h | 2 ++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ea8472b..90cfdfb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1189,6 +1189,18 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->ops->platform_send_init_74_clocks(host, ios->power_mode); ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + if (ios->bus_width == MMC_BUS_WIDTH_8) { + ctrl &= ~SDHCI_CTRL_4BITBUS; + if (host->version >= SDHCI_SPEC_300) + ctrl |= SDHCI_CTRL_8BITBUS; + } else { + if (host->version >= SDHCI_SPEC_300) + ctrl &= ~SDHCI_CTRL_8BITBUS; + if (ios->bus_width == MMC_BUS_WIDTH_4) + ctrl |= SDHCI_CTRL_4BITBUS; + else + ctrl &= ~SDHCI_CTRL_4BITBUS; + } if (ios->bus_width == MMC_BUS_WIDTH_8) ctrl |= SDHCI_CTRL_8BITBUS; @@ -1848,8 +1860,16 @@ int sdhci_add_host(struct sdhci_host *host) mmc->f_max = host->max_clk; mmc->caps |= MMC_CAP_SDIO_IRQ; - if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) - mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; + /* + * 8 bit width may be supported by v3 controller but not board. + * so the safest thing is to let the adaptation layer decide + * what to do by using the quirk + */ + if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) { + mmc->caps |= MMC_CAP_4_BIT_DATA; + if (host->quirks & SDHCI_QUIRK_SLOT_CAN_DO_8_BITS) + mmc->caps |= MMC_CAP_8_BIT_DATA; + } if (caps & SDHCI_CAN_DO_HISPD) 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 38ae340..c87e3c4 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -76,7 +76,7 @@ #define SDHCI_CTRL_ADMA1 0x08 #define SDHCI_CTRL_ADMA32 0x10 #define SDHCI_CTRL_ADMA64 0x18 -#define SDHCI_CTRL_8BITBUS 0x20 +#define SDHCI_CTRL_8BITBUS 0x20 #define SDHCI_POWER_CONTROL 0x29 #define SDHCI_POWER_ON 0x01 @@ -152,6 +152,7 @@ #define SDHCI_CLOCK_BASE_SHIFT 8 #define SDHCI_MAX_BLOCK_MASK 0x00030000 #define SDHCI_MAX_BLOCK_SHIFT 16 +#define SDHCI_CAN_DO_8BIT 0x00040000 #define SDHCI_CAN_DO_ADMA2 0x00080000 #define SDHCI_CAN_DO_ADMA1 0x00100000 #define SDHCI_CAN_DO_HISPD 0x00200000 diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 1fdc673..5be1cfc 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -83,6 +83,8 @@ struct sdhci_host { #define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1<<28) /* Controller doesn't have HISPD bit field in HI-SPEED SD card */ #define SDHCI_QUIRK_NO_HISPD_BIT (1<<29) +/* slot has 8 data pins going to eMMC/mmc card */ +#define SDHCI_QUIRK_SLOT_CAN_DO_8_BITS (1<<30) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html