Revision 142593c9

b/hw/arm/digic.c
24 24

  
25 25
#define DIGIC4_TIMER_BASE(n)    (0xc0210000 + (n) * 0x100)
26 26

  
27
#define DIGIC_UART_BASE          0xc0800000
28

  
27 29
static void digic_init(Object *obj)
28 30
{
29 31
    DigicState *s = DIGIC(obj);
......
43 45
        snprintf(name, DIGIC_TIMER_NAME_MLEN, "timer[%d]", i);
44 46
        object_property_add_child(obj, name, OBJECT(&s->timer[i]), NULL);
45 47
    }
48

  
49
    object_initialize(&s->uart, sizeof(s->uart), TYPE_DIGIC_UART);
50
    dev = DEVICE(&s->uart);
51
    qdev_set_parent_bus(dev, sysbus_get_default());
52
    object_property_add_child(obj, "uart", OBJECT(&s->uart), NULL);
46 53
}
47 54

  
48 55
static void digic_realize(DeviceState *dev, Error **errp)
......
74 81
        sbd = SYS_BUS_DEVICE(&s->timer[i]);
75 82
        sysbus_mmio_map(sbd, 0, DIGIC4_TIMER_BASE(i));
76 83
    }
84

  
85
    object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
86
    if (err != NULL) {
87
        error_propagate(errp, err);
88
        return;
89
    }
90

  
91
    sbd = SYS_BUS_DEVICE(&s->uart);
92
    sysbus_mmio_map(sbd, 0, DIGIC_UART_BASE);
77 93
}
78 94

  
79 95
static void digic_class_init(ObjectClass *oc, void *data)
b/hw/char/Makefile.objs
14 14
obj-$(CONFIG_OMAP) += omap_uart.o
15 15
obj-$(CONFIG_SH4) += sh_serial.o
16 16
obj-$(CONFIG_PSERIES) += spapr_vty.o
17
obj-$(CONFIG_DIGIC) += digic-uart.o
17 18

  
18 19
common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o
19 20
common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o
b/hw/char/digic-uart.c
1
/*
2
 * QEMU model of the Canon DIGIC UART block.
3
 *
4
 * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
5
 *
6
 * This model is based on reverse engineering efforts
7
 * made by CHDK (http://chdk.wikia.com) and
8
 * Magic Lantern (http://www.magiclantern.fm) projects
9
 * contributors.
10
 *
11
 * See "Serial terminal" docs here:
12
 *   http://magiclantern.wikia.com/wiki/Register_Map#Misc_Registers
13
 *
14
 * The QEMU model of the Milkymist UART block by Michael Walle
15
 * is used as a template.
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 2 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
 * GNU General Public License for more details.
26
 *
27
 */
28

  
29
#include "hw/hw.h"
30
#include "hw/sysbus.h"
31
#include "sysemu/char.h"
32

  
33
#include "hw/char/digic-uart.h"
34

  
35
enum {
36
    ST_RX_RDY = (1 << 0),
37
    ST_TX_RDY = (1 << 1),
38
};
39

  
40
static uint64_t digic_uart_read(void *opaque, hwaddr addr,
41
                                unsigned size)
42
{
43
    DigicUartState *s = opaque;
44
    uint64_t ret = 0;
45

  
46
    addr >>= 2;
47

  
48
    switch (addr) {
49
    case R_RX:
50
        s->reg_st &= ~(ST_RX_RDY);
51
        ret = s->reg_rx;
52
        break;
53

  
54
    case R_ST:
55
        ret = s->reg_st;
56
        break;
57

  
58
    default:
59
        qemu_log_mask(LOG_UNIMP,
60
                      "digic-uart: read access to unknown register 0x"
61
                      TARGET_FMT_plx, addr << 2);
62
    }
63

  
64
    return ret;
65
}
66

  
67
static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
68
                             unsigned size)
