1 /* 2 * QEMU model of the UART on the SiFive E300 and U500 series SOCs. 3 * 4 * Copyright (c) 2016 Stefan O'Rear 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2 or later, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "qemu/osdep.h" 20 #include "qapi/error.h" 21 #include "qemu/log.h" 22 #include "migration/vmstate.h" 23 #include "chardev/char.h" 24 #include "chardev/char-fe.h" 25 #include "hw/irq.h" 26 #include "hw/char/sifive_uart.h" 27 #include "hw/qdev-properties-system.h" 28 29 #define TX_INTERRUPT_TRIGGER_DELAY_NS 100 30 31 /* 32 * Not yet implemented: 33 * 34 * Transmit FIFO using "qemu/fifo8.h" 35 */ 36 37 /* Returns the state of the IP (interrupt pending) register */ 38 static uint64_t sifive_uart_ip(SiFiveUARTState *s) 39 { 40 uint64_t ret = 0; 41 42 uint64_t txcnt = SIFIVE_UART_GET_TXCNT(s->txctrl); 43 uint64_t rxcnt = SIFIVE_UART_GET_RXCNT(s->rxctrl); 44 45 if (txcnt != 0) { 46 ret |= SIFIVE_UART_IP_TXWM; 47 } 48 if (s->rx_fifo_len > rxcnt) { 49 ret |= SIFIVE_UART_IP_RXWM; 50 } 51 52 return ret; 53 } 54 55 static void sifive_uart_update_irq(SiFiveUARTState *s) 56 { 57 int cond = 0; 58 if ((s->ie & SIFIVE_UART_IE_TXWM) || 59 ((s->ie & SIFIVE_UART_IE_RXWM) && s->rx_fifo_len)) { 60 cond = 1; 61 } 62 if (cond) { 63 qemu_irq_raise(s->irq); 64 } else { 65 qemu_irq_lower(s->irq); 66 } 67 } 68 69 static gboolean sifive_uart_xmit(void *do_not_use, GIOCondition cond, 70 void *opaque) 71 { 72 SiFiveUARTState *s = opaque; 73 int ret; 74 const uint8_t *characters; 75 uint32_t numptr = 0; 76 77 /* instant drain the fifo when there's no back-end */ 78 if (!qemu_chr_fe_backend_connected(&s->chr)) { 79 fifo8_reset(&s->tx_fifo); 80 return G_SOURCE_REMOVE; 81 } 82 83 if (fifo8_is_empty(&s->tx_fifo)) { 84 return G_SOURCE_REMOVE; 85 } 86 87 /* Don't pop the FIFO in case the write fails */ 88 characters = fifo8_peek_bufptr(&s->tx_fifo, 89 fifo8_num_used(&s->tx_fifo), &numptr); 90 ret = qemu_chr_fe_write(&s->chr, characters, numptr); 91 92 if (ret >= 0) { 93 /* We wrote the data, actually pop the fifo */ 94 fifo8_pop_bufptr(&s->tx_fifo, ret, NULL); 95 } 96 97 if (!fifo8_is_empty(&s->tx_fifo)) { 98 guint r = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, 99 sifive_uart_xmit, s); 100 if (!r) { 101 fifo8_reset(&s->tx_fifo); 102 return G_SOURCE_REMOVE; 103 } 104 } 105 106 /* Clear the TX Full bit */ 107 if (!fifo8_is_full(&s->tx_fifo)) { 108 s->txfifo &= ~SIFIVE_UART_TXFIFO_FULL; 109 } 110 111 sifive_uart_update_irq(s); 112 return G_SOURCE_REMOVE; 113 } 114 115 static void sifive_uart_write_tx_fifo(SiFiveUARTState *s, const uint8_t *buf, 116 int size) 117 { 118 uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 119 120 if (size > fifo8_num_free(&s->tx_fifo)) { 121 size = fifo8_num_free(&s->tx_fifo); 122 qemu_log_mask(LOG_GUEST_ERROR, "sifive_uart: TX FIFO overflow"); 123 } 124 125 fifo8_push_all(&s->tx_fifo, buf, size); 126 127 if (fifo8_is_full(&s->tx_fifo)) { 128 s->txfifo |= SIFIVE_UART_TXFIFO_FULL; 129 } 130 131 if (!timer_pending(s->fifo_trigger_handle)) { 132 timer_mod(s->fifo_trigger_handle, current_time + 133 TX_INTERRUPT_TRIGGER_DELAY_NS); 134 } 135 } 136 137 static uint64_t 138 sifive_uart_read(void *opaque, hwaddr addr, unsigned int size) 139 { 140 SiFiveUARTState *s = opaque; 141 unsigned char r; 142 switch (addr) { 143 case SIFIVE_UART_RXFIFO: 144 if (s->rx_fifo_len) { 145 r = s->rx_fifo[0]; 146 memmove(s->rx_fifo, s->rx_fifo + 1, s->rx_fifo_len - 1); 147 s->rx_fifo_len--; 148 qemu_chr_fe_accept_input(&s->chr); 149 sifive_uart_update_irq(s); 150 return r; 151 } 152 return 0x80000000; 153 154 case SIFIVE_UART_TXFIFO: 155 return s->txfifo; 156 case SIFIVE_UART_IE: 157 return s->ie; 158 case SIFIVE_UART_IP: 159 return sifive_uart_ip(s); 160 case SIFIVE_UART_TXCTRL: 161 return s->txctrl; 162 case SIFIVE_UART_RXCTRL: 163 return s->rxctrl; 164 case SIFIVE_UART_DIV: 165 return s->div; 166 } 167 168 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read: addr=0x%x\n", 169 __func__, (int)addr); 170 return 0; 171 } 172 173 static void 174 sifive_uart_write(void *opaque, hwaddr addr, 175 uint64_t val64, unsigned int size) 176 { 177 SiFiveUARTState *s = opaque; 178 uint32_t value = val64; 179 uint8_t ch = value; 180 181 switch (addr) { 182 case SIFIVE_UART_TXFIFO: 183 sifive_uart_write_tx_fifo(s, &ch, 1); 184 return; 185 case SIFIVE_UART_IE: 186 s->ie = val64; 187 sifive_uart_update_irq(s); 188 return; 189 case SIFIVE_UART_TXCTRL: 190 s->txctrl = val64; 191 return; 192 case SIFIVE_UART_RXCTRL: 193 s->rxctrl = val64; 194 return; 195 case SIFIVE_UART_DIV: 196 s->div = val64; 197 return; 198 } 199 qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x v=0x%x\n", 200 __func__, (int)addr, (int)value); 201 } 202 203 static void fifo_trigger_update(void *opaque) 204 { 205 SiFiveUARTState *s = opaque; 206 207 sifive_uart_xmit(NULL, G_IO_OUT, s); 208 } 209 210 static const MemoryRegionOps sifive_uart_ops = { 211 .read = sifive_uart_read, 212 .write = sifive_uart_write, 213 .endianness = DEVICE_NATIVE_ENDIAN, 214 .valid = { 215 .min_access_size = 4, 216 .max_access_size = 4 217 } 218 }; 219 220 static void sifive_uart_rx(void *opaque, const uint8_t *buf, int size) 221 { 222 SiFiveUARTState *s = opaque; 223 224 /* Got a byte. */ 225 if (s->rx_fifo_len >= sizeof(s->rx_fifo)) { 226 printf("WARNING: UART dropped char.\n"); 227 return; 228 } 229 s->rx_fifo[s->rx_fifo_len++] = *buf; 230 231 sifive_uart_update_irq(s); 232 } 233 234 static int sifive_uart_can_rx(void *opaque) 235 { 236 SiFiveUARTState *s = opaque; 237 238 return s->rx_fifo_len < sizeof(s->rx_fifo); 239 } 240 241 static void sifive_uart_event(void *opaque, QEMUChrEvent event) 242 { 243 } 244 245 static int sifive_uart_be_change(void *opaque) 246 { 247 SiFiveUARTState *s = opaque; 248 249 qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, 250 sifive_uart_event, sifive_uart_be_change, s, 251 NULL, true); 252 253 return 0; 254 } 255 256 static void sifive_uart_reset_enter(Object *obj, ResetType type) 257 { 258 SiFiveUARTState *s = SIFIVE_UART(obj); 259 260 s->txfifo = 0; 261 s->ie = 0; 262 s->ip = 0; 263 s->txctrl = 0; 264 s->rxctrl = 0; 265 s->div = 0; 266 267 s->rx_fifo_len = 0; 268 269 memset(s->rx_fifo, 0, SIFIVE_UART_RX_FIFO_SIZE); 270 fifo8_reset(&s->tx_fifo); 271 } 272 273 static const Property sifive_uart_properties[] = { 274 DEFINE_PROP_CHR("chardev", SiFiveUARTState, chr), 275 }; 276 277 static void sifive_uart_init(Object *obj) 278 { 279 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 280 SiFiveUARTState *s = SIFIVE_UART(obj); 281 282 memory_region_init_io(&s->mmio, OBJECT(s), &sifive_uart_ops, s, 283 TYPE_SIFIVE_UART, SIFIVE_UART_MAX); 284 sysbus_init_mmio(sbd, &s->mmio); 285 sysbus_init_irq(sbd, &s->irq); 286 } 287 288 static void sifive_uart_realize(DeviceState *dev, Error **errp) 289 { 290 SiFiveUARTState *s = SIFIVE_UART(dev); 291 292 fifo8_create(&s->tx_fifo, SIFIVE_UART_TX_FIFO_SIZE); 293 294 s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL, 295 fifo_trigger_update, s); 296 297 if (qemu_chr_fe_backend_connected(&s->chr)) { 298 qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, 299 sifive_uart_event, sifive_uart_be_change, s, 300 NULL, true); 301 } 302 303 } 304 305 static void sifive_uart_unrealize(DeviceState *dev) 306 { 307 SiFiveUARTState *s = SIFIVE_UART(dev); 308 309 fifo8_destroy(&s->tx_fifo); 310 } 311 312 static void sifive_uart_reset_hold(Object *obj, ResetType type) 313 { 314 SiFiveUARTState *s = SIFIVE_UART(obj); 315 qemu_irq_lower(s->irq); 316 } 317 318 static const VMStateDescription vmstate_sifive_uart = { 319 .name = TYPE_SIFIVE_UART, 320 .version_id = 2, 321 .minimum_version_id = 2, 322 .fields = (const VMStateField[]) { 323 VMSTATE_UINT8_ARRAY(rx_fifo, SiFiveUARTState, 324 SIFIVE_UART_RX_FIFO_SIZE), 325 VMSTATE_UINT8(rx_fifo_len, SiFiveUARTState), 326 VMSTATE_UINT32(ie, SiFiveUARTState), 327 VMSTATE_UINT32(ip, SiFiveUARTState), 328 VMSTATE_UINT32(txctrl, SiFiveUARTState), 329 VMSTATE_UINT32(rxctrl, SiFiveUARTState), 330 VMSTATE_UINT32(div, SiFiveUARTState), 331 VMSTATE_UINT32(txfifo, SiFiveUARTState), 332 VMSTATE_FIFO8(tx_fifo, SiFiveUARTState), 333 VMSTATE_TIMER_PTR(fifo_trigger_handle, SiFiveUARTState), 334 VMSTATE_END_OF_LIST() 335 }, 336 }; 337 338 339 static void sifive_uart_class_init(ObjectClass *oc, const void *data) 340 { 341 DeviceClass *dc = DEVICE_CLASS(oc); 342 ResettableClass *rc = RESETTABLE_CLASS(oc); 343 344 dc->realize = sifive_uart_realize; 345 dc->unrealize = sifive_uart_unrealize; 346 dc->vmsd = &vmstate_sifive_uart; 347 rc->phases.enter = sifive_uart_reset_enter; 348 rc->phases.hold = sifive_uart_reset_hold; 349 device_class_set_props(dc, sifive_uart_properties); 350 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 351 } 352 353 static const TypeInfo sifive_uart_info = { 354 .name = TYPE_SIFIVE_UART, 355 .parent = TYPE_SYS_BUS_DEVICE, 356 .instance_size = sizeof(SiFiveUARTState), 357 .instance_init = sifive_uart_init, 358 .class_init = sifive_uart_class_init, 359 }; 360 361 static void sifive_uart_register_types(void) 362 { 363 type_register_static(&sifive_uart_info); 364 } 365 366 type_init(sifive_uart_register_types) 367 368 /* 369 * Create UART device. 370 */ 371 SiFiveUARTState *sifive_uart_create(MemoryRegion *address_space, hwaddr base, 372 Chardev *chr, qemu_irq irq) 373 { 374 DeviceState *dev; 375 SysBusDevice *s; 376 377 dev = qdev_new("riscv.sifive.uart"); 378 s = SYS_BUS_DEVICE(dev); 379 qdev_prop_set_chr(dev, "chardev", chr); 380 sysbus_realize_and_unref(s, &error_fatal); 381 memory_region_add_subregion(address_space, base, 382 sysbus_mmio_get_region(s, 0)); 383 sysbus_connect_irq(s, 0, irq); 384 385 return SIFIVE_UART(dev); 386 } 387