pxa2xx_pcmcia.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
  3. *
  4. * Copyright (c) 2006 Openedhand Ltd.
  5. * Written by Andrzej Zaborowski <balrog@zabor.org>
  6. *
  7. * This code is licensed under the GPLv2.
  8. */
  9. #include "hw.h"
  10. #include "pcmcia.h"
  11. #include "pxa.h"
  12. struct pxa2xx_pcmcia_s {
  13. struct pcmcia_socket_s slot;
  14. struct pcmcia_card_s *card;
  15. qemu_irq irq;
  16. qemu_irq cd_irq;
  17. };
  18. static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
  19. target_phys_addr_t offset)
  20. {
  21. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  22. if (s->slot.attached) {
  23. return s->card->common_read(s->card->state, offset);
  24. }
  25. return 0;
  26. }
  27. static void pxa2xx_pcmcia_common_write(void *opaque,
  28. target_phys_addr_t offset, uint32_t value)
  29. {
  30. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  31. if (s->slot.attached) {
  32. s->card->common_write(s->card->state, offset, value);
  33. }
  34. }
  35. static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
  36. target_phys_addr_t offset)
  37. {
  38. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  39. if (s->slot.attached) {
  40. return s->card->attr_read(s->card->state, offset);
  41. }
  42. return 0;
  43. }
  44. static void pxa2xx_pcmcia_attr_write(void *opaque,
  45. target_phys_addr_t offset, uint32_t value)
  46. {
  47. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  48. if (s->slot.attached) {
  49. s->card->attr_write(s->card->state, offset, value);
  50. }
  51. }
  52. static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
  53. target_phys_addr_t offset)
  54. {
  55. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  56. if (s->slot.attached) {
  57. return s->card->io_read(s->card->state, offset);
  58. }
  59. return 0;
  60. }
  61. static void pxa2xx_pcmcia_io_write(void *opaque,
  62. target_phys_addr_t offset, uint32_t value)
  63. {
  64. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  65. if (s->slot.attached) {
  66. s->card->io_write(s->card->state, offset, value);
  67. }
  68. }
  69. static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
  70. pxa2xx_pcmcia_common_read,
  71. pxa2xx_pcmcia_common_read,
  72. pxa2xx_pcmcia_common_read,
  73. };
  74. static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
  75. pxa2xx_pcmcia_common_write,
  76. pxa2xx_pcmcia_common_write,
  77. pxa2xx_pcmcia_common_write,
  78. };
  79. static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
  80. pxa2xx_pcmcia_attr_read,
  81. pxa2xx_pcmcia_attr_read,
  82. pxa2xx_pcmcia_attr_read,
  83. };
  84. static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
  85. pxa2xx_pcmcia_attr_write,
  86. pxa2xx_pcmcia_attr_write,
  87. pxa2xx_pcmcia_attr_write,
  88. };
  89. static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
  90. pxa2xx_pcmcia_io_read,
  91. pxa2xx_pcmcia_io_read,
  92. pxa2xx_pcmcia_io_read,
  93. };
  94. static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
  95. pxa2xx_pcmcia_io_write,
  96. pxa2xx_pcmcia_io_write,
  97. pxa2xx_pcmcia_io_write,
  98. };
  99. static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
  100. {
  101. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  102. if (!s->irq)
  103. return;
  104. qemu_set_irq(s->irq, level);
  105. }
  106. struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
  107. {
  108. int iomemtype;
  109. struct pxa2xx_pcmcia_s *s;
  110. s = (struct pxa2xx_pcmcia_s *)
  111. qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s));
  112. /* Socket I/O Memory Space */
  113. iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_io_readfn,
  114. pxa2xx_pcmcia_io_writefn, s);
  115. cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
  116. /* Then next 64 MB is reserved */
  117. /* Socket Attribute Memory Space */
  118. iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_attr_readfn,
  119. pxa2xx_pcmcia_attr_writefn, s);
  120. cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
  121. /* Socket Common Memory Space */
  122. iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_common_readfn,
  123. pxa2xx_pcmcia_common_writefn, s);
  124. cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype);
  125. if (base == 0x30000000)
  126. s->slot.slot_string = "PXA PC Card Socket 1";
  127. else
  128. s->slot.slot_string = "PXA PC Card Socket 0";
  129. s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
  130. pcmcia_socket_register(&s->slot);
  131. return s;
  132. }
  133. /* Insert a new card into a slot */
  134. int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card)
  135. {
  136. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  137. if (s->slot.attached)
  138. return -EEXIST;
  139. if (s->cd_irq) {
  140. qemu_irq_raise(s->cd_irq);
  141. }
  142. s->card = card;
  143. s->slot.attached = 1;
  144. s->card->slot = &s->slot;
  145. s->card->attach(s->card->state);
  146. return 0;
  147. }
  148. /* Eject card from the slot */
  149. int pxa2xx_pcmcia_dettach(void *opaque)
  150. {
  151. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  152. if (!s->slot.attached)
  153. return -ENOENT;
  154. s->card->detach(s->card->state);
  155. s->card->slot = 0;
  156. s->card = 0;
  157. s->slot.attached = 0;
  158. if (s->irq)
  159. qemu_irq_lower(s->irq);
  160. if (s->cd_irq)
  161. qemu_irq_lower(s->cd_irq);
  162. return 0;
  163. }
  164. /* Who to notify on card events */
  165. void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
  166. {
  167. struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
  168. s->irq = irq;
  169. s->cd_irq = cd_irq;
  170. }