|
|
1.1 root 1: /*
2: * QEMU GRLIB APB UART Emulator
3: *
4: * Copyright (c) 2010-2011 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 "sysbus.h"
26: #include "qemu-char.h"
27:
28: #include "trace.h"
29:
30: #define UART_REG_SIZE 20 /* Size of memory mapped registers */
31:
32: /* UART status register fields */
33: #define UART_DATA_READY (1 << 0)
34: #define UART_TRANSMIT_SHIFT_EMPTY (1 << 1)
35: #define UART_TRANSMIT_FIFO_EMPTY (1 << 2)
36: #define UART_BREAK_RECEIVED (1 << 3)
37: #define UART_OVERRUN (1 << 4)
38: #define UART_PARITY_ERROR (1 << 5)
39: #define UART_FRAMING_ERROR (1 << 6)
40: #define UART_TRANSMIT_FIFO_HALF (1 << 7)
41: #define UART_RECEIVE_FIFO_HALF (1 << 8)
42: #define UART_TRANSMIT_FIFO_FULL (1 << 9)
43: #define UART_RECEIVE_FIFO_FULL (1 << 10)
44:
45: /* UART control register fields */
46: #define UART_RECEIVE_ENABLE (1 << 0)
47: #define UART_TRANSMIT_ENABLE (1 << 1)
48: #define UART_RECEIVE_INTERRUPT (1 << 2)
49: #define UART_TRANSMIT_INTERRUPT (1 << 3)
50: #define UART_PARITY_SELECT (1 << 4)
51: #define UART_PARITY_ENABLE (1 << 5)
52: #define UART_FLOW_CONTROL (1 << 6)
53: #define UART_LOOPBACK (1 << 7)
54: #define UART_EXTERNAL_CLOCK (1 << 8)
55: #define UART_RECEIVE_FIFO_INTERRUPT (1 << 9)
56: #define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10)
57: #define UART_FIFO_DEBUG_MODE (1 << 11)
58: #define UART_OUTPUT_ENABLE (1 << 12)
59: #define UART_FIFO_AVAILABLE (1 << 31)
60:
61: /* Memory mapped register offsets */
62: #define DATA_OFFSET 0x00
63: #define STATUS_OFFSET 0x04
64: #define CONTROL_OFFSET 0x08
65: #define SCALER_OFFSET 0x0C /* not supported */
66: #define FIFO_DEBUG_OFFSET 0x10 /* not supported */
67:
1.1.1.4 ! root 68: #define FIFO_LENGTH 1024
! 69:
1.1 root 70: typedef struct UART {
71: SysBusDevice busdev;
1.1.1.4 ! root 72: MemoryRegion iomem;
1.1 root 73: qemu_irq irq;
74:
75: CharDriverState *chr;
76:
77: /* registers */
78: uint32_t receive;
79: uint32_t status;
80: uint32_t control;
1.1.1.4 ! root 81:
! 82: /* FIFO */
! 83: char buffer[FIFO_LENGTH];
! 84: int len;
! 85: int current;
1.1 root 86: } UART;
87:
1.1.1.4 ! root 88: static int uart_data_to_read(UART *uart)
! 89: {
! 90: return uart->current < uart->len;
! 91: }
! 92:
! 93: static char uart_pop(UART *uart)
! 94: {
! 95: char ret;
! 96:
! 97: if (uart->len == 0) {
! 98: uart->status &= ~UART_DATA_READY;
! 99: return 0;
! 100: }
! 101:
! 102: ret = uart->buffer[uart->current++];
! 103:
! 104: if (uart->current >= uart->len) {
! 105: /* Flush */
! 106: uart->len = 0;
! 107: uart->current = 0;
! 108: }
! 109:
! 110: if (!uart_data_to_read(uart)) {
! 111: uart->status &= ~UART_DATA_READY;
! 112: }
! 113:
! 114: return ret;
! 115: }
! 116:
! 117: static void uart_add_to_fifo(UART *uart,
! 118: const uint8_t *buffer,
! 119: int length)
! 120: {
! 121: if (uart->len + length > FIFO_LENGTH) {
! 122: abort();
! 123: }
! 124: memcpy(uart->buffer + uart->len, buffer, length);
! 125: uart->len += length;
! 126: }
! 127:
1.1 root 128: static int grlib_apbuart_can_receive(void *opaque)
129: {
130: UART *uart = opaque;
131:
1.1.1.4 ! root 132: return FIFO_LENGTH - uart->len;
1.1 root 133: }
134:
135: static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
136: {
137: UART *uart = opaque;
138:
1.1.1.4 ! root 139: uart_add_to_fifo(uart, buf, size);
! 140:
! 141: uart->status |= UART_DATA_READY;
1.1 root 142:
143: if (uart->control & UART_RECEIVE_INTERRUPT) {
144: qemu_irq_pulse(uart->irq);
145: }
146: }
147:
148: static void grlib_apbuart_event(void *opaque, int event)
149: {
150: trace_grlib_apbuart_event(event);
151: }
152:
1.1.1.4 ! root 153:
! 154: static uint64_t grlib_apbuart_read(void *opaque, target_phys_addr_t addr,
! 155: unsigned size)
! 156: {
! 157: UART *uart = opaque;
! 158:
! 159: addr &= 0xff;
! 160:
! 161: /* Unit registers */
! 162: switch (addr) {
! 163: case DATA_OFFSET:
! 164: case DATA_OFFSET + 3: /* when only one byte read */
! 165: return uart_pop(uart);
! 166:
! 167: case STATUS_OFFSET:
! 168: /* Read Only */
! 169: return uart->status;
! 170:
! 171: case CONTROL_OFFSET:
! 172: return uart->control;
! 173:
! 174: case SCALER_OFFSET:
! 175: /* Not supported */
! 176: return 0;
! 177:
! 178: default:
! 179: trace_grlib_apbuart_readl_unknown(addr);
! 180: return 0;
! 181: }
! 182: }
! 183:
! 184: static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr,
! 185: uint64_t value, unsigned size)
1.1 root 186: {
187: UART *uart = opaque;
188: unsigned char c = 0;
189:
190: addr &= 0xff;
191:
192: /* Unit registers */
193: switch (addr) {
194: case DATA_OFFSET:
1.1.1.4 ! root 195: case DATA_OFFSET + 3: /* When only one byte write */
1.1 root 196: c = value & 0xFF;
1.1.1.3 root 197: qemu_chr_fe_write(uart->chr, &c, 1);
1.1 root 198: return;
199:
200: case STATUS_OFFSET:
201: /* Read Only */
202: return;
203:
204: case CONTROL_OFFSET:
1.1.1.4 ! root 205: uart->control = value;
1.1 root 206: return;
207:
208: case SCALER_OFFSET:
209: /* Not supported */
210: return;
211:
212: default:
213: break;
214: }
215:
1.1.1.2 root 216: trace_grlib_apbuart_writel_unknown(addr, value);
1.1 root 217: }
218:
1.1.1.4 ! root 219: static const MemoryRegionOps grlib_apbuart_ops = {
! 220: .write = grlib_apbuart_write,
! 221: .read = grlib_apbuart_read,
! 222: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 223: };
224:
225: static int grlib_apbuart_init(SysBusDevice *dev)
226: {
1.1.1.4 ! root 227: UART *uart = FROM_SYSBUS(typeof(*uart), dev);
1.1 root 228:
229: qemu_chr_add_handlers(uart->chr,
230: grlib_apbuart_can_receive,
231: grlib_apbuart_receive,
232: grlib_apbuart_event,
233: uart);
234:
235: sysbus_init_irq(dev, &uart->irq);
236:
1.1.1.4 ! root 237: memory_region_init_io(&uart->iomem, &grlib_apbuart_ops, uart,
! 238: "uart", UART_REG_SIZE);
1.1 root 239:
1.1.1.4 ! root 240: sysbus_init_mmio(dev, &uart->iomem);
1.1 root 241:
242: return 0;
243: }
244:
1.1.1.4 ! root 245: static Property grlib_gptimer_properties[] = {
! 246: DEFINE_PROP_CHR("chrdev", UART, chr),
! 247: DEFINE_PROP_END_OF_LIST(),
! 248: };
! 249:
! 250: static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
! 251: {
! 252: DeviceClass *dc = DEVICE_CLASS(klass);
! 253: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
! 254:
! 255: k->init = grlib_apbuart_init;
! 256: dc->props = grlib_gptimer_properties;
! 257: }
! 258:
! 259: static TypeInfo grlib_gptimer_info = {
! 260: .name = "grlib,apbuart",
! 261: .parent = TYPE_SYS_BUS_DEVICE,
! 262: .instance_size = sizeof(UART),
! 263: .class_init = grlib_gptimer_class_init,
1.1 root 264: };
265:
1.1.1.4 ! root 266: static void grlib_gptimer_register_types(void)
1.1 root 267: {
1.1.1.4 ! root 268: type_register_static(&grlib_gptimer_info);
1.1 root 269: }
270:
1.1.1.4 ! root 271: type_init(grlib_gptimer_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.