pxa2xx_balloon3.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * linux/drivers/pcmcia/pxa2xx_balloon3.c
  3. *
  4. * Balloon3 PCMCIA specific routines.
  5. *
  6. * Author: Nick Bane
  7. * Created: June, 2006
  8. * Copyright: Toby Churchill Ltd
  9. * Derived from pxa2xx_mainstone.c, by Nico Pitre
  10. *
  11. * Various modification by Marek Vasut <marek.vasut@gmail.com>
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License version 2 as
  15. * published by the Free Software Foundation.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/gpio.h>
  19. #include <linux/errno.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/irq.h>
  23. #include <linux/io.h>
  24. #include <mach/balloon3.h>
  25. #include "soc_common.h"
  26. /*
  27. * These are a list of interrupt sources that provokes a polled
  28. * check of status
  29. */
  30. static struct pcmcia_irqs irqs[] = {
  31. { 0, BALLOON3_S0_CD_IRQ, "PCMCIA0 CD" },
  32. { 0, BALLOON3_BP_NSTSCHG_IRQ, "PCMCIA0 STSCHG" },
  33. };
  34. static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  35. {
  36. uint16_t ver;
  37. int ret;
  38. static void __iomem *fpga_ver;
  39. ver = __raw_readw(BALLOON3_FPGA_VER);
  40. if (ver > 0x0201)
  41. pr_warn("The FPGA code, version 0x%04x, is newer than rel-0.3. "
  42. "PCMCIA/CF support might be broken in this version!",
  43. ver);
  44. skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ;
  45. return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
  46. }
  47. static void balloon3_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  48. {
  49. soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
  50. }
  51. static unsigned long balloon3_pcmcia_status[2] = {
  52. BALLOON3_CF_nSTSCHG_BVD1,
  53. BALLOON3_CF_nSTSCHG_BVD1
  54. };
  55. static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  56. struct pcmcia_state *state)
  57. {
  58. uint16_t status;
  59. int flip;
  60. /* This actually reads the STATUS register */
  61. status = __raw_readw(BALLOON3_CF_STATUS_REG);
  62. flip = (status ^ balloon3_pcmcia_status[skt->nr])
  63. & BALLOON3_CF_nSTSCHG_BVD1;
  64. /*
  65. * Workaround for STSCHG which can't be deasserted:
  66. * We therefore disable/enable corresponding IRQs
  67. * as needed to avoid IRQ locks.
  68. */
  69. if (flip) {
  70. balloon3_pcmcia_status[skt->nr] = status;
  71. if (status & BALLOON3_CF_nSTSCHG_BVD1)
  72. enable_irq(BALLOON3_BP_NSTSCHG_IRQ);
  73. else
  74. disable_irq(BALLOON3_BP_NSTSCHG_IRQ);
  75. }
  76. state->detect = !gpio_get_value(BALLOON3_GPIO_S0_CD);
  77. state->ready = !!(status & BALLOON3_CF_nIRQ);
  78. state->bvd1 = !!(status & BALLOON3_CF_nSTSCHG_BVD1);
  79. state->bvd2 = 0; /* not available */
  80. state->vs_3v = 1; /* Always true its a CF card */
  81. state->vs_Xv = 0; /* not available */
  82. state->wrprot = 0; /* not available */
  83. }
  84. static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  85. const socket_state_t *state)
  86. {
  87. __raw_writew((state->flags & SS_RESET) ? BALLOON3_CF_RESET : 0,
  88. BALLOON3_CF_CONTROL_REG);
  89. return 0;
  90. }
  91. static void balloon3_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  92. {
  93. }
  94. static void balloon3_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  95. {
  96. }
  97. static struct pcmcia_low_level balloon3_pcmcia_ops = {
  98. .owner = THIS_MODULE,
  99. .hw_init = balloon3_pcmcia_hw_init,
  100. .hw_shutdown = balloon3_pcmcia_hw_shutdown,
  101. .socket_state = balloon3_pcmcia_socket_state,
  102. .configure_socket = balloon3_pcmcia_configure_socket,
  103. .socket_init = balloon3_pcmcia_socket_init,
  104. .socket_suspend = balloon3_pcmcia_socket_suspend,
  105. .first = 0,
  106. .nr = 1,
  107. };
  108. static struct platform_device *balloon3_pcmcia_device;
  109. static int __init balloon3_pcmcia_init(void)
  110. {
  111. int ret;
  112. balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
  113. if (!balloon3_pcmcia_device)
  114. return -ENOMEM;
  115. ret = platform_device_add_data(balloon3_pcmcia_device,
  116. &balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops));
  117. if (!ret)
  118. ret = platform_device_add(balloon3_pcmcia_device);
  119. if (ret)
  120. platform_device_put(balloon3_pcmcia_device);
  121. return ret;
  122. }
  123. static void __exit balloon3_pcmcia_exit(void)
  124. {
  125. platform_device_unregister(balloon3_pcmcia_device);
  126. }
  127. module_init(balloon3_pcmcia_init);
  128. module_exit(balloon3_pcmcia_exit);
  129. MODULE_LICENSE("GPL");
  130. MODULE_AUTHOR("Nick Bane <nick@cecomputing.co.uk>");
  131. MODULE_ALIAS("platform:pxa2xx-pcmcia");
  132. MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver");