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