]> Git Repo - qemu.git/blame - hw/char/grlib_apbuart.c
Include qemu/module.h where needed, drop it from qemu-common.h
[qemu.git] / hw / char / grlib_apbuart.c
CommitLineData
8b1e1320
FC
1/*
2 * QEMU GRLIB APB UART Emulator
3 *
b70447aa 4 * Copyright (c) 2010-2019 AdaCore
8b1e1320
FC
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
db5ebe5f 25#include "qemu/osdep.h"
b70447aa 26#include "hw/sparc/grlib.h"
83c9f4ca 27#include "hw/sysbus.h"
0b8fa32f 28#include "qemu/module.h"
4d43a603 29#include "chardev/char-fe.h"
8b1e1320
FC
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
0c685d28
FC
71#define FIFO_LENGTH 1024
72
ae8e0490
AF
73#define GRLIB_APB_UART(obj) \
74 OBJECT_CHECK(UART, (obj), TYPE_GRLIB_APB_UART)
75
8b1e1320 76typedef struct UART {
ae8e0490
AF
77 SysBusDevice parent_obj;
78
6281f7d1 79 MemoryRegion iomem;
8b1e1320
FC
80 qemu_irq irq;
81
becdfa00 82 CharBackend chr;
8b1e1320
FC
83
84 /* registers */
8b1e1320
FC
85 uint32_t status;
86 uint32_t control;
0c685d28
FC
87
88 /* FIFO */
89 char buffer[FIFO_LENGTH];
90 int len;
91 int current;
8b1e1320
FC
92} UART;
93
0c685d28
FC
94static int uart_data_to_read(UART *uart)
95{
96 return uart->current < uart->len;
97}
98
99static 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
123static 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
8b1e1320
FC
134static int grlib_apbuart_can_receive(void *opaque)
135{
136 UART *uart = opaque;
137
0c685d28 138 return FIFO_LENGTH - uart->len;
8b1e1320
FC
139}
140
141static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
142{
143 UART *uart = opaque;
144
99e44800
RH
145 if (uart->control & UART_RECEIVE_ENABLE) {
146 uart_add_to_fifo(uart, buf, size);
0c685d28 147
99e44800 148 uart->status |= UART_DATA_READY;
8b1e1320 149
99e44800
RH
150 if (uart->control & UART_RECEIVE_INTERRUPT) {
151 qemu_irq_pulse(uart->irq);
152 }
8b1e1320
FC
153 }
154}
155
156static void grlib_apbuart_event(void *opaque, int event)
157{
158 trace_grlib_apbuart_event(event);
159}
160
0c685d28 161
a8170e5e 162static uint64_t grlib_apbuart_read(void *opaque, hwaddr addr,
0c685d28
FC
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
a8170e5e 192static void grlib_apbuart_write(void *opaque, hwaddr addr,
0c685d28 193 uint64_t value, unsigned size)
8b1e1320
FC
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:
0c685d28 203 case DATA_OFFSET + 3: /* When only one byte write */
99e44800 204 /* Transmit when character device available and transmitter enabled */
30650701 205 if (qemu_chr_fe_backend_connected(&uart->chr) &&
5345fdb4 206 (uart->control & UART_TRANSMIT_ENABLE)) {
99e44800 207 c = value & 0xFF;
6ab3fc32
DB
208 /* XXX this blocks entire thread. Rewrite to use
209 * qemu_chr_fe_write and background I/O callbacks */
5345fdb4 210 qemu_chr_fe_write_all(&uart->chr, &c, 1);
99e44800
RH
211 /* Generate interrupt */
212 if (uart->control & UART_TRANSMIT_INTERRUPT) {
213 qemu_irq_pulse(uart->irq);
214 }
215 }
8b1e1320
FC
216 return;
217
218 case STATUS_OFFSET:
219 /* Read Only */
220 return;
221
222 case CONTROL_OFFSET:
0c685d28 223 uart->control = value;
8b1e1320
FC
224 return;
225
226 case SCALER_OFFSET:
227 /* Not supported */
228 return;
229
230 default:
231 break;
232 }
233
b4548fcc 234 trace_grlib_apbuart_writel_unknown(addr, value);
8b1e1320
FC
235}
236
6281f7d1 237static const MemoryRegionOps grlib_apbuart_ops = {
0c685d28
FC
238 .write = grlib_apbuart_write,
239 .read = grlib_apbuart_read,
6281f7d1 240 .endianness = DEVICE_NATIVE_ENDIAN,
8b1e1320
FC
241};
242
ddaa6e04 243static void grlib_apbuart_realize(DeviceState *dev, Error **errp)
8b1e1320 244{
ae8e0490 245 UART *uart = GRLIB_APB_UART(dev);
ddaa6e04 246 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
8b1e1320 247
5345fdb4
MAL
248 qemu_chr_fe_set_handlers(&uart->chr,
249 grlib_apbuart_can_receive,
250 grlib_apbuart_receive,
251 grlib_apbuart_event,
81517ba3 252 NULL, uart, NULL, true);
8b1e1320 253
ddaa6e04 254 sysbus_init_irq(sbd, &uart->irq);
8b1e1320 255
300b1fc6 256 memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart,
6281f7d1 257 "uart", UART_REG_SIZE);
8b1e1320 258
ddaa6e04 259 sysbus_init_mmio(sbd, &uart->iomem);
8b1e1320
FC
260}
261
99e44800
RH
262static void grlib_apbuart_reset(DeviceState *d)
263{
ae8e0490 264 UART *uart = GRLIB_APB_UART(d);
99e44800
RH
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
8eda2228 275static Property grlib_apbuart_properties[] = {
999e12bb
AL
276 DEFINE_PROP_CHR("chrdev", UART, chr),
277 DEFINE_PROP_END_OF_LIST(),
278};
279
8eda2228 280static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
999e12bb 281{
39bffca2 282 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 283
ddaa6e04 284 dc->realize = grlib_apbuart_realize;
99e44800 285 dc->reset = grlib_apbuart_reset;
8eda2228 286 dc->props = grlib_apbuart_properties;
999e12bb
AL
287}
288
8eda2228 289static const TypeInfo grlib_apbuart_info = {
ae8e0490 290 .name = TYPE_GRLIB_APB_UART,
39bffca2
AL
291 .parent = TYPE_SYS_BUS_DEVICE,
292 .instance_size = sizeof(UART),
8eda2228 293 .class_init = grlib_apbuart_class_init,
8b1e1320
FC
294};
295
8eda2228 296static void grlib_apbuart_register_types(void)
8b1e1320 297{
8eda2228 298 type_register_static(&grlib_apbuart_info);
8b1e1320
FC
299}
300
8eda2228 301type_init(grlib_apbuart_register_types)
This page took 0.562583 seconds and 4 git commands to generate.