Statistics
| Branch: | Revision:

root / hw / grlib_irqmp.c @ 11d6dded

History | View | Annotate | Download (9.3 kB)

1 3f10bcbb Fabien Chouteau
/*
2 3f10bcbb Fabien Chouteau
 * QEMU GRLIB IRQMP Emulator
3 3f10bcbb Fabien Chouteau
 *
4 3f10bcbb Fabien Chouteau
 * (Multiprocessor and extended interrupt not supported)
5 3f10bcbb Fabien Chouteau
 *
6 3f10bcbb Fabien Chouteau
 * Copyright (c) 2010-2011 AdaCore
7 3f10bcbb Fabien Chouteau
 *
8 3f10bcbb Fabien Chouteau
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 3f10bcbb Fabien Chouteau
 * of this software and associated documentation files (the "Software"), to deal
10 3f10bcbb Fabien Chouteau
 * in the Software without restriction, including without limitation the rights
11 3f10bcbb Fabien Chouteau
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 3f10bcbb Fabien Chouteau
 * copies of the Software, and to permit persons to whom the Software is
13 3f10bcbb Fabien Chouteau
 * furnished to do so, subject to the following conditions:
14 3f10bcbb Fabien Chouteau
 *
15 3f10bcbb Fabien Chouteau
 * The above copyright notice and this permission notice shall be included in
16 3f10bcbb Fabien Chouteau
 * all copies or substantial portions of the Software.
17 3f10bcbb Fabien Chouteau
 *
18 3f10bcbb Fabien Chouteau
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 3f10bcbb Fabien Chouteau
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 3f10bcbb Fabien Chouteau
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 3f10bcbb Fabien Chouteau
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 3f10bcbb Fabien Chouteau
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 3f10bcbb Fabien Chouteau
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 3f10bcbb Fabien Chouteau
 * THE SOFTWARE.
25 3f10bcbb Fabien Chouteau
 */
