icmp: Fix regression in nexthop resolution during replies.
[pandora-kernel.git] / drivers / mmc / host / sdhci-pxa.c
1 /* linux/drivers/mmc/host/sdhci-pxa.c
2  *
3  * Copyright (C) 2010 Marvell International Ltd.
4  *              Zhangfei Gao <zhangfei.gao@marvell.com>
5  *              Kevin Wang <dwang4@marvell.com>
6  *              Mingwei Wang <mwwang@marvell.com>
7  *              Philip Rakity <prakity@marvell.com>
8  *              Mark Brown <markb@marvell.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 /* Supports:
16  * SDHCI support for MMP2/PXA910/PXA168
17  *
18  * Refer to sdhci-s3c.c.
19  */
20
21 #include <linux/delay.h>
22 #include <linux/platform_device.h>
23 #include <linux/mmc/host.h>
24 #include <linux/clk.h>
25 #include <linux/io.h>
26 #include <linux/err.h>
27 #include <plat/sdhci.h>
28 #include "sdhci.h"
29
30 #define DRIVER_NAME     "sdhci-pxa"
31
32 #define SD_FIFO_PARAM           0x104
33 #define DIS_PAD_SD_CLK_GATE     0x400
34
35 struct sdhci_pxa {
36         struct sdhci_host               *host;
37         struct sdhci_pxa_platdata       *pdata;
38         struct clk                      *clk;
39         struct resource                 *res;
40
41         u8 clk_enable;
42 };
43
44 /*****************************************************************************\
45  *                                                                           *
46  * SDHCI core callbacks                                                      *
47  *                                                                           *
48 \*****************************************************************************/
49 static void set_clock(struct sdhci_host *host, unsigned int clock)
50 {
51         struct sdhci_pxa *pxa = sdhci_priv(host);
52         u32 tmp = 0;
53
54         if (clock == 0) {
55                 if (pxa->clk_enable) {
56                         clk_disable(pxa->clk);
57                         pxa->clk_enable = 0;
58                 }
59         } else {
60                 if (0 == pxa->clk_enable) {
61                         if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
62                                 tmp = readl(host->ioaddr + SD_FIFO_PARAM);
63                                 tmp |= DIS_PAD_SD_CLK_GATE;
64                                 writel(tmp, host->ioaddr + SD_FIFO_PARAM);
65                         }
66                         clk_enable(pxa->clk);
67                         pxa->clk_enable = 1;
68                 }
69         }
70 }
71
72 static int set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
73 {
74         u16 ctrl_2;
75
76         /*
77          * Set V18_EN -- UHS modes do not work without this.
78          * does not change signaling voltage
79          */
80         ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
81
82         /* Select Bus Speed Mode for host */
83         ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
84         switch (uhs) {
85         case MMC_TIMING_UHS_SDR12:
86                 ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
87                 break;
88         case MMC_TIMING_UHS_SDR25:
89                 ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
90                 break;
91         case MMC_TIMING_UHS_SDR50:
92                 ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
93                 break;
94         case MMC_TIMING_UHS_SDR104:
95                 ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
96                 break;
97         case MMC_TIMING_UHS_DDR50:
98                 ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
99                 break;
100         }
101
102         sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
103         pr_debug("%s:%s uhs = %d, ctrl_2 = %04X\n",
104                 __func__, mmc_hostname(host->mmc), uhs, ctrl_2);
105
106         return 0;
107 }
108
109 static struct sdhci_ops sdhci_pxa_ops = {
110         .set_uhs_signaling = set_uhs_signaling,
111         .set_clock = set_clock,
112 };
113
114 /*****************************************************************************\
115  *                                                                           *
116  * Device probing/removal                                                    *
117  *                                                                           *
118 \*****************************************************************************/
119
120 static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
121 {
122         struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
123         struct device *dev = &pdev->dev;
124         struct sdhci_host *host = NULL;
125         struct resource *iomem = NULL;
126         struct sdhci_pxa *pxa = NULL;
127         int ret, irq;
128
129         irq = platform_get_irq(pdev, 0);
130         if (irq < 0) {
131                 dev_err(dev, "no irq specified\n");
132                 return irq;
133         }
134
135         iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
136         if (!iomem) {
137                 dev_err(dev, "no memory specified\n");
138                 return -ENOENT;
139         }
140
141         host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
142         if (IS_ERR(host)) {
143                 dev_err(dev, "failed to alloc host\n");
144                 return PTR_ERR(host);
145         }
146
147         pxa = sdhci_priv(host);
148         pxa->host = host;
149         pxa->pdata = pdata;
150         pxa->clk_enable = 0;
151
152         pxa->clk = clk_get(dev, "PXA-SDHCLK");
153         if (IS_ERR(pxa->clk)) {
154                 dev_err(dev, "failed to get io clock\n");
155                 ret = PTR_ERR(pxa->clk);
156                 goto out;
157         }
158
159         pxa->res = request_mem_region(iomem->start, resource_size(iomem),
160                                       mmc_hostname(host->mmc));
161         if (!pxa->res) {
162                 dev_err(&pdev->dev, "cannot request region\n");
163                 ret = -EBUSY;
164                 goto out;
165         }
166
167         host->ioaddr = ioremap(iomem->start, resource_size(iomem));
168         if (!host->ioaddr) {
169                 dev_err(&pdev->dev, "failed to remap registers\n");
170                 ret = -ENOMEM;
171                 goto out;
172         }
173
174         host->hw_name = "MMC";
175         host->ops = &sdhci_pxa_ops;
176         host->irq = irq;
177         host->quirks = SDHCI_QUIRK_BROKEN_ADMA
178                 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
179                 | SDHCI_QUIRK_32BIT_DMA_ADDR
180                 | SDHCI_QUIRK_32BIT_DMA_SIZE
181                 | SDHCI_QUIRK_32BIT_ADMA_SIZE
182                 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
183
184         if (pdata->quirks)
185                 host->quirks |= pdata->quirks;
186
187         /* enable 1/8V DDR capable */
188         host->mmc->caps |= MMC_CAP_1_8V_DDR;
189
190         /* If slot design supports 8 bit data, indicate this to MMC. */
191         if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
192                 host->mmc->caps |= MMC_CAP_8_BIT_DATA;
193
194         ret = sdhci_add_host(host);
195         if (ret) {
196                 dev_err(&pdev->dev, "failed to add host\n");
197                 goto out;
198         }
199
200         if (pxa->pdata->max_speed)
201                 host->mmc->f_max = pxa->pdata->max_speed;
202
203         platform_set_drvdata(pdev, host);
204
205         return 0;
206 out:
207         if (host) {
208                 clk_put(pxa->clk);
209                 if (host->ioaddr)
210                         iounmap(host->ioaddr);
211                 if (pxa->res)
212                         release_mem_region(pxa->res->start,
213                                            resource_size(pxa->res));
214                 sdhci_free_host(host);
215         }
216
217         return ret;
218 }
219
220 static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
221 {
222         struct sdhci_host *host = platform_get_drvdata(pdev);
223         struct sdhci_pxa *pxa = sdhci_priv(host);
224         int dead = 0;
225         u32 scratch;
226
227         if (host) {
228                 scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
229                 if (scratch == (u32)-1)
230                         dead = 1;
231
232                 sdhci_remove_host(host, dead);
233
234                 if (host->ioaddr)
235                         iounmap(host->ioaddr);
236                 if (pxa->res)
237                         release_mem_region(pxa->res->start,
238                                            resource_size(pxa->res));
239                 if (pxa->clk_enable) {
240                         clk_disable(pxa->clk);
241                         pxa->clk_enable = 0;
242                 }
243                 clk_put(pxa->clk);
244
245                 sdhci_free_host(host);
246                 platform_set_drvdata(pdev, NULL);
247         }
248
249         return 0;
250 }
251
252 #ifdef CONFIG_PM
253 static int sdhci_pxa_suspend(struct platform_device *dev, pm_message_t state)
254 {
255         struct sdhci_host *host = platform_get_drvdata(dev);
256
257         return sdhci_suspend_host(host, state);
258 }
259
260 static int sdhci_pxa_resume(struct platform_device *dev)
261 {
262         struct sdhci_host *host = platform_get_drvdata(dev);
263
264         return sdhci_resume_host(host);
265 }
266 #else
267 #define sdhci_pxa_suspend       NULL
268 #define sdhci_pxa_resume        NULL
269 #endif
270
271 static struct platform_driver sdhci_pxa_driver = {
272         .probe          = sdhci_pxa_probe,
273         .remove         = __devexit_p(sdhci_pxa_remove),
274         .suspend        = sdhci_pxa_suspend,
275         .resume         = sdhci_pxa_resume,
276         .driver         = {
277                 .name   = DRIVER_NAME,
278                 .owner  = THIS_MODULE,
279         },
280 };
281
282 /*****************************************************************************\
283  *                                                                           *
284  * Driver init/exit                                                          *
285  *                                                                           *
286 \*****************************************************************************/
287
288 static int __init sdhci_pxa_init(void)
289 {
290         return platform_driver_register(&sdhci_pxa_driver);
291 }
292
293 static void __exit sdhci_pxa_exit(void)
294 {
295         platform_driver_unregister(&sdhci_pxa_driver);
296 }
297
298 module_init(sdhci_pxa_init);
299 module_exit(sdhci_pxa_exit);
300
301 MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
302 MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
303 MODULE_LICENSE("GPL v2");