Statistics
| Branch: | Revision:

root / hw / grlib_apbuart.c @ 47188700

History | View | Annotate | Download (5.2 kB)

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)