Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b42b9b12 authored by Russell King's avatar Russell King Committed by Chris Ball
Browse files

mmc: sdhci-spear: use generic card detection gpio support



sdhci has support for using GPIOs for card detection.  If we have a
GPIO specified, we can use that directly, without needing our own
interrupt handler.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarChris Ball <chris@printf.net>
parent 42c1add9
Loading
Loading
Loading
Loading
+17 −62
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/mmc/host.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-spear.h>
#include <linux/mmc/sdhci-spear.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/io.h>
#include <linux/io.h>
#include "sdhci.h"
#include "sdhci.h"


@@ -40,28 +41,6 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
	/* Nothing to do for now. */
	/* Nothing to do for now. */
};
};


/* gpio card detection interrupt handler */
static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
{
	struct platform_device *pdev = dev_id;
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
	unsigned long gpio_irq_type;
	int val;

	val = gpio_get_value(sdhci->data->card_int_gpio);

	/* val == 1 -> card removed, val == 0 -> card inserted */
	/* if card removed - set irq for low level, else vice versa */
	gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
	irq_set_irq_type(irq, gpio_irq_type);

	/* inform sdhci driver about card insertion/removal */
	tasklet_schedule(&host->card_tasklet);

	return IRQ_HANDLED;
}

#ifdef CONFIG_OF
#ifdef CONFIG_OF
static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
{
{
@@ -152,56 +131,32 @@ static int sdhci_probe(struct platform_device *pdev)
		sdhci->data = dev_get_platdata(&pdev->dev);
		sdhci->data = dev_get_platdata(&pdev->dev);
	}
	}


	ret = sdhci_add_host(host);
	if (ret) {
		dev_dbg(&pdev->dev, "error adding host\n");
		goto disable_clk;
	}

	platform_set_drvdata(pdev, host);

	/*
	/*
	 * It is optional to use GPIOs for sdhci Power control & sdhci card
	 * It is optional to use GPIOs for sdhci card detection. If
	 * interrupt detection. If sdhci->data is NULL, then use original sdhci
	 * sdhci->data is NULL, then use original sdhci lines otherwise
	 * lines otherwise GPIO lines.
	 * GPIO lines. We use the built-in GPIO support for this.
	 * If GPIO is selected for power control, then power should be disabled
	 * after card removal and should be enabled when card insertion
	 * interrupt occurs
	 */
	 */
	if (!sdhci->data)
	if (sdhci->data && sdhci->data->card_int_gpio >= 0) {
		return 0;
		ret = mmc_gpio_request_cd(host->mmc,

					  sdhci->data->card_int_gpio, 0);
	if (sdhci->data->card_int_gpio >= 0) {
		ret = devm_gpio_request(&pdev->dev, sdhci->data->card_int_gpio,
				"sdhci");
		if (ret < 0) {
		if (ret < 0) {
			dev_dbg(&pdev->dev, "gpio request fail: %d\n",
			dev_dbg(&pdev->dev,
				"failed to request card-detect gpio%d\n",
				sdhci->data->card_int_gpio);
				sdhci->data->card_int_gpio);
			goto set_drvdata;
			goto disable_clk;
		}
		}

		ret = gpio_direction_input(sdhci->data->card_int_gpio);
		if (ret) {
			dev_dbg(&pdev->dev, "gpio set direction fail: %d\n",
					sdhci->data->card_int_gpio);
			goto set_drvdata;
	}
	}
		ret = devm_request_irq(&pdev->dev,

				gpio_to_irq(sdhci->data->card_int_gpio),
	ret = sdhci_add_host(host);
				sdhci_gpio_irq, IRQF_TRIGGER_LOW,
				mmc_hostname(host->mmc), pdev);
	if (ret) {
	if (ret) {
			dev_dbg(&pdev->dev, "gpio request irq fail: %d\n",
		dev_dbg(&pdev->dev, "error adding host\n");
					sdhci->data->card_int_gpio);
		goto disable_clk;
			goto set_drvdata;
	}
	}


	}
	platform_set_drvdata(pdev, host);


	return 0;
	return 0;


set_drvdata:
	sdhci_remove_host(host, 1);
disable_clk:
disable_clk:
	clk_disable_unprepare(sdhci->clk);
	clk_disable_unprepare(sdhci->clk);
err_host:
err_host: