1 /* 2 * MAX78000 UART 3 * 4 * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "hw/char/max78000_uart.h" 11 #include "hw/irq.h" 12 #include "hw/qdev-properties.h" 13 #include "hw/qdev-properties-system.h" 14 #include "qemu/log.h" 15 #include "qemu/module.h" 16 #include "migration/vmstate.h" 17 #include "trace.h" 18 19 20 static int max78000_uart_can_receive(void *opaque) 21 { 22 Max78000UartState *s = opaque; 23 if (!(s->ctrl & UART_BCLKEN)) { 24 return 0; 25 } 26 return fifo8_num_free(&s->rx_fifo); 27 } 28 29 static void max78000_update_irq(Max78000UartState *s) 30 { 31 int interrupt_level; 32 33 interrupt_level = s->int_fl & s->int_en; 34 qemu_set_irq(s->irq, interrupt_level); 35 } 36 37 static void max78000_uart_receive(void *opaque, const uint8_t *buf, int size) 38 { 39 Max78000UartState *s = opaque; 40 41 assert(size <= fifo8_num_free(&s->rx_fifo)); 42 43 fifo8_push_all(&s->rx_fifo, buf, size); 44 45 uint32_t rx_threshold = s->ctrl & 0xf; 46 47 if (fifo8_num_used(&s->rx_fifo) >= rx_threshold) { 48 s->int_fl |= UART_RX_THD; 49 } 50 51 max78000_update_irq(s); 52 } 53 54 static void max78000_uart_reset_hold(Object *obj, ResetType type) 55 { 56 Max78000UartState *s = MAX78000_UART(obj); 57 58 s->ctrl = 0; 59 s->status = UART_TX_EM | UART_RX_EM; 60 s->int_en = 0; 61 s->int_fl = 0; 62 s->osr = 0; 63 s->txpeek = 0; 64 s->pnr = UART_RTS; 65 s->fifo = 0; 66 s->dma = 0; 67 s->wken = 0; 68 s->wkfl = 0; 69 fifo8_reset(&s->rx_fifo); 70 } 71 72 static uint64_t max78000_uart_read(void *opaque, hwaddr addr, 73 unsigned int size) 74 { 75 Max78000UartState *s = opaque; 76 uint64_t retvalue = 0; 77 switch (addr) { 78 case UART_CTRL: 79 retvalue = s->ctrl; 80 break; 81 case UART_STATUS: 82 retvalue = (fifo8_num_used(&s->rx_fifo) << UART_RX_LVL) | 83 UART_TX_EM | 84 (fifo8_is_empty(&s->rx_fifo) ? UART_RX_EM : 0); 85 break; 86 case UART_INT_EN: 87 retvalue = s->int_en; 88 break; 89 case UART_INT_FL: 90 retvalue = s->int_fl; 91 break; 92 case UART_CLKDIV: 93 retvalue = s->clkdiv; 94 break; 95 case UART_OSR: 96 retvalue = s->osr; 97 break; 98 case UART_TXPEEK: 99 if (!fifo8_is_empty(&s->rx_fifo)) { 100 retvalue = fifo8_peek(&s->rx_fifo); 101 } 102 break; 103 case UART_PNR: 104 retvalue = s->pnr; 105 break; 106 case UART_FIFO: 107 if (!fifo8_is_empty(&s->rx_fifo)) { 108 retvalue = fifo8_pop(&s->rx_fifo); 109 max78000_update_irq(s); 110 } 111 break; 112 case UART_DMA: 113 /* DMA not implemented */ 114 retvalue = s->dma; 115 break; 116 case UART_WKEN: 117 retvalue = s->wken; 118 break; 119 case UART_WKFL: 120 retvalue = s->wkfl; 121 break; 122 default: 123 qemu_log_mask(LOG_GUEST_ERROR, 124 "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); 125 break; 126 } 127 128 return retvalue; 129 } 130 131 static void max78000_uart_write(void *opaque, hwaddr addr, 132 uint64_t val64, unsigned int size) 133 { 134 Max78000UartState *s = opaque; 135 136 uint32_t value = val64; 137 uint8_t data; 138 139 switch (addr) { 140 case UART_CTRL: 141 if (value & UART_FLUSH_RX) { 142 fifo8_reset(&s->rx_fifo); 143 } 144 if (value & UART_BCLKEN) { 145 value = value | UART_BCLKRDY; 146 } 147 s->ctrl = value & ~(UART_FLUSH_RX | UART_FLUSH_TX); 148 149 /* 150 * Software can manage UART flow control manually by setting hfc_en 151 * in UART_CTRL. This would require emulating uart at a lower level, 152 * and is currently unimplemented. 153 */ 154 155 return; 156 case UART_STATUS: 157 /* UART_STATUS is read only */ 158 return; 159 case UART_INT_EN: 160 s->int_en = value; 161 return; 162 case UART_INT_FL: 163 s->int_fl = s->int_fl & ~(value); 164 max78000_update_irq(s); 165 return; 166 case UART_CLKDIV: 167 s->clkdiv = value; 168 return; 169 case UART_OSR: 170 s->osr = value; 171 return; 172 case UART_PNR: 173 s->pnr = value; 174 return; 175 case UART_FIFO: 176 data = value & 0xff; 177 /* 178 * XXX this blocks entire thread. Rewrite to use 179 * qemu_chr_fe_write and background I/O callbacks 180 */ 181 qemu_chr_fe_write_all(&s->chr, &data, 1); 182 183 /* TX is always empty */ 184 s->int_fl |= UART_TX_HE; 185 max78000_update_irq(s); 186 187 return; 188 case UART_DMA: 189 /* DMA not implemented */ 190 s->dma = value; 191 return; 192 case UART_WKEN: 193 s->wken = value; 194 return; 195 case UART_WKFL: 196 s->wkfl = value; 197 return; 198 default: 199 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" 200 HWADDR_PRIx "\n", __func__, addr); 201 } 202 } 203 204 static const MemoryRegionOps max78000_uart_ops = { 205 .read = max78000_uart_read, 206 .write = max78000_uart_write, 207 .endianness = DEVICE_LITTLE_ENDIAN, 208 .valid.min_access_size = 4, 209 .valid.max_access_size = 4, 210 }; 211 212 static const Property max78000_uart_properties[] = { 213 DEFINE_PROP_CHR("chardev", Max78000UartState, chr), 214 }; 215 216 static const VMStateDescription max78000_uart_vmstate = { 217 .name = TYPE_MAX78000_UART, 218 .version_id = 1, 219 .minimum_version_id = 1, 220 .fields = (VMStateField[]) { 221 VMSTATE_UINT32(ctrl, Max78000UartState), 222 VMSTATE_UINT32(status, Max78000UartState), 223 VMSTATE_UINT32(int_en, Max78000UartState), 224 VMSTATE_UINT32(int_fl, Max78000UartState), 225 VMSTATE_UINT32(clkdiv, Max78000UartState), 226 VMSTATE_UINT32(osr, Max78000UartState), 227 VMSTATE_UINT32(txpeek, Max78000UartState), 228 VMSTATE_UINT32(pnr, Max78000UartState), 229 VMSTATE_UINT32(fifo, Max78000UartState), 230 VMSTATE_UINT32(dma, Max78000UartState), 231 VMSTATE_UINT32(wken, Max78000UartState), 232 VMSTATE_UINT32(wkfl, Max78000UartState), 233 VMSTATE_FIFO8(rx_fifo, Max78000UartState), 234 VMSTATE_END_OF_LIST() 235 } 236 }; 237 238 static void max78000_uart_init(Object *obj) 239 { 240 Max78000UartState *s = MAX78000_UART(obj); 241 fifo8_create(&s->rx_fifo, 8); 242 243 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); 244 245 memory_region_init_io(&s->mmio, obj, &max78000_uart_ops, s, 246 TYPE_MAX78000_UART, 0x400); 247 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); 248 } 249 250 static void max78000_uart_realize(DeviceState *dev, Error **errp) 251 { 252 Max78000UartState *s = MAX78000_UART(dev); 253 254 qemu_chr_fe_set_handlers(&s->chr, max78000_uart_can_receive, 255 max78000_uart_receive, NULL, NULL, 256 s, NULL, true); 257 } 258 259 static void max78000_uart_class_init(ObjectClass *klass, const void *data) 260 { 261 DeviceClass *dc = DEVICE_CLASS(klass); 262 ResettableClass *rc = RESETTABLE_CLASS(klass); 263 264 rc->phases.hold = max78000_uart_reset_hold; 265 266 device_class_set_props(dc, max78000_uart_properties); 267 dc->realize = max78000_uart_realize; 268 269 dc->vmsd = &max78000_uart_vmstate; 270 } 271 272 static const TypeInfo max78000_uart_info = { 273 .name = TYPE_MAX78000_UART, 274 .parent = TYPE_SYS_BUS_DEVICE, 275 .instance_size = sizeof(Max78000UartState), 276 .instance_init = max78000_uart_init, 277 .class_init = max78000_uart_class_init, 278 }; 279 280 static void max78000_uart_register_types(void) 281 { 282 type_register_static(&max78000_uart_info); 283 } 284 285 type_init(max78000_uart_register_types) 286