]> git.proxmox.com Git - qemu.git/blame - hw/slavio_intctl.c
Correct spelling of licensed
[qemu.git] / hw / slavio_intctl.c
CommitLineData
e80cfcfc
FB
1/*
2 * QEMU Sparc SLAVIO interrupt controller emulation
5fafdf24 3 *
66321a11 4 * Copyright (c) 2003-2005 Fabrice Bellard
5fafdf24 5 *
e80cfcfc
FB
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 */
a1961a4b 24
87ecb68b 25#include "sun4m.h"
376253ec 26#include "monitor.h"
a1961a4b 27#include "sysbus.h"
97bf4851 28#include "trace.h"
87ecb68b 29
e80cfcfc
FB
30//#define DEBUG_IRQ_COUNT
31
32/*
33 * Registers of interrupt controller in sun4m.
34 *
35 * This is the interrupt controller part of chip STP2001 (Slave I/O), also
36 * produced as NCR89C105. See
37 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
38 *
39 * There is a system master controller and one for each cpu.
5fafdf24 40 *
e80cfcfc
FB
41 */
42
43#define MAX_CPUS 16
b3a23197 44#define MAX_PILS 16
e80cfcfc 45
a1961a4b
BS
46struct SLAVIO_INTCTLState;
47
48typedef struct SLAVIO_CPUINTCTLState {
49 uint32_t intreg_pending;
50 struct SLAVIO_INTCTLState *master;
51 uint32_t cpu;
462eda24 52 uint32_t irl_out;
a1961a4b 53} SLAVIO_CPUINTCTLState;
a8f48dcc 54
e80cfcfc 55typedef struct SLAVIO_INTCTLState {
a1961a4b 56 SysBusDevice busdev;
e80cfcfc
FB
57 uint32_t intregm_pending;
58 uint32_t intregm_disabled;
59 uint32_t target_cpu;
60#ifdef DEBUG_IRQ_COUNT
61 uint64_t irq_count[32];
62#endif
a1961a4b 63 qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS];
a1961a4b 64 SLAVIO_CPUINTCTLState slaves[MAX_CPUS];
e80cfcfc
FB
65} SLAVIO_INTCTLState;
66
67#define INTCTL_MAXADDR 0xf
5aca8c3b 68#define INTCTL_SIZE (INTCTL_MAXADDR + 1)
a8f48dcc 69#define INTCTLM_SIZE 0x14
80be36b8 70#define MASTER_IRQ_MASK ~0x0fa2007f
9a87ce9b 71#define MASTER_DISABLE 0x80000000
6341fdcb 72#define CPU_SOFTIRQ_MASK 0xfffe0000
462eda24
BS
73#define CPU_IRQ_INT15_IN (1 << 15)
74#define CPU_IRQ_TIMER_IN (1 << 14)
9a87ce9b 75
0d0a7e69 76static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs);
e80cfcfc
FB
77
78// per-cpu interrupt controller
c227f099 79static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
e80cfcfc 80{
a8f48dcc 81 SLAVIO_CPUINTCTLState *s = opaque;
dd4131b3 82 uint32_t saddr, ret;
e80cfcfc 83
a8f48dcc 84 saddr = addr >> 2;
e80cfcfc
FB
85 switch (saddr) {
86 case 0:
a8f48dcc 87 ret = s->intreg_pending;
dd4131b3 88 break;
e80cfcfc 89 default:
dd4131b3
BS
90 ret = 0;
91 break;
e80cfcfc 92 }
97bf4851 93 trace_slavio_intctl_mem_readl(s->cpu, addr, ret);
dd4131b3
BS
94
95 return ret;
e80cfcfc
FB
96}
97
c227f099 98static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr,
77f193da 99 uint32_t val)
e80cfcfc 100{
a8f48dcc 101 SLAVIO_CPUINTCTLState *s = opaque;
e80cfcfc 102 uint32_t saddr;
e80cfcfc 103
a8f48dcc 104 saddr = addr >> 2;
97bf4851 105 trace_slavio_intctl_mem_writel(s->cpu, addr, val);
e80cfcfc
FB
106 switch (saddr) {
107 case 1: // clear pending softints
462eda24 108 val &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN;
a8f48dcc 109 s->intreg_pending &= ~val;
0d0a7e69 110 slavio_check_interrupts(s->master, 1);
97bf4851 111 trace_slavio_intctl_mem_writel_clear(s->cpu, val, s->intreg_pending);
f930d07e 112 break;
e80cfcfc 113 case 2: // set softint
6341fdcb 114 val &= CPU_SOFTIRQ_MASK;
a8f48dcc 115 s->intreg_pending |= val;
0d0a7e69 116 slavio_check_interrupts(s->master, 1);
97bf4851 117 trace_slavio_intctl_mem_writel_set(s->cpu, val, s->intreg_pending);
f930d07e 118 break;
e80cfcfc 119 default:
f930d07e 120 break;
e80cfcfc
FB
121 }
122}
123
d60efc6b 124static CPUReadMemoryFunc * const slavio_intctl_mem_read[3] = {
7c560456
BS
125 NULL,
126 NULL,
e80cfcfc
FB
127 slavio_intctl_mem_readl,
128};
129
d60efc6b 130static CPUWriteMemoryFunc * const slavio_intctl_mem_write[3] = {
7c560456
BS
131 NULL,
132 NULL,
e80cfcfc
FB
133 slavio_intctl_mem_writel,
134};
135
136// master system interrupt controller
c227f099 137static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
e80cfcfc
FB
138{
139 SLAVIO_INTCTLState *s = opaque;
dd4131b3 140 uint32_t saddr, ret;
e80cfcfc 141
a8f48dcc 142 saddr = addr >> 2;
e80cfcfc
FB
143 switch (saddr) {
144 case 0:
9a87ce9b 145 ret = s->intregm_pending & ~MASTER_DISABLE;
dd4131b3 146 break;
e80cfcfc 147 case 1:
80be36b8 148 ret = s->intregm_disabled & MASTER_IRQ_MASK;
dd4131b3 149 break;
e80cfcfc 150 case 4:
dd4131b3
BS
151 ret = s->target_cpu;
152 break;
e80cfcfc 153 default:
dd4131b3
BS
154 ret = 0;
155 break;
e80cfcfc 156 }
97bf4851 157 trace_slavio_intctlm_mem_readl(addr, ret);
dd4131b3
BS
158
159 return ret;
e80cfcfc
FB
160}
161
c227f099 162static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr,
77f193da 163 uint32_t val)
e80cfcfc
FB
164{
165 SLAVIO_INTCTLState *s = opaque;
166 uint32_t saddr;
167
a8f48dcc 168 saddr = addr >> 2;
97bf4851 169 trace_slavio_intctlm_mem_writel(addr, val);
e80cfcfc
FB
170 switch (saddr) {
171 case 2: // clear (enable)
f930d07e 172 // Force clear unused bits
9a87ce9b 173 val &= MASTER_IRQ_MASK;
f930d07e 174 s->intregm_disabled &= ~val;
97bf4851 175 trace_slavio_intctlm_mem_writel_enable(val, s->intregm_disabled);
0d0a7e69 176 slavio_check_interrupts(s, 1);
f930d07e 177 break;
10760f0f 178 case 3: // set (disable; doesn't affect pending)
f930d07e 179 // Force clear unused bits
9a87ce9b 180 val &= MASTER_IRQ_MASK;
f930d07e 181 s->intregm_disabled |= val;
0d0a7e69 182 slavio_check_interrupts(s, 1);
97bf4851 183 trace_slavio_intctlm_mem_writel_disable(val, s->intregm_disabled);
f930d07e 184 break;
e80cfcfc 185 case 4:
f930d07e 186 s->target_cpu = val & (MAX_CPUS - 1);
0d0a7e69 187 slavio_check_interrupts(s, 1);
97bf4851 188 trace_slavio_intctlm_mem_writel_target(s->target_cpu);
f930d07e 189 break;
e80cfcfc 190 default:
f930d07e 191 break;
e80cfcfc
FB
192 }
193}
194
d60efc6b 195static CPUReadMemoryFunc * const slavio_intctlm_mem_read[3] = {
7c560456
BS
196 NULL,
197 NULL,
e80cfcfc
FB
198 slavio_intctlm_mem_readl,
199};
200
d60efc6b 201static CPUWriteMemoryFunc * const slavio_intctlm_mem_write[3] = {
7c560456
BS
202 NULL,
203 NULL,
e80cfcfc
FB
204 slavio_intctlm_mem_writel,
205};
206
d453c2c3 207void slavio_pic_info(Monitor *mon, DeviceState *dev)
e80cfcfc 208{
d453c2c3
BS
209 SysBusDevice *sd;
210 SLAVIO_INTCTLState *s;
e80cfcfc
FB
211 int i;
212
d453c2c3
BS
213 sd = sysbus_from_qdev(dev);
214 s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
e80cfcfc 215 for (i = 0; i < MAX_CPUS; i++) {
376253ec 216 monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
a1961a4b 217 s->slaves[i].intreg_pending);
e80cfcfc 218 }
376253ec
AL
219 monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n",
220 s->intregm_pending, s->intregm_disabled);
e80cfcfc
FB
221}
222
d453c2c3 223void slavio_irq_info(Monitor *mon, DeviceState *dev)
e80cfcfc
FB
224{
225#ifndef DEBUG_IRQ_COUNT
376253ec 226 monitor_printf(mon, "irq statistic code not compiled.\n");
e80cfcfc 227#else
d453c2c3
BS
228 SysBusDevice *sd;
229 SLAVIO_INTCTLState *s;
e80cfcfc
FB
230 int i;
231 int64_t count;
232
d453c2c3
BS
233 sd = sysbus_from_qdev(dev);
234 s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
376253ec 235 monitor_printf(mon, "IRQ statistics:\n");
e80cfcfc
FB
236 for (i = 0; i < 32; i++) {
237 count = s->irq_count[i];
238 if (count > 0)
376253ec 239 monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
e80cfcfc
FB
240 }
241#endif
242}
243
68556e2e 244static const uint32_t intbit_to_level[] = {
462eda24
BS
245 2, 3, 5, 7, 9, 11, 13, 2, 3, 5, 7, 9, 11, 13, 12, 12,
246 6, 13, 4, 10, 8, 9, 11, 0, 0, 0, 0, 15, 15, 15, 15, 0,
68556e2e
BS
247};
248
0d0a7e69 249static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
66321a11 250{
327ac2e7
BS
251 uint32_t pending = s->intregm_pending, pil_pending;
252 unsigned int i, j;
66321a11
FB
253
254 pending &= ~s->intregm_disabled;
255
97bf4851 256 trace_slavio_check_interrupts(pending, s->intregm_disabled);
ba3c64fb 257 for (i = 0; i < MAX_CPUS; i++) {
327ac2e7 258 pil_pending = 0;
462eda24
BS
259
260 /* If we are the current interrupt target, get hard interrupts */
9a87ce9b 261 if (pending && !(s->intregm_disabled & MASTER_DISABLE) &&
b3a23197
BS
262 (i == s->target_cpu)) {
263 for (j = 0; j < 32; j++) {
462eda24 264 if ((pending & (1 << j)) && intbit_to_level[j]) {
68556e2e 265 pil_pending |= 1 << intbit_to_level[j];
462eda24
BS
266 }
267 }
268 }
269
270 /* Calculate current pending hard interrupts for display */
271 s->slaves[i].intreg_pending &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN |
272 CPU_IRQ_TIMER_IN;
273 if (i == s->target_cpu) {
274 for (j = 0; j < 32; j++) {
275 if ((s->intregm_pending & (1 << j)) && intbit_to_level[j]) {
276 s->slaves[i].intreg_pending |= 1 << intbit_to_level[j];
277 }
b3a23197
BS
278 }
279 }
462eda24 280
94c5f455
AT
281 /* Level 15 and CPU timer interrupts are only masked when
282 the MASTER_DISABLE bit is set */
283 if (!(s->intregm_disabled & MASTER_DISABLE)) {
284 pil_pending |= s->slaves[i].intreg_pending &
285 (CPU_IRQ_INT15_IN | CPU_IRQ_TIMER_IN);
286 }
462eda24
BS
287
288 /* Add soft interrupts */
a1961a4b 289 pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
327ac2e7 290
0d0a7e69 291 if (set_irqs) {
c84a88d8
PM
292 /* Since there is not really an interrupt 0 (and pil_pending
293 * and irl_out bit zero are thus always zero) there is no need
294 * to do anything with cpu_irqs[i][0] and it is OK not to do
295 * the j=0 iteration of this loop.
296 */
297 for (j = MAX_PILS-1; j > 0; j--) {
0d0a7e69 298 if (pil_pending & (1 << j)) {
462eda24 299 if (!(s->slaves[i].irl_out & (1 << j))) {
0d0a7e69
BS
300 qemu_irq_raise(s->cpu_irqs[i][j]);
301 }
302 } else {
462eda24 303 if (s->slaves[i].irl_out & (1 << j)) {
0d0a7e69
BS
304 qemu_irq_lower(s->cpu_irqs[i][j]);
305 }
306 }
ba3c64fb
FB
307 }
308 }
462eda24 309 s->slaves[i].irl_out = pil_pending;
ba3c64fb 310 }
66321a11
FB
311}
312
e80cfcfc
FB
313/*
314 * "irq" here is the bit number in the system interrupt register to
315 * separate serial and keyboard interrupts sharing a level.
316 */
d7edfd27 317static void slavio_set_irq(void *opaque, int irq, int level)
e80cfcfc
FB
318{
319 SLAVIO_INTCTLState *s = opaque;
b3a23197 320 uint32_t mask = 1 << irq;
68556e2e 321 uint32_t pil = intbit_to_level[irq];
462eda24 322 unsigned int i;
b3a23197 323
97bf4851 324 trace_slavio_set_irq(s->target_cpu, irq, pil, level);
b3a23197
BS
325 if (pil > 0) {
326 if (level) {
327ac2e7
BS
327#ifdef DEBUG_IRQ_COUNT
328 s->irq_count[pil]++;
329#endif
b3a23197 330 s->intregm_pending |= mask;
462eda24
BS
331 if (pil == 15) {
332 for (i = 0; i < MAX_CPUS; i++) {
333 s->slaves[i].intreg_pending |= 1 << pil;
334 }
335 }
b3a23197
BS
336 } else {
337 s->intregm_pending &= ~mask;
462eda24
BS
338 if (pil == 15) {
339 for (i = 0; i < MAX_CPUS; i++) {
340 s->slaves[i].intreg_pending &= ~(1 << pil);
341 }
342 }
b3a23197 343 }
0d0a7e69 344 slavio_check_interrupts(s, 1);
e80cfcfc
FB
345 }
346}
347
d7edfd27 348static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
ba3c64fb
FB
349{
350 SLAVIO_INTCTLState *s = opaque;
351
97bf4851 352 trace_slavio_set_timer_irq_cpu(cpu, level);
d7edfd27 353
e3a79bca 354 if (level) {
462eda24 355 s->slaves[cpu].intreg_pending |= CPU_IRQ_TIMER_IN;
e3a79bca 356 } else {
462eda24 357 s->slaves[cpu].intreg_pending &= ~CPU_IRQ_TIMER_IN;
e3a79bca 358 }
d7edfd27 359
0d0a7e69 360 slavio_check_interrupts(s, 1);
ba3c64fb
FB
361}
362
a1961a4b
BS
363static void slavio_set_irq_all(void *opaque, int irq, int level)
364{
365 if (irq < 32) {
366 slavio_set_irq(opaque, irq, level);
367 } else {
368 slavio_set_timer_irq_cpu(opaque, irq - 32, level);
369 }
370}
371
e59fb374 372static int vmstate_intctl_post_load(void *opaque, int version_id)
e80cfcfc
FB
373{
374 SLAVIO_INTCTLState *s = opaque;
3b46e624 375
c9e95029
BS
376 slavio_check_interrupts(s, 0);
377 return 0;
e80cfcfc
FB
378}
379
c9e95029
BS
380static const VMStateDescription vmstate_intctl_cpu = {
381 .name ="slavio_intctl_cpu",
382 .version_id = 1,
383 .minimum_version_id = 1,
384 .minimum_version_id_old = 1,
385 .fields = (VMStateField []) {
386 VMSTATE_UINT32(intreg_pending, SLAVIO_CPUINTCTLState),
387 VMSTATE_END_OF_LIST()
388 }
389};
e80cfcfc 390
c9e95029
BS
391static const VMStateDescription vmstate_intctl = {
392 .name ="slavio_intctl",
393 .version_id = 1,
394 .minimum_version_id = 1,
395 .minimum_version_id_old = 1,
752ff2fa 396 .post_load = vmstate_intctl_post_load,
c9e95029
BS
397 .fields = (VMStateField []) {
398 VMSTATE_STRUCT_ARRAY(slaves, SLAVIO_INTCTLState, MAX_CPUS, 1,
399 vmstate_intctl_cpu, SLAVIO_CPUINTCTLState),
400 VMSTATE_UINT32(intregm_pending, SLAVIO_INTCTLState),
401 VMSTATE_UINT32(intregm_disabled, SLAVIO_INTCTLState),
402 VMSTATE_UINT32(target_cpu, SLAVIO_INTCTLState),
403 VMSTATE_END_OF_LIST()
e80cfcfc 404 }
c9e95029 405};
e80cfcfc 406
78971d57 407static void slavio_intctl_reset(DeviceState *d)
e80cfcfc 408{
78971d57 409 SLAVIO_INTCTLState *s = container_of(d, SLAVIO_INTCTLState, busdev.qdev);
e80cfcfc
FB
410 int i;
411
412 for (i = 0; i < MAX_CPUS; i++) {
a1961a4b 413 s->slaves[i].intreg_pending = 0;
462eda24 414 s->slaves[i].irl_out = 0;
e80cfcfc 415 }
9a87ce9b 416 s->intregm_disabled = ~MASTER_IRQ_MASK;
e80cfcfc
FB
417 s->intregm_pending = 0;
418 s->target_cpu = 0;
0d0a7e69 419 slavio_check_interrupts(s, 0);
e80cfcfc
FB
420}
421
81a322d4 422static int slavio_intctl_init1(SysBusDevice *dev)
e80cfcfc 423{
a1961a4b 424 SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
ee6847d1 425 int io_memory;
a1961a4b 426 unsigned int i, j;
e80cfcfc 427
a1961a4b
BS
428 qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
429 io_memory = cpu_register_io_memory(slavio_intctlm_mem_read,
2507c12a
AG
430 slavio_intctlm_mem_write, s,
431 DEVICE_NATIVE_ENDIAN);
a1961a4b 432 sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory);
e80cfcfc
FB
433
434 for (i = 0; i < MAX_CPUS; i++) {
a1961a4b
BS
435 for (j = 0; j < MAX_PILS; j++) {
436 sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
437 }
438 io_memory = cpu_register_io_memory(slavio_intctl_mem_read,
439 slavio_intctl_mem_write,
2507c12a
AG
440 &s->slaves[i],
441 DEVICE_NATIVE_ENDIAN);
a1961a4b
BS
442 sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
443 s->slaves[i].cpu = i;
444 s->slaves[i].master = s;
445 }
78971d57 446
81a322d4 447 return 0;
a1961a4b
BS
448}
449
a1961a4b
BS
450static SysBusDeviceInfo slavio_intctl_info = {
451 .init = slavio_intctl_init1,
452 .qdev.name = "slavio_intctl",
453 .qdev.size = sizeof(SLAVIO_INTCTLState),
78971d57
BS
454 .qdev.vmsd = &vmstate_intctl,
455 .qdev.reset = slavio_intctl_reset,
a1961a4b 456};
d7edfd27 457
a1961a4b
BS
458static void slavio_intctl_register_devices(void)
459{
460 sysbus_register_withprop(&slavio_intctl_info);
e80cfcfc 461}
a1961a4b
BS
462
463device_init(slavio_intctl_register_devices)