MAINTAINERS: Update my git address
[qemu/ar7.git] / hw / char / avr_usart.c
blobfbe2a112b7027b59421ab63e3cb563df61779d56
1 /*
2 * AVR USART
4 * Copyright (c) 2018 University of Kent
5 * Author: Sarah Harris
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.
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.
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>
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"
28 static int avr_usart_can_receive(void *opaque)
30 AVRUsartState *usart = opaque;
32 if (usart->data_valid || !(usart->csrb & USART_CSRB_RXEN)) {
33 return 0;
35 return 1;
38 static void avr_usart_receive(void *opaque, const uint8_t *buffer, int size)
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);
51 static void update_char_mask(AVRUsartState *usart)
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);
92 static void avr_usart_reset(DeviceState *dev)
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);
107 static uint64_t avr_usart_read(void *opaque, hwaddr addr, unsigned int size)
109 AVRUsartState *usart = opaque;
110 uint8_t data;
111 assert(size == 1);
113 if (!usart->enabled) {
114 return 0;
117 switch (addr) {
118 case USART_DR:
119 if (!(usart->csrb & USART_CSRB_RXEN)) {
120 /* Receiver disabled, ignore. */
121 return 0;
123 if (usart->data_valid) {
124 data = usart->data & usart->char_mask;
125 usart->data_valid = false;
126 } else {
127 data = 0;
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);
150 return 0;
153 static void avr_usart_write(void *opaque, hwaddr addr, uint64_t value,
154 unsigned int size)
156 AVRUsartState *usart = opaque;
157 uint8_t mask;
158 uint8_t data;
159 assert((value & 0xff) == value);
160 assert(size == 1);
162 if (!usart->enabled) {
163 return;
166 switch (addr) {
167 case USART_DR:
168 if (!(usart->csrb & USART_CSRB_TXEN)) {
169 /* Transmitter disabled, ignore. */
170 return;
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;
178 if (usart->csrb & USART_CSRB_DREIE) {
179 qemu_set_irq(usart->dre_irq, 1);
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);
193 if (value & USART_CSRA_MPCM) {
194 qemu_log_mask(
195 LOG_GUEST_ERROR,
196 "%s: MPCM not supported by USART\n",
197 __func__);
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;
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__);
228 if ((value & USART_CSRC_MSEL1) && !(value & USART_CSRC_MSEL0)) {
229 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad USART mode\n", __func__);
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__);
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);
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}
261 static Property avr_usart_properties[] = {
262 DEFINE_PROP_CHR("chardev", AVRUsartState, chr),
263 DEFINE_PROP_END_OF_LIST(),
266 static void avr_usart_pr(void *opaque, int irq, int level)
268 AVRUsartState *s = AVR_USART(opaque);
270 s->enabled = !level;
272 if (!s->enabled) {
273 avr_usart_reset(DEVICE(s));
277 static void avr_usart_init(Object *obj)
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;
289 static void avr_usart_realize(DeviceState *dev, Error **errp)
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);
298 static void avr_usart_class_init(ObjectClass *klass, void *data)
300 DeviceClass *dc = DEVICE_CLASS(klass);
302 dc->reset = avr_usart_reset;
303 device_class_set_props(dc, avr_usart_properties);
304 dc->realize = avr_usart_realize;
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,
315 static void avr_usart_register_types(void)
317 type_register_static(&avr_usart_info);
320 type_init(avr_usart_register_types)