]> Git Repo - qemu.git/blob - hw/char/lm32_uart.c
softfloat: Name rounding mode enum
[qemu.git] / hw / char / lm32_uart.c
1 /*
2  *  QEMU model of the LatticeMico32 UART block.
3  *
4  *  Copyright (c) 2010 Michael Walle <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  * Specification available at:
21  *   http://www.latticesemi.com/documents/mico32uart.pdf
22  */
23
24
25 #include "qemu/osdep.h"
26 #include "hw/irq.h"
27 #include "hw/qdev-properties.h"
28 #include "hw/sysbus.h"
29 #include "migration/vmstate.h"
30 #include "trace.h"
31 #include "chardev/char-fe.h"
32 #include "qemu/error-report.h"
33 #include "qemu/module.h"
34
35 enum {
36     R_RXTX = 0,
37     R_IER,
38     R_IIR,
39     R_LCR,
40     R_MCR,
41     R_LSR,
42     R_MSR,
43     R_DIV,
44     R_MAX
45 };
46
47 enum {
48     IER_RBRI = (1<<0),
49     IER_THRI = (1<<1),
50     IER_RLSI = (1<<2),
51     IER_MSI  = (1<<3),
52 };
53
54 enum {
55     IIR_STAT = (1<<0),
56     IIR_ID0  = (1<<1),
57     IIR_ID1  = (1<<2),
58 };
59
60 enum {
61     LCR_WLS0 = (1<<0),
62     LCR_WLS1 = (1<<1),
63     LCR_STB  = (1<<2),
64     LCR_PEN  = (1<<3),
65     LCR_EPS  = (1<<4),
66     LCR_SP   = (1<<5),
67     LCR_SB   = (1<<6),
68 };
69
70 enum {
71     MCR_DTR  = (1<<0),
72     MCR_RTS  = (1<<1),
73 };
74
75 enum {
76     LSR_DR   = (1<<0),
77     LSR_OE   = (1<<1),
78     LSR_PE   = (1<<2),
79     LSR_FE   = (1<<3),
80     LSR_BI   = (1<<4),
81     LSR_THRE = (1<<5),
82     LSR_TEMT = (1<<6),
83 };
84
85 enum {
86     MSR_DCTS = (1<<0),
87     MSR_DDSR = (1<<1),
88     MSR_TERI = (1<<2),
89     MSR_DDCD = (1<<3),
90     MSR_CTS  = (1<<4),
91     MSR_DSR  = (1<<5),
92     MSR_RI   = (1<<6),
93     MSR_DCD  = (1<<7),
94 };
95
96 #define TYPE_LM32_UART "lm32-uart"
97 #define LM32_UART(obj) OBJECT_CHECK(LM32UartState, (obj), TYPE_LM32_UART)
98
99 struct LM32UartState {
100     SysBusDevice parent_obj;
101
102     MemoryRegion iomem;
103     CharBackend chr;
104     qemu_irq irq;
105
106     uint32_t regs[R_MAX];
107 };
108 typedef struct LM32UartState LM32UartState;
109
110 static void uart_update_irq(LM32UartState *s)
111 {
112     unsigned int irq;
113
114     if ((s->regs[R_LSR] & (LSR_OE | LSR_PE | LSR_FE | LSR_BI))
115             && (s->regs[R_IER] & IER_RLSI)) {
116         irq = 1;
117         s->regs[R_IIR] = IIR_ID1 | IIR_ID0;
118     } else if ((s->regs[R_LSR] & LSR_DR) && (s->regs[R_IER] & IER_RBRI)) {
119         irq = 1;
120         s->regs[R_IIR] = IIR_ID1;
121     } else if ((s->regs[R_LSR] & LSR_THRE) && (s->regs[R_IER] & IER_THRI)) {
122         irq = 1;
123         s->regs[R_IIR] = IIR_ID0;
124     } else if ((s->regs[R_MSR] & 0x0f) && (s->regs[R_IER] & IER_MSI)) {
125         irq = 1;
126         s->regs[R_IIR] = 0;
127     } else {
128         irq = 0;
129         s->regs[R_IIR] = IIR_STAT;
130     }
131
132     trace_lm32_uart_irq_state(irq);
133     qemu_set_irq(s->irq, irq);
134 }
135
136 static uint64_t uart_read(void *opaque, hwaddr addr,
137                           unsigned size)
138 {
139     LM32UartState *s = opaque;
140     uint32_t r = 0;
141
142     addr >>= 2;
143     switch (addr) {
144     case R_RXTX:
145         r = s->regs[R_RXTX];
146         s->regs[R_LSR] &= ~LSR_DR;
147         uart_update_irq(s);
148         qemu_chr_fe_accept_input(&s->chr);
149         break;
150     case R_IIR:
151     case R_LSR:
152     case R_MSR:
153         r = s->regs[addr];
154         break;
155     case R_IER:
156     case R_LCR:
157     case R_MCR:
158     case R_DIV:
159         error_report("lm32_uart: read access to write only register 0x"
160                 TARGET_FMT_plx, addr << 2);
161         break;
162     default:
163         error_report("lm32_uart: read access to unknown register 0x"
164                 TARGET_FMT_plx, addr << 2);
165         break;
166     }
167
168     trace_lm32_uart_memory_read(addr << 2, r);
169     return r;
170 }
171
172 static void uart_write(void *opaque, hwaddr addr,
173                        uint64_t value, unsigned size)
174 {
175     LM32UartState *s = opaque;
176     unsigned char ch = value;
177
178     trace_lm32_uart_memory_write(addr, value);
179
180     addr >>= 2;
181     switch (addr) {
182     case R_RXTX:
183         /* XXX this blocks entire thread. Rewrite to use
184          * qemu_chr_fe_write and background I/O callbacks */
185         qemu_chr_fe_write_all(&s->chr, &ch, 1);
186         break;
187     case R_IER:
188     case R_LCR:
189     case R_MCR:
190     case R_DIV:
191         s->regs[addr] = value;
192         break;
193     case R_IIR:
194     case R_LSR:
195     case R_MSR:
196         error_report("lm32_uart: write access to read only register 0x"
197                 TARGET_FMT_plx, addr << 2);
198         break;
199     default:
200         error_report("lm32_uart: write access to unknown register 0x"
201                 TARGET_FMT_plx, addr << 2);
202         break;
203     }
204     uart_update_irq(s);
205 }
206
207 static const MemoryRegionOps uart_ops = {
208     .read = uart_read,
209     .write = uart_write,
210     .endianness = DEVICE_NATIVE_ENDIAN,
211     .valid = {
212         .min_access_size = 4,
213         .max_access_size = 4,
214     },
215 };
216
217 static void uart_rx(void *opaque, const uint8_t *buf, int size)
218 {
219     LM32UartState *s = opaque;
220
221     if (s->regs[R_LSR] & LSR_DR) {
222         s->regs[R_LSR] |= LSR_OE;
223     }
224
225     s->regs[R_LSR] |= LSR_DR;
226     s->regs[R_RXTX] = *buf;
227
228     uart_update_irq(s);
229 }
230
231 static int uart_can_rx(void *opaque)
232 {
233     LM32UartState *s = opaque;
234
235     return !(s->regs[R_LSR] & LSR_DR);
236 }
237
238 static void uart_event(void *opaque, QEMUChrEvent event)
239 {
240 }
241
242 static void uart_reset(DeviceState *d)
243 {
244     LM32UartState *s = LM32_UART(d);
245     int i;
246
247     for (i = 0; i < R_MAX; i++) {
248         s->regs[i] = 0;
249     }
250
251     /* defaults */
252     s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
253 }
254
255 static void lm32_uart_init(Object *obj)
256 {
257     LM32UartState *s = LM32_UART(obj);
258     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
259
260     sysbus_init_irq(dev, &s->irq);
261
262     memory_region_init_io(&s->iomem, obj, &uart_ops, s,
263                           "uart", R_MAX * 4);
264     sysbus_init_mmio(dev, &s->iomem);
265 }
266
267 static void lm32_uart_realize(DeviceState *dev, Error **errp)
268 {
269     LM32UartState *s = LM32_UART(dev);
270
271     qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
272                              uart_event, NULL, s, NULL, true);
273 }
274
275 static const VMStateDescription vmstate_lm32_uart = {
276     .name = "lm32-uart",
277     .version_id = 1,
278     .minimum_version_id = 1,
279     .fields = (VMStateField[]) {
280         VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX),
281         VMSTATE_END_OF_LIST()
282     }
283 };
284
285 static Property lm32_uart_properties[] = {
286     DEFINE_PROP_CHR("chardev", LM32UartState, chr),
287     DEFINE_PROP_END_OF_LIST(),
288 };
289
290 static void lm32_uart_class_init(ObjectClass *klass, void *data)
291 {
292     DeviceClass *dc = DEVICE_CLASS(klass);
293
294     dc->reset = uart_reset;
295     dc->vmsd = &vmstate_lm32_uart;
296     device_class_set_props(dc, lm32_uart_properties);
297     dc->realize = lm32_uart_realize;
298 }
299
300 static const TypeInfo lm32_uart_info = {
301     .name          = TYPE_LM32_UART,
302     .parent        = TYPE_SYS_BUS_DEVICE,
303     .instance_size = sizeof(LM32UartState),
304     .instance_init = lm32_uart_init,
305     .class_init    = lm32_uart_class_init,
306 };
307
308 static void lm32_uart_register_types(void)
309 {
310     type_register_static(&lm32_uart_info);
311 }
312
313 type_init(lm32_uart_register_types)
This page took 0.040548 seconds and 4 git commands to generate.