diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-07-09 10:16:07 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-07-09 10:16:07 -0400 |
commit | 89001446925d6da8785c3265a71316e34c6d15de (patch) | |
tree | 467acdeafd056c93456d4db33ada112ae804eabe /drivers/mmc | |
parent | 7fb2bbf4d9e7e62057184f1e061566459eef6c79 (diff) |
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>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/mmci.c | 63 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 2 |
2 files changed, 63 insertions, 2 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index ac43f395eec0..5eb86a8c943b 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/amba/bus.h> | 21 | #include <linux/amba/bus.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | #include <linux/gpio.h> | ||
24 | 25 | ||
25 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
26 | #include <asm/div64.h> | 27 | #include <asm/div64.h> |
@@ -472,17 +473,41 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
472 | } | 473 | } |
473 | } | 474 | } |
474 | 475 | ||
476 | static int mmci_get_ro(struct mmc_host *mmc) | ||
477 | { | ||
478 | struct mmci_host *host = mmc_priv(mmc); | ||
479 | |||
480 | if (host->gpio_wp == -ENOSYS) | ||
481 | return -ENOSYS; | ||
482 | |||
483 | return gpio_get_value(host->gpio_wp); | ||
484 | } | ||
485 | |||
486 | static int mmci_get_cd(struct mmc_host *mmc) | ||
487 | { | ||
488 | struct mmci_host *host = mmc_priv(mmc); | ||
489 | unsigned int status; | ||
490 | |||
491 | if (host->gpio_cd == -ENOSYS) | ||
492 | status = host->plat->status(mmc_dev(host->mmc)); | ||
493 | else | ||
494 | status = gpio_get_value(host->gpio_cd); | ||
495 | |||
496 | return !status; | ||
497 | } | ||
498 | |||
475 | static const struct mmc_host_ops mmci_ops = { | 499 | static const struct mmc_host_ops mmci_ops = { |
476 | .request = mmci_request, | 500 | .request = mmci_request, |
477 | .set_ios = mmci_set_ios, | 501 | .set_ios = mmci_set_ios, |
502 | .get_ro = mmci_get_ro, | ||
503 | .get_cd = mmci_get_cd, | ||
478 | }; | 504 | }; |
479 | 505 | ||
480 | static void mmci_check_status(unsigned long data) | 506 | static void mmci_check_status(unsigned long data) |
481 | { | 507 | { |
482 | struct mmci_host *host = (struct mmci_host *)data; | 508 | struct mmci_host *host = (struct mmci_host *)data; |
483 | unsigned int status; | 509 | unsigned int status = mmci_get_cd(host->mmc); |
484 | 510 | ||
485 | status = host->plat->status(mmc_dev(host->mmc)); | ||
486 | if (status ^ host->oldstat) | 511 | if (status ^ host->oldstat) |
487 | mmc_detect_change(host->mmc, 0); | 512 | mmc_detect_change(host->mmc, 0); |
488 | 513 | ||
@@ -516,6 +541,9 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
516 | host = mmc_priv(mmc); | 541 | host = mmc_priv(mmc); |
517 | host->mmc = mmc; | 542 | host->mmc = mmc; |
518 | 543 | ||
544 | host->gpio_wp = -ENOSYS; | ||
545 | host->gpio_cd = -ENOSYS; | ||
546 | |||
519 | host->hw_designer = amba_manf(dev); | 547 | host->hw_designer = amba_manf(dev); |
520 | host->hw_revision = amba_rev(dev); | 548 | host->hw_revision = amba_rev(dev); |
521 | DBG(host, "designer ID = 0x%02x\n", host->hw_designer); | 549 | 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) | |||
591 | writel(0, host->base + MMCIMASK1); | 619 | writel(0, host->base + MMCIMASK1); |
592 | writel(0xfff, host->base + MMCICLEAR); | 620 | writel(0xfff, host->base + MMCICLEAR); |
593 | 621 | ||
622 | if (gpio_is_valid(plat->gpio_cd)) { | ||
623 | ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)"); | ||
624 | if (ret == 0) | ||
625 | ret = gpio_direction_input(plat->gpio_cd); | ||
626 | if (ret == 0) | ||
627 | host->gpio_cd = plat->gpio_cd; | ||
628 | else if (ret != -ENOSYS) | ||
629 | goto err_gpio_cd; | ||
630 | } | ||
631 | if (gpio_is_valid(plat->gpio_wp)) { | ||
632 | ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); | ||
633 | if (ret == 0) | ||
634 | ret = gpio_direction_input(plat->gpio_wp); | ||
635 | if (ret == 0) | ||
636 | host->gpio_wp = plat->gpio_wp; | ||
637 | else if (ret != -ENOSYS) | ||
638 | goto err_gpio_wp; | ||
639 | } | ||
640 | |||
594 | ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); | 641 | ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); |
595 | if (ret) | 642 | if (ret) |
596 | goto unmap; | 643 | goto unmap; |
@@ -602,6 +649,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
602 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); | 649 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); |
603 | 650 | ||
604 | amba_set_drvdata(dev, mmc); | 651 | amba_set_drvdata(dev, mmc); |
652 | host->oldstat = mmci_get_cd(host->mmc); | ||
605 | 653 | ||
606 | mmc_add_host(mmc); | 654 | mmc_add_host(mmc); |
607 | 655 | ||
@@ -620,6 +668,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
620 | irq0_free: | 668 | irq0_free: |
621 | free_irq(dev->irq[0], host); | 669 | free_irq(dev->irq[0], host); |
622 | unmap: | 670 | unmap: |
671 | if (host->gpio_wp != -ENOSYS) | ||
672 | gpio_free(host->gpio_wp); | ||
673 | err_gpio_wp: | ||
674 | if (host->gpio_cd != -ENOSYS) | ||
675 | gpio_free(host->gpio_cd); | ||
676 | err_gpio_cd: | ||
623 | iounmap(host->base); | 677 | iounmap(host->base); |
624 | clk_disable: | 678 | clk_disable: |
625 | clk_disable(host->clk); | 679 | clk_disable(host->clk); |
@@ -655,6 +709,11 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
655 | free_irq(dev->irq[0], host); | 709 | free_irq(dev->irq[0], host); |
656 | free_irq(dev->irq[1], host); | 710 | free_irq(dev->irq[1], host); |
657 | 711 | ||
712 | if (host->gpio_wp != -ENOSYS) | ||
713 | gpio_free(host->gpio_wp); | ||
714 | if (host->gpio_cd != -ENOSYS) | ||
715 | gpio_free(host->gpio_cd); | ||
716 | |||
658 | iounmap(host->base); | 717 | iounmap(host->base); |
659 | clk_disable(host->clk); | 718 | clk_disable(host->clk); |
660 | clk_put(host->clk); | 719 | clk_put(host->clk); |
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 0441bac1c0ec..839f264c9725 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
@@ -151,6 +151,8 @@ struct mmci_host { | |||
151 | struct mmc_data *data; | 151 | struct mmc_data *data; |
152 | struct mmc_host *mmc; | 152 | struct mmc_host *mmc; |
153 | struct clk *clk; | 153 | struct clk *clk; |
154 | int gpio_cd; | ||
155 | int gpio_wp; | ||
154 | 156 | ||
155 | unsigned int data_xfered; | 157 | unsigned int data_xfered; |
156 | 158 | ||