|
|
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: ! 68: typedef struct UART { ! 69: SysBusDevice busdev; ! 70: ! 71: qemu_irq irq; ! 72: ! 73: CharDriverState *chr; ! 74: ! 75: /* registers */ ! 76: uint32_t receive; ! 77: uint32_t status; ! 78: uint32_t control; ! 79: } UART; ! 80: ! 81: static int grlib_apbuart_can_receive(void *opaque) ! 82: { ! 83: UART *uart = opaque; ! 84: ! 85: return !!(uart->status & UART_DATA_READY); ! 86: } ! 87: ! 88: static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size) ! 89: { ! 90: UART *uart = opaque; ! 91: ! 92: uart->receive = *buf; ! 93: uart->status |= UART_DATA_READY; ! 94: ! 95: if (uart->control & UART_RECEIVE_INTERRUPT) { ! 96: qemu_irq_pulse(uart->irq); ! 97: } ! 98: } ! 99: ! 100: static void grlib_apbuart_event(void *opaque, int event) ! 101: { ! 102: trace_grlib_apbuart_event(event); ! 103: } ! 104: ! 105: static void ! 106: grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value) ! 107: { ! 108: UART *uart = opaque; ! 109: unsigned char c = 0; ! 110: ! 111: addr &= 0xff; ! 112: ! 113: /* Unit registers */ ! 114: switch (addr) { ! 115: case DATA_OFFSET: ! 116: c = value & 0xFF; ! 117: qemu_chr_write(uart->chr, &c, 1); ! 118: return; ! 119: ! 120: case STATUS_OFFSET: ! 121: /* Read Only */ ! 122: return; ! 123: ! 124: case CONTROL_OFFSET: ! 125: /* Not supported */ ! 126: return; ! 127: ! 128: case SCALER_OFFSET: ! 129: /* Not supported */ ! 130: return; ! 131: ! 132: default: ! 133: break; ! 134: } ! 135: ! 136: trace_grlib_apbuart_unknown_register("write", addr); ! 137: } ! 138: ! 139: static CPUReadMemoryFunc * const grlib_apbuart_read[] = { ! 140: NULL, NULL, NULL, ! 141: }; ! 142: ! 143: static CPUWriteMemoryFunc * const grlib_apbuart_write[] = { ! 144: NULL, NULL, grlib_apbuart_writel, ! 145: }; ! 146: ! 147: static int grlib_apbuart_init(SysBusDevice *dev) ! 148: { ! 149: UART *uart = FROM_SYSBUS(typeof(*uart), dev); ! 150: int uart_regs = 0; ! 151: ! 152: qemu_chr_add_handlers(uart->chr, ! 153: grlib_apbuart_can_receive, ! 154: grlib_apbuart_receive, ! 155: grlib_apbuart_event, ! 156: uart); ! 157: ! 158: sysbus_init_irq(dev, &uart->irq); ! 159: ! 160: uart_regs = cpu_register_io_memory(grlib_apbuart_read, ! 161: grlib_apbuart_write, ! 162: uart, DEVICE_NATIVE_ENDIAN); ! 163: if (uart_regs < 0) { ! 164: return -1; ! 165: } ! 166: ! 167: sysbus_init_mmio(dev, UART_REG_SIZE, uart_regs); ! 168: ! 169: return 0; ! 170: } ! 171: ! 172: static SysBusDeviceInfo grlib_gptimer_info = { ! 173: .init = grlib_apbuart_init, ! 174: .qdev.name = "grlib,apbuart", ! 175: .qdev.size = sizeof(UART), ! 176: .qdev.props = (Property[]) { ! 177: DEFINE_PROP_CHR("chrdev", UART, chr), ! 178: DEFINE_PROP_END_OF_LIST() ! 179: } ! 180: }; ! 181: ! 182: static void grlib_gptimer_register(void) ! 183: { ! 184: sysbus_register_withprop(&grlib_gptimer_info); ! 185: } ! 186: ! 187: device_init(grlib_gptimer_register)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.