]> Git Repo - qemu.git/blame - hw/etraxfs_pic.c
Sparc32: convert slavio_misc to qdev
[qemu.git] / hw / 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
fd6dc90b 25#include "sysbus.h"
e62b5b13 26#include "hw.h"
1ad2134f
PB
27//#include "pc.h"
28//#include "etraxfs.h"
e62b5b13
EI
29
30#define D(x)
31
979d98ca
EI
32#define R_RW_MASK 0
33#define R_R_VECT 1
34#define R_R_MASKED_VECT 2
35#define R_R_NMI 3
36#define R_R_GURU 4
37#define R_MAX 5
8d13fcc0 38
fd6dc90b 39struct etrax_pic
e62b5b13 40{
fd6dc90b
EI
41 SysBusDevice busdev;
42 uint32_t *interrupt_vector;
43 qemu_irq parent_irq;
44 qemu_irq parent_nmi;
979d98ca 45 uint32_t regs[R_MAX];
e62b5b13
EI
46};
47
fd6dc90b 48static void pic_update(struct etrax_pic *fs)
979d98ca 49{
979d98ca
EI
50 uint32_t vector = 0;
51 int i;
52
53 fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
54
55 /* The ETRAX interrupt controller signals interrupts to teh core
56 through an interrupt request wire and an irq vector bus. If
57 multiple interrupts are simultaneously active it chooses vector
58 0x30 and lets the sw choose the priorities. */
59 if (fs->regs[R_R_MASKED_VECT]) {
60 uint32_t mv = fs->regs[R_R_MASKED_VECT];
61 for (i = 0; i < 31; i++) {
62 if (mv & 1) {
63 vector = 0x31 + i;
64 /* Check for multiple interrupts. */
65 if (mv > 1)
66 vector = 0x30;
67 break;
68 }
69 mv >>= 1;
70 }
979d98ca 71 }
fd6dc90b
EI
72
73 if (fs->interrupt_vector) {
74 *fs->interrupt_vector = vector;
75 }
76 qemu_set_irq(fs->parent_irq, !!vector);
e62b5b13
EI
77}
78
79static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
80{
fd6dc90b 81 struct etrax_pic *fs = opaque;
979d98ca 82 uint32_t rval;
e62b5b13 83
979d98ca
EI
84 rval = fs->regs[addr >> 2];
85 D(printf("%s %x=%x\n", __func__, addr, rval));
86 return rval;
e62b5b13
EI
87}
88
e62b5b13
EI
89static void
90pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
91{
fd6dc90b 92 struct etrax_pic *fs = opaque;
979d98ca 93 D(printf("%s addr=%x val=%x\n", __func__, addr, value));
8d13fcc0 94
979d98ca
EI
95 if (addr == R_RW_MASK) {
96 fs->regs[R_RW_MASK] = value;
97 pic_update(fs);
98 }
e62b5b13
EI
99}
100
101static CPUReadMemoryFunc *pic_read[] = {
979d98ca
EI
102 NULL, NULL,
103 &pic_readl,
e62b5b13
EI
104};
105
106static CPUWriteMemoryFunc *pic_write[] = {
979d98ca
EI
107 NULL, NULL,
108 &pic_writel,
e62b5b13
EI
109};
110
5ef98b47 111static void nmi_handler(void *opaque, int irq, int level)
979d98ca 112{
fd6dc90b 113 struct etrax_pic *fs = (void *)opaque;
979d98ca
EI
114 uint32_t mask;
115
116 mask = 1 << irq;
117 if (level)
118 fs->regs[R_R_NMI] |= mask;
119 else
120 fs->regs[R_R_NMI] &= ~mask;
121
fd6dc90b 122 qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
5ef98b47
EI
123}
124
73cfd29f 125static void irq_handler(void *opaque, int irq, int level)
979d98ca 126{
fd6dc90b 127 struct etrax_pic *fs = (void *)opaque;
73cfd29f 128
979d98ca
EI
129 if (irq >= 30)
130 return nmi_handler(opaque, irq, level);
73cfd29f 131
979d98ca
EI
132 irq -= 1;
133 fs->regs[R_R_VECT] &= ~(1 << irq);
134 fs->regs[R_R_VECT] |= (!!level << irq);
135 pic_update(fs);
5ef98b47
EI
136}
137
fd6dc90b 138static void etraxfs_pic_init(SysBusDevice *dev)
e62b5b13 139{
fd6dc90b 140 struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
979d98ca 141 int intr_vect_regs;
e62b5b13 142
fd6dc90b 143 s->interrupt_vector = qdev_get_prop_ptr(&dev->qdev, "interrupt_vector");
067a3ddc 144 qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
fd6dc90b
EI
145 sysbus_init_irq(dev, &s->parent_irq);
146 sysbus_init_irq(dev, &s->parent_nmi);
e62b5b13 147
1eed09cb 148 intr_vect_regs = cpu_register_io_memory(pic_read, pic_write, s);
fd6dc90b 149 sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
e62b5b13 150}
fd6dc90b
EI
151
152static void etraxfs_pic_register(void)
153{
154 sysbus_register_dev("etraxfs,pic", sizeof (struct etrax_pic),
155 etraxfs_pic_init);
156}
157
158device_init(etraxfs_pic_register)
This page took 0.214468 seconds and 4 git commands to generate.