qemu

Форк
0
/
zaurus.c 
308 строк · 7.6 Кб
1
/*
2
 * Copyright (c) 2006-2008 Openedhand Ltd.
3
 * Written by Andrzej Zaborowski <balrog@zabor.org>
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License as
7
 * published by the Free Software Foundation; either version 2 or
8
 * (at your option) version 3 of the License.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
#include "qemu/osdep.h"
20
#include "hw/irq.h"
21
#include "hw/arm/sharpsl.h"
22
#include "hw/sysbus.h"
23
#include "migration/vmstate.h"
24
#include "qemu/module.h"
25
#include "qemu/log.h"
26
#include "qom/object.h"
27

28
/* SCOOP devices */
29

30
#define TYPE_SCOOP "scoop"
31
OBJECT_DECLARE_SIMPLE_TYPE(ScoopInfo, SCOOP)
32

33
struct ScoopInfo {
34
    SysBusDevice parent_obj;
35

36
    qemu_irq handler[16];
37
    MemoryRegion iomem;
38
    uint16_t status;
39
    uint16_t power;
40
    uint32_t gpio_level;
41
    uint32_t gpio_dir;
42
    uint32_t prev_level;
43

44
    uint16_t mcr;
45
    uint16_t cdr;
46
    uint16_t ccr;
47
    uint16_t irr;
48
    uint16_t imr;
49
    uint16_t isr;
50
};
51

52
#define SCOOP_MCR       0x00
53
#define SCOOP_CDR       0x04
54
#define SCOOP_CSR       0x08
55
#define SCOOP_CPR       0x0c
56
#define SCOOP_CCR       0x10
57
#define SCOOP_IRR_IRM   0x14
58
#define SCOOP_IMR       0x18
59
#define SCOOP_ISR       0x1c
60
#define SCOOP_GPCR      0x20
61
#define SCOOP_GPWR      0x24
62
#define SCOOP_GPRR      0x28
63

64
static inline void scoop_gpio_handler_update(ScoopInfo *s)
65
{
66
    uint32_t level, diff;
67
    int bit;
68
    level = s->gpio_level & s->gpio_dir;
69

70
    for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
71
        bit = ctz32(diff);
72
        qemu_set_irq(s->handler[bit], (level >> bit) & 1);
73
    }
74

75
    s->prev_level = level;
76
}
77

78
static uint64_t scoop_read(void *opaque, hwaddr addr,
79
                           unsigned size)
80
{
81
    ScoopInfo *s = (ScoopInfo *) opaque;
82

83
    switch (addr & 0x3f) {
84
    case SCOOP_MCR:
85
        return s->mcr;
86
    case SCOOP_CDR:
87
        return s->cdr;
88
    case SCOOP_CSR:
89
        return s->status;
90
    case SCOOP_CPR:
91
        return s->power;
92
    case SCOOP_CCR:
93
        return s->ccr;
94
    case SCOOP_IRR_IRM:
95
        return s->irr;
96
    case SCOOP_IMR:
97
        return s->imr;
98
    case SCOOP_ISR:
99
        return s->isr;
100
    case SCOOP_GPCR:
101
        return s->gpio_dir;
102
    case SCOOP_GPWR:
103
    case SCOOP_GPRR:
104
        return s->gpio_level;
105
    default:
106
        qemu_log_mask(LOG_GUEST_ERROR,
107
                      "scoop_read: bad register offset 0x%02" HWADDR_PRIx "\n",
108
                      addr);
109
    }
110

111
    return 0;
112
}
113

114
static void scoop_write(void *opaque, hwaddr addr,
115
                        uint64_t value, unsigned size)
116
{
117
    ScoopInfo *s = (ScoopInfo *) opaque;
118
    value &= 0xffff;
119

120
    switch (addr & 0x3f) {
121
    case SCOOP_MCR:
122
        s->mcr = value;
123
        break;
124
    case SCOOP_CDR:
125
        s->cdr = value;
126
        break;
127
    case SCOOP_CPR:
128
        s->power = value;
129
        if (value & 0x80) {
130
            s->power |= 0x8040;
131
        }
132
        break;
133
    case SCOOP_CCR:
134
        s->ccr = value;
135
        break;
136
    case SCOOP_IRR_IRM:
137
        s->irr = value;
138
        break;
139
    case SCOOP_IMR:
140
        s->imr = value;
141
        break;
142
    case SCOOP_ISR:
143
        s->isr = value;
144
        break;
145
    case SCOOP_GPCR:
146
        s->gpio_dir = value;
147
        scoop_gpio_handler_update(s);
148
        break;
149
    case SCOOP_GPWR:
150
    case SCOOP_GPRR:    /* GPRR is probably R/O in real HW */
151
        s->gpio_level = value & s->gpio_dir;
152
        scoop_gpio_handler_update(s);
153
        break;
154
    default:
155
        qemu_log_mask(LOG_GUEST_ERROR,
156
                      "scoop_write: bad register offset 0x%02" HWADDR_PRIx "\n",
157
                      addr);
158
    }
159
}
160

161
static const MemoryRegionOps scoop_ops = {
162
    .read = scoop_read,
163
    .write = scoop_write,
164
    .endianness = DEVICE_NATIVE_ENDIAN,
165
};
166

