tc6387xb.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Toshiba TC6387XB support
  3. * Copyright (c) 2005 Ian Molton
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This file contains TC6387XB base support.
  10. *
  11. */
  12. #include <linux/module.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/err.h>
  15. #include <linux/mfd/core.h>
  16. #include <linux/mfd/tmio.h>
  17. #include <linux/mfd/tc6387xb.h>
  18. enum {
  19. TC6387XB_CELL_MMC,
  20. };
  21. #ifdef CONFIG_PM
  22. static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
  23. {
  24. struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev);
  25. if (pdata && pdata->suspend)
  26. pdata->suspend(dev);
  27. return 0;
  28. }
  29. static int tc6387xb_resume(struct platform_device *dev)
  30. {
  31. struct tc6387xb_platform_data *pdata = platform_get_drvdata(dev);
  32. if (pdata && pdata->resume)
  33. pdata->resume(dev);
  34. return 0;
  35. }
  36. #else
  37. #define tc6387xb_suspend NULL
  38. #define tc6387xb_resume NULL
  39. #endif
  40. /*--------------------------------------------------------------------------*/
  41. static int tc6387xb_mmc_enable(struct platform_device *mmc)
  42. {
  43. struct platform_device *dev = to_platform_device(mmc->dev.parent);
  44. struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data;
  45. if (tc6387xb->enable_clk32k)
  46. tc6387xb->enable_clk32k(dev);
  47. return 0;
  48. }
  49. static int tc6387xb_mmc_disable(struct platform_device *mmc)
  50. {
  51. struct platform_device *dev = to_platform_device(mmc->dev.parent);
  52. struct tc6387xb_platform_data *tc6387xb = dev->dev.platform_data;
  53. if (tc6387xb->disable_clk32k)
  54. tc6387xb->disable_clk32k(dev);
  55. return 0;
  56. }
  57. /*--------------------------------------------------------------------------*/
  58. static struct resource tc6387xb_mmc_resources[] = {
  59. {
  60. .start = 0x800,
  61. .end = 0x9ff,
  62. .flags = IORESOURCE_MEM,
  63. },
  64. {
  65. .start = 0x200,
  66. .end = 0x2ff,
  67. .flags = IORESOURCE_MEM,
  68. },
  69. {
  70. .start = 0,
  71. .end = 0,
  72. .flags = IORESOURCE_IRQ,
  73. },
  74. };
  75. static struct mfd_cell tc6387xb_cells[] = {
  76. [TC6387XB_CELL_MMC] = {
  77. .name = "tmio-mmc",
  78. .enable = tc6387xb_mmc_enable,
  79. .disable = tc6387xb_mmc_disable,
  80. .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
  81. .resources = tc6387xb_mmc_resources,
  82. },
  83. };
  84. static int tc6387xb_probe(struct platform_device *dev)
  85. {
  86. struct tc6387xb_platform_data *data = platform_get_drvdata(dev);
  87. struct resource *iomem;
  88. int irq, ret;
  89. iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
  90. if (!iomem) {
  91. ret = -EINVAL;
  92. goto err_resource;
  93. }
  94. ret = platform_get_irq(dev, 0);
  95. if (ret >= 0)
  96. irq = ret;
  97. else
  98. goto err_resource;
  99. if (data && data->enable)
  100. data->enable(dev);
  101. printk(KERN_INFO "Toshiba tc6387xb initialised\n");
  102. tc6387xb_cells[TC6387XB_CELL_MMC].platform_data =
  103. &tc6387xb_cells[TC6387XB_CELL_MMC];
  104. tc6387xb_cells[TC6387XB_CELL_MMC].data_size =
  105. sizeof(tc6387xb_cells[TC6387XB_CELL_MMC]);
  106. ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
  107. ARRAY_SIZE(tc6387xb_cells), iomem, irq);
  108. if (!ret)
  109. return 0;
  110. err_resource:
  111. return ret;
  112. }
  113. static int tc6387xb_remove(struct platform_device *dev)
  114. {
  115. struct tc6387xb_platform_data *data = platform_get_drvdata(dev);
  116. if (data && data->disable)
  117. data->disable(dev);
  118. /* FIXME - free the resources! */
  119. return 0;
  120. }
  121. static struct platform_driver tc6387xb_platform_driver = {
  122. .driver = {
  123. .name = "tc6387xb",
  124. },
  125. .probe = tc6387xb_probe,
  126. .remove = tc6387xb_remove,
  127. .suspend = tc6387xb_suspend,
  128. .resume = tc6387xb_resume,
  129. };
  130. static int __init tc6387xb_init(void)
  131. {
  132. return platform_driver_register(&tc6387xb_platform_driver);
  133. }
  134. static void __exit tc6387xb_exit(void)
  135. {
  136. platform_driver_unregister(&tc6387xb_platform_driver);
  137. }
  138. module_init(tc6387xb_init);
  139. module_exit(tc6387xb_exit);
  140. MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
  141. MODULE_LICENSE("GPL v2");
  142. MODULE_AUTHOR("Ian Molton");
  143. MODULE_ALIAS("platform:tc6387xb");