0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/clk.h>
0017 #include <linux/delay.h>
0018 #include <linux/highmem.h>
0019 #include <linux/module.h>
0020 #include <linux/interrupt.h>
0021 #include <linux/irq.h>
0022 #include <linux/of.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/pm.h>
0025 #include <linux/slab.h>
0026 #include <linux/mmc/host.h>
0027 #include <linux/mmc/slot-gpio.h>
0028 #include <linux/io.h>
0029 #include "sdhci.h"
0030
0031 struct spear_sdhci {
0032 struct clk *clk;
0033 };
0034
0035
0036 static const struct sdhci_ops sdhci_pltfm_ops = {
0037 .set_clock = sdhci_set_clock,
0038 .set_bus_width = sdhci_set_bus_width,
0039 .reset = sdhci_reset,
0040 .set_uhs_signaling = sdhci_set_uhs_signaling,
0041 };
0042
0043 static int sdhci_probe(struct platform_device *pdev)
0044 {
0045 struct sdhci_host *host;
0046 struct spear_sdhci *sdhci;
0047 struct device *dev;
0048 int ret;
0049
0050 dev = pdev->dev.parent ? pdev->dev.parent : &pdev->dev;
0051 host = sdhci_alloc_host(dev, sizeof(*sdhci));
0052 if (IS_ERR(host)) {
0053 ret = PTR_ERR(host);
0054 dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n");
0055 goto err;
0056 }
0057
0058 host->ioaddr = devm_platform_ioremap_resource(pdev, 0);
0059 if (IS_ERR(host->ioaddr)) {
0060 ret = PTR_ERR(host->ioaddr);
0061 dev_dbg(&pdev->dev, "unable to map iomem: %d\n", ret);
0062 goto err_host;
0063 }
0064
0065 host->hw_name = "sdhci";
0066 host->ops = &sdhci_pltfm_ops;
0067 host->irq = platform_get_irq(pdev, 0);
0068 if (host->irq <= 0) {
0069 ret = -EINVAL;
0070 goto err_host;
0071 }
0072 host->quirks = SDHCI_QUIRK_BROKEN_ADMA;
0073
0074 sdhci = sdhci_priv(host);
0075
0076
0077 sdhci->clk = devm_clk_get(&pdev->dev, NULL);
0078 if (IS_ERR(sdhci->clk)) {
0079 ret = PTR_ERR(sdhci->clk);
0080 dev_dbg(&pdev->dev, "Error getting clock\n");
0081 goto err_host;
0082 }
0083
0084 ret = clk_prepare_enable(sdhci->clk);
0085 if (ret) {
0086 dev_dbg(&pdev->dev, "Error enabling clock\n");
0087 goto err_host;
0088 }
0089
0090 ret = clk_set_rate(sdhci->clk, 50000000);
0091 if (ret)
0092 dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n",
0093 clk_get_rate(sdhci->clk));
0094
0095
0096
0097
0098
0099 ret = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0);
0100 if (ret == -EPROBE_DEFER)
0101 goto disable_clk;
0102
0103 ret = sdhci_add_host(host);
0104 if (ret)
0105 goto disable_clk;
0106
0107 platform_set_drvdata(pdev, host);
0108
0109 return 0;
0110
0111 disable_clk:
0112 clk_disable_unprepare(sdhci->clk);
0113 err_host:
0114 sdhci_free_host(host);
0115 err:
0116 dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret);
0117 return ret;
0118 }
0119
0120 static int sdhci_remove(struct platform_device *pdev)
0121 {
0122 struct sdhci_host *host = platform_get_drvdata(pdev);
0123 struct spear_sdhci *sdhci = sdhci_priv(host);
0124 int dead = 0;
0125 u32 scratch;
0126
0127 scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
0128 if (scratch == (u32)-1)
0129 dead = 1;
0130
0131 sdhci_remove_host(host, dead);
0132 clk_disable_unprepare(sdhci->clk);
0133 sdhci_free_host(host);
0134
0135 return 0;
0136 }
0137
0138 #ifdef CONFIG_PM_SLEEP
0139 static int sdhci_suspend(struct device *dev)
0140 {
0141 struct sdhci_host *host = dev_get_drvdata(dev);
0142 struct spear_sdhci *sdhci = sdhci_priv(host);
0143 int ret;
0144
0145 if (host->tuning_mode != SDHCI_TUNING_MODE_3)
0146 mmc_retune_needed(host->mmc);
0147
0148 ret = sdhci_suspend_host(host);
0149 if (!ret)
0150 clk_disable(sdhci->clk);
0151
0152 return ret;
0153 }
0154
0155 static int sdhci_resume(struct device *dev)
0156 {
0157 struct sdhci_host *host = dev_get_drvdata(dev);
0158 struct spear_sdhci *sdhci = sdhci_priv(host);
0159 int ret;
0160
0161 ret = clk_enable(sdhci->clk);
0162 if (ret) {
0163 dev_dbg(dev, "Resume: Error enabling clock\n");
0164 return ret;
0165 }
0166
0167 return sdhci_resume_host(host);
0168 }
0169 #endif
0170
0171 static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume);
0172
0173 #ifdef CONFIG_OF
0174 static const struct of_device_id sdhci_spear_id_table[] = {
0175 { .compatible = "st,spear300-sdhci" },
0176 {}
0177 };
0178 MODULE_DEVICE_TABLE(of, sdhci_spear_id_table);
0179 #endif
0180
0181 static struct platform_driver sdhci_driver = {
0182 .driver = {
0183 .name = "sdhci",
0184 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0185 .pm = &sdhci_pm_ops,
0186 .of_match_table = of_match_ptr(sdhci_spear_id_table),
0187 },
0188 .probe = sdhci_probe,
0189 .remove = sdhci_remove,
0190 };
0191
0192 module_platform_driver(sdhci_driver);
0193
0194 MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver");
0195 MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>");
0196 MODULE_LICENSE("GPL v2");