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