diff options
Diffstat (limited to 'drivers/mci/mci_spi.c')
-rw-r--r-- | drivers/mci/mci_spi.c | 77 |
1 files changed, 46 insertions, 31 deletions
diff --git a/drivers/mci/mci_spi.c b/drivers/mci/mci_spi.c index 42072da58a..ad743d19d9 100644 --- a/drivers/mci/mci_spi.c +++ b/drivers/mci/mci_spi.c @@ -1,30 +1,12 @@ -/* - * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com> - * - * This code was inspired from u-boot mmc_spi.c: - * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> - * - * and linux mmc_spi.c: - * (C) Copyright 2005, Intec Automation, - * Mike Lavender (mike@steroidmicros) - * (C) Copyright 2006-2007, David Brownell - * (C) Copyright 2007, Axis Communications, - * Hans-Peter Nilsson (hp@axis.com) - * (C) Copyright 2007, ATRON electronic GmbH, - * Jan Nikitenko <jan.nikitenko@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * - */ +// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: 2011 Franck JULLIEN <elec4fun@gmail.com> +// SPDX-FileCopyrightText: 2010 Thomas Chou <thomas@wytron.com.tw> +// SPDX-FileCopyrightText: 2005 Intec Automation (Mike Lavender <mike@steroidmicros>) +// SPDX-FileCopyrightText: 2006-2007 David Brownell +// SPDX-FileCopyrightText: 2007 Axis Communications (Hans-Peter Nilsson <hp@axis.com>) +// SPDX-FileCopyrightText: 2007 ATRON electronic GmbH (Jan Nikitenko <jan.nikitenko@gmail.com>) + +/* This code was inspired from u-boot mmc_spi.c and linux mmc_spi.c. */ #include <common.h> #include <init.h> @@ -36,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) @@ -64,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; @@ -329,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); @@ -369,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; @@ -380,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 @@ -434,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); |