]> git.proxmox.com Git - qemu.git/blame - hw/etraxfs_pic.c
tcg-sparc: Use TCG_TARGET_REG_BITS in conditional compilation.
[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 41 SysBusDevice busdev;
ddde095c 42 void *interrupt_vector;
fd6dc90b
EI
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) {
ddde095c
GH
74 /* hack alert: ptr property */
75 *(uint32_t*)(fs->interrupt_vector) = vector;
fd6dc90b
EI
76 }
77 qemu_set_irq(fs->parent_irq, !!vector);
e62b5b13
EI
78}
79
c227f099 80static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
e62b5b13 81{
fd6dc90b 82 struct etrax_pic *fs = opaque;
979d98ca 83 uint32_t rval;
e62b5b13 84
979d98ca
EI
85 rval = fs->regs[addr >> 2];
86 D(printf("%s %x=%x\n", __func__, addr, rval));
87 return rval;
e62b5b13
EI
88}
89
e62b5b13 90static void
c227f099 91pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
e62b5b13 92{
fd6dc90b 93 struct etrax_pic *fs = opaque;
979d98ca 94 D(printf("%s addr=%x val=%x\n", __func__, addr, value));
8d13fcc0 95
979d98ca
EI
96 if (addr == R_RW_MASK) {
97 fs->regs[R_RW_MASK] = value;
98 pic_update(fs);
99 }
e62b5b13
EI
100}
101
d60efc6b 102static CPUReadMemoryFunc * const pic_read[] = {
979d98ca
EI
103 NULL, NULL,
104 &pic_readl,
e62b5b13
EI
105};
106
d60efc6b 107static CPUWriteMemoryFunc * const pic_write[] = {
979d98ca
EI
108 NULL, NULL,
109 &pic_writel,
e62b5b13
EI
110};
111
5ef98b47 112static void nmi_handler(void *opaque, int irq, int level)
979d98ca 113{
fd6dc90b 114 struct etrax_pic *fs = (void *)opaque;
979d98ca
EI
115 uint32_t mask;
116
117 mask = 1 << irq;
118 if (level)
119 fs->regs[R_R_NMI] |= mask;
120 else
121 fs->regs[R_R_NMI] &= ~mask;
122
fd6dc90b 123 qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
5ef98b47
EI
124}
125
73cfd29f 126static void irq_handler(void *opaque, int irq, int level)
979d98ca 127{
fd6dc90b 128 struct etrax_pic *fs = (void *)opaque;
73cfd29f 129
979d98ca
EI
130 if (irq >= 30)
131 return nmi_handler(opaque, irq, level);
73cfd29f 132
979d98ca
EI
133 irq -= 1;
134 fs->regs[R_R_VECT] &= ~(1 << irq);
135 fs->regs[R_R_VECT] |= (!!level << irq);
136 pic_update(fs);
5ef98b47
EI
137}
138
81a322d4 139static int etraxfs_pic_init(SysBusDevice *dev)
e62b5b13 140{
fd6dc90b 141 struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
979d98ca 142 int intr_vect_regs;
e62b5b13 143
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);
81a322d4 150 return 0;
e62b5b13 151}
fd6dc90b 152
ee6847d1
GH
153static SysBusDeviceInfo etraxfs_pic_info = {
154 .init = etraxfs_pic_init,
155 .qdev.name = "etraxfs,pic",
156 .qdev.size = sizeof(struct etrax_pic),
157 .qdev.props = (Property[]) {
ddde095c
GH
158 DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector),
159 DEFINE_PROP_END_OF_LIST(),
ee6847d1
GH
160 }
161};
162
fd6dc90b
EI
163static void etraxfs_pic_register(void)
164{
ee6847d1 165 sysbus_register_withprop(&etraxfs_pic_info);
fd6dc90b
EI
166}
167
168device_init(etraxfs_pic_register)