]> git.proxmox.com Git - mirror_qemu.git/blame - hw/intc/etraxfs_pic.c
qdev: Replace cannot_instantiate_with_device_add_yet with !user_creatable
[mirror_qemu.git] / hw / intc / etraxfs_pic.c
CommitLineData
e62b5b13
EI
1/*
2 * QEMU ETRAX Interrupt Controller.
3 *
4 * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
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
90191d07 25#include "qemu/osdep.h"
83c9f4ca
PB
26#include "hw/sysbus.h"
27#include "hw/hw.h"
1ad2134f
PB
28//#include "pc.h"
29//#include "etraxfs.h"
e62b5b13
EI
30
31#define D(x)
32
979d98ca
EI
33#define R_RW_MASK 0
34#define R_R_VECT 1
35#define R_R_MASKED_VECT 2
36#define R_R_NMI 3
37#define R_R_GURU 4
38#define R_MAX 5
8d13fcc0 39
9062143f
AF
40#define TYPE_ETRAX_FS_PIC "etraxfs,pic"
41#define ETRAX_FS_PIC(obj) \
42 OBJECT_CHECK(struct etrax_pic, (obj), TYPE_ETRAX_FS_PIC)
43
fd6dc90b 44struct etrax_pic
e62b5b13 45{
9062143f
AF
46 SysBusDevice parent_obj;
47
5dd25f36 48 MemoryRegion mmio;
ddde095c 49 void *interrupt_vector;
fd6dc90b
EI
50 qemu_irq parent_irq;
51 qemu_irq parent_nmi;
979d98ca 52 uint32_t regs[R_MAX];
e62b5b13
EI
53};
54
fd6dc90b 55static void pic_update(struct etrax_pic *fs)
979d98ca 56{
979d98ca
EI
57 uint32_t vector = 0;
58 int i;
59
60 fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
61
66a0a2cb 62 /* The ETRAX interrupt controller signals interrupts to the core
979d98ca
EI
63 through an interrupt request wire and an irq vector bus. If
64 multiple interrupts are simultaneously active it chooses vector
65 0x30 and lets the sw choose the priorities. */
66 if (fs->regs[R_R_MASKED_VECT]) {
67 uint32_t mv = fs->regs[R_R_MASKED_VECT];
68 for (i = 0; i < 31; i++) {
69 if (mv & 1) {
70 vector = 0x31 + i;
71 /* Check for multiple interrupts. */
72 if (mv > 1)
73 vector = 0x30;
74 break;
75 }
76 mv >>= 1;
77 }
979d98ca 78 }
fd6dc90b
EI
79
80 if (fs->interrupt_vector) {
ddde095c
GH
81 /* hack alert: ptr property */
82 *(uint32_t*)(fs->interrupt_vector) = vector;
fd6dc90b
EI
83 }
84 qemu_set_irq(fs->parent_irq, !!vector);
e62b5b13
EI
85}
86
5dd25f36 87static uint64_t
a8170e5e 88pic_read(void *opaque, hwaddr addr, unsigned int size)
e62b5b13 89{
fd6dc90b 90 struct etrax_pic *fs = opaque;
979d98ca 91 uint32_t rval;
e62b5b13 92
979d98ca
EI
93 rval = fs->regs[addr >> 2];
94 D(printf("%s %x=%x\n", __func__, addr, rval));
95 return rval;
e62b5b13
EI
96}
97
a8170e5e 98static void pic_write(void *opaque, hwaddr addr,
5dd25f36 99 uint64_t value, unsigned int size)
e62b5b13 100{
fd6dc90b 101 struct etrax_pic *fs = opaque;
979d98ca 102 D(printf("%s addr=%x val=%x\n", __func__, addr, value));
8d13fcc0 103
979d98ca
EI
104 if (addr == R_RW_MASK) {
105 fs->regs[R_RW_MASK] = value;
106 pic_update(fs);
107 }
e62b5b13
EI
108}
109
5dd25f36
EI
110static const MemoryRegionOps pic_ops = {
111 .read = pic_read,
112 .write = pic_write,
113 .endianness = DEVICE_NATIVE_ENDIAN,
114 .valid = {
115 .min_access_size = 4,
116 .max_access_size = 4
117 }
e62b5b13
EI
118};
119
5ef98b47 120static void nmi_handler(void *opaque, int irq, int level)
979d98ca 121{
fd6dc90b 122 struct etrax_pic *fs = (void *)opaque;
979d98ca
EI
123 uint32_t mask;
124
125 mask = 1 << irq;
126 if (level)
127 fs->regs[R_R_NMI] |= mask;
128 else
129 fs->regs[R_R_NMI] &= ~mask;
130
fd6dc90b 131 qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
5ef98b47
EI
132}
133
73cfd29f 134static void irq_handler(void *opaque, int irq, int level)
e7ae771f 135{
fd6dc90b 136 struct etrax_pic *fs = (void *)opaque;
73cfd29f 137
e7ae771f
SW
138 if (irq >= 30) {
139 nmi_handler(opaque, irq, level);
140 return;
141 }
73cfd29f 142
979d98ca
EI
143 irq -= 1;
144 fs->regs[R_R_VECT] &= ~(1 << irq);
145 fs->regs[R_R_VECT] |= (!!level << irq);
146 pic_update(fs);
5ef98b47
EI
147}
148
b46818e9 149static void etraxfs_pic_init(Object *obj)
e62b5b13 150{
b46818e9
XZ
151 DeviceState *dev = DEVICE(obj);
152 struct etrax_pic *s = ETRAX_FS_PIC(obj);
153 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
e62b5b13 154
9062143f
AF
155 qdev_init_gpio_in(dev, irq_handler, 32);
156 sysbus_init_irq(sbd, &s->parent_irq);
157 sysbus_init_irq(sbd, &s->parent_nmi);
e62b5b13 158
b46818e9 159 memory_region_init_io(&s->mmio, obj, &pic_ops, s,
1437c94b 160 "etraxfs-pic", R_MAX * 4);
9062143f 161 sysbus_init_mmio(sbd, &s->mmio);
e62b5b13 162}
fd6dc90b 163
999e12bb
AL
164static Property etraxfs_pic_properties[] = {
165 DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector),
166 DEFINE_PROP_END_OF_LIST(),
167};
168
169static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
170{
39bffca2 171 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 172
39bffca2 173 dc->props = etraxfs_pic_properties;
1b111dc1
MA
174 /*
175 * Note: pointer property "interrupt_vector" may remain null, thus
aab00230 176 * no need for dc->user_creatable = false;
1b111dc1 177 */
999e12bb
AL
178}
179
8c43a6f0 180static const TypeInfo etraxfs_pic_info = {
9062143f 181 .name = TYPE_ETRAX_FS_PIC,
39bffca2
AL
182 .parent = TYPE_SYS_BUS_DEVICE,
183 .instance_size = sizeof(struct etrax_pic),
b46818e9 184 .instance_init = etraxfs_pic_init,
39bffca2 185 .class_init = etraxfs_pic_class_init,
ee6847d1
GH
186};
187
83f7d43a 188static void etraxfs_pic_register_types(void)
fd6dc90b 189{
39bffca2 190 type_register_static(&etraxfs_pic_info);
fd6dc90b
EI
191}
192
83f7d43a 193type_init(etraxfs_pic_register_types)