69
{
70
    DigicUartState *s = opaque;
71
    unsigned char ch = value;
72

  
73
    addr >>= 2;
74

  
75
    switch (addr) {
76
    case R_TX:
77
        if (s->chr) {
78
            qemu_chr_fe_write_all(s->chr, &ch, 1);
79
        }
80
        break;
81

  
82
    case R_ST:
83
        /*
84
         * Ignore write to R_ST.
85
         *
86
         * The point is that this register is actively used
87
         * during receiving and transmitting symbols,
88
         * but we don't know the function of most of bits.
89
         *
90
         * Ignoring writes to R_ST is only a simplification
91
         * of the model. It has no perceptible side effects
92
         * for existing guests.
93
         */
94
        break;
95

  
96
    default:
97
        qemu_log_mask(LOG_UNIMP,
98
                      "digic-uart: write access to unknown register 0x"
99
                      TARGET_FMT_plx, addr << 2);
100
    }
101
}
102

  
103
static const MemoryRegionOps uart_mmio_ops = {
104
    .read = digic_uart_read,
105
    .write = digic_uart_write,
106
    .valid = {
107
        .min_access_size = 4,
108
        .max_access_size = 4,
109
    },
110
    .endianness = DEVICE_NATIVE_ENDIAN,
111
};
112

  
113
static int uart_can_rx(void *opaque)
114
{
115
    DigicUartState *s = opaque;
116

  
117
    return !(s->reg_st & ST_RX_RDY);
118
}
119

  
120
static void uart_rx(void *opaque, const uint8_t *buf, int size)
121
{
122
    DigicUartState *s = opaque;
123

  
124
    assert(uart_can_rx(opaque));
125

  
126
    s->reg_st |= ST_RX_RDY;
127
    s->reg_rx = *buf;
128
}
129

  
130
static void uart_event(void *opaque, int event)
131
{
132
}
133

  
134
static void digic_uart_reset(DeviceState *d)
135
{
136
    DigicUartState *s = DIGIC_UART(d);
137

  
138
    s->reg_rx = 0;
139
    s->reg_st = ST_TX_RDY;
140
}
141

  
142
static void digic_uart_realize(DeviceState *dev, Error **errp)
143
{
144
    DigicUartState *s = DIGIC_UART(dev);
145

  
146
    s->chr = qemu_char_get_next_serial();
147
    if (s->chr) {
148
        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
149
    }
150
}
151

  
152
static void digic_uart_init(Object *obj)
153
{
154
    DigicUartState *s = DIGIC_UART(obj);
155

  
156
    memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
157
                          TYPE_DIGIC_UART, 0x18);
158
    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->regs_region);
159
}
160

  
161
static const VMStateDescription vmstate_digic_uart = {
162
    .name = "digic-uart",
163
    .version_id = 1,
164
    .minimum_version_id = 1,
165
    .minimum_version_id_old = 1,
166
    .fields = (VMStateField[]) {
167
        VMSTATE_UINT32(reg_rx, DigicUartState),
168
        VMSTATE_UINT32(reg_st, DigicUartState),
169
        VMSTATE_END_OF_LIST()
170
    }
171
};
172

  
173
static void digic_uart_class_init(ObjectClass *klass, void *data)
174
{
175
    DeviceClass *dc = DEVICE_CLASS(klass);
176

  
177
    dc->realize = digic_uart_realize;
178
    dc->reset = digic_uart_reset;
179
    dc->vmsd = &vmstate_digic_uart;
180
}
181

  
182
static const TypeInfo digic_uart_info = {
183
    .name = TYPE_DIGIC_UART,
184
    .parent = TYPE_SYS_BUS_DEVICE,
185
    .instance_size = sizeof(DigicUartState),
186
    .instance_init = digic_uart_init,
187
    .class_init = digic_uart_class_init,
188
};
189

  
190
static void digic_uart_register_types(void)
191
{
192
    type_register_static(&digic_uart_info);
193
}
194

  
195
type_init(digic_uart_register_types)
b/include/hw/arm/digic.h
21 21
#include "cpu.h"
22 22

  
23 23
#include "hw/timer/digic-timer.h"
24
#include "hw/char/digic-uart.h"
24 25

  
25 26
#define TYPE_DIGIC "digic"
26 27

  
......
36 37
    ARMCPU cpu;
37 38

  
38 39
    DigicTimerState timer[DIGIC4_NB_TIMERS];
40
    DigicUartState uart;
39 41
} DigicState;
40 42

  
41 43
#endif /* HW_ARM_DIGIC_H */
b/include/hw/char/digic-uart.h
1
/*
2
 * Canon DIGIC UART block declarations.
3
 *
4
 * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU General Public License for more details.
15
 *
16
 */
17

  
18
#ifndef HW_CHAR_DIGIC_UART_H
19
#define HW_CHAR_DIGIC_UART_H
20

  
21
#include "hw/sysbus.h"
22
#include "qemu/typedefs.h"
23

  
24
#define TYPE_DIGIC_UART "digic-uart"
25
#define DIGIC_UART(obj) \
26
    OBJECT_CHECK(DigicUartState, (obj), TYPE_DIGIC_UART)
27

  
28
enum {
29
    R_TX = 0x00,
30
    R_RX,
31
    R_ST = (0x14 >> 2),
32
    R_MAX
33
};
34

  
35
typedef struct DigicUartState {
36
    /*< private >*/
37
    SysBusDevice parent_obj;
38
    /*< public >*/
39

  
40
    MemoryRegion regs_region;
41
    CharDriverState *chr;
42

  
43
    uint32_t reg_rx;
44
    uint32_t reg_st;
45
} DigicUartState;
46

  
47
#endif /* HW_CHAR_DIGIC_UART_H */

Also available in: Unified diff