aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-08-08 06:38:32 -0400
committerChris Ball <cjb@laptop.org>2013-08-24 23:45:22 -0400
commitbf287a90ceedf86e3313ba0dcff606ac5399b39a (patch)
treea3337495e68fde2270c406574774a283c0b4e002 /drivers/mmc
parent214fc309d1387e822d606a33a10e31cacfe83520 (diff)
mmc: mmc_spi: Support CD/RO GPIOs
Add support for passing CD/RO GPIO numbers directly to the mmc_spi driver instead of relying solely on board code callbacks to retrieve the CD/RO signals values. The driver will enable debouncing on the card detect GPIO if the cd_debounce field is set to a non-zero value. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mmc_spi.c33
-rw-r--r--drivers/mmc/host/of_mmc_spi.c46
2 files changed, 36 insertions, 43 deletions
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 74145d1d51f5..62fb82d7c942 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -36,6 +36,7 @@
36 36
37#include <linux/mmc/host.h> 37#include <linux/mmc/host.h>
38#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */ 38#include <linux/mmc/mmc.h> /* for R1_SPI_* bit values */
39#include <linux/mmc/slot-gpio.h>
39 40
40#include <linux/spi/spi.h> 41#include <linux/spi/spi.h>
41#include <linux/spi/mmc_spi.h> 42#include <linux/spi/mmc_spi.h>
@@ -1278,11 +1279,8 @@ static int mmc_spi_get_ro(struct mmc_host *mmc)
1278 1279
1279 if (host->pdata && host->pdata->get_ro) 1280 if (host->pdata && host->pdata->get_ro)
1280 return !!host->pdata->get_ro(mmc->parent); 1281 return !!host->pdata->get_ro(mmc->parent);
1281 /* 1282 else
1282 * Board doesn't support read only detection; let the mmc core 1283 return mmc_gpio_get_ro(mmc);
1283 * decide what to do.
1284 */
1285 return -ENOSYS;
1286} 1284}
1287 1285
1288static int mmc_spi_get_cd(struct mmc_host *mmc) 1286static int mmc_spi_get_cd(struct mmc_host *mmc)
@@ -1291,7 +1289,8 @@ static int mmc_spi_get_cd(struct mmc_host *mmc)
1291 1289
1292 if (host->pdata && host->pdata->get_cd) 1290 if (host->pdata && host->pdata->get_cd)
1293 return !!host->pdata->get_cd(mmc->parent); 1291 return !!host->pdata->get_cd(mmc->parent);
1294 return -ENOSYS; 1292 else
1293 return mmc_gpio_get_cd(mmc);
1295} 1294}
1296 1295
1297static const struct mmc_host_ops mmc_spi_ops = { 1296static const struct mmc_host_ops mmc_spi_ops = {
@@ -1324,6 +1323,7 @@ static int mmc_spi_probe(struct spi_device *spi)
1324 struct mmc_host *mmc; 1323 struct mmc_host *mmc;
1325 struct mmc_spi_host *host; 1324 struct mmc_spi_host *host;
1326 int status; 1325 int status;
1326 bool has_ro = false;
1327 1327
1328 /* We rely on full duplex transfers, mostly to reduce 1328 /* We rely on full duplex transfers, mostly to reduce
1329 * per-transfer overheads (by making fewer transfers). 1329 * per-transfer overheads (by making fewer transfers).
@@ -1448,18 +1448,33 @@ static int mmc_spi_probe(struct spi_device *spi)
1448 } 1448 }
1449 1449
1450 /* pass platform capabilities, if any */ 1450 /* pass platform capabilities, if any */
1451 if (host->pdata) 1451 if (host->pdata) {
1452 mmc->caps |= host->pdata->caps; 1452 mmc->caps |= host->pdata->caps;
1453 mmc->caps2 |= host->pdata->caps2;
1454 }
1453 1455
1454 status = mmc_add_host(mmc); 1456 status = mmc_add_host(mmc);
1455 if (status != 0) 1457 if (status != 0)
1456 goto fail_add_host; 1458 goto fail_add_host;
1457 1459
1460 if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) {
1461 status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio,
1462 host->pdata->cd_debounce);
1463 if (status != 0)
1464 goto fail_add_host;
1465 }
1466
1467 if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) {
1468 has_ro = true;
1469 status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio);
1470 if (status != 0)
1471 goto fail_add_host;
1472 }
1473
1458 dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n", 1474 dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n",
1459 dev_name(&mmc->class_dev), 1475 dev_name(&mmc->class_dev),
1460 host->dma_dev ? "" : ", no DMA", 1476 host->dma_dev ? "" : ", no DMA",
1461 (host->pdata && host->pdata->get_ro) 1477 has_ro ? "" : ", no WP",
1462 ? "" : ", no WP",
1463 (host->pdata && host->pdata->setpower) 1478 (host->pdata && host->pdata->setpower)
1464 ? "" : ", no poweroff", 1479 ? "" : ", no poweroff",
1465 (mmc->caps & MMC_CAP_NEEDS_POLL) 1480 (mmc->caps & MMC_CAP_NEEDS_POLL)
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index d720b5e05b9c..6e218fb1a669 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -50,25 +50,6 @@ static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
50 return container_of(dev->platform_data, struct of_mmc_spi, pdata); 50 return container_of(dev->platform_data, struct of_mmc_spi, pdata);
51} 51}
52 52
53static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num)
54{
55 struct of_mmc_spi *oms = to_of_mmc_spi(dev);
56 bool active_low = oms->alow_gpios[gpio_num];
57 bool value = gpio_get_value(oms->gpios[gpio_num]);
58
59 return active_low ^ value;
60}
61
62static int of_mmc_spi_get_cd(struct device *dev)
63{
64 return of_mmc_spi_read_gpio(dev, CD_GPIO);
65}
66
67static int of_mmc_spi_get_ro(struct device *dev)
68{
69 return of_mmc_spi_read_gpio(dev, WP_GPIO);
70}
71
72static int of_mmc_spi_init(struct device *dev, 53static int of_mmc_spi_init(struct device *dev,
73 irqreturn_t (*irqhandler)(int, void *), void *mmc) 54 irqreturn_t (*irqhandler)(int, void *), void *mmc)
74{ 55{
@@ -130,20 +111,22 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
130 if (!gpio_is_valid(oms->gpios[i])) 111 if (!gpio_is_valid(oms->gpios[i]))
131 continue; 112 continue;
132 113
133 ret = gpio_request(oms->gpios[i], dev_name(dev));
134 if (ret < 0) {
135 oms->gpios[i] = -EINVAL;
136 continue;
137 }
138
139 if (gpio_flags & OF_GPIO_ACTIVE_LOW) 114 if (gpio_flags & OF_GPIO_ACTIVE_LOW)
140 oms->alow_gpios[i] = true; 115 oms->alow_gpios[i] = true;
141 } 116 }
142 117
143 if (gpio_is_valid(oms->gpios[CD_GPIO])) 118 if (gpio_is_valid(oms->gpios[CD_GPIO])) {
144 oms->pdata.get_cd = of_mmc_spi_get_cd; 119 oms->pdata.cd_gpio = oms->gpios[CD_GPIO];
145 if (gpio_is_valid(oms->gpios[WP_GPIO])) 120 oms->pdata.flags |= MMC_SPI_USE_CD_GPIO;
146 oms->pdata.get_ro = of_mmc_spi_get_ro; 121 if (!oms->alow_gpios[CD_GPIO])
122 oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
123 }
124 if (gpio_is_valid(oms->gpios[WP_GPIO])) {
125 oms->pdata.ro_gpio = oms->gpios[WP_GPIO];
126 oms->pdata.flags |= MMC_SPI_USE_RO_GPIO;
127 if (!oms->alow_gpios[WP_GPIO])
128 oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
129 }
147 130
148 oms->detect_irq = irq_of_parse_and_map(np, 0); 131 oms->detect_irq = irq_of_parse_and_map(np, 0);
149 if (oms->detect_irq != 0) { 132 if (oms->detect_irq != 0) {
@@ -166,15 +149,10 @@ void mmc_spi_put_pdata(struct spi_device *spi)
166 struct device *dev = &spi->dev; 149 struct device *dev = &spi->dev;
167 struct device_node *np = dev->of_node; 150 struct device_node *np = dev->of_node;
168 struct of_mmc_spi *oms = to_of_mmc_spi(dev); 151 struct of_mmc_spi *oms = to_of_mmc_spi(dev);
169 int i;
170 152
171 if (!dev->platform_data || !np) 153 if (!dev->platform_data || !np)
172 return; 154 return;
173 155
174 for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
175 if (gpio_is_valid(oms->gpios[i]))
176 gpio_free(oms->gpios[i]);
177 }
178 kfree(oms); 156 kfree(oms);
179 dev->platform_data = NULL; 157 dev->platform_data = NULL;
180} 158}