diff options
-rw-r--r-- | drivers/mmc/host/mmc_spi.c | 33 | ||||
-rw-r--r-- | drivers/mmc/host/of_mmc_spi.c | 46 | ||||
-rw-r--r-- | include/linux/spi/mmc_spi.h | 16 |
3 files changed, 52 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 | ||
1288 | static int mmc_spi_get_cd(struct mmc_host *mmc) | 1286 | static 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 | ||
1297 | static const struct mmc_host_ops mmc_spi_ops = { | 1296 | static 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 | ||
53 | static 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 | |||
62 | static int of_mmc_spi_get_cd(struct device *dev) | ||
63 | { | ||
64 | return of_mmc_spi_read_gpio(dev, CD_GPIO); | ||
65 | } | ||
66 | |||
67 | static int of_mmc_spi_get_ro(struct device *dev) | ||
68 | { | ||
69 | return of_mmc_spi_read_gpio(dev, WP_GPIO); | ||
70 | } | ||
71 | |||
72 | static int of_mmc_spi_init(struct device *dev, | 53 | static 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 | } |
diff --git a/include/linux/spi/mmc_spi.h b/include/linux/spi/mmc_spi.h index 32be8dbdf191..87cdb35bedda 100644 --- a/include/linux/spi/mmc_spi.h +++ b/include/linux/spi/mmc_spi.h | |||
@@ -7,6 +7,11 @@ | |||
7 | struct device; | 7 | struct device; |
8 | struct mmc_host; | 8 | struct mmc_host; |
9 | 9 | ||
10 | #define MMC_SPI_USE_CD_GPIO (1 << 0) | ||
11 | #define MMC_SPI_USE_RO_GPIO (1 << 1) | ||
12 | #define MMC_SPI_CD_GPIO_ACTIVE_LOW (1 << 2) | ||
13 | #define MMC_SPI_RO_GPIO_ACTIVE_LOW (1 << 3) | ||
14 | |||
10 | /* Put this in platform_data of a device being used to manage an MMC/SD | 15 | /* Put this in platform_data of a device being used to manage an MMC/SD |
11 | * card slot. (Modeled after PXA mmc glue; see that for usage examples.) | 16 | * card slot. (Modeled after PXA mmc glue; see that for usage examples.) |
12 | * | 17 | * |
@@ -30,8 +35,19 @@ struct mmc_spi_platform_data { | |||
30 | */ | 35 | */ |
31 | int (*get_cd)(struct device *); | 36 | int (*get_cd)(struct device *); |
32 | 37 | ||
38 | /* | ||
39 | * Card Detect and Read Only GPIOs. To enable debouncing on the card | ||
40 | * detect GPIO, set the cd_debounce to the debounce time in | ||
41 | * microseconds. | ||
42 | */ | ||
43 | unsigned int flags; | ||
44 | unsigned int cd_gpio; | ||
45 | unsigned int cd_debounce; | ||
46 | unsigned int ro_gpio; | ||
47 | |||
33 | /* Capabilities to pass into mmc core (e.g. MMC_CAP_NEEDS_POLL). */ | 48 | /* Capabilities to pass into mmc core (e.g. MMC_CAP_NEEDS_POLL). */ |
34 | unsigned long caps; | 49 | unsigned long caps; |
50 | unsigned long caps2; | ||
35 | 51 | ||
36 | /* how long to debounce card detect, in msecs */ | 52 | /* how long to debounce card detect, in msecs */ |
37 | u16 detect_delay; | 53 | u16 detect_delay; |