1 | /* |
2 | * QEMU GRLIB APB UART Emulator |
3 | * |
4 | * Copyright (c) 2010-2019 AdaCore |
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 | |
25 | #include "qemu/osdep.h" |
26 | #include "hw/irq.h" |
27 | #include "hw/qdev-properties.h" |
28 | #include "hw/sparc/grlib.h" |
29 | #include "hw/sysbus.h" |
30 | #include "qemu/module.h" |
31 | #include "chardev/char-fe.h" |
32 | |
33 | #include "trace.h" |
34 | |
35 | #define UART_REG_SIZE 20 /* Size of memory mapped registers */ |
36 | |
37 | /* UART status register fields */ |
38 | #define UART_DATA_READY (1 << 0) |
39 | #define UART_TRANSMIT_SHIFT_EMPTY (1 << 1) |
40 | #define UART_TRANSMIT_FIFO_EMPTY (1 << 2) |
41 | #define UART_BREAK_RECEIVED (1 << 3) |
42 | #define UART_OVERRUN (1 << 4) |
43 | #define UART_PARITY_ERROR (1 << 5) |
44 | #define UART_FRAMING_ERROR (1 << 6) |
45 | #define UART_TRANSMIT_FIFO_HALF (1 << 7) |
46 | #define UART_RECEIVE_FIFO_HALF (1 << 8) |
47 | #define UART_TRANSMIT_FIFO_FULL (1 << 9) |
48 | #define UART_RECEIVE_FIFO_FULL (1 << 10) |
49 | |
50 | /* UART control register fields */ |
51 | #define UART_RECEIVE_ENABLE (1 << 0) |
52 | #define UART_TRANSMIT_ENABLE (1 << 1) |
53 | #define UART_RECEIVE_INTERRUPT (1 << 2) |
54 | #define UART_TRANSMIT_INTERRUPT (1 << 3) |
55 | #define UART_PARITY_SELECT (1 << 4) |
56 | #define UART_PARITY_ENABLE (1 << 5) |
57 | #define UART_FLOW_CONTROL (1 << 6) |
58 | #define UART_LOOPBACK (1 << 7) |
59 | #define UART_EXTERNAL_CLOCK (1 << 8) |
60 | #define UART_RECEIVE_FIFO_INTERRUPT (1 << 9) |
61 | #define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10) |
62 | #define UART_FIFO_DEBUG_MODE (1 << 11) |
63 | #define UART_OUTPUT_ENABLE (1 << 12) |
64 | #define UART_FIFO_AVAILABLE (1 << 31) |
65 | |
66 | /* Memory mapped register offsets */ |
67 | #define DATA_OFFSET 0x00 |
68 | #define STATUS_OFFSET 0x04 |
69 | #define CONTROL_OFFSET 0x08 |
70 | #define SCALER_OFFSET 0x0C /* not supported */ |
71 | #define FIFO_DEBUG_OFFSET 0x10 /* not supported */ |
72 | |
73 | #define FIFO_LENGTH 1024 |
74 | |
75 | #define GRLIB_APB_UART(obj) \ |
76 | OBJECT_CHECK(UART, (obj), TYPE_GRLIB_APB_UART) |
77 | |
78 | typedef struct UART { |
79 | SysBusDevice parent_obj; |
80 | |
81 | MemoryRegion iomem; |
82 | qemu_irq irq; |
83 | |
84 | CharBackend chr; |
85 | |
86 | /* registers */ |
87 | uint32_t status; |
88 | uint32_t control; |
89 | |
90 | /* FIFO */ |
91 | char buffer[FIFO_LENGTH]; |
92 | int len; |
93 | int current; |
94 | } UART; |
95 | |
96 | static int uart_data_to_read(UART *uart) |
97 | { |
98 | return uart->current < uart->len; |
99 | } |
100 | |
101 | static char uart_pop(UART *uart) |
102 | { |
103 | char ret; |
104 | |
105 | if (uart->len == 0) { |
106 | uart->status &= ~UART_DATA_READY; |
107 | return 0; |
108 | } |
109 | |
110 | ret = uart->buffer[uart->current++]; |
111 | |
112 | if (uart->current >= uart->len) { |
113 | /* Flush */ |
114 | uart->len = 0; |
115 | uart->current = 0; |
116 | } |
117 | |
118 | if (!uart_data_to_read(uart)) { |
119 | uart->status &= ~UART_DATA_READY; |
120 | } |
121 | |
122 | return ret; |
123 | } |
124 | |
125 | static void uart_add_to_fifo(UART *uart, |
126 | const uint8_t *buffer, |
127 | int length) |
128 | { |
129 | if (uart->len + length > FIFO_LENGTH) { |
130 | abort(); |
131 | } |
132 | memcpy(uart->buffer + uart->len, buffer, length); |
133 | uart->len += length; |
134 | } |
135 | |
136 | static int grlib_apbuart_can_receive(void *opaque) |
137 | { |
138 | UART *uart = opaque; |
139 | |
140 | return FIFO_LENGTH - uart->len; |
141 | } |
142 | |
143 | static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size) |
144 | { |
145 | UART *uart = opaque; |
146 | |
147 | if (uart->control & UART_RECEIVE_ENABLE) { |
148 | uart_add_to_fifo(uart, buf, size); |
149 | |
150 | uart->status |= UART_DATA_READY; |
151 | |
152 | if (uart->control & UART_RECEIVE_INTERRUPT) { |
153 | qemu_irq_pulse(uart->irq); |
154 | } |
155 | } |
156 | } |
157 | |
158 | static void grlib_apbuart_event(void *opaque, int event) |
159 | { |
160 | trace_grlib_apbuart_event(event); |
161 | } |
162 | |
163 | |
164 | static uint64_t grlib_apbuart_read(void *opaque, hwaddr addr, |
165 | unsigned size) |
166 | { |
167 | UART *uart = opaque; |
168 | |
169 | addr &= 0xff; |
170 | |
171 | /* Unit registers */ |
172 | switch (addr) { |
173 | case DATA_OFFSET: |
174 | case DATA_OFFSET + 3: /* when only one byte read */ |
175 | return uart_pop(uart); |
176 | |
177 | case STATUS_OFFSET: |
178 | /* Read Only */ |
179 | return uart->status; |
180 | |
181 | case CONTROL_OFFSET: |
182 | return uart->control; |
183 | |
184 | case SCALER_OFFSET: |
185 | /* Not supported */ |
186 | return 0; |
187 | |
188 | default: |
189 | trace_grlib_apbuart_readl_unknown(addr); |
190 | return 0; |
191 | } |
192 | } |
193 | |
194 | static void grlib_apbuart_write(void *opaque, hwaddr addr, |
195 | uint64_t value, unsigned size) |
196 | { |
197 | UART *uart = opaque; |
198 | unsigned char c = 0; |
199 | |
200 | addr &= 0xff; |
201 | |
202 | /* Unit registers */ |
203 | switch (addr) { |
204 | case DATA_OFFSET: |
205 | case DATA_OFFSET + 3: /* When only one byte write */ |
206 | /* Transmit when character device available and transmitter enabled */ |
207 | if (qemu_chr_fe_backend_connected(&uart->chr) && |
208 | (uart->control & UART_TRANSMIT_ENABLE)) { |
209 | c = value & 0xFF; |
210 | /* XXX this blocks entire thread. Rewrite to use |
211 | * qemu_chr_fe_write and background I/O callbacks */ |
212 | qemu_chr_fe_write_all(&uart->chr, &c, 1); |
213 | /* Generate interrupt */ |
214 | if (uart->control & UART_TRANSMIT_INTERRUPT) { |
215 | qemu_irq_pulse(uart->irq); |
216 | } |
217 | } |
218 | return; |
219 | |
220 | case STATUS_OFFSET: |
221 | /* Read Only */ |
222 | return; |
223 | |
224 | case CONTROL_OFFSET: |
225 | uart->control = value; |
226 | return; |
227 | |
228 | case SCALER_OFFSET: |
229 | /* Not supported */ |
230 | return; |
231 | |
232 | default: |
233 | break; |
234 | } |
235 | |
236 | trace_grlib_apbuart_writel_unknown(addr, value); |
237 | } |
238 | |
239 | static const MemoryRegionOps grlib_apbuart_ops = { |
240 | .write = grlib_apbuart_write, |
241 | .read = grlib_apbuart_read, |
242 | .endianness = DEVICE_NATIVE_ENDIAN, |
243 | }; |
244 | |
245 | static void grlib_apbuart_realize(DeviceState *dev, Error **errp) |
246 | { |
247 | UART *uart = GRLIB_APB_UART(dev); |
248 | SysBusDevice *sbd = SYS_BUS_DEVICE(dev); |
249 | |
250 | qemu_chr_fe_set_handlers(&uart->chr, |
251 | grlib_apbuart_can_receive, |
252 | grlib_apbuart_receive, |
253 | grlib_apbuart_event, |
254 | NULL, uart, NULL, true); |
255 | |
256 | sysbus_init_irq(sbd, &uart->irq); |
257 | |
258 | memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart, |
259 | "uart" , UART_REG_SIZE); |
260 | |
261 | sysbus_init_mmio(sbd, &uart->iomem); |
262 | } |
263 | |
264 | static void grlib_apbuart_reset(DeviceState *d) |
265 | { |
266 | UART *uart = GRLIB_APB_UART(d); |
267 | |
268 | /* Transmitter FIFO and shift registers are always empty in QEMU */ |
269 | uart->status = UART_TRANSMIT_FIFO_EMPTY | UART_TRANSMIT_SHIFT_EMPTY; |
270 | /* Everything is off */ |
271 | uart->control = 0; |
272 | /* Flush receive FIFO */ |
273 | uart->len = 0; |
274 | uart->current = 0; |
275 | } |
276 | |
277 | static Property grlib_apbuart_properties[] = { |
278 | DEFINE_PROP_CHR("chrdev" , UART, chr), |
279 | DEFINE_PROP_END_OF_LIST(), |
280 | }; |
281 | |
282 | static void grlib_apbuart_class_init(ObjectClass *klass, void *data) |
283 | { |
284 | DeviceClass *dc = DEVICE_CLASS(klass); |
285 | |
286 | dc->realize = grlib_apbuart_realize; |
287 | dc->reset = grlib_apbuart_reset; |
288 | dc->props = grlib_apbuart_properties; |
289 | } |
290 | |
291 | static const TypeInfo grlib_apbuart_info = { |
292 | .name = TYPE_GRLIB_APB_UART, |
293 | .parent = TYPE_SYS_BUS_DEVICE, |
294 | .instance_size = sizeof(UART), |
295 | .class_init = grlib_apbuart_class_init, |
296 | }; |
297 | |
298 | static void grlib_apbuart_register_types(void) |
299 | { |
300 | type_register_static(&grlib_apbuart_info); |
301 | } |
302 | |
303 | type_init(grlib_apbuart_register_types) |
304 | |