xref: /openbmc/qemu/hw/char/avr_usart.c (revision 7acafcfa)
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)
321