xref: /openbmc/qemu/hw/char/grlib_apbuart.c (revision 64f7aece)
1 /*
2  * QEMU GRLIB APB UART Emulator
3  *
4  * Copyright (c) 2010-2019 AdaCore
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "hw/irq.h"
27 #include "hw/qdev-properties.h"
28 #include "hw/sparc/grlib.h"
29 #include "hw/sysbus.h"
30 #include "qemu/module.h"
31 #include "chardev/char-fe.h"
32 
33 #include "trace.h"
34 #include "qom/object.h"
35 
36 #define UART_REG_SIZE 20     /* Size of memory mapped registers */
37 
38 /* UART status register fields */
39 #define UART_DATA_READY           (1 <<  0)
40 #define UART_TRANSMIT_SHIFT_EMPTY (1 <<  1)
41 #define UART_TRANSMIT_FIFO_EMPTY  (1 <<  2)
42 #define UART_BREAK_RECEIVED       (1 <<  3)
43 #define UART_OVERRUN              (1 <<  4)
44 #define UART_PARITY_ERROR         (1 <<  5)
45 #define UART_FRAMING_ERROR        (1 <<  6)
46 #define UART_TRANSMIT_FIFO_HALF   (1 <<  7)
47 #define UART_RECEIVE_FIFO_HALF    (1 <<  8)
48 #define UART_TRANSMIT_FIFO_FULL   (1 <<  9)
49 #define UART_RECEIVE_FIFO_FULL    (1 << 10)
50 
51 /* UART control register fields */
52 #define UART_RECEIVE_ENABLE          (1 <<  0)
53 #define UART_TRANSMIT_ENABLE         (1 <<  1)
54 #define UART_RECEIVE_INTERRUPT       (1 <<  2)
55 #define UART_TRANSMIT_INTERRUPT      (1 <<  3)
56 #define UART_PARITY_SELECT           (1 <<  4)
57 #define UART_PARITY_ENABLE           (1 <<  5)
58 #define UART_FLOW_CONTROL            (1 <<  6)
59 #define UART_LOOPBACK                (1 <<  7)
60 #define UART_EXTERNAL_CLOCK          (1 <<  8)
61 #define UART_RECEIVE_FIFO_INTERRUPT  (1 <<  9)
62 #define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10)
63 #define UART_FIFO_DEBUG_MODE         (1 << 11)
64 #define UART_OUTPUT_ENABLE           (1 << 12)
65 #define UART_FIFO_AVAILABLE          (1 << 31)
66 
67 /* Memory mapped register offsets */
68 #define DATA_OFFSET       0x00
69 #define STATUS_OFFSET     0x04
70 #define CONTROL_OFFSET    0x08
71 #define SCALER_OFFSET     0x0C  /* not supported */
72 #define FIFO_DEBUG_OFFSET 0x10  /* not supported */
73 
74 #define FIFO_LENGTH 1024
75 
76 typedef struct UART UART;
77 DECLARE_INSTANCE_CHECKER(UART, GRLIB_APB_UART,
78                          TYPE_GRLIB_APB_UART)
79 
80 struct UART {
81     SysBusDevice parent_obj;
82 
83     MemoryRegion iomem;
84     qemu_irq irq;
85 
86     CharBackend chr;
87 
88     /* registers */
89     uint32_t status;
90     uint32_t control;
91 
92     /* FIFO */
93     char buffer[FIFO_LENGTH];
94     int  len;
95     int  current;
96 };
97 
98 static int uart_data_to_read(UART *uart)
99 {
100     return uart->current < uart->len;
101 }
102 
103 static char uart_pop(UART *uart)
104 {
105     char ret;
106 
107     if (uart->len == 0) {
108         uart->status &= ~UART_DATA_READY;
109         return 0;
110     }
111 
112     ret = uart->buffer[uart->current++];
113 
114     if (uart->current >= uart->len) {
115         /* Flush */
116         uart->len     = 0;
117         uart->current = 0;
118     }
119 
120     if (!uart_data_to_read(uart)) {
121         uart->status &= ~UART_DATA_READY;
122     }
123 
124     return ret;
125 }
126 
127 static void uart_add_to_fifo(UART          *uart,
128                              const uint8_t *buffer,
129                              int            length)
130 {
131     if (uart->len + length > FIFO_LENGTH) {
132         abort();
133     }
134     memcpy(uart->buffer + uart->len, buffer, length);
135     uart->len += length;
136 }
137 
138 static int grlib_apbuart_can_receive(void *opaque)
139 {
140     UART *uart = opaque;
141 
142     return FIFO_LENGTH - uart->len;
143 }
144 
145 static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
146 {
147     UART *uart = opaque;
148 
149     if (uart->control & UART_RECEIVE_ENABLE) {
150         uart_add_to_fifo(uart, buf, size);
151 
152         uart->status |= UART_DATA_READY;
153 
154         if (uart->control & UART_RECEIVE_INTERRUPT) {
155             qemu_irq_pulse(uart->irq);
156         }
157     }
158 }
159 
160 static void grlib_apbuart_event(void *opaque, QEMUChrEvent event)
161 {
162     trace_grlib_apbuart_event(event);
163 }
164 
165 
166 static uint64_t grlib_apbuart_read(void *opaque, hwaddr addr,
167                                    unsigned size)
168 {
169     UART     *uart = opaque;
170 
171     addr &= 0xff;
172 
173     /* Unit registers */
174     switch (addr) {
175     case DATA_OFFSET:
176     case DATA_OFFSET + 3:       /* when only one byte read */
177         return uart_pop(uart);
178 
179     case STATUS_OFFSET:
180         /* Read Only */
181         return uart->status;
182 
183     case CONTROL_OFFSET:
184         return uart->control;
185 
186     case SCALER_OFFSET:
187         /* Not supported */
188         return 0;
189 
190     default:
191         trace_grlib_apbuart_readl_unknown(addr);
192         return 0;
193     }
194 }
195 
196 static void grlib_apbuart_write(void *opaque, hwaddr addr,
197                                 uint64_t value, unsigned size)
198 {
199     UART          *uart = opaque;
200     unsigned char  c    = 0;
201 
202     addr &= 0xff;
203 
204     /* Unit registers */
205     switch (addr) {
206     case DATA_OFFSET:
207     case DATA_OFFSET + 3:       /* When only one byte write */
208         /* Transmit when character device available and transmitter enabled */
209         if (qemu_chr_fe_backend_connected(&uart->chr) &&
210             (uart->control & UART_TRANSMIT_ENABLE)) {
211             c = value & 0xFF;
212             /* XXX this blocks entire thread. Rewrite to use
213              * qemu_chr_fe_write and background I/O callbacks */
214             qemu_chr_fe_write_all(&uart->chr, &c, 1);
215             /* Generate interrupt */
216             if (uart->control & UART_TRANSMIT_INTERRUPT) {
217                 qemu_irq_pulse(uart->irq);
218             }
219         }
220         return;
221 
222     case STATUS_OFFSET:
223         /* Read Only */
224         return;
225 
226     case CONTROL_OFFSET:
227         uart->control = value;
228         return;
229 
230     case SCALER_OFFSET:
231         /* Not supported */
232         return;
233 
234     default:
235         break;
236     }
237 
238     trace_grlib_apbuart_writel_unknown(addr, value);
239 }
240 
241 static const MemoryRegionOps grlib_apbuart_ops = {
242     .write      = grlib_apbuart_write,
243     .read       = grlib_apbuart_read,
244     .endianness = DEVICE_NATIVE_ENDIAN,
245 };
246 
247 static void grlib_apbuart_realize(DeviceState *dev, Error **errp)
248 {
249     UART *uart = GRLIB_APB_UART(dev);
250     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
251 
252     qemu_chr_fe_set_handlers(&uart->chr,
253                              grlib_apbuart_can_receive,
254                              grlib_apbuart_receive,
255                              grlib_apbuart_event,
256                              NULL, uart, NULL, true);
257 
258     sysbus_init_irq(sbd, &uart->irq);
259 
260     memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart,
261                           "uart", UART_REG_SIZE);
262 
263     sysbus_init_mmio(sbd, &uart->iomem);
264 }
265 
266 static void grlib_apbuart_reset(DeviceState *d)
267 {
268     UART *uart = GRLIB_APB_UART(d);
269 
270     /* Transmitter FIFO and shift registers are always empty in QEMU */
271     uart->status =  UART_TRANSMIT_FIFO_EMPTY | UART_TRANSMIT_SHIFT_EMPTY;
272     /* Everything is off */
273     uart->control = 0;
274     /* Flush receive FIFO */
275     uart->len = 0;
276     uart->current = 0;
277 }
278 
279 static Property grlib_apbuart_properties[] = {
280     DEFINE_PROP_CHR("chrdev", UART, chr),
281     DEFINE_PROP_END_OF_LIST(),
282 };
283 
284 static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
285 {
286     DeviceClass *dc = DEVICE_CLASS(klass);
287 
288     dc->realize = grlib_apbuart_realize;
289     dc->reset = grlib_apbuart_reset;
290     device_class_set_props(dc, grlib_apbuart_properties);
291 }
292 
293 static const TypeInfo grlib_apbuart_info = {
294     .name          = TYPE_GRLIB_APB_UART,
295     .parent        = TYPE_SYS_BUS_DEVICE,
296     .instance_size = sizeof(UART),
297     .class_init    = grlib_apbuart_class_init,
298 };
299 
300 static void grlib_apbuart_register_types(void)
301 {
302     type_register_static(&grlib_apbuart_info);
303 }
304 
305 type_init(grlib_apbuart_register_types)
306