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:
parent
42c1add970
commit
b42b9b12e9
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user