2
* Allwinner A10 interrupt controller device emulation
4
* Copyright (C) 2013 Li Guang
5
* Written by Li Guang <lig.fnst@cn.fujitsu.com>
7
* This program is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License as published by the
9
* Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful, but WITHOUT
13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18
#include "hw/sysbus.h"
19
#include "hw/devices.h"
20
#include "sysemu/sysemu.h"
21
#include "hw/intc/allwinner-a10-pic.h"
23
static void aw_a10_pic_update(AwA10PICState *s)
28
for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
29
irq |= s->irq_pending[i] & ~s->mask[i];
30
fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
33
qemu_set_irq(s->parent_irq, !!irq);
34
qemu_set_irq(s->parent_fiq, !!fiq);
37
static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
39
AwA10PICState *s = opaque;
42
set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
47
static uint64_t aw_a10_pic_read(void *opaque, hwaddr offset, unsigned size)
49
AwA10PICState *s = opaque;
50
uint8_t index = (offset & 0xc) / 4;
53
case AW_A10_PIC_VECTOR:
55
case AW_A10_PIC_BASE_ADDR:
57
case AW_A10_PIC_PROTECT:
61
case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
62
return s->irq_pending[index];
63
case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
64
return s->fiq_pending[index];
65
case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
66
return s->select[index];
67
case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
68
return s->enable[index];
69
case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
70
return s->mask[index];
72
qemu_log_mask(LOG_GUEST_ERROR,
73
"%s: Bad offset 0x%x\n", __func__, (int)offset);
80
static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
83
AwA10PICState *s = opaque;
84
uint8_t index = (offset & 0xc) / 4;
87
case AW_A10_PIC_VECTOR:
88
s->vector = value & ~0x3;
90
case AW_A10_PIC_BASE_ADDR:
91
s->base_addr = value & ~0x3;
92
case AW_A10_PIC_PROTECT:
98
case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
99
s->irq_pending[index] &= ~value;
101
case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
102
s->fiq_pending[index] &= ~value;
104
case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
105
s->select[index] = value;
107
case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
108
s->enable[index] = value;
110
case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
111
s->mask[index] = value;
114
qemu_log_mask(LOG_GUEST_ERROR,
115
"%s: Bad offset 0x%x\n", __func__, (int)offset);
119
aw_a10_pic_update(s);
122
static const MemoryRegionOps aw_a10_pic_ops = {
123
.read = aw_a10_pic_read,
124
.write = aw_a10_pic_write,
125
.endianness = DEVICE_NATIVE_ENDIAN,
128
static const VMStateDescription vmstate_aw_a10_pic = {
131
.minimum_version_id = 1,
132
.minimum_version_id_old = 1,
133
.fields = (VMStateField[]) {
134
VMSTATE_UINT32(vector, AwA10PICState),
135
VMSTATE_UINT32(base_addr, AwA10PICState),
136
VMSTATE_UINT32(protect, AwA10PICState),
137
VMSTATE_UINT32(nmi, AwA10PICState),
138
VMSTATE_UINT32_ARRAY(irq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
139
VMSTATE_UINT32_ARRAY(fiq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
140
VMSTATE_UINT32_ARRAY(enable, AwA10PICState, AW_A10_PIC_REG_NUM),
141
VMSTATE_UINT32_ARRAY(select, AwA10PICState, AW_A10_PIC_REG_NUM),
142
VMSTATE_UINT32_ARRAY(mask, AwA10PICState, AW_A10_PIC_REG_NUM),
143
VMSTATE_END_OF_LIST()
147
static void aw_a10_pic_init(Object *obj)
149
AwA10PICState *s = AW_A10_PIC(obj);
150
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
152
qdev_init_gpio_in(DEVICE(dev), aw_a10_pic_set_irq, AW_A10_PIC_INT_NR);
153
sysbus_init_irq(dev, &s->parent_irq);
154
sysbus_init_irq(dev, &s->parent_fiq);
155
memory_region_init_io(&s->iomem, OBJECT(s), &aw_a10_pic_ops, s,
156
TYPE_AW_A10_PIC, 0x400);
157
sysbus_init_mmio(dev, &s->iomem);
160
static void aw_a10_pic_reset(DeviceState *d)
162
AwA10PICState *s = AW_A10_PIC(d);
169
for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
170
s->irq_pending[i] = 0;
171
s->fiq_pending[i] = 0;
178
static void aw_a10_pic_class_init(ObjectClass *klass, void *data)
180
DeviceClass *dc = DEVICE_CLASS(klass);
182
dc->reset = aw_a10_pic_reset;
183
dc->desc = "allwinner a10 pic";
184
dc->vmsd = &vmstate_aw_a10_pic;
187
static const TypeInfo aw_a10_pic_info = {
188
.name = TYPE_AW_A10_PIC,
189
.parent = TYPE_SYS_BUS_DEVICE,
190
.instance_size = sizeof(AwA10PICState),
191
.instance_init = aw_a10_pic_init,
192
.class_init = aw_a10_pic_class_init,
195
static void aw_a10_register_types(void)
197
type_register_static(&aw_a10_pic_info);
200
type_init(aw_a10_register_types);