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>
This commit is contained in:
		
							parent
							
								
									ed919b0125
								
							
						
					
					
						commit
						15ec446119
					
				| @ -17,6 +17,9 @@ | ||||
| /* Require clock free running */ | ||||
| #define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0) | ||||
| 
 | ||||
| /* Board design supports 8-bit data on SD/SDIO BUS */ | ||||
| #define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2) | ||||
| 
 | ||||
| /*
 | ||||
|  * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI | ||||
|  * @max_speed: the maximum speed supported | ||||
|  | ||||
| @ -141,6 +141,10 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev) | ||||
| 	if (pdata->quirks) | ||||
| 		host->quirks |= pdata->quirks; | ||||
| 
 | ||||
| 	/* If slot design supports 8 bit data, indicate this to MMC. */ | ||||
| 	if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) | ||||
| 		host->mmc->caps |= MMC_CAP_8_BIT_DATA; | ||||
| 
 | ||||
| 	ret = sdhci_add_host(host); | ||||
| 	if (ret) { | ||||
| 		dev_err(&pdev->dev, "failed to add host\n"); | ||||
|  | ||||
| @ -1185,18 +1185,32 @@ 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); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * 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); | ||||
| 	} | ||||
| 
 | ||||
| 	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 (ios->bus_width == MMC_BUS_WIDTH_4) | ||||
| 		ctrl |= SDHCI_CTRL_4BITBUS; | ||||
| 	else | ||||
| 		ctrl &= ~SDHCI_CTRL_4BITBUS; | ||||
| 
 | ||||
| 	if ((ios->timing == MMC_TIMING_SD_HS || | ||||
| 	     ios->timing == MMC_TIMING_MMC_HS) | ||||
| 	    && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) | ||||
| @ -1855,11 +1869,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; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * A controller may support 8-bit width, but the board itself | ||||
| 	 * might not have the pins brought out.  Boards that support | ||||
| 	 * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in | ||||
| 	 * their platform code before calling sdhci_add_host(), and we | ||||
| 	 * won't assume 8-bit width for hosts without that CAP. | ||||
| 	 */ | ||||
| 	if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) | ||||
| 		mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; | ||||
| 		mmc->caps |= MMC_CAP_4_BIT_DATA; | ||||
| 
 | ||||
| 	if (caps & SDHCI_CAN_DO_HISPD) | ||||
| 		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user