shakti_uart.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * SHAKTI UART
  3. *
  4. * Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
  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 "qemu/osdep.h"
  25. #include "hw/char/shakti_uart.h"
  26. #include "hw/qdev-properties.h"
  27. #include "hw/qdev-properties-system.h"
  28. #include "qemu/log.h"
  29. static uint64_t shakti_uart_read(void *opaque, hwaddr addr, unsigned size)
  30. {
  31. ShaktiUartState *s = opaque;
  32. switch (addr) {
  33. case SHAKTI_UART_BAUD:
  34. return s->uart_baud;
  35. case SHAKTI_UART_RX:
  36. qemu_chr_fe_accept_input(&s->chr);
  37. s->uart_status &= ~SHAKTI_UART_STATUS_RX_NOT_EMPTY;
  38. return s->uart_rx;
  39. case SHAKTI_UART_STATUS:
  40. return s->uart_status;
  41. case SHAKTI_UART_DELAY:
  42. return s->uart_delay;
  43. case SHAKTI_UART_CONTROL:
  44. return s->uart_control;
  45. case SHAKTI_UART_INT_EN:
  46. return s->uart_interrupt;
  47. case SHAKTI_UART_IQ_CYCLES:
  48. return s->uart_iq_cycles;
  49. case SHAKTI_UART_RX_THRES:
  50. return s->uart_rx_threshold;
  51. default:
  52. /* Also handles TX REG which is write only */
  53. qemu_log_mask(LOG_GUEST_ERROR,
  54. "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
  55. }
  56. return 0;
  57. }
  58. static void shakti_uart_write(void *opaque, hwaddr addr,
  59. uint64_t data, unsigned size)
  60. {
  61. ShaktiUartState *s = opaque;
  62. uint32_t value = data;
  63. uint8_t ch;
  64. switch (addr) {
  65. case SHAKTI_UART_BAUD:
  66. s->uart_baud = value;
  67. break;
  68. case SHAKTI_UART_TX:
  69. ch = value;
  70. qemu_chr_fe_write_all(&s->chr, &ch, 1);
  71. s->uart_status &= ~SHAKTI_UART_STATUS_TX_FULL;
  72. break;
  73. case SHAKTI_UART_STATUS:
  74. s->uart_status = value;
  75. break;
  76. case SHAKTI_UART_DELAY:
  77. s->uart_delay = value;
  78. break;
  79. case SHAKTI_UART_CONTROL:
  80. s->uart_control = value;
  81. break;
  82. case SHAKTI_UART_INT_EN:
  83. s->uart_interrupt = value;
  84. break;
  85. case SHAKTI_UART_IQ_CYCLES:
  86. s->uart_iq_cycles = value;
  87. break;
  88. case SHAKTI_UART_RX_THRES:
  89. s->uart_rx_threshold = value;
  90. break;
  91. default:
  92. qemu_log_mask(LOG_GUEST_ERROR,
  93. "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
  94. }
  95. }
  96. static const MemoryRegionOps shakti_uart_ops = {
  97. .read = shakti_uart_read,
  98. .write = shakti_uart_write,
  99. .endianness = DEVICE_NATIVE_ENDIAN,
  100. .impl = {.min_access_size = 1, .max_access_size = 4},
  101. .valid = {.min_access_size = 1, .max_access_size = 4},
  102. };
  103. static void shakti_uart_reset(DeviceState *dev)
  104. {
  105. ShaktiUartState *s = SHAKTI_UART(dev);
  106. s->uart_baud = SHAKTI_UART_BAUD_DEFAULT;
  107. s->uart_tx = 0x0;
  108. s->uart_rx = 0x0;
  109. s->uart_status = 0x0000;
  110. s->uart_delay = 0x0000;
  111. s->uart_control = SHAKTI_UART_CONTROL_DEFAULT;
  112. s->uart_interrupt = 0x0000;
  113. s->uart_iq_cycles = 0x00;
  114. s->uart_rx_threshold = 0x00;
  115. }
  116. static int shakti_uart_can_receive(void *opaque)
  117. {
  118. ShaktiUartState *s = opaque;
  119. return !(s->uart_status & SHAKTI_UART_STATUS_RX_NOT_EMPTY);
  120. }
  121. static void shakti_uart_receive(void *opaque, const uint8_t *buf, int size)
  122. {
  123. ShaktiUartState *s = opaque;
  124. s->uart_rx = *buf;
  125. s->uart_status |= SHAKTI_UART_STATUS_RX_NOT_EMPTY;
  126. }
  127. static void shakti_uart_realize(DeviceState *dev, Error **errp)
  128. {
  129. ShaktiUartState *sus = SHAKTI_UART(dev);
  130. qemu_chr_fe_set_handlers(&sus->chr, shakti_uart_can_receive,
  131. shakti_uart_receive, NULL, NULL, sus, NULL, true);
  132. }
  133. static void shakti_uart_instance_init(Object *obj)
  134. {
  135. ShaktiUartState *sus = SHAKTI_UART(obj);
  136. memory_region_init_io(&sus->mmio,
  137. obj,
  138. &shakti_uart_ops,
  139. sus,
  140. TYPE_SHAKTI_UART,
  141. 0x1000);
  142. sysbus_init_mmio(SYS_BUS_DEVICE(obj), &sus->mmio);
  143. }
  144. static const Property shakti_uart_properties[] = {
  145. DEFINE_PROP_CHR("chardev", ShaktiUartState, chr),
  146. };
  147. static void shakti_uart_class_init(ObjectClass *klass, void *data)
  148. {
  149. DeviceClass *dc = DEVICE_CLASS(klass);
  150. device_class_set_legacy_reset(dc, shakti_uart_reset);
  151. dc->realize = shakti_uart_realize;
  152. device_class_set_props(dc, shakti_uart_properties);
  153. set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
  154. }
  155. static const TypeInfo shakti_uart_info = {
  156. .name = TYPE_SHAKTI_UART,
  157. .parent = TYPE_SYS_BUS_DEVICE,
  158. .instance_size = sizeof(ShaktiUartState),
  159. .class_init = shakti_uart_class_init,
  160. .instance_init = shakti_uart_instance_init,
  161. };
  162. static void shakti_uart_register_types(void)
  163. {
  164. type_register_static(&shakti_uart_info);
  165. }
  166. type_init(shakti_uart_register_types)