167
static void scoop_gpio_set(void *opaque, int line, int level)
168
{
169
    ScoopInfo *s = (ScoopInfo *) opaque;
170

171
    if (level) {
172
        s->gpio_level |= (1 << line);
173
    } else {
174
        s->gpio_level &= ~(1 << line);
175
    }
176
}
177

178
static void scoop_init(Object *obj)
179
{
180
    DeviceState *dev = DEVICE(obj);
181
    ScoopInfo *s = SCOOP(obj);
182
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
183

184
    s->status = 0x02;
185
    qdev_init_gpio_out(dev, s->handler, 16);
186
    qdev_init_gpio_in(dev, scoop_gpio_set, 16);
187
    memory_region_init_io(&s->iomem, obj, &scoop_ops, s, "scoop", 0x1000);
188

189
    sysbus_init_mmio(sbd, &s->iomem);
190
}
191

192
static int scoop_post_load(void *opaque, int version_id)
193
{
194
    ScoopInfo *s = (ScoopInfo *) opaque;
195
    int i;
196
    uint32_t level;
197

198
    level = s->gpio_level & s->gpio_dir;
199

200
    for (i = 0; i < 16; i++) {
201
        qemu_set_irq(s->handler[i], (level >> i) & 1);
202
    }
203

204
    s->prev_level = level;
205

206
    return 0;
207
}
208

209
static bool is_version_0(void *opaque, int version_id)
210
{
211
    return version_id == 0;
212
}
213

214
static bool vmstate_scoop_validate(void *opaque, int version_id)
215
{
216
    ScoopInfo *s = opaque;
217

218
    return !(s->prev_level & 0xffff0000) &&
219
        !(s->gpio_level & 0xffff0000) &&
220
        !(s->gpio_dir & 0xffff0000);
221
}
222

223
static const VMStateDescription vmstate_scoop_regs = {
224
    .name = "scoop",
225
    .version_id = 1,
226
    .minimum_version_id = 0,
227
    .post_load = scoop_post_load,
228
    .fields = (const VMStateField[]) {
229
        VMSTATE_UINT16(status, ScoopInfo),
230
        VMSTATE_UINT16(power, ScoopInfo),
231
        VMSTATE_UINT32(gpio_level, ScoopInfo),
232
        VMSTATE_UINT32(gpio_dir, ScoopInfo),
233
        VMSTATE_UINT32(prev_level, ScoopInfo),
234
        VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
235
        VMSTATE_UINT16(mcr, ScoopInfo),
236
        VMSTATE_UINT16(cdr, ScoopInfo),
237
        VMSTATE_UINT16(ccr, ScoopInfo),
238
        VMSTATE_UINT16(irr, ScoopInfo),
239
        VMSTATE_UINT16(imr, ScoopInfo),
240
        VMSTATE_UINT16(isr, ScoopInfo),
241
        VMSTATE_UNUSED_TEST(is_version_0, 2),
242
        VMSTATE_END_OF_LIST(),
243
    },
244
};
245

246
static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
247
{
248
    DeviceClass *dc = DEVICE_CLASS(klass);
249

250
    dc->desc = "Scoop2 Sharp custom ASIC";
251
    dc->vmsd = &vmstate_scoop_regs;
252
}
253

254
static const TypeInfo scoop_sysbus_info = {
255
    .name          = TYPE_SCOOP,
256
    .parent        = TYPE_SYS_BUS_DEVICE,
257
    .instance_size = sizeof(ScoopInfo),
258
    .instance_init = scoop_init,
259
    .class_init    = scoop_sysbus_class_init,
260
};
261

262
static void scoop_register_types(void)
263
{
264
    type_register_static(&scoop_sysbus_info);
265
}
266

267
type_init(scoop_register_types)
268

269
/* Write the bootloader parameters memory area.  */
270

271
#define MAGIC_CHG(a, b, c, d)   ((d << 24) | (c << 16) | (b << 8) | a)
272

273
static struct QEMU_PACKED sl_param_info {
274
    uint32_t comadj_keyword;
275
    int32_t comadj;
276

277
    uint32_t uuid_keyword;
278
    char uuid[16];
279

280
    uint32_t touch_keyword;
281
    int32_t touch_xp;
282
    int32_t touch_yp;
283
    int32_t touch_xd;
284
    int32_t touch_yd;
285

286
    uint32_t adadj_keyword;
287
    int32_t adadj;
288

289
    uint32_t phad_keyword;
290
    int32_t phadadj;
291
} zaurus_bootparam = {
292
    .comadj_keyword     = MAGIC_CHG('C', 'M', 'A', 'D'),
293
    .comadj             = 125,
294
    .uuid_keyword       = MAGIC_CHG('U', 'U', 'I', 'D'),
295
    .uuid               = { -1 },
296
    .touch_keyword      = MAGIC_CHG('T', 'U', 'C', 'H'),
297
    .touch_xp           = -1,
298
    .adadj_keyword      = MAGIC_CHG('B', 'V', 'A', 'D'),
299
    .adadj              = -1,
300
    .phad_keyword       = MAGIC_CHG('P', 'H', 'A', 'D'),
301
    .phadadj            = 0x01,
302
};
303

304
void sl_bootparam_write(hwaddr ptr)
305
{
306
    cpu_physical_memory_write(ptr, &zaurus_bootparam,
307
                              sizeof(struct sl_param_info));
308
}
309

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.