2
0

xilinx_uartlite.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * QEMU model of Xilinx uartlite.
  3. *
  4. * Copyright (c) 2009 Edgar E. Iglesias.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "sysbus.h"
  25. #include "qemu-char.h"
  26. #define DUART(x)
  27. #define R_RX 0
  28. #define R_TX 1
  29. #define R_STATUS 2
  30. #define R_CTRL 3
  31. #define R_MAX 4
  32. #define STATUS_RXVALID 0x01
  33. #define STATUS_RXFULL 0x02
  34. #define STATUS_TXEMPTY 0x04
  35. #define STATUS_TXFULL 0x08
  36. #define STATUS_IE 0x10
  37. #define STATUS_OVERRUN 0x20
  38. #define STATUS_FRAME 0x40
  39. #define STATUS_PARITY 0x80
  40. #define CONTROL_RST_TX 0x01
  41. #define CONTROL_RST_RX 0x02
  42. #define CONTROL_IE 0x10
  43. struct xlx_uartlite
  44. {
  45. SysBusDevice busdev;
  46. CharDriverState *chr;
  47. qemu_irq irq;
  48. uint8_t rx_fifo[8];
  49. unsigned int rx_fifo_pos;
  50. unsigned int rx_fifo_len;
  51. uint32_t regs[R_MAX];
  52. };
  53. static void uart_update_irq(struct xlx_uartlite *s)
  54. {
  55. unsigned int irq;
  56. if (s->rx_fifo_len)
  57. s->regs[R_STATUS] |= STATUS_IE;
  58. irq = (s->regs[R_STATUS] & STATUS_IE) && (s->regs[R_CTRL] & CONTROL_IE);
  59. qemu_set_irq(s->irq, irq);
  60. }
  61. static void uart_update_status(struct xlx_uartlite *s)
  62. {
  63. uint32_t r;
  64. r = s->regs[R_STATUS];
  65. r &= ~7;
  66. r |= 1 << 2; /* Tx fifo is always empty. We are fast :) */
  67. r |= (s->rx_fifo_len == sizeof (s->rx_fifo)) << 1;
  68. r |= (!!s->rx_fifo_len);
  69. s->regs[R_STATUS] = r;
  70. }
  71. static uint32_t uart_readl (void *opaque, target_phys_addr_t addr)
  72. {
  73. struct xlx_uartlite *s = opaque;
  74. uint32_t r = 0;
  75. addr >>= 2;
  76. switch (addr)
  77. {
  78. case R_RX:
  79. r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 7];
  80. if (s->rx_fifo_len)
  81. s->rx_fifo_len--;
  82. uart_update_status(s);
  83. uart_update_irq(s);
  84. break;
  85. default:
  86. if (addr < ARRAY_SIZE(s->regs))
  87. r = s->regs[addr];
  88. DUART(qemu_log("%s addr=%x v=%x\n", __func__, addr, r));
  89. break;
  90. }
  91. return r;
  92. }
  93. static void
  94. uart_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
  95. {
  96. struct xlx_uartlite *s = opaque;
  97. unsigned char ch = value;
  98. addr >>= 2;
  99. switch (addr)
  100. {
  101. case R_STATUS:
  102. hw_error("write to UART STATUS?\n");
  103. break;
  104. case R_CTRL:
  105. if (value & CONTROL_RST_RX) {
  106. s->rx_fifo_pos = 0;
  107. s->rx_fifo_len = 0;
  108. }
  109. s->regs[addr] = value;
  110. break;
  111. case R_TX:
  112. if (s->chr)
  113. qemu_chr_write(s->chr, &ch, 1);
  114. s->regs[addr] = value;
  115. /* hax. */
  116. s->regs[R_STATUS] |= STATUS_IE;
  117. break;
  118. default:
  119. DUART(printf("%s addr=%x v=%x\n", __func__, addr, value));
  120. if (addr < ARRAY_SIZE(s->regs))
  121. s->regs[addr] = value;
  122. break;
  123. }
  124. uart_update_status(s);
  125. uart_update_irq(s);
  126. }
  127. static CPUReadMemoryFunc * const uart_read[] = {
  128. &uart_readl,
  129. &uart_readl,
  130. &uart_readl,
  131. };
  132. static CPUWriteMemoryFunc * const uart_write[] = {
  133. &uart_writel,
  134. &uart_writel,
  135. &uart_writel,
  136. };
  137. static void uart_rx(void *opaque, const uint8_t *buf, int size)
  138. {
  139. struct xlx_uartlite *s = opaque;
  140. /* Got a byte. */
  141. if (s->rx_fifo_len >= 8) {
  142. printf("WARNING: UART dropped char.\n");
  143. return;
  144. }
  145. s->rx_fifo[s->rx_fifo_pos] = *buf;
  146. s->rx_fifo_pos++;
  147. s->rx_fifo_pos &= 0x7;
  148. s->rx_fifo_len++;
  149. uart_update_status(s);
  150. uart_update_irq(s);
  151. }
  152. static int uart_can_rx(void *opaque)
  153. {
  154. struct xlx_uartlite *s = opaque;
  155. int r;
  156. r = s->rx_fifo_len < sizeof(s->rx_fifo);
  157. if (!r)
  158. printf("cannot receive!\n");
  159. return r;
  160. }
  161. static void uart_event(void *opaque, int event)
  162. {
  163. }
  164. static int xilinx_uartlite_init(SysBusDevice *dev)
  165. {
  166. struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
  167. int uart_regs;
  168. sysbus_init_irq(dev, &s->irq);
  169. uart_update_status(s);
  170. uart_regs = cpu_register_io_memory(uart_read, uart_write, s,
  171. DEVICE_NATIVE_ENDIAN);
  172. sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
  173. s->chr = qdev_init_chardev(&dev->qdev);
  174. if (s->chr)
  175. qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
  176. return 0;
  177. }
  178. static void xilinx_uart_register(void)
  179. {
  180. sysbus_register_dev("xilinx,uartlite", sizeof (struct xlx_uartlite),
  181. xilinx_uartlite_init);
  182. }
  183. device_init(xilinx_uart_register)