Merge tag 'mac80211-next-for-john-2014-11-04' of git://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / drivers / mmc / host / sdhci-sirf.c
1 /*
2  * SDHCI support for SiRF primaII and marco SoCs
3  *
4  * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5  *
6  * Licensed under GPLv2 or later.
7  */
8
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/mmc/host.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/of_gpio.h>
15 #include <linux/mmc/slot-gpio.h>
16 #include "sdhci-pltfm.h"
17
18 #define SDHCI_SIRF_8BITBUS BIT(3)
19
20 struct sdhci_sirf_priv {
21         struct clk *clk;
22         int gpio_cd;
23 };
24
25 static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
26 {
27         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
28         struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
29         return clk_get_rate(priv->clk);
30 }
31
32 static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width)
33 {
34         u8 ctrl;
35
36         ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
37         ctrl &= ~(SDHCI_CTRL_4BITBUS | SDHCI_SIRF_8BITBUS);
38
39         /*
40          * CSR atlas7 and prima2 SD host version is not 3.0
41          * 8bit-width enable bit of CSR SD hosts is 3,
42          * while stardard hosts use bit 5
43          */
44         if (width == MMC_BUS_WIDTH_8)
45                 ctrl |= SDHCI_SIRF_8BITBUS;
46         else if (width == MMC_BUS_WIDTH_4)
47                 ctrl |= SDHCI_CTRL_4BITBUS;
48
49         sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
50 }
51
52 static struct sdhci_ops sdhci_sirf_ops = {
53         .set_clock = sdhci_set_clock,
54         .get_max_clock  = sdhci_sirf_get_max_clk,
55         .set_bus_width = sdhci_sirf_set_bus_width,
56         .reset = sdhci_reset,
57         .set_uhs_signaling = sdhci_set_uhs_signaling,
58 };
59
60 static struct sdhci_pltfm_data sdhci_sirf_pdata = {
61         .ops = &sdhci_sirf_ops,
62         .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
63                 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
64                 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
65                 SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
66                 SDHCI_QUIRK_DELAY_AFTER_POWER,
67 };
68
69 static int sdhci_sirf_probe(struct platform_device *pdev)
70 {
71         struct sdhci_host *host;
72         struct sdhci_pltfm_host *pltfm_host;
73         struct sdhci_sirf_priv *priv;
74         struct clk *clk;
75         int gpio_cd;
76         int ret;
77
78         clk = devm_clk_get(&pdev->dev, NULL);
79         if (IS_ERR(clk)) {
80                 dev_err(&pdev->dev, "unable to get clock");
81                 return PTR_ERR(clk);
82         }
83
84         if (pdev->dev.of_node)
85                 gpio_cd = of_get_named_gpio(pdev->dev.of_node, "cd-gpios", 0);
86         else
87                 gpio_cd = -EINVAL;
88
89         host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata, sizeof(struct sdhci_sirf_priv));
90         if (IS_ERR(host))
91                 return PTR_ERR(host);
92
93         pltfm_host = sdhci_priv(host);
94         priv = sdhci_pltfm_priv(pltfm_host);
95         priv->clk = clk;
96         priv->gpio_cd = gpio_cd;
97
98         sdhci_get_of_property(pdev);
99
100         ret = clk_prepare_enable(priv->clk);
101         if (ret)
102                 goto err_clk_prepare;
103
104         ret = sdhci_add_host(host);
105         if (ret)
106                 goto err_sdhci_add;
107
108         /*
109          * We must request the IRQ after sdhci_add_host(), as the tasklet only
110          * gets setup in sdhci_add_host() and we oops.
111          */
112         if (gpio_is_valid(priv->gpio_cd)) {
113                 ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0);
114                 if (ret) {
115                         dev_err(&pdev->dev, "card detect irq request failed: %d\n",
116                                 ret);
117                         goto err_request_cd;
118                 }
119                 mmc_gpiod_request_cd_irq(host->mmc);
120         }
121
122         return 0;
123
124 err_request_cd:
125         sdhci_remove_host(host, 0);
126 err_sdhci_add:
127         clk_disable_unprepare(priv->clk);
128 err_clk_prepare:
129         sdhci_pltfm_free(pdev);
130         return ret;
131 }
132
133 static int sdhci_sirf_remove(struct platform_device *pdev)
134 {
135         struct sdhci_host *host = platform_get_drvdata(pdev);
136         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
137         struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
138
139         sdhci_pltfm_unregister(pdev);
140
141         if (gpio_is_valid(priv->gpio_cd))
142                 mmc_gpio_free_cd(host->mmc);
143
144         clk_disable_unprepare(priv->clk);
145         return 0;
146 }
147
148 #ifdef CONFIG_PM_SLEEP
149 static int sdhci_sirf_suspend(struct device *dev)
150 {
151         struct sdhci_host *host = dev_get_drvdata(dev);
152         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
153         struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
154         int ret;
155
156         ret = sdhci_suspend_host(host);
157         if (ret)
158                 return ret;
159
160         clk_disable(priv->clk);
161
162         return 0;
163 }
164
165 static int sdhci_sirf_resume(struct device *dev)
166 {
167         struct sdhci_host *host = dev_get_drvdata(dev);
168         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
169         struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host);
170         int ret;
171
172         ret = clk_enable(priv->clk);
173         if (ret) {
174                 dev_dbg(dev, "Resume: Error enabling clock\n");
175                 return ret;
176         }
177
178         return sdhci_resume_host(host);
179 }
180
181 static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops, sdhci_sirf_suspend, sdhci_sirf_resume);
182 #endif
183
184 static const struct of_device_id sdhci_sirf_of_match[] = {
185         { .compatible = "sirf,prima2-sdhc" },
186         { }
187 };
188 MODULE_DEVICE_TABLE(of, sdhci_sirf_of_match);
189
190 static struct platform_driver sdhci_sirf_driver = {
191         .driver         = {
192                 .name   = "sdhci-sirf",
193                 .of_match_table = sdhci_sirf_of_match,
194 #ifdef CONFIG_PM_SLEEP
195                 .pm     = &sdhci_sirf_pm_ops,
196 #endif
197         },
198         .probe          = sdhci_sirf_probe,
199         .remove         = sdhci_sirf_remove,
200 };
201
202 module_platform_driver(sdhci_sirf_driver);
203
204 MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco");
205 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
206 MODULE_LICENSE("GPL v2");