1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27#include "hw/sysbus.h"
28#include "hw/ptimer.h"
29#include "sysemu/char.h"
30#include "hw/register.h"
31#include "qemu/log.h"
32
33#ifndef XILINX_IO_MODULE_UART_ERR_DEBUG
34#define XILINX_IO_MODULE_UART_ERR_DEBUG 0
35#endif
36
37#define TYPE_XILINX_IO_MODULE_UART "xlnx.io_uart"
38
39#define XILINX_IO_MODULE_UART(obj) \
40 OBJECT_CHECK(XilinxUART, (obj), TYPE_XILINX_IO_MODULE_UART)
41
42#define R_IOM_UART_RX (0x00 / 4)
43#define R_IOM_UART_TX (0x04 / 4)
44#define R_IOM_UART_STATUS (0x08 / 4)
45#define IOM_UART_STATUS_RX_VALID (1 << 0)
46#define IOM_UART_STATUS_TX_USED (1 << 3)
47#define IOM_UART_STATUS_OVERRUN (1 << 5)
48#define IOM_UART_STATUS_FRAME_ERR (1 << 6)
49#define IOM_UART_STATUS_PARITY_ERR (1 << 7)
50#define R_MAX_0 (R_IOM_UART_STATUS + 1)
51
52#define R_IOM_UART_BAUD (0x00 / 4)
53#define R_MAX_1 (1)
54
55typedef struct XilinxUART {
56 SysBusDevice parent_obj;
57 MemoryRegion iomem[2];
58 qemu_irq irq_rx;
59 qemu_irq irq_tx;
60 qemu_irq irq_err;
61
62 struct {
63 bool use_rx;
64 bool use_tx;
65 bool rx_interrupt;
66 bool tx_interrupt;
67 bool err_interrupt;
68 } cfg;
69 CharDriverState *chr;
70 uint32_t regs[R_MAX_0];
71 uint32_t baud;
72 RegisterInfo regs_info0[R_MAX_0];
73 RegisterInfo regs_info1[R_MAX_1];
74 RegisterInfo *regs_infos[2];
75 const char *prefix;
76} XilinxUART;
77
78static Property xlx_iom_properties[] = {
79 DEFINE_PROP_BOOL("use-uart-rx", XilinxUART, cfg.use_rx, 0),
80 DEFINE_PROP_BOOL("use-uart-tx", XilinxUART, cfg.use_tx, 0),
81 DEFINE_PROP_BOOL("uart-rx-interrupt", XilinxUART, cfg.rx_interrupt, 0),
82 DEFINE_PROP_BOOL("uart-tx-interrupt", XilinxUART, cfg.tx_interrupt, 0),
83 DEFINE_PROP_BOOL("uart-error-interrupt", XilinxUART, cfg.err_interrupt, 0),
84 DEFINE_PROP_END_OF_LIST(),
85};
86
87static void uart_rx(void *opaque, const uint8_t *buf, int size)
88{
89 XilinxUART *s = opaque;
90
91 if (!s->cfg.use_rx) {
92 return;
93 }
94
95 if (s->regs[R_IOM_UART_STATUS] & IOM_UART_STATUS_RX_VALID) {
96 s->regs[R_IOM_UART_STATUS] |= IOM_UART_STATUS_OVERRUN;
97 if (s->cfg.err_interrupt) {
98 qemu_irq_pulse(s->irq_err);
99 }
100 return;
101 }
102
103 s->regs[R_IOM_UART_RX] = *buf;
104 s->regs[R_IOM_UART_STATUS] |= IOM_UART_STATUS_RX_VALID;
105 if (s->cfg.rx_interrupt) {
106 qemu_irq_pulse(s->irq_rx);
107 }
108}
109
110static int uart_can_rx(void *opaque)
111{
112 XilinxUART *s = opaque;
113 return s->cfg.use_rx;
114}
115
116static void uart_event(void *opaque, int event)
117{
118}
119
120static uint64_t uart_rx_pr(RegisterInfo *reg, uint64_t val)
121{
122 XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque);
123 s->regs[R_IOM_UART_STATUS] &= ~IOM_UART_STATUS_OVERRUN;
124 s->regs[R_IOM_UART_STATUS] &= ~IOM_UART_STATUS_RX_VALID;
125 return s->regs[R_IOM_UART_RX];
126}
127
128static uint64_t uart_sts_pr(RegisterInfo *reg, uint64_t val)
129{
130 XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque);
131 s->regs[R_IOM_UART_STATUS] &= ~IOM_UART_STATUS_OVERRUN;
132 return val;
133}
134
135static void uart_tx_pw(RegisterInfo *reg, uint64_t value)
136{
137 XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque);
138 if (s->cfg.use_tx && s->chr) {
139 unsigned char ch = value;
140 qemu_chr_fe_write(s->chr, &ch, 1);
141 if (s->cfg.tx_interrupt) {
142 qemu_irq_pulse(s->irq_tx);
143 }
144 }
145}
146
147static const RegisterAccessInfo uart_regs_info0[] = {
148 [R_IOM_UART_RX] = { .name = "UART_RX", .post_read = uart_rx_pr },
149 [R_IOM_UART_TX] = { .name = "UART_TX", .post_write = uart_tx_pw },
150 [R_IOM_UART_STATUS] = { .name = "UART_STATUS", .post_read = uart_sts_pr },
151};
152
153static const RegisterAccessInfo uart_regs_info1[] = {
154 [R_IOM_UART_BAUD] = { .name = "UART_BAUD" },
155};
156static const RegisterAccessInfo *uart_reginfos[] = {
157 &uart_regs_info0[0], &uart_regs_info1[0]
158};
159
160static const unsigned int uart_reginfo_sizes[] = {
161 ARRAY_SIZE(uart_regs_info0),
162 ARRAY_SIZE(uart_regs_info1),
163};
164
165static const MemoryRegionOps iom_uart_ops = {
166 .read = register_read_memory_le,
167 .write = register_write_memory_le,
168 .endianness = DEVICE_LITTLE_ENDIAN,
169 .valid = {
170 .min_access_size = 4,
171 .max_access_size = 4,
172 },
173};
174
175static void iom_uart_reset(DeviceState *dev)
176{
177 XilinxUART *s = XILINX_IO_MODULE_UART(dev);
178 unsigned int i;
179 unsigned int rmap;
180
181 for (rmap = 0; rmap < ARRAY_SIZE(uart_reginfos); rmap++) {
182 for (i = 0; i < uart_reginfo_sizes[rmap]; ++i) {
183 register_reset(&s->regs_infos[rmap][i]);
184 }
185 }
186}
187
188static void xlx_iom_realize(DeviceState *dev, Error **errp)
189{
190 XilinxUART *s = XILINX_IO_MODULE_UART(dev);
191 unsigned int i, rmap;
192 uint32_t *regmaps[3] = { &s->regs[0], &s->baud };
193
194 s->prefix = object_get_canonical_path(OBJECT(dev));
195
196 for (rmap = 0; rmap < ARRAY_SIZE(uart_reginfos); rmap++) {
197 for (i = 0; i < uart_reginfo_sizes[rmap]; ++i) {
198 RegisterInfo *r = &s->regs_infos[rmap][i];
199
200 *r = (RegisterInfo) {
201 .data = (uint8_t *)®maps[rmap][i],
202 .data_size = sizeof(uint32_t),
203 .access = &uart_reginfos[rmap][i],
204 .debug = XILINX_IO_MODULE_UART_ERR_DEBUG,
205 .prefix = s->prefix,
206 .opaque = s,
207 };
208 memory_region_init_io(&r->mem, OBJECT(dev), &iom_uart_ops, r,
209 r->access->name, 4);
210 memory_region_add_subregion(&s->iomem[rmap], i * 4, &r->mem);
211 }
212 }
213
214 if (s->cfg.use_rx || s->cfg.use_tx) {
215 s->chr = qemu_char_get_next_serial();
216 if (s->chr) {
217 qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx,
218 uart_event, s);
219 }
220 }
221}
222
223static void xlx_iom_init(Object *obj)
224{
225 XilinxUART *s = XILINX_IO_MODULE_UART(obj);
226 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
227 unsigned int i;
228
229 s->regs_infos[0] = s->regs_info0;
230 s->regs_infos[1] = s->regs_info1;
231
232 for (i = 0; i < ARRAY_SIZE(s->iomem); i++) {
233 char *region_name = g_strdup_printf("%s-%d", TYPE_XILINX_IO_MODULE_UART,
234 i);
235 memory_region_init_io(&s->iomem[i], obj, &iom_uart_ops, s,
236 region_name, uart_reginfo_sizes[i] * 4);
237 g_free(region_name);
238 sysbus_init_mmio(sbd, &s->iomem[i]);
239 }
240 sysbus_init_irq(sbd, &s->irq_err);
241 sysbus_init_irq(sbd, &s->irq_tx);
242 sysbus_init_irq(sbd, &s->irq_rx);
243}
244
245static const VMStateDescription vmstate_xlx_iom = {
246 .name = TYPE_XILINX_IO_MODULE_UART,
247 .version_id = 1,
248 .minimum_version_id = 1,
249 .minimum_version_id_old = 1,
250 .fields = (VMStateField[]) {
251 VMSTATE_END_OF_LIST(),
252 }
253};
254
255static void xlx_iom_class_init(ObjectClass *klass, void *data)
256{
257 DeviceClass *dc = DEVICE_CLASS(klass);
258
259 dc->reset = iom_uart_reset;
260 dc->realize = xlx_iom_realize;
261 dc->props = xlx_iom_properties;
262 dc->vmsd = &vmstate_xlx_iom;
263}
264
265static const TypeInfo xlx_iom_info = {
266 .name = TYPE_XILINX_IO_MODULE_UART,
267 .parent = TYPE_SYS_BUS_DEVICE,
268 .instance_size = sizeof(XilinxUART),
269 .class_init = xlx_iom_class_init,
270 .instance_init = xlx_iom_init,
271};
272
273static void xlx_iom_register_types(void)
274{
275 type_register_static(&xlx_iom_info);
276}
277
278type_init(xlx_iom_register_types)
279