Merge remote-tracking branch 'remotes/philmd-gitlab/tags/renesas-20201027' into staging
[qemu.git] / hw / char / avr_usart.c
1 /*
2 * AVR USART
3 *
4 * Copyright (c) 2018 University of Kent
5 * Author: Sarah Harris
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see
19 * <http://www.gnu.org/licenses/lgpl-2.1.html>
20 */
21
22 #include "qemu/osdep.h"
23 #include "hw/char/avr_usart.h"
24 #include "qemu/log.h"
25 #include "hw/irq.h"
26 #include "hw/qdev-properties.h"
27
28 static int avr_usart_can_receive(void *opaque)
29 {
30 AVRUsartState *usart = opaque;
31
32 if (usart->data_valid || !(usart->csrb & USART_CSRB_RXEN)) {
33 return 0;
34 }
35 return 1;
36 }
37
38 static void avr_usart_receive(void *opaque, const uint8_t *buffer, int size)
39 {
40 AVRUsartState *usart = opaque;
41 assert(size == 1);
42 assert(!usart->data_valid);
43 usart->data = buffer[0];
44 usart->data_valid = true;
45 usart->csra |= USART_CSRA_RXC;
46 if (usart->csrb & USART_CSRB_RXCIE) {
47 qemu_set_irq(usart->rxc_irq, 1);
48 }
49 }
50
51 static void update_char_mask(AVRUsartState *usart)
52 {
53 uint8_t mode = ((usart->csrc & USART_CSRC_CSZ0) ? 1 : 0) |
54 ((usart->csrc & USART_CSRC_CSZ1) ? 2 : 0) |
55 ((usart->csrb & USART_CSRB_CSZ2) ? 4 : 0);
56 switch (mode) {
57 case 0:
58 usart->char_mask = 0b11111;
59 break;
60 case 1:
61 usart->char_mask = 0b111111;
62 break;
63 case 2:
64 usart->char_mask = 0b1111111;
65 break;
66 case 3:
67 usart->char_mask = 0b11111111;
68 break;
69 case 4:
70 /* Fallthrough. */
71 case 5:
72 /* Fallthrough. */
73 case 6:
74 qemu_log_mask(
75 LOG_GUEST_ERROR,
76 "%s: Reserved character size 0x%x\n",
77 __func__,
78 mode);
79 break;
80 case 7:
81 qemu_log_mask(
82 LOG_GUEST_ERROR,
83 "%s: Nine bit character size not supported (forcing eight)\n",
84 __func__);
85 usart->char_mask = 0b11111111;
86 break;
87 default:
88 assert(0);
89 }
90 }
91
92 static void avr_usart_reset(DeviceState *dev)
93 {
94 AVRUsartState *usart = AVR_USART(dev);
95 usart->data_valid = false;
96 usart->csra = 0b00100000;
97 usart->csrb = 0b00000000;
98 usart->csrc = 0b00000110;
99 usart->brrl = 0;
100 usart->brrh = 0;
101 update_char_mask(usart);
102 qemu_set_irq(usart->rxc_irq, 0);
103 qemu_set_irq(usart->txc_irq, 0);
104 qemu_set_irq(usart->dre_irq, 0);
105 }
106
107 static uint64_t avr_usart_read(void *opaque, hwaddr addr, unsigned int size)
108 {
109 AVRUsartState *usart = opaque;
110 uint8_t data;
111 assert(size == 1);
112
113 if (!usart->enabled) {
114 return 0;
115 }
116
117 switch (addr) {
118 case USART_DR:
119 if (!(usart->csrb & USART_CSRB_RXEN)) {
120 /* Receiver disabled, ignore. */
121 return 0;
122 }
123 if (usart->data_valid) {
124 data = usart->data & usart->char_mask;
125 usart->data_valid = false;
126 } else {
127 data = 0;
128 }
129 usart->csra &= 0xff ^ USART_CSRA_RXC;
130 qemu_set_irq(usart->rxc_irq, 0);
131 qemu_chr_fe_accept_input(&usart->chr);
132 return data;
133 case USART_CSRA:
134 return usart->csra;
135 case USART_CSRB:
136 return usart->csrb;
137 case USART_CSRC:
138 return usart->csrc;
139 case USART_BRRL:
140 return usart->brrl;
141 case USART_BRRH:
142 return usart->brrh;
143 default:
144 qemu_log_mask(
145 LOG_GUEST_ERROR,
146 "%s: Bad offset 0x%"HWADDR_PRIx"\n",
147 __func__,
148 addr);
149 }
150 return 0;
151 }
152
153 static void avr_usart_write(void *opaque, hwaddr addr, uint64_t value,
154 unsigned int size)
155 {
156 AVRUsartState *usart = opaque;
157 uint8_t mask;
158 uint8_t data;
159 assert((value & 0xff) == value);
160 assert(size == 1);
161
162 if (!usart->enabled) {
163 return;
164 }
165
166 switch (addr) {
167 case USART_DR:
168 if (!(usart->csrb & USART_CSRB_TXEN)) {
169 /* Transmitter disabled, ignore. */
170 return;
171 }
172 usart->csra |= USART_CSRA_TXC;
173 usart->csra |= USART_CSRA_DRE;
174 if (usart->csrb & USART_CSRB_TXCIE) {
175 qemu_set_irq(usart->txc_irq, 1);
176 usart->csra &= 0xff ^ USART_CSRA_TXC;
177 }
178 if (usart->csrb & USART_CSRB_DREIE) {
179 qemu_set_irq(usart->dre_irq, 1);
180 }
181 data = value;
182 qemu_chr_fe_write_all(&usart->chr, &data, 1);
183 break;
184 case USART_CSRA:
185 mask = 0b01000011;
186 /* Mask read-only bits. */
187 value = (value & mask) | (usart->csra & (0xff ^ mask));
188 usart->csra = value;
189 if (value & USART_CSRA_TXC) {
190 usart->csra ^= USART_CSRA_TXC;
191 qemu_set_irq(usart->txc_irq, 0);
192 }
193 if (value & USART_CSRA_MPCM) {
194 qemu_log_mask(
195 LOG_GUEST_ERROR,
196 "%s: MPCM not supported by USART\n",
197 __func__);
198 }
199 break;
200 case USART_CSRB:
201 mask = 0b11111101;
202 /* Mask read-only bits. */
203 value = (value & mask) | (usart->csrb & (0xff ^ mask));
204 usart->csrb = value;
205 if (!(value & USART_CSRB_RXEN)) {
206 /* Receiver disabled, flush input buffer. */
207 usart->data_valid = false;
208 }
209 qemu_set_irq(usart->rxc_irq,
210 ((value & USART_CSRB_RXCIE) &&
211 (usart->csra & USART_CSRA_RXC)) ? 1 : 0);
212 qemu_set_irq(usart->txc_irq,
213 ((value & USART_CSRB_TXCIE) &&
214 (usart->csra & USART_CSRA_TXC)) ? 1 : 0);
215 qemu_set_irq(usart->dre_irq,
216 ((value & USART_CSRB_DREIE) &&
217 (usart->csra & USART_CSRA_DRE)) ? 1 : 0);
218 update_char_mask(usart);
219 break;
220 case USART_CSRC:
221 usart->csrc = value;
222 if ((value & USART_CSRC_MSEL1) && (value & USART_CSRC_MSEL0)) {
223 qemu_log_mask(
224 LOG_GUEST_ERROR,
225 "%s: SPI mode not supported by USART\n",
226 __func__);
227 }
228 if ((value & USART_CSRC_MSEL1) && !(value & USART_CSRC_MSEL0)) {
229 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad USART mode\n", __func__);
230 }
231 if (!(value & USART_CSRC_PM1) && (value & USART_CSRC_PM0)) {
232 qemu_log_mask(
233 LOG_GUEST_ERROR,
234 "%s: Bad USART parity mode\n",
235 __func__);
236 }
237 update_char_mask(usart);
238 break;
239 case USART_BRRL:
240 usart->brrl = value;
241 break;
242 case USART_BRRH:
243 usart->brrh = value & 0b00001111;
244 break;
245 default:
246 qemu_log_mask(
247 LOG_GUEST_ERROR,
248 "%s: Bad offset 0x%"HWADDR_PRIx"\n",
249 __func__,
250 addr);
251 }
252 }
253
254 static const MemoryRegionOps avr_usart_ops = {
255 .read = avr_usart_read,
256 .write = avr_usart_write,
257 .endianness = DEVICE_NATIVE_ENDIAN,
258 .impl = {.min_access_size = 1, .max_access_size = 1}
259 };
260
261 static Property avr_usart_properties[] = {
262 DEFINE_PROP_CHR("chardev", AVRUsartState, chr),
263 DEFINE_PROP_END_OF_LIST(),
264 };
265
266 static void avr_usart_pr(void *opaque, int irq, int level)
267 {
268 AVRUsartState *s = AVR_USART(opaque);
269
270 s->enabled = !level;
271
272 if (!s->enabled) {
273 avr_usart_reset(DEVICE(s));
274 }
275 }
276
277 static void avr_usart_init(Object *obj)
278 {
279 AVRUsartState *s = AVR_USART(obj);
280 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rxc_irq);
281 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->dre_irq);
282 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->txc_irq);
283 memory_region_init_io(&s->mmio, obj, &avr_usart_ops, s, TYPE_AVR_USART, 7);
284 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
285 qdev_init_gpio_in(DEVICE(s), avr_usart_pr, 1);
286 s->enabled = true;
287 }
288
289 static void avr_usart_realize(DeviceState *dev, Error **errp)
290 {
291 AVRUsartState *s = AVR_USART(dev);
292 qemu_chr_fe_set_handlers(&s->chr, avr_usart_can_receive,
293 avr_usart_receive, NULL, NULL,
294 s, NULL, true);
295 avr_usart_reset(dev);
296 }
297
298 static void avr_usart_class_init(ObjectClass *klass, void *data)
299 {
300 DeviceClass *dc = DEVICE_CLASS(klass);
301
302 dc->reset = avr_usart_reset;
303 device_class_set_props(dc, avr_usart_properties);
304 dc->realize = avr_usart_realize;
305 }
306
307 static const TypeInfo avr_usart_info = {
308 .name = TYPE_AVR_USART,
309 .parent = TYPE_SYS_BUS_DEVICE,
310 .instance_size = sizeof(AVRUsartState),
311 .instance_init = avr_usart_init,
312 .class_init = avr_usart_class_init,
313 };
314
315 static void avr_usart_register_types(void)
316 {
317 type_register_static(&avr_usart_info);
318 }
319
320 type_init(avr_usart_register_types)