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: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Chris Ball <chris@printf.net>
This commit is contained in:
Russell King 2014-02-28 21:32:49 +00:00 committed by Chris Ball
parent 42c1add970
commit b42b9b12e9

View file

@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-spear.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/io.h>
#include "sdhci.h"
@ -40,28 +41,6 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
/* 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
static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
{
@ -152,6 +131,22 @@ static int sdhci_probe(struct platform_device *pdev)
sdhci->data = dev_get_platdata(&pdev->dev);
}
/*
* It is optional to use GPIOs for sdhci card detection. If
* sdhci->data is NULL, then use original sdhci lines otherwise
* GPIO lines. We use the built-in GPIO support for this.
*/
if (sdhci->data && sdhci->data->card_int_gpio >= 0) {
ret = mmc_gpio_request_cd(host->mmc,
sdhci->data->card_int_gpio, 0);
if (ret < 0) {
dev_dbg(&pdev->dev,
"failed to request card-detect gpio%d\n",
sdhci->data->card_int_gpio);
goto disable_clk;
}
}
ret = sdhci_add_host(host);
if (ret) {
dev_dbg(&pdev->dev, "error adding host\n");
@ -160,48 +155,8 @@ static int sdhci_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
/*
* It is optional to use GPIOs for sdhci Power control & sdhci card
* interrupt detection. If sdhci->data is NULL, then use original sdhci
* lines otherwise GPIO lines.
* 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)
return 0;
if (sdhci->data->card_int_gpio >= 0) {
ret = devm_gpio_request(&pdev->dev, sdhci->data->card_int_gpio,
"sdhci");
if (ret < 0) {
dev_dbg(&pdev->dev, "gpio request fail: %d\n",
sdhci->data->card_int_gpio);
goto set_drvdata;
}
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),
sdhci_gpio_irq, IRQF_TRIGGER_LOW,
mmc_hostname(host->mmc), pdev);
if (ret) {
dev_dbg(&pdev->dev, "gpio request irq fail: %d\n",
sdhci->data->card_int_gpio);
goto set_drvdata;
}
}
return 0;
set_drvdata:
sdhci_remove_host(host, 1);
disable_clk:
clk_disable_unprepare(sdhci->clk);
err_host: