Hello Philip, On 10/2/2010 12:45 AM, Philip Rakity wrote: > > From 80c581d354df180a4c2d6aa50c21788e6c7593b9 Mon Sep 17 00:00:00 2001 > From: Philip Rakity <prakity@xxxxxxxxxxx> > Date: Fri, 1 Oct 2010 13:42:58 -0700 > Subject: [RFC] sdhci: 8 bit bus width changes > > Check for v3 controller controller when doing 8 bit bus width > add support for adaption layer to set 8 bit width. > controller may support 8 bit bus but NOT board design > allow non v3 controllers to support 8 bit bus > Patches ported and tested on our ST target and it works for me. Thanks! > > > non v3 controller (platform_8bit_width) > ======================================= > platform_8bit_width is used to support 8 bit mode using our v2 > sd controller. We have private registers that are used for 8 bit support > > v2 - v3 controller and 8 bit support (SDHCI_QUIRK_SLOT_CAN_DO_8_BITS) > ===================================================================== > The quirk is needed since we support multiple SD controllers and > on the board sometimes 8 data lines are brought out and sometimes only 4. > The SD controller indicates it can support 8 bit (v3 controller) via the > capability field but has no knowledge of how the pins were configured > in the board design. There are only so many pins and the pins are > multiplexed. > > Signed-off-by: Philip Rakity <prakity@xxxxxxxxxxx> > Tested -by: Giuseppe Cavallaro <peppe.cavallaro@xxxxxx> Regards Peppe > > --- > drivers/mmc/host/sdhci.c | 44 > +++++++++++++++++++++++++++++++++----------- > drivers/mmc/host/sdhci.h | 7 ++++++- > 2 files changed, 39 insertions(+), 12 deletions(-) > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index 73a94fe..ec103c3 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -1182,17 +1182,31 @@ static void sdhci_set_ios(struct mmc_host > *mmc, struct mmc_ios *ios) > else > sdhci_set_power(host, ios->vdd); > > - ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); > > - if (ios->bus_width == MMC_BUS_WIDTH_8) > - ctrl |= SDHCI_CTRL_8BITBUS; > - else > - ctrl &= ~SDHCI_CTRL_8BITBUS; > + /* > + * use platform_8_bit_width if not v3 controller > + * or if special hw/board specific processing is needed > + */ > + if (host->ops->platform_8bit_width) > + host->ops->platform_8bit_width(host, ios->bus_width); > + else { > + 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; > + } > + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); > + } > > - if (ios->bus_width == MMC_BUS_WIDTH_4) > - ctrl |= SDHCI_CTRL_4BITBUS; > - else > - ctrl &= ~SDHCI_CTRL_4BITBUS; > + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); > > if (ios->timing == MMC_TIMING_SD_HS && > !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) > @@ -1838,11 +1852,19 @@ int sdhci_add_host(struct sdhci_host *host) > mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; > else > mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; > + > 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 adaption 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 112543a..b3288fd 100644 > --- a/drivers/mmc/host/sdhci.h > +++ b/drivers/mmc/host/sdhci.h > @@ -72,7 +72,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 > @@ -148,6 +148,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 > @@ -260,6 +261,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 */ > @@ -336,6 +339,8 @@ struct sdhci_ops { > unsigned int (*get_max_clock)(struct sdhci_host *host); > unsigned int (*get_min_clock)(struct sdhci_host *host); > unsigned int (*get_timeout_clock)(struct sdhci_host *host); > + int (*platform_8bit_width)(struct sdhci_host *host, > + int width); > }; > > #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS > -- > 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 > -- 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