code is fine. On Nov 19, 2010, at 1:53 PM, Chris Ball wrote: > On Fri, Nov 19, 2010 at 09:40:02PM +0000, Chris Ball wrote: >> I don't see why we should re-read ctrl here, since we've already written >> it back to the device at this point, and we don't use it anywhere below >> this line. > > Ah, I see why now; please ignore this. > > Here's a rebased version of the patch, with some more comments: > > From: Philip Rakity <prakity@xxxxxxxxxxx> > Date: Fri, 19 Nov 2010 16:48:39 -0500 > Subject: [PATCH] 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 > * introduce a quirk 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. > > Signed-off-by: Philip Rakity <prakity@xxxxxxxxxxx> > Tested-by: Giuseppe Cavallaro <peppe.cavallaro@xxxxxx> > Signed-off-by: Chris Ball <cjb@xxxxxxxxxx> > --- > drivers/mmc/host/sdhci.c | 48 +++++++++++++++++++++++++++++++++----------- > drivers/mmc/host/sdhci.h | 5 +++- > include/linux/mmc/sdhci.h | 2 + > 3 files changed, 42 insertions(+), 13 deletions(-) > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index 154cbf8..f1f9658 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) > if (host->ops->platform_send_init_74_clocks) > 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_8BITBUS; > - else > - ctrl &= ~SDHCI_CTRL_8BITBUS; > + /* > + * If your platform has 8-bit width support but is not a v3 controller, > + * or if it requires special setup code, you should implement that in > + * platform_8bit_width(). > + */ > + 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 || > ios->timing == MMC_TIMING_MMC_HS) > @@ -1855,11 +1869,21 @@ 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; > + /* > + * A controller may support 8-bit width, but the board itself > + * might not have the pins brought out. So, boards that support > + * 8-bit width should set the below quirk, and we won't assume > + * that devices without the quirk can use 8-bit width. > + */ > + 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 d52a716..e42d7f0 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 > @@ -155,6 +155,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 > @@ -215,6 +216,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); > void (*platform_send_init_74_clocks)(struct sdhci_host *host, > u8 power_mode); > unsigned int (*get_ro)(struct sdhci_host *host); > diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h > index 1fdc673..7fdcfca 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 */ > -- > Chris Ball <cjb@xxxxxxxxxx> <http://printf.net/> > One Laptop Per Child -- 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