mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
MMC: MMCI: use gpiolib for card detect/write protect
Use gpiolib where available (and when valid GPIOs are provided) for write protect/card detect status reporting. We fall back to the old 'status' method where gpiolib support is not available. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
7fb2bbf4d9
commit
8900144692
2 changed files with 63 additions and 2 deletions
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/amba/bus.h>
|
#include <linux/amba/bus.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
|
@ -472,17 +473,41 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mmci_get_ro(struct mmc_host *mmc)
|
||||||
|
{
|
||||||
|
struct mmci_host *host = mmc_priv(mmc);
|
||||||
|
|
||||||
|
if (host->gpio_wp == -ENOSYS)
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
return gpio_get_value(host->gpio_wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmci_get_cd(struct mmc_host *mmc)
|
||||||
|
{
|
||||||
|
struct mmci_host *host = mmc_priv(mmc);
|
||||||
|
unsigned int status;
|
||||||
|
|
||||||
|
if (host->gpio_cd == -ENOSYS)
|
||||||
|
status = host->plat->status(mmc_dev(host->mmc));
|
||||||
|
else
|
||||||
|
status = gpio_get_value(host->gpio_cd);
|
||||||
|
|
||||||
|
return !status;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct mmc_host_ops mmci_ops = {
|
static const struct mmc_host_ops mmci_ops = {
|
||||||
.request = mmci_request,
|
.request = mmci_request,
|
||||||
.set_ios = mmci_set_ios,
|
.set_ios = mmci_set_ios,
|
||||||
|
.get_ro = mmci_get_ro,
|
||||||
|
.get_cd = mmci_get_cd,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mmci_check_status(unsigned long data)
|
static void mmci_check_status(unsigned long data)
|
||||||
{
|
{
|
||||||
struct mmci_host *host = (struct mmci_host *)data;
|
struct mmci_host *host = (struct mmci_host *)data;
|
||||||
unsigned int status;
|
unsigned int status = mmci_get_cd(host->mmc);
|
||||||
|
|
||||||
status = host->plat->status(mmc_dev(host->mmc));
|
|
||||||
if (status ^ host->oldstat)
|
if (status ^ host->oldstat)
|
||||||
mmc_detect_change(host->mmc, 0);
|
mmc_detect_change(host->mmc, 0);
|
||||||
|
|
||||||
|
@ -516,6 +541,9 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
|
||||||
host = mmc_priv(mmc);
|
host = mmc_priv(mmc);
|
||||||
host->mmc = mmc;
|
host->mmc = mmc;
|
||||||
|
|
||||||
|
host->gpio_wp = -ENOSYS;
|
||||||
|
host->gpio_cd = -ENOSYS;
|
||||||
|
|
||||||
host->hw_designer = amba_manf(dev);
|
host->hw_designer = amba_manf(dev);
|
||||||
host->hw_revision = amba_rev(dev);
|
host->hw_revision = amba_rev(dev);
|
||||||
DBG(host, "designer ID = 0x%02x\n", host->hw_designer);
|
DBG(host, "designer ID = 0x%02x\n", host->hw_designer);
|
||||||
|
@ -591,6 +619,25 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
|
||||||
writel(0, host->base + MMCIMASK1);
|
writel(0, host->base + MMCIMASK1);
|
||||||
writel(0xfff, host->base + MMCICLEAR);
|
writel(0xfff, host->base + MMCICLEAR);
|
||||||
|
|
||||||
|
if (gpio_is_valid(plat->gpio_cd)) {
|
||||||
|
ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)");
|
||||||
|
if (ret == 0)
|
||||||
|
ret = gpio_direction_input(plat->gpio_cd);
|
||||||
|
if (ret == 0)
|
||||||
|
host->gpio_cd = plat->gpio_cd;
|
||||||
|
else if (ret != -ENOSYS)
|
||||||
|
goto err_gpio_cd;
|
||||||
|
}
|
||||||
|
if (gpio_is_valid(plat->gpio_wp)) {
|
||||||
|
ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
|
||||||
|
if (ret == 0)
|
||||||
|
ret = gpio_direction_input(plat->gpio_wp);
|
||||||
|
if (ret == 0)
|
||||||
|
host->gpio_wp = plat->gpio_wp;
|
||||||
|
else if (ret != -ENOSYS)
|
||||||
|
goto err_gpio_wp;
|
||||||
|
}
|
||||||
|
|
||||||
ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
|
ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto unmap;
|
goto unmap;
|
||||||
|
@ -602,6 +649,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
|
||||||
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
||||||
|
|
||||||
amba_set_drvdata(dev, mmc);
|
amba_set_drvdata(dev, mmc);
|
||||||
|
host->oldstat = mmci_get_cd(host->mmc);
|
||||||
|
|
||||||
mmc_add_host(mmc);
|
mmc_add_host(mmc);
|
||||||
|
|
||||||
|
@ -620,6 +668,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
|
||||||
irq0_free:
|
irq0_free:
|
||||||
free_irq(dev->irq[0], host);
|
free_irq(dev->irq[0], host);
|
||||||
unmap:
|
unmap:
|
||||||
|
if (host->gpio_wp != -ENOSYS)
|
||||||
|
gpio_free(host->gpio_wp);
|
||||||
|
err_gpio_wp:
|
||||||
|
if (host->gpio_cd != -ENOSYS)
|
||||||
|
gpio_free(host->gpio_cd);
|
||||||
|
err_gpio_cd:
|
||||||
iounmap(host->base);
|
iounmap(host->base);
|
||||||
clk_disable:
|
clk_disable:
|
||||||
clk_disable(host->clk);
|
clk_disable(host->clk);
|
||||||
|
@ -655,6 +709,11 @@ static int __devexit mmci_remove(struct amba_device *dev)
|
||||||
free_irq(dev->irq[0], host);
|
free_irq(dev->irq[0], host);
|
||||||
free_irq(dev->irq[1], host);
|
free_irq(dev->irq[1], host);
|
||||||
|
|
||||||
|
if (host->gpio_wp != -ENOSYS)
|
||||||
|
gpio_free(host->gpio_wp);
|
||||||
|
if (host->gpio_cd != -ENOSYS)
|
||||||
|
gpio_free(host->gpio_cd);
|
||||||
|
|
||||||
iounmap(host->base);
|
iounmap(host->base);
|
||||||
clk_disable(host->clk);
|
clk_disable(host->clk);
|
||||||
clk_put(host->clk);
|
clk_put(host->clk);
|
||||||
|
|
|
@ -151,6 +151,8 @@ struct mmci_host {
|
||||||
struct mmc_data *data;
|
struct mmc_data *data;
|
||||||
struct mmc_host *mmc;
|
struct mmc_host *mmc;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
int gpio_cd;
|
||||||
|
int gpio_wp;
|
||||||
|
|
||||||
unsigned int data_xfered;
|
unsigned int data_xfered;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue