xref: /openbmc/qemu/hw/char/grlib_apbuart.c (revision 8e6fe6b8)
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/sparc/grlib.h"
27 #include "hw/sysbus.h"
28 #include "qemu/module.h"
29 #include "chardev/char-fe.h"
30 
31 #include "trace.h"
32 
33 #define UART_REG_SIZE 20     /* Size of memory mapped registers */
34 
35 /* UART status register fields */
36 #define UART_DATA_READY           (1 <<  0)
37 #define UART_TRANSMIT_SHIFT_EMPTY (1 <<  1)
38 #define UART_TRANSMIT_FIFO_EMPTY  (1 <<  2)
39 #define UART_BREAK_RECEIVED       (1 <<  3)
40 #define UART_OVERRUN              (1 <<  4)
41 #define UART_PARITY_ERROR         (1 <<  5)
42 #define UART_FRAMING_ERROR        (1 <<  6)
43 #define UART_TRANSMIT_FIFO_HALF   (1 <<  7)
44 #define UART_RECEIVE_FIFO_HALF    (1 <<  8)
45 #define UART_TRANSMIT_FIFO_FULL   (1 <<  9)
46 #define UART_RECEIVE_FIFO_FULL    (1 << 10)
47 
48 /* UART control register fields */
49 #define UART_RECEIVE_ENABLE          (1 <<  0)
50 #define UART_TRANSMIT_ENABLE         (1 <<  1)
51 #define UART_RECEIVE_INTERRUPT       (1 <<  2)
52 #define UART_TRANSMIT_INTERRUPT      (1 <<  3)
53 #define UART_PARITY_SELECT           (1 <<  4)
54 #define UART_PARITY_ENABLE           (1 <<  5)
55 #define UART_FLOW_CONTROL            (1 <<  6)
56 #define UART_LOOPBACK                (1 <<  7)
57 #define UART_EXTERNAL_CLOCK          (1 <<  8)
58 #define UART_RECEIVE_FIFO_INTERRUPT  (1 <<  9)
59 #define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10)
60 #define UART_FIFO_DEBUG_MODE         (1 << 11)
61 #define UART_OUTPUT_ENABLE           (1 << 12)
62 #define UART_FIFO_AVAILABLE          (1 << 31)
63 
64 /* Memory mapped register offsets */
65 #define DATA_OFFSET       0x00
66 #define STATUS_OFFSET     0x04
67 #define CONTROL_OFFSET    0x08
68 #define SCALER_OFFSET     0x0C  /* not supported */
69 #define FIFO_DEBUG_OFFSET 0x10  /* not supported */
70 
71 #define FIFO_LENGTH 1024
72 
73 #define GRLIB_APB_UART(obj) \
74     OBJECT_CHECK(UART, (obj), TYPE_GRLIB_APB_UART)
75 
76 typedef struct UART {
77     SysBusDevice parent_obj;
78 
79     MemoryRegion iomem;
80     qemu_irq irq;
81 
82     CharBackend chr;
83 
84     /* registers */
85     uint32_t status;
86     uint32_t control;
87 
88     /* FIFO */
89     char buffer[FIFO_LENGTH];
90     int  len;
91     int  current;
92 } UART;
93 
94 static int uart_data_to_read(UART *uart)
95 {
96     return uart->current < uart->len;
97 }
98 
99 static char uart_pop(UART *uart)
100 {
101     char ret;
102 
103     if (uart->len == 0) {
104         uart->status &= ~UART_DATA_READY;
105         return 0;
106     }
107 
108     ret = uart->buffer[uart->current++];
109 
110     if (uart->current >= uart->len) {
111         /* Flush */
112         uart->len     = 0;
113         uart->current = 0;
114     }
115 
116     if (!uart_data_to_read(uart)) {
117         uart->status &= ~UART_DATA_READY;
118     }
119 
120     return ret;
121 }
122 
123 static void uart_add_to_fifo(UART          *uart,
124                              const uint8_t *buffer,
125                              int            length)
126 {
127     if (uart->len + length > FIFO_LENGTH) {
128         abort();
129     }
130     memcpy(uart->buffer + uart->len, buffer, length);
131     uart->len += length;
132 }
133 
134 static int grlib_apbuart_can_receive(void *opaque)
135 {
136     UART *uart = opaque;
137 
138     return FIFO_LENGTH - uart->len;
139 }
140 
141 static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
142 {
143     UART *uart = opaque;
144 
145     if (uart->control & UART_RECEIVE_ENABLE) {
146         uart_add_to_fifo(uart, buf, size);
147 
148         uart->status |= UART_DATA_READY;
149 
150         if (uart->control & UART_RECEIVE_INTERRUPT) {
151             qemu_irq_pulse(uart->irq);
152         }
153     }
154 }
155 
156 static void grlib_apbuart_event(void *opaque, int event)
157 {
158     trace_grlib_apbuart_event(event);
159 }
160 
161 
162 static uint64_t grlib_apbuart_read(void *opaque, hwaddr addr,
163                                    unsigned size)
164 {
165     UART     *uart = opaque;
166 
167     addr &= 0xff;
168 
169     /* Unit registers */
170     switch (addr) {
171     case DATA_OFFSET:
172     case DATA_OFFSET + 3:       /* when only one byte read */
173         return uart_pop(uart);
174 
175     case STATUS_OFFSET:
176         /* Read Only */
177         return uart->status;
178 
179     case CONTROL_OFFSET:
180         return uart->control;
181 
182     case SCALER_OFFSET:
183         /* Not supported */
184         return 0;
185 
186     default:
187         trace_grlib_apbuart_readl_unknown(addr);
188         return 0;
189     }
190 }
191 
192 static void grlib_apbuart_write(void *opaque, hwaddr addr,
193                                 uint64_t value, unsigned size)
194 {
195     UART          *uart = opaque;
196     unsigned char  c    = 0;
197 
198     addr &= 0xff;
199 
200     /* Unit registers */
201     switch (addr) {
202     case DATA_OFFSET:
203     case DATA_OFFSET + 3:       /* When only one byte write */
204         /* Transmit when character device available and transmitter enabled */
205         if (qemu_chr_fe_backend_connected(&uart->chr) &&
206             (uart->control & UART_TRANSMIT_ENABLE)) {
207             c = value & 0xFF;
208             /* XXX this blocks entire thread. Rewrite to use
209              * qemu_chr_fe_write and background I/O callbacks */
210             qemu_chr_fe_write_all(&uart->chr, &c, 1);
211             /* Generate interrupt */
212             if (uart->control & UART_TRANSMIT_INTERRUPT) {
213                 qemu_irq_pulse(uart->irq);
214             }
215         }
216         return;
217 
218     case STATUS_OFFSET:
219         /* Read Only */
220         return;
221 
222     case CONTROL_OFFSET:
223         uart->control = value;
224         return;
225 
226     case SCALER_OFFSET:
227         /* Not supported */
228         return;
229 
230     default:
231         break;
232     }
233 
234     trace_grlib_apbuart_writel_unknown(addr, value);
235 }
236 
237 static const MemoryRegionOps grlib_apbuart_ops = {
238     .write      = grlib_apbuart_write,
239     .read       = grlib_apbuart_read,
240     .endianness = DEVICE_NATIVE_ENDIAN,
241 };
242 
243 static void grlib_apbuart_realize(DeviceState *dev, Error **errp)
244 {
245     UART *uart = GRLIB_APB_UART(dev);
246     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
247 
248     qemu_chr_fe_set_handlers(&uart->chr,
249                              grlib_apbuart_can_receive,
250                              grlib_apbuart_receive,
251                              grlib_apbuart_event,
252                              NULL, uart, NULL, true);
253 
254     sysbus_init_irq(sbd, &uart->irq);
255 
256     memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart,
257                           "uart", UART_REG_SIZE);
258 
259     sysbus_init_mmio(sbd, &uart->iomem);
260 }
261 
262 static void grlib_apbuart_reset(DeviceState *d)
263 {
264     UART *uart = GRLIB_APB_UART(d);
265 
266     /* Transmitter FIFO and shift registers are always empty in QEMU */
267     uart->status =  UART_TRANSMIT_FIFO_EMPTY | UART_TRANSMIT_SHIFT_EMPTY;
268     /* Everything is off */
269     uart->control = 0;
270     /* Flush receive FIFO */
271     uart->len = 0;
272     uart->current = 0;
273 }
274 
275 static Property grlib_apbuart_properties[] = {
276     DEFINE_PROP_CHR("chrdev", UART, chr),
277     DEFINE_PROP_END_OF_LIST(),
278 };
279 
280 static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
281 {
282     DeviceClass *dc = DEVICE_CLASS(klass);
283 
284     dc->realize = grlib_apbuart_realize;
285     dc->reset = grlib_apbuart_reset;
286     dc->props = grlib_apbuart_properties;
287 }
288 
289 static const TypeInfo grlib_apbuart_info = {
290     .name          = TYPE_GRLIB_APB_UART,
291     .parent        = TYPE_SYS_BUS_DEVICE,
292     .instance_size = sizeof(UART),
293     .class_init    = grlib_apbuart_class_init,
294 };
295 
296 static void grlib_apbuart_register_types(void)
297 {
298     type_register_static(&grlib_apbuart_info);
299 }
300 
301 type_init(grlib_apbuart_register_types)
302