diff options
Diffstat (limited to 'drivers/mci/mci_spi.c')
-rw-r--r-- | drivers/mci/mci_spi.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/mci/mci_spi.c b/drivers/mci/mci_spi.c index ed3ddf890f..ad743d19d9 100644 --- a/drivers/mci/mci_spi.c +++ b/drivers/mci/mci_spi.c @@ -18,6 +18,8 @@ #include <mci.h> #include <crc.h> #include <crc7.h> +#include <of.h> +#include <linux/gpio/consumer.h> #define to_spi_host(mci) container_of(mci, struct mmc_spi_host, mci) #define spi_setup(spi) spi->master->setup(spi) @@ -46,7 +48,8 @@ struct mmc_spi_host { struct mci_host mci; struct spi_device *spi; - struct device_d *dev; + struct device *dev; + struct gpio_desc *detect_pin; /* for bulk data transfers */ struct spi_transfer t_tx; @@ -311,7 +314,7 @@ static void mmc_spi_set_ios(struct mci_host *mci, struct mci_ios *ios) } } -static int mmc_spi_init(struct mci_host *mci, struct device_d *mci_dev) +static int mmc_spi_init(struct mci_host *mci, struct device *mci_dev) { struct mmc_spi_host *host = to_spi_host(mci); mmc_spi_readbytes(host, 10, NULL); @@ -351,8 +354,23 @@ static int mmc_spi_init(struct mci_host *mci, struct device_d *mci_dev) return 0; } -static int spi_mci_probe(struct device_d *dev) +static int spi_mci_card_present(struct mci_host *mci) { + struct mmc_spi_host *host = to_spi_host(mci); + int ret; + + /* No gpio, assume card is present */ + if (IS_ERR_OR_NULL(host->detect_pin)) + return 1; + + ret = gpiod_get_value(host->detect_pin); + + return ret == 0 ? 1 : 0; +} + +static int spi_mci_probe(struct device *dev) +{ + struct device_node *np = dev_of_node(dev); struct spi_device *spi = (struct spi_device *)dev->type_data; struct mmc_spi_host *host; void *ones; @@ -362,6 +380,7 @@ static int spi_mci_probe(struct device_d *dev) host->mci.send_cmd = mmc_spi_request; host->mci.set_ios = mmc_spi_set_ios; host->mci.init = mmc_spi_init; + host->mci.card_present = spi_mci_card_present; host->mci.hw_dev = dev; /* MMC and SD specs only seem to care that sampling is on the @@ -416,13 +435,27 @@ static int spi_mci_probe(struct device_d *dev) host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; host->mci.host_caps = MMC_CAP_SPI; + if (np) { + host->mci.devname = xstrdup(of_alias_get(np)); + host->detect_pin = gpiod_get_optional(dev, NULL, GPIOD_IN); + if (IS_ERR(host->detect_pin)) + dev_warn(dev, "Failed to get 'reset' GPIO (ignored)\n"); + } + mci_register(&host->mci); return 0; } -static struct driver_d spi_mci_driver = { +static __maybe_unused struct of_device_id spi_mci_compatible[] = { + { .compatible = "mmc-spi-slot" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, spi_mci_compatible); + +static struct driver spi_mci_driver = { .name = "spi_mci", .probe = spi_mci_probe, + .of_compatible = DRV_OF_COMPAT(spi_mci_compatible), }; device_spi_driver(spi_mci_driver); |