tests/tcg: unify ppc64 and ppc64le Makefiles
[qemu.git] / hw / char / avr_usart.c
blob5bcf9db0b78108a62dbe54ecb8ea5a07ee866c72
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"
27 #include "hw/qdev-properties-system.h"
29 static int avr_usart_can_receive(void *opaque)
31 AVRUsartState *usart = opaque;
33 if (usart->data_valid || !(usart->csrb & USART_CSRB_RXEN)) {
34 return 0;
36 return 1;
39 static void avr_usart_receive(void *opaque, const uint8_t *buffer, int size)
41 AVRUsartState *usart = opaque;
42 assert(size == 1);
43 assert(!usart->data_valid);
44 usart->data = buffer[0];
45 usart->data_valid = true;
46 usart->csra |= USART_CSRA_RXC;
47 if (usart->csrb & USART_CSRB_RXCIE) {
48 qemu_set_irq(usart->rxc_irq, 1);
52 static void update_char_mask(AVRUsartState *usart)
54 uint8_t mode = ((usart->csrc & USART_CSRC_CSZ0) ? 1 : 0) |
55 ((usart->csrc & USART_CSRC_CSZ1) ? 2 : 0) |
56 ((usart->csrb & USART_CSRB_CSZ2) ? 4 : 0);
57 switch (mode) {
58 case 0:
59 usart->char_mask = 0b11111;
60 break;
61 case 1:
62 usart->char_mask = 0b111111;
63 break;
64 case 2:
65 usart->char_mask = 0b1111111;
66 break;
67 case 3:
68 usart->char_mask = 0b11111111;
69 break;
70 case 4:
71 /* Fallthrough. */
72 case 5:
73 /* Fallthrough. */
74 case 6:
75 qemu_log_mask(
76 LOG_GUEST_ERROR,
77 "%s: Reserved character size 0x%x\n",
78 __func__,
79 mode);
80 break;
81 case 7:
82 qemu_log_mask(
83 LOG_GUEST_ERROR,
84 "%s: Nine bit character size not supported (forcing eight)\n",
85 __func__);
86 usart->char_mask = 0b11111111;
87 break;
88 default:
89 assert(0);
93 static void avr_usart_reset(DeviceState *dev)
95 AVRUsartState *usart = AVR_USART(dev);
96 usart->data_valid = false;
97 usart->csra = 0b00100000;
98 usart->csrb = 0b00000000;
99 usart->csrc = 0b00000110;
100 usart->brrl = 0;
101 usart->brrh = 0;
102 update_char_mask(usart);
103 qemu_set_irq(usart->rxc_irq, 0);
104 qemu_set_irq(usart->txc_irq, 0);
105 qemu_set_irq(usart->dre_irq, 0);
108 static uint64_t avr_usart_read(void *opaque, hwaddr addr, unsigned int size)
110 AVRUsartState *usart = opaque;
111 uint8_t data;
112 assert(size == 1);
114 if (!usart->enabled) {
115 return 0;
118 switch (addr) {
119 case USART_DR:
120 if (!(usart->csrb & USART_CSRB_RXEN)) {
121 /* Receiver disabled, ignore. */
122 return 0;
124 if (usart->data_valid) {
125 data = usart->data & usart->char_mask;
126 usart->data_valid = false;
127 } else {
128 data = 0;
130 usart->csra &= 0xff ^ USART_CSRA_RXC;
131 qemu_set_irq(usart->rxc_irq, 0);
132 qemu_chr_fe_accept_input(&usart->chr);
133 return data;
134 case USART_CSRA:
135 return usart->csra;
136 case USART_CSRB:
137 return usart->csrb;
138 case USART_CSRC:
139 return usart->csrc;
140 case USART_BRRL:
141 return usart->brrl;
142 case USART_BRRH:
143 return usart->brrh;
144 default:
145 qemu_log_mask(
146 LOG_GUEST_ERROR,
147 "%s: Bad offset 0x%"HWADDR_PRIx"\n",
148 __func__,
149 addr);
151 return 0;
154 static void avr_usart_write(void *opaque, hwaddr addr, uint64_t value,
155 unsigned int size)
157 AVRUsartState *usart = opaque;
158 uint8_t mask;
159 uint8_t data;
160 assert((value & 0xff) == value);
161 assert(size == 1);
163 if (!usart->enabled) {
164 return;
167 switch (addr) {
168 case USART_DR:
169 if (!(usart->csrb & USART_CSRB_TXEN)) {
170 /* Transmitter disabled, ignore. */
171 return;
173 usart->csra |= USART_CSRA_TXC;
174 usart->csra |= USART_CSRA_DRE;
175 if (usart->csrb & USART_CSRB_TXCIE) {
176 qemu_set_irq(usart->txc_irq, 1);
177 usart->csra &= 0xff ^ USART_CSRA_TXC;
179 if (usart->csrb & USART_CSRB_DREIE) {
180 qemu_set_irq(usart->dre_irq, 1);
182 data = value;
183 qemu_chr_fe_write_all(&usart->chr, &data, 1);
184 break;
185 case USART_CSRA:
186 mask = 0b01000011;
187 /* Mask read-only bits. */
188 value = (value & mask) | (usart->csra & (0xff ^ mask));
189 usart->csra = value;
190 if (value & USART_CSRA_TXC) {
191 usart->csra ^= USART_CSRA_TXC;
192 qemu_set_irq(usart->txc_irq, 0);
194 if (value & USART_CSRA_MPCM) {
195 qemu_log_mask(
196 LOG_GUEST_ERROR,
197 "%s: MPCM not supported by USART\n",
198 __func__);
200 break;
201 case USART_CSRB:
202 mask = 0b11111101;
203 /* Mask read-only bits. */
204 value = (value & mask) | (usart->csrb & (0xff ^ mask));
205 usart->csrb = value;
206 if (!(value & USART_CSRB_RXEN)) {
207 /* Receiver disabled, flush input buffer. */
208 usart->data_valid = false;
210 qemu_set_irq(usart->rxc_irq,
211 ((value & USART_CSRB_RXCIE) &&
212 (usart->csra & USART_CSRA_RXC)) ? 1 : 0);
213 qemu_set_irq(usart->txc_irq,
214 ((value & USART_CSRB_TXCIE) &&
215 (usart->csra & USART_CSRA_TXC)) ? 1 : 0);
216 qemu_set_irq(usart->dre_irq,
217 ((value & USART_CSRB_DREIE) &&
218 (usart->csra & USART_CSRA_DRE)) ? 1 : 0);
219 update_char_mask(usart);
220 break;
221 case USART_CSRC:
222 usart->csrc = value;
223 if ((value & USART_CSRC_MSEL1) && (value & USART_CSRC_MSEL0)) {
224 qemu_log_mask(
225 LOG_GUEST_ERROR,
226 "%s: SPI mode not supported by USART\n",
227 __func__);
229 if ((value & USART_CSRC_MSEL1) && !(value & USART_CSRC_MSEL0)) {
230 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad USART mode\n", __func__);
232 if (!(value & USART_CSRC_PM1) && (value & USART_CSRC_PM0)) {
233 qemu_log_mask(
234 LOG_GUEST_ERROR,
235 "%s: Bad USART parity mode\n",
236 __func__);
238 update_char_mask(usart);
239 break;
240 case USART_BRRL:
241 usart->brrl = value;
242 break;
243 case USART_BRRH:
244 usart->brrh = value & 0b00001111;
245 break;
246 default:
247 qemu_log_mask(
248 LOG_GUEST_ERROR,
249 "%s: Bad offset 0x%"HWADDR_PRIx"\n",
250 __func__,
251 addr);
255 static const MemoryRegionOps avr_usart_ops = {
256 .read = avr_usart_read,
257 .write = avr_usart_write,
258 .endianness = DEVICE_NATIVE_ENDIAN,
259 .impl = {.min_access_size = 1, .max_access_size = 1}
262 static Property avr_usart_properties[] = {
263 DEFINE_PROP_CHR("chardev", AVRUsartState, chr),
264 DEFINE_PROP_END_OF_LIST(),
267 static void avr_usart_pr(void *opaque, int irq, int level)
269 AVRUsartState *s = AVR_USART(opaque);
271 s->enabled = !level;
273 if (!s->enabled) {
274 avr_usart_reset(DEVICE(s));
278 static void avr_usart_init(Object *obj)
280 AVRUsartState *s = AVR_USART(obj);
281 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->rxc_irq);
282 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->dre_irq);
283 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->txc_irq);
284 memory_region_init_io(&s->mmio, obj, &avr_usart_ops, s, TYPE_AVR_USART, 7);
285 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
286 qdev_init_gpio_in(DEVICE(s), avr_usart_pr, 1);
287 s->enabled = true;
290 static void avr_usart_realize(DeviceState *dev, Error **errp)
292 AVRUsartState *s = AVR_USART(dev);
293 qemu_chr_fe_set_handlers(&s->chr, avr_usart_can_receive,
294 avr_usart_receive, NULL, NULL,
295 s, NULL, true);
296 avr_usart_reset(dev);
299 static void avr_usart_class_init(ObjectClass *klass, void *data)
301 DeviceClass *dc = DEVICE_CLASS(klass);
303 dc->reset = avr_usart_reset;
304 device_class_set_props(dc, avr_usart_properties);
305 dc->realize = avr_usart_realize;
308 static const TypeInfo avr_usart_info = {
309 .name = TYPE_AVR_USART,
310 .parent = TYPE_SYS_BUS_DEVICE,
311 .instance_size = sizeof(AVRUsartState),
312 .instance_init = avr_usart_init,
313 .class_init = avr_usart_class_init,
316 static void avr_usart_register_types(void)
318 type_register_static(&avr_usart_info);
321 type_init(avr_usart_register_types)