]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/mmc/host/sdhci-s3c.c
sdhci-s3c: enable SDHCI_QUIRK_NO_HISPD_BIT quirk
[net-next-2.6.git] / drivers / mmc / host / sdhci-s3c.c
1 /* linux/drivers/mmc/host/sdhci-s3c.c
2  *
3  * Copyright 2008 Openmoko Inc.
4  * Copyright 2008 Simtec Electronics
5  *      Ben Dooks <ben@simtec.co.uk>
6  *      http://armlinux.simtec.co.uk/
7  *
8  * SDHCI (HSMMC) support for Samsung SoC
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 #include <linux/delay.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19 #include <linux/clk.h>
20 #include <linux/io.h>
21
22 #include <linux/mmc/host.h>
23
24 #include <plat/sdhci.h>
25 #include <plat/regs-sdhci.h>
26
27 #include "sdhci.h"
28
29 #define MAX_BUS_CLK     (4)
30
31 /**
32  * struct sdhci_s3c - S3C SDHCI instance
33  * @host: The SDHCI host created
34  * @pdev: The platform device we where created from.
35  * @ioarea: The resource created when we claimed the IO area.
36  * @pdata: The platform data for this controller.
37  * @cur_clk: The index of the current bus clock.
38  * @clk_io: The clock for the internal bus interface.
39  * @clk_bus: The clocks that are available for the SD/MMC bus clock.
40  */
41 struct sdhci_s3c {
42         struct sdhci_host       *host;
43         struct platform_device  *pdev;
44         struct resource         *ioarea;
45         struct s3c_sdhci_platdata *pdata;
46         unsigned int            cur_clk;
47
48         struct clk              *clk_io;
49         struct clk              *clk_bus[MAX_BUS_CLK];
50 };
51
52 static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
53 {
54         return sdhci_priv(host);
55 }
56
57 /**
58  * get_curclk - convert ctrl2 register to clock source number
59  * @ctrl2: Control2 register value.
60  */
61 static u32 get_curclk(u32 ctrl2)
62 {
63         ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
64         ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
65
66         return ctrl2;
67 }
68
69 static void sdhci_s3c_check_sclk(struct sdhci_host *host)
70 {
71         struct sdhci_s3c *ourhost = to_s3c(host);
72         u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
73
74         if (get_curclk(tmp) != ourhost->cur_clk) {
75                 dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
76
77                 tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
78                 tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
79                 writel(tmp, host->ioaddr + 0x80);
80         }
81 }
82
83 /**
84  * sdhci_s3c_get_max_clk - callback to get maximum clock frequency.
85  * @host: The SDHCI host instance.
86  *
87  * Callback to return the maximum clock rate acheivable by the controller.
88 */
89 static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
90 {
91         struct sdhci_s3c *ourhost = to_s3c(host);
92         struct clk *busclk;
93         unsigned int rate, max;
94         int clk;
95
96         /* note, a reset will reset the clock source */
97
98         sdhci_s3c_check_sclk(host);
99
100         for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
101                 busclk = ourhost->clk_bus[clk];
102                 if (!busclk)
103                         continue;
104
105                 rate = clk_get_rate(busclk);
106                 if (rate > max)
107                         max = rate;
108         }
109
110         return max;
111 }
112
113 /**
114  * sdhci_s3c_consider_clock - consider one the bus clocks for current setting
115  * @ourhost: Our SDHCI instance.
116  * @src: The source clock index.
117  * @wanted: The clock frequency wanted.
118  */
119 static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
120                                              unsigned int src,
121                                              unsigned int wanted)
122 {
123         unsigned long rate;
124         struct clk *clksrc = ourhost->clk_bus[src];
125         int div;
126
127         if (!clksrc)
128                 return UINT_MAX;
129
130         rate = clk_get_rate(clksrc);
131
132         for (div = 1; div < 256; div *= 2) {
133                 if ((rate / div) <= wanted)
134                         break;
135         }
136
137         dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
138                 src, rate, wanted, rate / div);
139
140         return (wanted - (rate / div));
141 }
142
143 /**
144  * sdhci_s3c_set_clock - callback on clock change
145  * @host: The SDHCI host being changed
146  * @clock: The clock rate being requested.
147  *
148  * When the card's clock is going to be changed, look at the new frequency
149  * and find the best clock source to go with it.
150 */
151 static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
152 {
153         struct sdhci_s3c *ourhost = to_s3c(host);
154         unsigned int best = UINT_MAX;
155         unsigned int delta;
156         int best_src = 0;
157         int src;
158         u32 ctrl;
159
160         /* don't bother if the clock is going off. */
161         if (clock == 0)
162                 return;
163
164         for (src = 0; src < MAX_BUS_CLK; src++) {
165                 delta = sdhci_s3c_consider_clock(ourhost, src, clock);
166                 if (delta < best) {
167                         best = delta;
168                         best_src = src;
169                 }
170         }
171
172         dev_dbg(&ourhost->pdev->dev,
173                 "selected source %d, clock %d, delta %d\n",
174                  best_src, clock, best);
175
176         /* select the new clock source */
177
178         if (ourhost->cur_clk != best_src) {
179                 struct clk *clk = ourhost->clk_bus[best_src];
180
181                 /* turn clock off to card before changing clock source */
182                 writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
183
184                 ourhost->cur_clk = best_src;
185                 host->max_clk = clk_get_rate(clk);
186
187                 ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
188                 ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
189                 ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
190                 writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
191         }
192
193         /* reconfigure the hardware for new clock rate */
194
195         {
196                 struct mmc_ios ios;
197
198                 ios.clock = clock;
199
200                 if (ourhost->pdata->cfg_card)
201                         (ourhost->pdata->cfg_card)(ourhost->pdev, host->ioaddr,
202                                                    &ios, NULL);
203         }
204 }
205
206 /**
207  * sdhci_s3c_get_min_clock - callback to get minimal supported clock value
208  * @host: The SDHCI host being queried
209  *
210  * To init mmc host properly a minimal clock value is needed. For high system
211  * bus clock's values the standard formula gives values out of allowed range.
212  * The clock still can be set to lower values, if clock source other then
213  * system bus is selected.
214 */
215 static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host)
216 {
217         struct sdhci_s3c *ourhost = to_s3c(host);
218         unsigned int delta, min = UINT_MAX;
219         int src;
220
221         for (src = 0; src < MAX_BUS_CLK; src++) {
222                 delta = sdhci_s3c_consider_clock(ourhost, src, 0);
223                 if (delta == UINT_MAX)
224                         continue;
225                 /* delta is a negative value in this case */
226                 if (-delta < min)
227                         min = -delta;
228         }
229         return min;
230 }
231
232 static struct sdhci_ops sdhci_s3c_ops = {
233         .get_max_clock          = sdhci_s3c_get_max_clk,
234         .set_clock              = sdhci_s3c_set_clock,
235         .get_min_clock          = sdhci_s3c_get_min_clock,
236 };
237
238 static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
239 {
240         struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
241         struct device *dev = &pdev->dev;
242         struct sdhci_host *host;
243         struct sdhci_s3c *sc;
244         struct resource *res;
245         int ret, irq, ptr, clks;
246
247         if (!pdata) {
248                 dev_err(dev, "no device data specified\n");
249                 return -ENOENT;
250         }
251
252         irq = platform_get_irq(pdev, 0);
253         if (irq < 0) {
254                 dev_err(dev, "no irq specified\n");
255                 return irq;
256         }
257
258         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
259         if (!res) {
260                 dev_err(dev, "no memory specified\n");
261                 return -ENOENT;
262         }
263
264         host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
265         if (IS_ERR(host)) {
266                 dev_err(dev, "sdhci_alloc_host() failed\n");
267                 return PTR_ERR(host);
268         }
269
270         sc = sdhci_priv(host);
271
272         sc->host = host;
273         sc->pdev = pdev;
274         sc->pdata = pdata;
275
276         platform_set_drvdata(pdev, host);
277
278         sc->clk_io = clk_get(dev, "hsmmc");
279         if (IS_ERR(sc->clk_io)) {
280                 dev_err(dev, "failed to get io clock\n");
281                 ret = PTR_ERR(sc->clk_io);
282                 goto err_io_clk;
283         }
284
285         /* enable the local io clock and keep it running for the moment. */
286         clk_enable(sc->clk_io);
287
288         for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
289                 struct clk *clk;
290                 char *name = pdata->clocks[ptr];
291
292                 if (name == NULL)
293                         continue;
294
295                 clk = clk_get(dev, name);
296                 if (IS_ERR(clk)) {
297                         dev_err(dev, "failed to get clock %s\n", name);
298                         continue;
299                 }
300
301                 clks++;
302                 sc->clk_bus[ptr] = clk;
303                 clk_enable(clk);
304
305                 dev_info(dev, "clock source %d: %s (%ld Hz)\n",
306                          ptr, name, clk_get_rate(clk));
307         }
308
309         if (clks == 0) {
310                 dev_err(dev, "failed to find any bus clocks\n");
311                 ret = -ENOENT;
312                 goto err_no_busclks;
313         }
314
315         sc->ioarea = request_mem_region(res->start, resource_size(res),
316                                         mmc_hostname(host->mmc));
317         if (!sc->ioarea) {
318                 dev_err(dev, "failed to reserve register area\n");
319                 ret = -ENXIO;
320                 goto err_req_regs;
321         }
322
323         host->ioaddr = ioremap_nocache(res->start, resource_size(res));
324         if (!host->ioaddr) {
325                 dev_err(dev, "failed to map registers\n");
326                 ret = -ENXIO;
327                 goto err_req_regs;
328         }
329
330         /* Ensure we have minimal gpio selected CMD/CLK/Detect */
331         if (pdata->cfg_gpio)
332                 pdata->cfg_gpio(pdev, pdata->max_width);
333
334         host->hw_name = "samsung-hsmmc";
335         host->ops = &sdhci_s3c_ops;
336         host->quirks = 0;
337         host->irq = irq;
338
339         /* Setup quirks for the controller */
340         host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
341         host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
342
343 #ifndef CONFIG_MMC_SDHCI_S3C_DMA
344
345         /* we currently see overruns on errors, so disable the SDMA
346          * support as well. */
347         host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
348
349 #endif /* CONFIG_MMC_SDHCI_S3C_DMA */
350
351         /* It seems we do not get an DATA transfer complete on non-busy
352          * transfers, not sure if this is a problem with this specific
353          * SDHCI block, or a missing configuration that needs to be set. */
354         host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
355
356         host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
357                          SDHCI_QUIRK_32BIT_DMA_SIZE);
358
359         /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */
360         host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
361
362         ret = sdhci_add_host(host);
363         if (ret) {
364                 dev_err(dev, "sdhci_add_host() failed\n");
365                 goto err_add_host;
366         }
367
368         return 0;
369
370  err_add_host:
371         release_resource(sc->ioarea);
372         kfree(sc->ioarea);
373
374  err_req_regs:
375         for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
376                 clk_disable(sc->clk_bus[ptr]);
377                 clk_put(sc->clk_bus[ptr]);
378         }
379
380  err_no_busclks:
381         clk_disable(sc->clk_io);
382         clk_put(sc->clk_io);
383
384  err_io_clk:
385         sdhci_free_host(host);
386
387         return ret;
388 }
389
390 static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
391 {
392         struct sdhci_host *host =  platform_get_drvdata(pdev);
393         struct sdhci_s3c *sc = sdhci_priv(host);
394         int ptr;
395
396         sdhci_remove_host(host, 1);
397
398         for (ptr = 0; ptr < 3; ptr++) {
399                 clk_disable(sc->clk_bus[ptr]);
400                 clk_put(sc->clk_bus[ptr]);
401         }
402         clk_disable(sc->clk_io);
403         clk_put(sc->clk_io);
404
405         iounmap(host->ioaddr);
406         release_resource(sc->ioarea);
407         kfree(sc->ioarea);
408
409         sdhci_free_host(host);
410         platform_set_drvdata(pdev, NULL);
411
412         return 0;
413 }
414
415 #ifdef CONFIG_PM
416
417 static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
418 {
419         struct sdhci_host *host = platform_get_drvdata(dev);
420
421         sdhci_suspend_host(host, pm);
422         return 0;
423 }
424
425 static int sdhci_s3c_resume(struct platform_device *dev)
426 {
427         struct sdhci_host *host = platform_get_drvdata(dev);
428
429         sdhci_resume_host(host);
430         return 0;
431 }
432
433 #else
434 #define sdhci_s3c_suspend NULL
435 #define sdhci_s3c_resume NULL
436 #endif
437
438 static struct platform_driver sdhci_s3c_driver = {
439         .probe          = sdhci_s3c_probe,
440         .remove         = __devexit_p(sdhci_s3c_remove),
441         .suspend        = sdhci_s3c_suspend,
442         .resume         = sdhci_s3c_resume,
443         .driver         = {
444                 .owner  = THIS_MODULE,
445                 .name   = "s3c-sdhci",
446         },
447 };
448
449 static int __init sdhci_s3c_init(void)
450 {
451         return platform_driver_register(&sdhci_s3c_driver);
452 }
453
454 static void __exit sdhci_s3c_exit(void)
455 {
456         platform_driver_unregister(&sdhci_s3c_driver);
457 }
458
459 module_init(sdhci_s3c_init);
460 module_exit(sdhci_s3c_exit);
461
462 MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
463 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
464 MODULE_LICENSE("GPL v2");
465 MODULE_ALIAS("platform:s3c-sdhci");