pxa2xx_vpac270.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * linux/drivers/pcmcia/pxa2xx_vpac270.c
  3. *
  4. * Driver for Voipac PXA270 PCMCIA and CF sockets
  5. *
  6. * Copyright (C) 2010
  7. * Marek Vasut <marek.vasut@gmail.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. *
  13. */
  14. #include <linux/module.h>
  15. #include <linux/platform_device.h>
  16. #include <asm/mach-types.h>
  17. #include <mach/gpio.h>
  18. #include <mach/vpac270.h>
  19. #include "soc_common.h"
  20. static struct pcmcia_irqs cd_irqs[] = {
  21. {
  22. .sock = 0,
  23. .irq = IRQ_GPIO(GPIO84_VPAC270_PCMCIA_CD),
  24. .str = "PCMCIA CD"
  25. },
  26. {
  27. .sock = 1,
  28. .irq = IRQ_GPIO(GPIO17_VPAC270_CF_CD),
  29. .str = "CF CD"
  30. },
  31. };
  32. static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  33. {
  34. int ret;
  35. if (skt->nr == 0) {
  36. ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD");
  37. if (ret)
  38. goto err1;
  39. ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD);
  40. if (ret)
  41. goto err2;
  42. ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY");
  43. if (ret)
  44. goto err2;
  45. ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY);
  46. if (ret)
  47. goto err3;
  48. ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN");
  49. if (ret)
  50. goto err3;
  51. ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0);
  52. if (ret)
  53. goto err4;
  54. ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET");
  55. if (ret)
  56. goto err4;
  57. ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0);
  58. if (ret)
  59. goto err5;
  60. skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY);
  61. return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1);
  62. err5:
  63. gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
  64. err4:
  65. gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
  66. err3:
  67. gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
  68. err2:
  69. gpio_free(GPIO84_VPAC270_PCMCIA_CD);
  70. err1:
  71. return ret;
  72. } else {
  73. ret = gpio_request(GPIO17_VPAC270_CF_CD, "CF CD");
  74. if (ret)
  75. goto err6;
  76. ret = gpio_direction_input(GPIO17_VPAC270_CF_CD);
  77. if (ret)
  78. goto err7;
  79. ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY");
  80. if (ret)
  81. goto err7;
  82. ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY);
  83. if (ret)
  84. goto err8;
  85. ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET");
  86. if (ret)
  87. goto err8;
  88. ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0);
  89. if (ret)
  90. goto err9;
  91. skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY);
  92. return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1);
  93. err9:
  94. gpio_free(GPIO16_VPAC270_CF_RESET);
  95. err8:
  96. gpio_free(GPIO12_VPAC270_CF_RDY);
  97. err7:
  98. gpio_free(GPIO17_VPAC270_CF_CD);
  99. err6:
  100. return ret;
  101. }
  102. }
  103. static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  104. {
  105. gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
  106. gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
  107. gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
  108. gpio_free(GPIO84_VPAC270_PCMCIA_CD);
  109. gpio_free(GPIO16_VPAC270_CF_RESET);
  110. gpio_free(GPIO12_VPAC270_CF_RDY);
  111. gpio_free(GPIO17_VPAC270_CF_CD);
  112. }
  113. static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  114. struct pcmcia_state *state)
  115. {
  116. if (skt->nr == 0) {
  117. state->detect = !gpio_get_value(GPIO84_VPAC270_PCMCIA_CD);
  118. state->ready = !!gpio_get_value(GPIO35_VPAC270_PCMCIA_RDY);
  119. } else {
  120. state->detect = !gpio_get_value(GPIO17_VPAC270_CF_CD);
  121. state->ready = !!gpio_get_value(GPIO12_VPAC270_CF_RDY);
  122. }
  123. state->bvd1 = 1;
  124. state->bvd2 = 1;
  125. state->wrprot = 0;
  126. state->vs_3v = 1;
  127. state->vs_Xv = 0;
  128. }
  129. static int
  130. vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  131. const socket_state_t *state)
  132. {
  133. if (skt->nr == 0) {
  134. gpio_set_value(GPIO11_VPAC270_PCMCIA_RESET,
  135. (state->flags & SS_RESET));
  136. gpio_set_value(GPIO107_VPAC270_PCMCIA_PPEN,
  137. !(state->Vcc == 33 || state->Vcc == 50));
  138. } else {
  139. gpio_set_value(GPIO16_VPAC270_CF_RESET,
  140. (state->flags & SS_RESET));
  141. }
  142. return 0;
  143. }
  144. static void vpac270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  145. {
  146. }
  147. static void vpac270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  148. {
  149. }
  150. static struct pcmcia_low_level vpac270_pcmcia_ops = {
  151. .owner = THIS_MODULE,
  152. .first = 0,
  153. .nr = 2,
  154. .hw_init = vpac270_pcmcia_hw_init,
  155. .hw_shutdown = vpac270_pcmcia_hw_shutdown,
  156. .socket_state = vpac270_pcmcia_socket_state,
  157. .configure_socket = vpac270_pcmcia_configure_socket,
  158. .socket_init = vpac270_pcmcia_socket_init,
  159. .socket_suspend = vpac270_pcmcia_socket_suspend,
  160. };
  161. static struct platform_device *vpac270_pcmcia_device;
  162. static int __init vpac270_pcmcia_init(void)
  163. {
  164. int ret;
  165. if (!machine_is_vpac270())
  166. return -ENODEV;
  167. vpac270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
  168. if (!vpac270_pcmcia_device)
  169. return -ENOMEM;
  170. ret = platform_device_add_data(vpac270_pcmcia_device,
  171. &vpac270_pcmcia_ops, sizeof(vpac270_pcmcia_ops));
  172. if (!ret)
  173. ret = platform_device_add(vpac270_pcmcia_device);
  174. if (ret)
  175. platform_device_put(vpac270_pcmcia_device);
  176. return ret;
  177. }
  178. static void __exit vpac270_pcmcia_exit(void)
  179. {
  180. platform_device_unregister(vpac270_pcmcia_device);
  181. }
  182. module_init(vpac270_pcmcia_init);
  183. module_exit(vpac270_pcmcia_exit);
  184. MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
  185. MODULE_DESCRIPTION("PCMCIA support for Voipac PXA270");
  186. MODULE_ALIAS("platform:pxa2xx-pcmcia");
  187. MODULE_LICENSE("GPL");