sdhci-pxa.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. /* Supports:
  15. * SDHCI support for MMP2/PXA910/PXA168
  16. *
  17. * Refer to sdhci-s3c.c.
  18. */
  19. #include <linux/delay.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/mmc/host.h>
  22. #include <linux/clk.h>
  23. #include <linux/io.h>
  24. #include <linux/err.h>
  25. #include <plat/sdhci.h>
  26. #include "sdhci.h"
  27. #define DRIVER_NAME "sdhci-pxa"
  28. #define SD_FIFO_PARAM 0x104
  29. #define DIS_PAD_SD_CLK_GATE 0x400
  30. struct sdhci_pxa {
  31. struct sdhci_host *host;
  32. struct sdhci_pxa_platdata *pdata;
  33. struct clk *clk;
  34. struct resource *res;
  35. u8 clk_enable;
  36. };
  37. /*****************************************************************************\
  38. * *
  39. * SDHCI core callbacks *
  40. * *
  41. \*****************************************************************************/
  42. static void set_clock(struct sdhci_host *host, unsigned int clock)
  43. {
  44. struct sdhci_pxa *pxa = sdhci_priv(host);
  45. u32 tmp = 0;
  46. if (clock == 0) {
  47. if (pxa->clk_enable) {
  48. clk_disable(pxa->clk);
  49. pxa->clk_enable = 0;
  50. }
  51. } else {
  52. if (0 == pxa->clk_enable) {
  53. if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
  54. tmp = readl(host->ioaddr + SD_FIFO_PARAM);
  55. tmp |= DIS_PAD_SD_CLK_GATE;
  56. writel(tmp, host->ioaddr + SD_FIFO_PARAM);
  57. }
  58. clk_enable(pxa->clk);
  59. pxa->clk_enable = 1;
  60. }
  61. }
  62. }
  63. static struct sdhci_ops sdhci_pxa_ops = {
  64. .set_clock = set_clock,
  65. };
  66. /*****************************************************************************\
  67. * *
  68. * Device probing/removal *
  69. * *
  70. \*****************************************************************************/
  71. static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
  72. {
  73. struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
  74. struct device *dev = &pdev->dev;
  75. struct sdhci_host *host = NULL;
  76. struct resource *iomem = NULL;
  77. struct sdhci_pxa *pxa = NULL;
  78. int ret, irq;
  79. irq = platform_get_irq(pdev, 0);
  80. if (irq < 0) {
  81. dev_err(dev, "no irq specified\n");
  82. return irq;
  83. }
  84. iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  85. if (!iomem) {
  86. dev_err(dev, "no memory specified\n");
  87. return -ENOENT;
  88. }
  89. host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
  90. if (IS_ERR(host)) {
  91. dev_err(dev, "failed to alloc host\n");
  92. return PTR_ERR(host);
  93. }
  94. pxa = sdhci_priv(host);
  95. pxa->host = host;
  96. pxa->pdata = pdata;
  97. pxa->clk_enable = 0;
  98. pxa->clk = clk_get(dev, "PXA-SDHCLK");
  99. if (IS_ERR(pxa->clk)) {
  100. dev_err(dev, "failed to get io clock\n");
  101. ret = PTR_ERR(pxa->clk);
  102. goto out;
  103. }
  104. pxa->res = request_mem_region(iomem->start, resource_size(iomem),
  105. mmc_hostname(host->mmc));
  106. if (!pxa->res) {
  107. dev_err(&pdev->dev, "cannot request region\n");
  108. ret = -EBUSY;
  109. goto out;
  110. }
  111. host->ioaddr = ioremap(iomem->start, resource_size(iomem));
  112. if (!host->ioaddr) {
  113. dev_err(&pdev->dev, "failed to remap registers\n");
  114. ret = -ENOMEM;
  115. goto out;
  116. }
  117. host->hw_name = "MMC";
  118. host->ops = &sdhci_pxa_ops;
  119. host->irq = irq;
  120. host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
  121. if (pdata->quirks)
  122. host->quirks |= pdata->quirks;
  123. /* If slot design supports 8 bit data, indicate this to MMC. */
  124. if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
  125. host->mmc->caps |= MMC_CAP_8_BIT_DATA;
  126. ret = sdhci_add_host(host);
  127. if (ret) {
  128. dev_err(&pdev->dev, "failed to add host\n");
  129. goto out;
  130. }
  131. if (pxa->pdata->max_speed)
  132. host->mmc->f_max = pxa->pdata->max_speed;
  133. platform_set_drvdata(pdev, host);
  134. return 0;
  135. out:
  136. if (host) {
  137. clk_put(pxa->clk);
  138. if (host->ioaddr)
  139. iounmap(host->ioaddr);
  140. if (pxa->res)
  141. release_mem_region(pxa->res->start,
  142. resource_size(pxa->res));
  143. sdhci_free_host(host);
  144. }
  145. return ret;
  146. }
  147. static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
  148. {
  149. struct sdhci_host *host = platform_get_drvdata(pdev);
  150. struct sdhci_pxa *pxa = sdhci_priv(host);
  151. int dead = 0;
  152. u32 scratch;
  153. if (host) {
  154. scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
  155. if (scratch == (u32)-1)
  156. dead = 1;
  157. sdhci_remove_host(host, dead);
  158. if (host->ioaddr)
  159. iounmap(host->ioaddr);
  160. if (pxa->res)
  161. release_mem_region(pxa->res->start,
  162. resource_size(pxa->res));
  163. if (pxa->clk_enable) {
  164. clk_disable(pxa->clk);
  165. pxa->clk_enable = 0;
  166. }
  167. clk_put(pxa->clk);
  168. sdhci_free_host(host);
  169. platform_set_drvdata(pdev, NULL);
  170. }
  171. return 0;
  172. }
  173. #ifdef CONFIG_PM
  174. static int sdhci_pxa_suspend(struct platform_device *dev, pm_message_t state)
  175. {
  176. struct sdhci_host *host = platform_get_drvdata(dev);
  177. return sdhci_suspend_host(host, state);
  178. }
  179. static int sdhci_pxa_resume(struct platform_device *dev)
  180. {
  181. struct sdhci_host *host = platform_get_drvdata(dev);
  182. return sdhci_resume_host(host);
  183. }
  184. #else
  185. #define sdhci_pxa_suspend NULL
  186. #define sdhci_pxa_resume NULL
  187. #endif
  188. static struct platform_driver sdhci_pxa_driver = {
  189. .probe = sdhci_pxa_probe,
  190. .remove = __devexit_p(sdhci_pxa_remove),
  191. .suspend = sdhci_pxa_suspend,
  192. .resume = sdhci_pxa_resume,
  193. .driver = {
  194. .name = DRIVER_NAME,
  195. .owner = THIS_MODULE,
  196. },
  197. };
  198. /*****************************************************************************\
  199. * *
  200. * Driver init/exit *
  201. * *
  202. \*****************************************************************************/
  203. static int __init sdhci_pxa_init(void)
  204. {
  205. return platform_driver_register(&sdhci_pxa_driver);
  206. }
  207. static void __exit sdhci_pxa_exit(void)
  208. {
  209. platform_driver_unregister(&sdhci_pxa_driver);
  210. }
  211. module_init(sdhci_pxa_init);
  212. module_exit(sdhci_pxa_exit);
  213. MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
  214. MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
  215. MODULE_LICENSE("GPL v2");