aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2013-01-16 08:13:59 -0500
committerChris Ball <cjb@laptop.org>2013-02-11 13:28:54 -0500
commit111936ff3bc33585b475c1033fc98cd6b3370a74 (patch)
treec561cf4562672e29145bb16faff448639e18e259
parent07728b77c03dc0721daaf551976d95e6f714af1a (diff)
mmc: mvsdio: implement a Device Tree binding
This patch adds a simple Device Tree binding for the mvsdio driver, as well as the necessary documentation for it. Compatibility with non-DT platforms is preserved, by keeping the platform_data based initialization. We introduce a small difference between non-DT and DT platforms: DT platforms are required to provide a clocks = <...> property, which the driver uses to get the frequency of the clock that goes to the SDIO IP. The behaviour on non-DT platforms is kept unchanged: a clock reference is not mandatory, but the clock frequency must be passed in the "clock" field of the mvsdio_platform_data structure. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Tested-by: Stefan Peter <s.peter@mpl.ch> Tested-by: Florian Fainelli <florian@openwrt.org> Signed-off-by: Jason Cooper <jason@lakedaemon.net> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--Documentation/devicetree/bindings/mmc/orion-sdio.txt17
-rw-r--r--drivers/mmc/host/mvsdio.c64
2 files changed, 66 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/mmc/orion-sdio.txt b/Documentation/devicetree/bindings/mmc/orion-sdio.txt
new file mode 100644
index 000000000000..84f0ebd67a13
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/orion-sdio.txt
@@ -0,0 +1,17 @@
1* Marvell orion-sdio controller
2
3This file documents differences between the core properties in mmc.txt
4and the properties used by the orion-sdio driver.
5
6- compatible: Should be "marvell,orion-sdio"
7- clocks: reference to the clock of the SDIO interface
8
9Example:
10
11 mvsdio@d00d4000 {
12 compatible = "marvell,orion-sdio";
13 reg = <0xd00d4000 0x200>;
14 interrupts = <54>;
15 clocks = <&gateclk 17>;
16 status = "disabled";
17 };
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 704b7a3fe873..78d3abf837c2 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -21,6 +21,8 @@
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/gpio.h> 23#include <linux/gpio.h>
24#include <linux/of_gpio.h>
25#include <linux/of_irq.h>
24#include <linux/mmc/host.h> 26#include <linux/mmc/host.h>
25#include <linux/mmc/slot-gpio.h> 27#include <linux/mmc/slot-gpio.h>
26 28
@@ -681,17 +683,17 @@ mv_conf_mbus_windows(struct mvsd_host *host,
681 683
682static int __init mvsd_probe(struct platform_device *pdev) 684static int __init mvsd_probe(struct platform_device *pdev)
683{ 685{
686 struct device_node *np = pdev->dev.of_node;
684 struct mmc_host *mmc = NULL; 687 struct mmc_host *mmc = NULL;
685 struct mvsd_host *host = NULL; 688 struct mvsd_host *host = NULL;
686 const struct mvsdio_platform_data *mvsd_data;
687 const struct mbus_dram_target_info *dram; 689 const struct mbus_dram_target_info *dram;
688 struct resource *r; 690 struct resource *r;
689 int ret, irq; 691 int ret, irq;
692 int gpio_card_detect, gpio_write_protect;
690 693
691 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 694 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
692 irq = platform_get_irq(pdev, 0); 695 irq = platform_get_irq(pdev, 0);
693 mvsd_data = pdev->dev.platform_data; 696 if (!r || irq < 0)
694 if (!r || irq < 0 || !mvsd_data)
695 return -ENXIO; 697 return -ENXIO;
696 698
697 mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); 699 mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
@@ -703,8 +705,39 @@ static int __init mvsd_probe(struct platform_device *pdev)
703 host = mmc_priv(mmc); 705 host = mmc_priv(mmc);
704 host->mmc = mmc; 706 host->mmc = mmc;
705 host->dev = &pdev->dev; 707 host->dev = &pdev->dev;
706 host->base_clock = mvsd_data->clock / 2; 708
707 host->clk = ERR_PTR(-EINVAL); 709 /*
710 * Some non-DT platforms do not pass a clock, and the clock
711 * frequency is passed through platform_data. On DT platforms,
712 * a clock must always be passed, even if there is no gatable
713 * clock associated to the SDIO interface (it can simply be a
714 * fixed rate clock).
715 */
716 host->clk = devm_clk_get(&pdev->dev, NULL);
717 if (!IS_ERR(host->clk))
718 clk_prepare_enable(host->clk);
719
720 if (np) {
721 if (IS_ERR(host->clk)) {
722 dev_err(&pdev->dev, "DT platforms must have a clock associated\n");
723 ret = -EINVAL;
724 goto out;
725 }
726
727 host->base_clock = clk_get_rate(host->clk) / 2;
728 gpio_card_detect = of_get_named_gpio(np, "cd-gpios", 0);
729 gpio_write_protect = of_get_named_gpio(np, "wp-gpios", 0);
730 } else {
731 const struct mvsdio_platform_data *mvsd_data;
732 mvsd_data = pdev->dev.platform_data;
733 if (!mvsd_data) {
734 ret = -ENXIO;
735 goto out;
736 }
737 host->base_clock = mvsd_data->clock / 2;
738 gpio_card_detect = mvsd_data->gpio_card_detect;
739 gpio_write_protect = mvsd_data->gpio_write_protect;
740 }
708 741
709 mmc->ops = &mvsd_ops; 742 mmc->ops = &mvsd_ops;
710 743
@@ -743,20 +776,14 @@ static int __init mvsd_probe(struct platform_device *pdev)
743 goto out; 776 goto out;
744 } 777 }
745 778
746 /* Not all platforms can gate the clock, so it is not 779 if (gpio_is_valid(gpio_card_detect)) {
747 an error if the clock does not exists. */ 780 ret = mmc_gpio_request_cd(mmc, gpio_card_detect);
748 host->clk = devm_clk_get(&pdev->dev, NULL);
749 if (!IS_ERR(host->clk))
750 clk_prepare_enable(host->clk);
751
752 if (gpio_is_valid(mvsd_data->gpio_card_detect)) {
753 ret = mmc_gpio_request_cd(mmc, mvsd_data->gpio_card_detect);
754 if (ret) 781 if (ret)
755 goto out; 782 goto out;
756 } else 783 } else
757 mmc->caps |= MMC_CAP_NEEDS_POLL; 784 mmc->caps |= MMC_CAP_NEEDS_POLL;
758 785
759 mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect); 786 mmc_gpio_request_ro(mmc, gpio_write_protect);
760 787
761 setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); 788 setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host);
762 platform_set_drvdata(pdev, mmc); 789 platform_set_drvdata(pdev, mmc);
@@ -768,7 +795,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
768 mmc_hostname(mmc), DRIVER_NAME); 795 mmc_hostname(mmc), DRIVER_NAME);
769 if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) 796 if (!(mmc->caps & MMC_CAP_NEEDS_POLL))
770 printk("using GPIO %d for card detection\n", 797 printk("using GPIO %d for card detection\n",
771 mvsd_data->gpio_card_detect); 798 gpio_card_detect);
772 else 799 else
773 printk("lacking card detect (fall back to polling)\n"); 800 printk("lacking card detect (fall back to polling)\n");
774 return 0; 801 return 0;
@@ -832,12 +859,19 @@ static int mvsd_resume(struct platform_device *dev)
832#define mvsd_resume NULL 859#define mvsd_resume NULL
833#endif 860#endif
834 861
862static const struct of_device_id mvsdio_dt_ids[] = {
863 { .compatible = "marvell,orion-sdio" },
864 { /* sentinel */ }
865};
866MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
867
835static struct platform_driver mvsd_driver = { 868static struct platform_driver mvsd_driver = {
836 .remove = __exit_p(mvsd_remove), 869 .remove = __exit_p(mvsd_remove),
837 .suspend = mvsd_suspend, 870 .suspend = mvsd_suspend,
838 .resume = mvsd_resume, 871 .resume = mvsd_resume,
839 .driver = { 872 .driver = {
840 .name = DRIVER_NAME, 873 .name = DRIVER_NAME,
874 .of_match_table = mvsdio_dt_ids,
841 }, 875 },
842}; 876};
843 877