26 3f10bcbb Fabien Chouteau
27 3f10bcbb Fabien Chouteau
#include "sysbus.h"
28 3f10bcbb Fabien Chouteau
#include "cpu.h"
29 3f10bcbb Fabien Chouteau
30 3f10bcbb Fabien Chouteau
#include "grlib.h"
31 3f10bcbb Fabien Chouteau
32 3f10bcbb Fabien Chouteau
#include "trace.h"
33 3f10bcbb Fabien Chouteau
34 3f10bcbb Fabien Chouteau
#define IRQMP_MAX_CPU 16
35 3f10bcbb Fabien Chouteau
#define IRQMP_REG_SIZE 256      /* Size of memory mapped registers */
36 3f10bcbb Fabien Chouteau
37 3f10bcbb Fabien Chouteau
/* Memory mapped register offsets */
38 3f10bcbb Fabien Chouteau
#define LEVEL_OFFSET     0x00
39 3f10bcbb Fabien Chouteau
#define PENDING_OFFSET   0x04
40 3f10bcbb Fabien Chouteau
#define FORCE0_OFFSET    0x08
41 3f10bcbb Fabien Chouteau
#define CLEAR_OFFSET     0x0C
42 3f10bcbb Fabien Chouteau
#define MP_STATUS_OFFSET 0x10
43 3f10bcbb Fabien Chouteau
#define BROADCAST_OFFSET 0x14
44 3f10bcbb Fabien Chouteau
#define MASK_OFFSET      0x40
45 3f10bcbb Fabien Chouteau
#define FORCE_OFFSET     0x80
46 3f10bcbb Fabien Chouteau
#define EXTENDED_OFFSET  0xC0
47 3f10bcbb Fabien Chouteau
48 3f10bcbb Fabien Chouteau
typedef struct IRQMPState IRQMPState;
49 3f10bcbb Fabien Chouteau
50 3f10bcbb Fabien Chouteau
typedef struct IRQMP {
51 3f10bcbb Fabien Chouteau
    SysBusDevice busdev;
52 3f10bcbb Fabien Chouteau
53 3f10bcbb Fabien Chouteau
    void *set_pil_in;
54 3f10bcbb Fabien Chouteau
    void *set_pil_in_opaque;
55 3f10bcbb Fabien Chouteau
56 3f10bcbb Fabien Chouteau
    IRQMPState *state;
57 3f10bcbb Fabien Chouteau
} IRQMP;
58 3f10bcbb Fabien Chouteau
59 3f10bcbb Fabien Chouteau
struct IRQMPState {
60 3f10bcbb Fabien Chouteau
    uint32_t level;
61 3f10bcbb Fabien Chouteau
    uint32_t pending;
62 3f10bcbb Fabien Chouteau
    uint32_t clear;
63 3f10bcbb Fabien Chouteau
    uint32_t broadcast;
64 3f10bcbb Fabien Chouteau
65 3f10bcbb Fabien Chouteau
    uint32_t mask[IRQMP_MAX_CPU];
66 3f10bcbb Fabien Chouteau
    uint32_t force[IRQMP_MAX_CPU];
67 3f10bcbb Fabien Chouteau
    uint32_t extended[IRQMP_MAX_CPU];
68 3f10bcbb Fabien Chouteau
69 3f10bcbb Fabien Chouteau
    IRQMP    *parent;
70 3f10bcbb Fabien Chouteau
};
71 3f10bcbb Fabien Chouteau
72 3f10bcbb Fabien Chouteau
static void grlib_irqmp_check_irqs(IRQMPState *state)
73 3f10bcbb Fabien Chouteau
{
74 3f10bcbb Fabien Chouteau
    uint32_t      pend   = 0;
75 3f10bcbb Fabien Chouteau
    uint32_t      level0 = 0;
76 3f10bcbb Fabien Chouteau
    uint32_t      level1 = 0;
77 3f10bcbb Fabien Chouteau
    set_pil_in_fn set_pil_in;
78 3f10bcbb Fabien Chouteau
79 3f10bcbb Fabien Chouteau
    assert(state != NULL);
80 3f10bcbb Fabien Chouteau
    assert(state->parent != NULL);
81 3f10bcbb Fabien Chouteau
82 3f10bcbb Fabien Chouteau
    /* IRQ for CPU 0 (no SMP support) */
83 3f10bcbb Fabien Chouteau
    pend = (state->pending | state->force[0])
84 3f10bcbb Fabien Chouteau
        & state->mask[0];
85 3f10bcbb Fabien Chouteau
86 3f10bcbb Fabien Chouteau
    level0 = pend & ~state->level;
87 3f10bcbb Fabien Chouteau
    level1 = pend &  state->level;
88 3f10bcbb Fabien Chouteau
89 3f10bcbb Fabien Chouteau
    trace_grlib_irqmp_check_irqs(state->pending, state->force[0],
90 3f10bcbb Fabien Chouteau
                                 state->mask[0], level1, level0);
91 3f10bcbb Fabien Chouteau
92 3f10bcbb Fabien Chouteau
    set_pil_in = (set_pil_in_fn)state->parent->set_pil_in;
93 3f10bcbb Fabien Chouteau
94 3f10bcbb Fabien Chouteau
    /* Trigger level1 interrupt first and level0 if there is no level1 */
95 3f10bcbb Fabien Chouteau
    if (level1 != 0) {
96 3f10bcbb Fabien Chouteau
        set_pil_in(state->parent->set_pil_in_opaque, level1);
97 3f10bcbb Fabien Chouteau
    } else {
98 3f10bcbb Fabien Chouteau
        set_pil_in(state->parent->set_pil_in_opaque, level0);
99 3f10bcbb Fabien Chouteau
    }
100 3f10bcbb Fabien Chouteau
}
101 3f10bcbb Fabien Chouteau
102 3f10bcbb Fabien Chouteau
void grlib_irqmp_ack(DeviceState *dev, int intno)
103 3f10bcbb Fabien Chouteau
{
104 3f10bcbb Fabien Chouteau
    SysBusDevice *sdev;
105 3f10bcbb Fabien Chouteau
    IRQMP        *irqmp;
106 3f10bcbb Fabien Chouteau
    IRQMPState   *state;
107 3f10bcbb Fabien Chouteau
    uint32_t      mask;
108 3f10bcbb Fabien Chouteau
109 3f10bcbb Fabien Chouteau
    assert(dev != NULL);
110 3f10bcbb Fabien Chouteau
111 3f10bcbb Fabien Chouteau
    sdev = sysbus_from_qdev(dev);
112 3f10bcbb Fabien Chouteau
    assert(sdev != NULL);
113 3f10bcbb Fabien Chouteau
114 3f10bcbb Fabien Chouteau
    irqmp = FROM_SYSBUS(typeof(*irqmp), sdev);
115 3f10bcbb Fabien Chouteau
    assert(irqmp != NULL);
116 3f10bcbb Fabien Chouteau
117 3f10bcbb Fabien Chouteau
    state = irqmp->state;
118 3f10bcbb Fabien Chouteau
    assert(state != NULL);
119 3f10bcbb Fabien Chouteau
120 3f10bcbb Fabien Chouteau
    intno &= 15;
121 3f10bcbb Fabien Chouteau
    mask = 1 << intno;
122 3f10bcbb Fabien Chouteau
123 3f10bcbb Fabien Chouteau
    trace_grlib_irqmp_ack(intno);
124 3f10bcbb Fabien Chouteau
125 3f10bcbb Fabien Chouteau
    /* Clear registers */
126 3f10bcbb Fabien Chouteau
    state->pending  &= ~mask;
127 3f10bcbb Fabien Chouteau
    state->force[0] &= ~mask; /* Only CPU 0 (No SMP support) */
128 3f10bcbb Fabien Chouteau
129 3f10bcbb Fabien Chouteau
    grlib_irqmp_check_irqs(state);
130 3f10bcbb Fabien Chouteau
}
131 3f10bcbb Fabien Chouteau
132 3f10bcbb Fabien Chouteau
void grlib_irqmp_set_irq(void *opaque, int irq, int level)
133 3f10bcbb Fabien Chouteau
{
134 3f10bcbb Fabien Chouteau
    IRQMP      *irqmp;
135 3f10bcbb Fabien Chouteau
    IRQMPState *s;
136 3f10bcbb Fabien Chouteau
    int         i = 0;
137 3f10bcbb Fabien Chouteau
138 3f10bcbb Fabien Chouteau
    assert(opaque != NULL);
139 3f10bcbb Fabien Chouteau
140 3f10bcbb Fabien Chouteau
    irqmp = FROM_SYSBUS(typeof(*irqmp), sysbus_from_qdev(opaque));
141 3f10bcbb Fabien Chouteau
    assert(irqmp != NULL);
142 3f10bcbb Fabien Chouteau
143 3f10bcbb Fabien Chouteau
    s = irqmp->state;
144 3f10bcbb Fabien Chouteau
    assert(s         != NULL);
145 3f10bcbb Fabien Chouteau
    assert(s->parent != NULL);
146 3f10bcbb Fabien Chouteau
147 3f10bcbb Fabien Chouteau
148 3f10bcbb Fabien Chouteau
    if (level) {
149 3f10bcbb Fabien Chouteau
        trace_grlib_irqmp_set_irq(irq);
150 3f10bcbb Fabien Chouteau
151 3f10bcbb Fabien Chouteau
        if (s->broadcast & 1 << irq) {
152 3f10bcbb Fabien Chouteau
            /* Broadcasted IRQ */
153 3f10bcbb Fabien Chouteau
            for (i = 0; i < IRQMP_MAX_CPU; i++) {
154 3f10bcbb Fabien Chouteau
                s->force[i] |= 1 << irq;
155 3f10bcbb Fabien Chouteau
            }
156 3f10bcbb Fabien Chouteau
        } else {
157 3f10bcbb Fabien Chouteau
            s->pending |= 1 << irq;
158 3f10bcbb Fabien Chouteau
        }
159 3f10bcbb Fabien Chouteau
        grlib_irqmp_check_irqs(s);
160 3f10bcbb Fabien Chouteau
161 3f10bcbb Fabien Chouteau
    }
162 3f10bcbb Fabien Chouteau
}
163 3f10bcbb Fabien Chouteau
164 3f10bcbb Fabien Chouteau
static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
165 3f10bcbb Fabien Chouteau
{
166 3f10bcbb Fabien Chouteau
    IRQMP      *irqmp = opaque;
167 3f10bcbb Fabien Chouteau
    IRQMPState *state;
168 3f10bcbb Fabien Chouteau
169 3f10bcbb Fabien Chouteau
    assert(irqmp != NULL);
170 3f10bcbb Fabien Chouteau
    state = irqmp->state;
171 3f10bcbb Fabien Chouteau
    assert(state != NULL);
172 3f10bcbb Fabien Chouteau
173 3f10bcbb Fabien Chouteau
    addr &= 0xff;
174 3f10bcbb Fabien Chouteau
175 3f10bcbb Fabien Chouteau
    /* global registers */
176 3f10bcbb Fabien Chouteau
    switch (addr) {
177 3f10bcbb Fabien Chouteau
    case LEVEL_OFFSET:
178 3f10bcbb Fabien Chouteau
        return state->level;
179 3f10bcbb Fabien Chouteau
180 3f10bcbb Fabien Chouteau
    case PENDING_OFFSET:
181 3f10bcbb Fabien Chouteau
        return state->pending;
182 3f10bcbb Fabien Chouteau
183 3f10bcbb Fabien Chouteau
    case FORCE0_OFFSET:
184 3f10bcbb Fabien Chouteau
        /* This register is an "alias" for the force register of CPU 0 */
185 3f10bcbb Fabien Chouteau
        return state->force[0];
186 3f10bcbb Fabien Chouteau
187 3f10bcbb Fabien Chouteau
    case CLEAR_OFFSET:
188 3f10bcbb Fabien Chouteau
    case MP_STATUS_OFFSET:
189 3f10bcbb Fabien Chouteau
        /* Always read as 0 */
190 3f10bcbb Fabien Chouteau
        return 0;
191 3f10bcbb Fabien Chouteau
192 3f10bcbb Fabien Chouteau
    case BROADCAST_OFFSET:
193 3f10bcbb Fabien Chouteau
        return state->broadcast;
194 3f10bcbb Fabien Chouteau
195 3f10bcbb Fabien Chouteau
    default:
196 3f10bcbb Fabien Chouteau
        break;
197 3f10bcbb Fabien Chouteau
    }
198 3f10bcbb Fabien Chouteau
199 3f10bcbb Fabien Chouteau
    /* mask registers */
200 3f10bcbb Fabien Chouteau
    if (addr >= MASK_OFFSET && addr < FORCE_OFFSET) {
201 3f10bcbb Fabien Chouteau
        int cpu = (addr - MASK_OFFSET) / 4;
202 3f10bcbb Fabien Chouteau
        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
203 3f10bcbb Fabien Chouteau
204 3f10bcbb Fabien Chouteau
        return state->mask[cpu];
205 3f10bcbb Fabien Chouteau
    }
206 3f10bcbb Fabien Chouteau
207 3f10bcbb Fabien Chouteau
    /* force registers */
208 3f10bcbb Fabien Chouteau
    if (addr >= FORCE_OFFSET && addr < EXTENDED_OFFSET) {
209 3f10bcbb Fabien Chouteau
        int cpu = (addr - FORCE_OFFSET) / 4;
210 3f10bcbb Fabien Chouteau
        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
211 3f10bcbb Fabien Chouteau
212 3f10bcbb Fabien Chouteau
        return state->force[cpu];
213 3f10bcbb Fabien Chouteau
    }
214 3f10bcbb Fabien Chouteau
215 3f10bcbb Fabien Chouteau
    /* extended (not supported) */
216 3f10bcbb Fabien Chouteau
    if (addr >= EXTENDED_OFFSET && addr < IRQMP_REG_SIZE) {
217 3f10bcbb Fabien Chouteau
        int cpu = (addr - EXTENDED_OFFSET) / 4;
218 3f10bcbb Fabien Chouteau
        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
219 3f10bcbb Fabien Chouteau
220 3f10bcbb Fabien Chouteau
        return state->extended[cpu];
221 3f10bcbb Fabien Chouteau
    }
222 3f10bcbb Fabien Chouteau
223 b4548fcc Stefan Hajnoczi
    trace_grlib_irqmp_readl_unknown(addr);
224 3f10bcbb Fabien Chouteau
    return 0;
225 3f10bcbb Fabien Chouteau
}
226 3f10bcbb Fabien Chouteau
227 3f10bcbb Fabien Chouteau
static void
228 3f10bcbb Fabien Chouteau
grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
229 3f10bcbb Fabien Chouteau
{
230 3f10bcbb Fabien Chouteau
    IRQMP      *irqmp = opaque;
231 3f10bcbb Fabien Chouteau
    IRQMPState *state;
232 3f10bcbb Fabien Chouteau
233 3f10bcbb Fabien Chouteau
    assert(irqmp != NULL);
234 3f10bcbb Fabien Chouteau
    state = irqmp->state;
235 3f10bcbb Fabien Chouteau
    assert(state != NULL);
236 3f10bcbb Fabien Chouteau
237 3f10bcbb Fabien Chouteau
    addr &= 0xff;
238 3f10bcbb Fabien Chouteau
239 3f10bcbb Fabien Chouteau
    /* global registers */
240 3f10bcbb Fabien Chouteau
    switch (addr) {
241 3f10bcbb Fabien Chouteau
    case LEVEL_OFFSET:
242 3f10bcbb Fabien Chouteau
        value &= 0xFFFF << 1; /* clean up the value */
243 3f10bcbb Fabien Chouteau
        state->level = value;
244 3f10bcbb Fabien Chouteau
        return;
245 3f10bcbb Fabien Chouteau
246 3f10bcbb Fabien Chouteau
    case PENDING_OFFSET:
247 3f10bcbb Fabien Chouteau
        /* Read Only */
248 3f10bcbb Fabien Chouteau
        return;
249 3f10bcbb Fabien Chouteau
250 3f10bcbb Fabien Chouteau
    case FORCE0_OFFSET:
251 3f10bcbb Fabien Chouteau
        /* This register is an "alias" for the force register of CPU 0 */
252 3f10bcbb Fabien Chouteau
253 3f10bcbb Fabien Chouteau
        value &= 0xFFFE; /* clean up the value */
254 3f10bcbb Fabien Chouteau
        state->force[0] = value;
255 3f10bcbb Fabien Chouteau
        grlib_irqmp_check_irqs(irqmp->state);
256 3f10bcbb Fabien Chouteau
        return;
257 3f10bcbb Fabien Chouteau
258 3f10bcbb Fabien Chouteau
    case CLEAR_OFFSET:
259 3f10bcbb Fabien Chouteau
        value &= ~1; /* clean up the value */
260 3f10bcbb Fabien Chouteau
        state->pending &= ~value;
261 3f10bcbb Fabien Chouteau
        return;
262 3f10bcbb Fabien Chouteau
263 3f10bcbb Fabien Chouteau
    case MP_STATUS_OFFSET:
264 3f10bcbb Fabien Chouteau
        /* Read Only (no SMP support) */
265 3f10bcbb Fabien Chouteau
        return;
266 3f10bcbb Fabien Chouteau
267 3f10bcbb Fabien Chouteau
    case BROADCAST_OFFSET:
268 3f10bcbb Fabien Chouteau
        value &= 0xFFFE; /* clean up the value */
269 3f10bcbb Fabien Chouteau
        state->broadcast = value;
270 3f10bcbb Fabien Chouteau
        return;
271 3f10bcbb Fabien Chouteau
272 3f10bcbb Fabien Chouteau
    default:
273 3f10bcbb Fabien Chouteau
        break;
274 3f10bcbb Fabien Chouteau
    }
275 3f10bcbb Fabien Chouteau
276 3f10bcbb Fabien Chouteau
    /* mask registers */
277 3f10bcbb Fabien Chouteau
    if (addr >= MASK_OFFSET && addr < FORCE_OFFSET) {
278 3f10bcbb Fabien Chouteau
        int cpu = (addr - MASK_OFFSET) / 4;
279 3f10bcbb Fabien Chouteau
        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
280 3f10bcbb Fabien Chouteau
281 3f10bcbb Fabien Chouteau
        value &= ~1; /* clean up the value */
282 3f10bcbb Fabien Chouteau
        state->mask[cpu] = value;
283 3f10bcbb Fabien Chouteau
        grlib_irqmp_check_irqs(irqmp->state);
284 3f10bcbb Fabien Chouteau
        return;
285 3f10bcbb Fabien Chouteau
    }
286 3f10bcbb Fabien Chouteau
287 3f10bcbb Fabien Chouteau
    /* force registers */
288 3f10bcbb Fabien Chouteau
    if (addr >= FORCE_OFFSET && addr < EXTENDED_OFFSET) {
289 3f10bcbb Fabien Chouteau
        int cpu = (addr - FORCE_OFFSET) / 4;
290 3f10bcbb Fabien Chouteau
        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
291 3f10bcbb Fabien Chouteau
292 3f10bcbb Fabien Chouteau
        uint32_t force = value & 0xFFFE;
293 3f10bcbb Fabien Chouteau
        uint32_t clear = (value >> 16) & 0xFFFE;
294 3f10bcbb Fabien Chouteau
        uint32_t old   = state->force[cpu];
295 3f10bcbb Fabien Chouteau
296 3f10bcbb Fabien Chouteau
        state->force[cpu] = (old | force) & ~clear;
297 3f10bcbb Fabien Chouteau
        grlib_irqmp_check_irqs(irqmp->state);
298 3f10bcbb Fabien Chouteau
        return;
299 3f10bcbb Fabien Chouteau
    }
300 3f10bcbb Fabien Chouteau
301 3f10bcbb Fabien Chouteau
    /* extended (not supported) */
302 3f10bcbb Fabien Chouteau
    if (addr >= EXTENDED_OFFSET && addr < IRQMP_REG_SIZE) {
303 3f10bcbb Fabien Chouteau
        int cpu = (addr - EXTENDED_OFFSET) / 4;
304 3f10bcbb Fabien Chouteau
        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
305 3f10bcbb Fabien Chouteau
306 3f10bcbb Fabien Chouteau
        value &= 0xF; /* clean up the value */
307 3f10bcbb Fabien Chouteau
        state->extended[cpu] = value;
308 3f10bcbb Fabien Chouteau
        return;
309 3f10bcbb Fabien Chouteau
    }
310 3f10bcbb Fabien Chouteau
311 b4548fcc Stefan Hajnoczi
    trace_grlib_irqmp_writel_unknown(addr, value);
312 3f10bcbb Fabien Chouteau
}
313 3f10bcbb Fabien Chouteau
314 3f10bcbb Fabien Chouteau
static CPUReadMemoryFunc * const grlib_irqmp_read[] = {
315 3f10bcbb Fabien Chouteau
    NULL, NULL, &grlib_irqmp_readl,
316 3f10bcbb Fabien Chouteau
};
317 3f10bcbb Fabien Chouteau
318 3f10bcbb Fabien Chouteau
static CPUWriteMemoryFunc * const grlib_irqmp_write[] = {
319 3f10bcbb Fabien Chouteau
    NULL, NULL, &grlib_irqmp_writel,
320 3f10bcbb Fabien Chouteau
};
321 3f10bcbb Fabien Chouteau
322 3f10bcbb Fabien Chouteau
static void grlib_irqmp_reset(DeviceState *d)
323 3f10bcbb Fabien Chouteau
{
324 3f10bcbb Fabien Chouteau
    IRQMP *irqmp = container_of(d, IRQMP, busdev.qdev);
325 3f10bcbb Fabien Chouteau
    assert(irqmp        != NULL);
326 3f10bcbb Fabien Chouteau
    assert(irqmp->state != NULL);
327 3f10bcbb Fabien Chouteau
328 3f10bcbb Fabien Chouteau
    memset(irqmp->state, 0, sizeof *irqmp->state);
329 3f10bcbb Fabien Chouteau
    irqmp->state->parent = irqmp;
330 3f10bcbb Fabien Chouteau
}
331 3f10bcbb Fabien Chouteau
332 3f10bcbb Fabien Chouteau
static int grlib_irqmp_init(SysBusDevice *dev)
333 3f10bcbb Fabien Chouteau
{
334 3f10bcbb Fabien Chouteau
    IRQMP *irqmp = FROM_SYSBUS(typeof(*irqmp), dev);
335 3f10bcbb Fabien Chouteau
    int    irqmp_regs;
336 3f10bcbb Fabien Chouteau
337 3f10bcbb Fabien Chouteau
    assert(irqmp != NULL);
338 3f10bcbb Fabien Chouteau
339 3f10bcbb Fabien Chouteau
    /* Check parameters */
340 3f10bcbb Fabien Chouteau
    if (irqmp->set_pil_in == NULL) {
341 3f10bcbb Fabien Chouteau
        return -1;
342 3f10bcbb Fabien Chouteau
    }
343 3f10bcbb Fabien Chouteau
344 3f10bcbb Fabien Chouteau
    irqmp_regs = cpu_register_io_memory(grlib_irqmp_read,
345 3f10bcbb Fabien Chouteau
                                        grlib_irqmp_write,
346 3f10bcbb Fabien Chouteau
                                        irqmp, DEVICE_NATIVE_ENDIAN);
347 3f10bcbb Fabien Chouteau
348 7267c094 Anthony Liguori
    irqmp->state = g_malloc0(sizeof *irqmp->state);
349 3f10bcbb Fabien Chouteau
350 3f10bcbb Fabien Chouteau
    if (irqmp_regs < 0) {
351 3f10bcbb Fabien Chouteau
        return -1;
352 3f10bcbb Fabien Chouteau
    }
353 3f10bcbb Fabien Chouteau
354 3f10bcbb Fabien Chouteau
    sysbus_init_mmio(dev, IRQMP_REG_SIZE, irqmp_regs);
355 3f10bcbb Fabien Chouteau
356 3f10bcbb Fabien Chouteau
    return 0;
357 3f10bcbb Fabien Chouteau
}
358 3f10bcbb Fabien Chouteau
359 3f10bcbb Fabien Chouteau
static SysBusDeviceInfo grlib_irqmp_info = {
360 3f10bcbb Fabien Chouteau
    .init = grlib_irqmp_init,
361 3f10bcbb Fabien Chouteau
    .qdev.name  = "grlib,irqmp",
362 3f10bcbb Fabien Chouteau
    .qdev.reset = grlib_irqmp_reset,
363 3f10bcbb Fabien Chouteau
    .qdev.size  = sizeof(IRQMP),
364 3f10bcbb Fabien Chouteau
    .qdev.props = (Property[]) {
365 3f10bcbb Fabien Chouteau
        DEFINE_PROP_PTR("set_pil_in", IRQMP, set_pil_in),
366 3f10bcbb Fabien Chouteau
        DEFINE_PROP_PTR("set_pil_in_opaque", IRQMP, set_pil_in_opaque),
367 3f10bcbb Fabien Chouteau
        DEFINE_PROP_END_OF_LIST(),
368 3f10bcbb Fabien Chouteau
    }
369 3f10bcbb Fabien Chouteau
};
370 3f10bcbb Fabien Chouteau
371 3f10bcbb Fabien Chouteau
static void grlib_irqmp_register(void)
372 3f10bcbb Fabien Chouteau
{
373 3f10bcbb Fabien Chouteau
    sysbus_register_withprop(&grlib_irqmp_info);
374 3f10bcbb Fabien Chouteau
}
375 3f10bcbb Fabien Chouteau
376 3f10bcbb Fabien Chouteau
device_init(grlib_irqmp_register)