diff options
Diffstat (limited to 'drivers/mmc/host/mmc_spi.c')
| -rw-r--r-- | drivers/mmc/host/mmc_spi.c | 96 | 
1 files changed, 34 insertions, 62 deletions
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index fd877f633dd..cc8d4a6099c 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -27,6 +27,7 @@  #include <linux/sched.h>  #include <linux/delay.h>  #include <linux/slab.h> +#include <linux/module.h>  #include <linux/bio.h>  #include <linux/dma-mapping.h>  #include <linux/crc7.h> @@ -35,6 +36,7 @@  #include <linux/mmc/host.h>  #include <linux/mmc/mmc.h>		/* for R1_SPI_* bit values */ +#include <linux/mmc/slot-gpio.h>  #include <linux/spi/spi.h>  #include <linux/spi/mmc_spi.h> @@ -99,7 +101,7 @@  #define r1b_timeout		(HZ * 3)  /* One of the critical speed parameters is the amount of data which may - * be transfered in one command. If this value is too low, the SD card + * be transferred in one command. If this value is too low, the SD card   * controller has to do multiple partial block writes (argggh!). With   * today (2008) SD cards there is little speed gain if we transfer more   * than 64 KBytes at a time. So use this value until there is any indication @@ -446,7 +448,6 @@ mmc_spi_command_send(struct mmc_spi_host *host,  {  	struct scratch		*data = host->data;  	u8			*cp = data->status; -	u32			arg = cmd->arg;  	int			status;  	struct spi_transfer	*t; @@ -463,14 +464,12 @@ mmc_spi_command_send(struct mmc_spi_host *host,  	 * We init the whole buffer to all-ones, which is what we need  	 * to write while we're reading (later) response data.  	 */ -	memset(cp++, 0xff, sizeof(data->status)); +	memset(cp, 0xff, sizeof(data->status)); -	*cp++ = 0x40 | cmd->opcode; -	*cp++ = (u8)(arg >> 24); -	*cp++ = (u8)(arg >> 16); -	*cp++ = (u8)(arg >> 8); -	*cp++ = (u8)arg; -	*cp++ = (crc7(0, &data->status[1], 5) << 1) | 0x01; +	cp[1] = 0x40 | cmd->opcode; +	put_unaligned_be32(cmd->arg, cp+2); +	cp[6] = crc7_be(0, cp+1, 5) | 0x01; +	cp += 7;  	/* Then, read up to 13 bytes (while writing all-ones):  	 *  - N(CR) (== 1..8) bytes of all-ones @@ -709,10 +708,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,  	 * so we have to cope with this situation and check the response  	 * bit-by-bit. Arggh!!!  	 */ -	pattern  = scratch->status[0] << 24; -	pattern |= scratch->status[1] << 16; -	pattern |= scratch->status[2] << 8; -	pattern |= scratch->status[3]; +	pattern = get_unaligned_be32(scratch->status);  	/* First 3 bit of pattern are undefined */  	pattern |= 0xE0000000; @@ -1271,33 +1267,11 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)  	}  } -static int mmc_spi_get_ro(struct mmc_host *mmc) -{ -	struct mmc_spi_host *host = mmc_priv(mmc); - -	if (host->pdata && host->pdata->get_ro) -		return !!host->pdata->get_ro(mmc->parent); -	/* -	 * Board doesn't support read only detection; let the mmc core -	 * decide what to do. -	 */ -	return -ENOSYS; -} - -static int mmc_spi_get_cd(struct mmc_host *mmc) -{ -	struct mmc_spi_host *host = mmc_priv(mmc); - -	if (host->pdata && host->pdata->get_cd) -		return !!host->pdata->get_cd(mmc->parent); -	return -ENOSYS; -} -  static const struct mmc_host_ops mmc_spi_ops = {  	.request	= mmc_spi_request,  	.set_ios	= mmc_spi_set_ios, -	.get_ro		= mmc_spi_get_ro, -	.get_cd		= mmc_spi_get_cd, +	.get_ro		= mmc_gpio_get_ro, +	.get_cd		= mmc_gpio_get_cd,  }; @@ -1323,6 +1297,7 @@ static int mmc_spi_probe(struct spi_device *spi)  	struct mmc_host		*mmc;  	struct mmc_spi_host	*host;  	int			status; +	bool			has_ro = false;  	/* We rely on full duplex transfers, mostly to reduce  	 * per-transfer overheads (by making fewer transfers). @@ -1447,18 +1422,33 @@ static int mmc_spi_probe(struct spi_device *spi)  	}  	/* pass platform capabilities, if any */ -	if (host->pdata) +	if (host->pdata) {  		mmc->caps |= host->pdata->caps; +		mmc->caps2 |= host->pdata->caps2; +	}  	status = mmc_add_host(mmc);  	if (status != 0)  		goto fail_add_host; +	if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) { +		status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio, +					     host->pdata->cd_debounce); +		if (status != 0) +			goto fail_add_host; +	} + +	if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) { +		has_ro = true; +		status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio); +		if (status != 0) +			goto fail_add_host; +	} +  	dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",  			dev_name(&mmc->class_dev),  			host->dma_dev ? "" : ", no DMA", -			(host->pdata && host->pdata->get_ro) -				? "" : ", no WP", +			has_ro ? "" : ", no WP",  			(host->pdata && host->pdata->setpower)  				? "" : ", no poweroff",  			(mmc->caps & MMC_CAP_NEEDS_POLL) @@ -1484,7 +1474,7 @@ nomem:  } -static int __devexit mmc_spi_remove(struct spi_device *spi) +static int mmc_spi_remove(struct spi_device *spi)  {  	struct mmc_host		*mmc = dev_get_drvdata(&spi->dev);  	struct mmc_spi_host	*host; @@ -1516,40 +1506,22 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)  	return 0;  } -#if defined(CONFIG_OF) -static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { +static struct of_device_id mmc_spi_of_match_table[] = {  	{ .compatible = "mmc-spi-slot", },  	{},  }; -#endif  static struct spi_driver mmc_spi_driver = {  	.driver = {  		.name =		"mmc_spi", -		.bus =		&spi_bus_type,  		.owner =	THIS_MODULE, -#if defined(CONFIG_OF)  		.of_match_table = mmc_spi_of_match_table, -#endif  	},  	.probe =	mmc_spi_probe, -	.remove =	__devexit_p(mmc_spi_remove), +	.remove =	mmc_spi_remove,  }; - -static int __init mmc_spi_init(void) -{ -	return spi_register_driver(&mmc_spi_driver); -} -module_init(mmc_spi_init); - - -static void __exit mmc_spi_exit(void) -{ -	spi_unregister_driver(&mmc_spi_driver); -} -module_exit(mmc_spi_exit); - +module_spi_driver(mmc_spi_driver);  MODULE_AUTHOR("Mike Lavender, David Brownell, "  		"Hans-Peter Nilsson, Jan Nikitenko");  | 
