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 "chardev/char.h"
30#include "chardev/char-fe.h"
31#include "hw/register-dep.h"
32#include "qemu/log.h"
33#include "sysemu/sysemu.h"
34
35#ifndef XILINX_IO_MODULE_UART_ERR_DEBUG
36#define XILINX_IO_MODULE_UART_ERR_DEBUG 0
37#endif
38
39#define TYPE_XILINX_IO_MODULE_UART "xlnx.io_uart"
40
41#define XILINX_IO_MODULE_UART(obj) \
42 OBJECT_CHECK(XilinxUART, (obj), TYPE_XILINX_IO_MODULE_UART)
43
44#define R_IOM_UART_RX (0x00 / 4)
45#define R_IOM_UART_TX (0x04 / 4)
46#define R_IOM_UART_STATUS (0x08 / 4)
47#define IOM_UART_STATUS_RX_VALID (1 << 0)
48#define IOM_UART_STATUS_TX_USED (1 << 3)
49#define IOM_UART_STATUS_OVERRUN (1 << 5)
50#define IOM_UART_STATUS_FRAME_ERR (1 << 6)
51#define IOM_UART_STATUS_PARITY_ERR (1 << 7)
52#define R_MAX_0 (R_IOM_UART_STATUS + 1)
53
54#define R_IOM_UART_BAUD (0x00 / 4)
55#define R_MAX_1 (1)
56
57typedef struct XilinxUART {
58 SysBusDevice parent_obj;
59 MemoryRegion iomem[2];
60 qemu_irq irq_rx;
61 qemu_irq irq_tx;
62 qemu_irq irq_err;
63
64 struct {
65 bool use_rx;
66 bool use_tx;
67 bool rx_interrupt;
68 bool tx_interrupt;
69 bool err_interrupt;
70 } cfg;
71 CharBackend chr;
72 uint32_t regs[R_MAX_0];
73 uint32_t baud;
74 DepRegisterInfo regs_info0[R_MAX_0];
75 DepRegisterInfo regs_info1[R_MAX_1];
76 DepRegisterInfo *regs_infos[2];
77 const char *prefix;
78} XilinxUART;
79
80static Property xlx_iom_properties[] = {
81 DEFINE_PROP_BOOL("use-uart-rx", XilinxUART, cfg.use_rx, 0),
82 DEFINE_PROP_BOOL("use-uart-tx", XilinxUART, cfg.use_tx, 0),
83 DEFINE_PROP_BOOL("uart-rx-interrupt", XilinxUART, cfg.rx_interrupt, 0),
84 DEFINE_PROP_BOOL("uart-tx-interrupt", XilinxUART, cfg.tx_interrupt, 0),
85 DEFINE_PROP_BOOL("uart-error-interrupt", XilinxUART, cfg.err_interrupt, 0),
86 DEFINE_PROP_CHR("chardev", XilinxUART, chr),
87 DEFINE_PROP_END_OF_LIST(),
88};
89
90static void uart_rx(void *opaque, const uint8_t *buf, int size)
91{
92 XilinxUART *s = opaque;
93
94 if (!s->cfg.use_rx) {
95 return;
96 }
97
98 if (s->regs[R_IOM_UART_STATUS] & IOM_UART_STATUS_RX_VALID) {
99 s->regs[R_IOM_UART_STATUS] |= IOM_UART_STATUS_OVERRUN;
100 if (s->cfg.err_interrupt) {
101 qemu_irq_pulse(s->irq_err);
102 }
103 return;
104 }
105
106 s->regs[R_IOM_UART_RX] = *buf;
107 s->regs[R_IOM_UART_STATUS] |= IOM_UART_STATUS_RX_VALID;
108 if (s->cfg.rx_interrupt) {
109 qemu_irq_pulse(s->irq_rx);
110 }
111}
112
113static int uart_can_rx(void *opaque)
114{
115 XilinxUART *s = opaque;
116 return s->cfg.use_rx;
117}
118
119static void uart_event(void *opaque, int event)
120{
121}
122
123static uint64_t uart_rx_pr(DepRegisterInfo *reg, uint64_t val)
124{
125 XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque);
126 s->regs[R_IOM_UART_STATUS] &= ~IOM_UART_STATUS_OVERRUN;
127 s->regs[R_IOM_UART_STATUS] &= ~IOM_UART_STATUS_RX_VALID;
128 return s->regs[R_IOM_UART_RX];
129}
130
131static uint64_t uart_sts_pr(DepRegisterInfo *reg, uint64_t val)
132{
133 XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque);
134 s->regs[R_IOM_UART_STATUS] &= ~IOM_UART_STATUS_OVERRUN;
135 return val;
136}
137
138static void uart_tx_pw(DepRegisterInfo *reg, uint64_t value)
139{
140 XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque);
141 if (s->cfg.use_tx) {
142 unsigned char ch = value;
143 qemu_chr_fe_write(&s->chr, &ch, 1);
144 if (s->cfg.tx_interrupt) {
145 qemu_irq_pulse(s->irq_tx);
146 }
147 }
148}
149
150static const DepRegisterAccessInfo uart_regs_info0[] = {
151 [R_IOM_UART_RX] = { .name = "UART_RX", .post_read = uart_rx_pr },
152 [R_IOM_UART_TX] = { .name = "UART_TX", .post_write = uart_tx_pw },
153 [R_IOM_UART_STATUS] = { .name = "UART_STATUS", .post_read = uart_sts_pr },
154};
155
156static const DepRegisterAccessInfo uart_regs_info1[] = {
157 [R_IOM_UART_BAUD] = { .name = "UART_BAUD" },
158};
159static const DepRegisterAccessInfo *uart_reginfos[] = {
160 &uart_regs_info0[0], &uart_regs_info1[0]
161};
162
163static const unsigned int uart_reginfo_sizes[] = {
164 ARRAY_SIZE(uart_regs_info0),
165 ARRAY_SIZE(uart_regs_info1),
166};
167
168static const MemoryRegionOps iom_uart_ops = {
169 .read = dep_register_read_memory_le,
170 .write = dep_register_write_memory_le,
171 .endianness = DEVICE_LITTLE_ENDIAN,
172 .valid = {
173 .min_access_size = 4,
174 .max_access_size = 4,
175 },
176};
177
178static void iom_uart_reset(DeviceState *dev)
179{
180 XilinxUART *s = XILINX_IO_MODULE_UART(dev);
181 unsigned int i;
182 unsigned int rmap;
183
184 for (rmap = 0; rmap < ARRAY_SIZE(uart_reginfos); rmap++) {
185 for (i = 0; i < uart_reginfo_sizes[rmap]; ++i) {
186 dep_register_reset(&s->regs_infos[rmap][i]);
187 }
188 }
189}
190
191static void xlx_iom_realize(DeviceState *dev, Error **errp)
192{
193 XilinxUART *s = XILINX_IO_MODULE_UART(dev);
194 unsigned int i, rmap;
195 uint32_t *regmaps[3] = { &s->regs[0], &s->baud };
196
197 s->prefix = object_get_canonical_path(OBJECT(dev));
198
199 for (rmap = 0; rmap < ARRAY_SIZE(uart_reginfos); rmap++) {
200 for (i = 0; i < uart_reginfo_sizes[rmap]; ++i) {
201 DepRegisterInfo *r = &s->regs_infos[rmap][i];
202
203 *r = (DepRegisterInfo) {
204 .data = (uint8_t *)®maps[rmap][i],
205 .data_size = sizeof(uint32_t),
206 .access = &uart_reginfos[rmap][i],
207 .debug = XILINX_IO_MODULE_UART_ERR_DEBUG,
208 .prefix = s->prefix,
209 .opaque = s,
210 };
211 memory_region_init_io(&r->mem, OBJECT(dev), &iom_uart_ops, r,
212 r->access->name, 4);
213 memory_region_add_subregion(&s->iomem[rmap], i * 4, &r->mem);
214 }
215 }
216
217 if (s->cfg.use_rx || s->cfg.use_tx) {
218 qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event,
219 NULL, s, NULL, true);
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