Statistics
| Branch: | Revision:

root / hw / openpic.c @ f8f48b69

History | View | Annotate | Download (36.2 kB)

1 dbda808a bellard
/*
2 dbda808a bellard
 * OpenPIC emulation
3 5fafdf24 ths
 *
4 dbda808a bellard
 * Copyright (c) 2004 Jocelyn Mayer
5 704c7e5d Alexander Graf
 *               2011 Alexander Graf
6 5fafdf24 ths
 *
7 dbda808a bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 dbda808a bellard
 * of this software and associated documentation files (the "Software"), to deal
9 dbda808a bellard
 * in the Software without restriction, including without limitation the rights
10 dbda808a bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 dbda808a bellard
 * copies of the Software, and to permit persons to whom the Software is
12 dbda808a bellard
 * furnished to do so, subject to the following conditions:
13 dbda808a bellard
 *
14 dbda808a bellard
 * The above copyright notice and this permission notice shall be included in
15 dbda808a bellard
 * all copies or substantial portions of the Software.
16 dbda808a bellard
 *
17 dbda808a bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 dbda808a bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 dbda808a bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 dbda808a bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 dbda808a bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 dbda808a bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 dbda808a bellard
 * THE SOFTWARE.
24 dbda808a bellard
 */
25 dbda808a bellard
/*
26 dbda808a bellard
 *
27 dbda808a bellard
 * Based on OpenPic implementations:
28 67b55785 blueswir1
 * - Intel GW80314 I/O companion chip developer's manual
29 dbda808a bellard
 * - Motorola MPC8245 & MPC8540 user manuals.
30 dbda808a bellard
 * - Motorola MCP750 (aka Raven) programmer manual.
31 dbda808a bellard
 * - Motorola Harrier programmer manuel
32 dbda808a bellard
 *
33 dbda808a bellard
 * Serial interrupts, as implemented in Raven chipset are not supported yet.
34 5fafdf24 ths
 *
35 dbda808a bellard
 */
36 87ecb68b pbrook
#include "hw.h"
37 87ecb68b pbrook
#include "ppc_mac.h"
38 a2cb15b0 Michael S. Tsirkin
#include "pci/pci.h"
39 b7169916 aurel32
#include "openpic.h"
40 d0b72631 Alexander Graf
#include "sysbus.h"
41 6f991980 Paolo Bonzini
#include "pci/msi.h"
42 dbda808a bellard
43 611493d9 bellard
//#define DEBUG_OPENPIC
44 dbda808a bellard
45 dbda808a bellard
#ifdef DEBUG_OPENPIC
46 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
47 dbda808a bellard
#else
48 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) do { } while (0)
49 dbda808a bellard
#endif
50 dbda808a bellard
51 cdbb912a Alexander Graf
#define MAX_CPU     15
52 cdbb912a Alexander Graf
#define MAX_SRC     256
53 dbda808a bellard
#define MAX_TMR     4
54 dbda808a bellard
#define VECTOR_BITS 8
55 dbda808a bellard
#define MAX_IPI     4
56 732aa6ec Alexander Graf
#define MAX_MSI     8
57 cdbb912a Alexander Graf
#define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
58 dbda808a bellard
#define VID         0x03 /* MPIC version ID */
59 dbda808a bellard
60 d0b72631 Alexander Graf
/* OpenPIC capability flags */
61 d0b72631 Alexander Graf
#define OPENPIC_FLAG_IDE_CRIT     (1 << 0)
62 dbda808a bellard
63 d0b72631 Alexander Graf
/* OpenPIC address map */
64 780d16b7 Alexander Graf
#define OPENPIC_GLB_REG_START        0x0
65 780d16b7 Alexander Graf
#define OPENPIC_GLB_REG_SIZE         0x10F0
66 780d16b7 Alexander Graf
#define OPENPIC_TMR_REG_START        0x10F0
67 780d16b7 Alexander Graf
#define OPENPIC_TMR_REG_SIZE         0x220
68 732aa6ec Alexander Graf
#define OPENPIC_MSI_REG_START        0x1600
69 732aa6ec Alexander Graf
#define OPENPIC_MSI_REG_SIZE         0x200
70 780d16b7 Alexander Graf
#define OPENPIC_SRC_REG_START        0x10000
71 780d16b7 Alexander Graf
#define OPENPIC_SRC_REG_SIZE         (MAX_SRC * 0x20)
72 780d16b7 Alexander Graf
#define OPENPIC_CPU_REG_START        0x20000
73 780d16b7 Alexander Graf
#define OPENPIC_CPU_REG_SIZE         0x100 + ((MAX_CPU - 1) * 0x1000)
74 780d16b7 Alexander Graf
75 d0b72631 Alexander Graf
/* Raven */
76 d0b72631 Alexander Graf
#define RAVEN_MAX_CPU      2
77 d0b72631 Alexander Graf
#define RAVEN_MAX_EXT     48
78 d0b72631 Alexander Graf
#define RAVEN_MAX_IRQ     64
79 d0b72631 Alexander Graf
#define RAVEN_MAX_TMR      MAX_TMR
80 d0b72631 Alexander Graf
#define RAVEN_MAX_IPI      MAX_IPI
81 d0b72631 Alexander Graf
82 d0b72631 Alexander Graf
/* Interrupt definitions */
83 d0b72631 Alexander Graf
#define RAVEN_FE_IRQ     (RAVEN_MAX_EXT)     /* Internal functional IRQ */
84 d0b72631 Alexander Graf
#define RAVEN_ERR_IRQ    (RAVEN_MAX_EXT + 1) /* Error IRQ */
85 d0b72631 Alexander Graf
#define RAVEN_TMR_IRQ    (RAVEN_MAX_EXT + 2) /* First timer IRQ */
86 d0b72631 Alexander Graf
#define RAVEN_IPI_IRQ    (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */
87 d0b72631 Alexander Graf
/* First doorbell IRQ */
88 d0b72631 Alexander Graf
#define RAVEN_DBL_IRQ    (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI))
89 d0b72631 Alexander Graf
90 d0b72631 Alexander Graf
/* FSL_MPIC_20 */
91 d0b72631 Alexander Graf
#define FSL_MPIC_20_MAX_CPU      1
92 d0b72631 Alexander Graf
#define FSL_MPIC_20_MAX_EXT     12
93 d0b72631 Alexander Graf
#define FSL_MPIC_20_MAX_INT     64
94 d0b72631 Alexander Graf
#define FSL_MPIC_20_MAX_IRQ     MAX_IRQ
95 dbda808a bellard
96 dbda808a bellard
/* Interrupt definitions */
97 cdbb912a Alexander Graf
/* IRQs, accessible through the IRQ region */
98 d0b72631 Alexander Graf
#define FSL_MPIC_20_EXT_IRQ      0x00
99 d0b72631 Alexander Graf
#define FSL_MPIC_20_INT_IRQ      0x10
100 d0b72631 Alexander Graf
#define FSL_MPIC_20_MSG_IRQ      0xb0
101 d0b72631 Alexander Graf
#define FSL_MPIC_20_MSI_IRQ      0xe0
102 cdbb912a Alexander Graf
/* These are available through separate regions, but
103 cdbb912a Alexander Graf
   for simplicity's sake mapped into the same number space */
104 d0b72631 Alexander Graf
#define FSL_MPIC_20_TMR_IRQ      0x100
105 d0b72631 Alexander Graf
#define FSL_MPIC_20_IPI_IRQ      0x104
106 b7169916 aurel32
107 3e772232 Bharat Bhushan
/*
108 3e772232 Bharat Bhushan
 * Block Revision Register1 (BRR1): QEMU does not fully emulate
109 3e772232 Bharat Bhushan
 * any version on MPIC. So to start with, set the IP version to 0.
110 3e772232 Bharat Bhushan
 *
111 3e772232 Bharat Bhushan
 * NOTE: This is Freescale MPIC specific register. Keep it here till
112 3e772232 Bharat Bhushan
 * this code is refactored for different variants of OPENPIC and MPIC.
113 3e772232 Bharat Bhushan
 */
114 3e772232 Bharat Bhushan
#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
115 3e772232 Bharat Bhushan
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
116 3e772232 Bharat Bhushan
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
117 3e772232 Bharat Bhushan
118 825463b3 Alexander Graf
#define FREP_NIRQ_SHIFT   16
119 825463b3 Alexander Graf
#define FREP_NCPU_SHIFT    8
120 825463b3 Alexander Graf
#define FREP_VID_SHIFT     0
121 825463b3 Alexander Graf
122 825463b3 Alexander Graf
#define VID_REVISION_1_2   2
123 d0b72631 Alexander Graf
#define VID_REVISION_1_3   3
124 825463b3 Alexander Graf
125 825463b3 Alexander Graf
#define VENI_GENERIC      0x00000000 /* Generic Vendor ID */
126 825463b3 Alexander Graf
127 1945dbc1 Alexander Graf
#define IDR_EP_SHIFT      31
128 1945dbc1 Alexander Graf
#define IDR_EP_MASK       (1 << IDR_EP_SHIFT)
129 1945dbc1 Alexander Graf
#define IDR_CI0_SHIFT     30
130 1945dbc1 Alexander Graf
#define IDR_CI1_SHIFT     29
131 1945dbc1 Alexander Graf
#define IDR_P1_SHIFT      1
132 1945dbc1 Alexander Graf
#define IDR_P0_SHIFT      0
133 b7169916 aurel32
134 732aa6ec Alexander Graf
#define MSIIR_OFFSET       0x140
135 732aa6ec Alexander Graf
#define MSIIR_SRS_SHIFT    29
136 732aa6ec Alexander Graf
#define MSIIR_SRS_MASK     (0x7 << MSIIR_SRS_SHIFT)
137 732aa6ec Alexander Graf
#define MSIIR_IBS_SHIFT    24
138 732aa6ec Alexander Graf
#define MSIIR_IBS_MASK     (0x1f << MSIIR_IBS_SHIFT)
139 732aa6ec Alexander Graf
140 dbda808a bellard
#define BF_WIDTH(_bits_) \
141 dbda808a bellard
(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
142 dbda808a bellard
143 dbe30e13 Alexander Graf
static inline void set_bit(uint32_t *field, int bit)
144 dbda808a bellard
{
145 dbda808a bellard
    field[bit >> 5] |= 1 << (bit & 0x1F);
146 dbda808a bellard
}
147 dbda808a bellard
148 dbe30e13 Alexander Graf
static inline void reset_bit(uint32_t *field, int bit)
149 dbda808a bellard
{
150 dbda808a bellard
    field[bit >> 5] &= ~(1 << (bit & 0x1F));
151 dbda808a bellard
}
152 dbda808a bellard
153 dbe30e13 Alexander Graf
static inline int test_bit(uint32_t *field, int bit)
154 dbda808a bellard
{
155 dbda808a bellard
    return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
156 dbda808a bellard
}
157 dbda808a bellard
158 704c7e5d Alexander Graf
static int get_current_cpu(void)
159 704c7e5d Alexander Graf
{
160 704c7e5d Alexander Graf
  return cpu_single_env->cpu_index;
161 704c7e5d Alexander Graf
}
162 704c7e5d Alexander Graf
163 a8170e5e Avi Kivity
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
164 704c7e5d Alexander Graf
                                          int idx);
165 a8170e5e Avi Kivity
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
166 704c7e5d Alexander Graf
                                       uint32_t val, int idx);
167 704c7e5d Alexander Graf
168 c227f099 Anthony Liguori
typedef struct IRQ_queue_t {
169 dbda808a bellard
    uint32_t queue[BF_WIDTH(MAX_IRQ)];
170 dbda808a bellard
    int next;
171 dbda808a bellard
    int priority;
172 76aec1f8 Alexander Graf
    int pending;    /* nr of pending bits in queue */
173 c227f099 Anthony Liguori
} IRQ_queue_t;
174 dbda808a bellard
175 c227f099 Anthony Liguori
typedef struct IRQ_src_t {
176 dbda808a bellard
    uint32_t ipvp;  /* IRQ vector/priority register */
177 dbda808a bellard
    uint32_t ide;   /* IRQ destination register */
178 dbda808a bellard
    int last_cpu;
179 611493d9 bellard
    int pending;    /* TRUE if IRQ is pending */
180 c227f099 Anthony Liguori
} IRQ_src_t;
181 dbda808a bellard
182 1945dbc1 Alexander Graf
#define IPVP_MASK_SHIFT       31
183 1945dbc1 Alexander Graf
#define IPVP_MASK_MASK        (1 << IPVP_MASK_SHIFT)
184 1945dbc1 Alexander Graf
#define IPVP_ACTIVITY_SHIFT   30
185 1945dbc1 Alexander Graf
#define IPVP_ACTIVITY_MASK    (1 << IPVP_ACTIVITY_SHIFT)
186 1945dbc1 Alexander Graf
#define IPVP_MODE_SHIFT       29
187 1945dbc1 Alexander Graf
#define IPVP_MODE_MASK        (1 << IPVP_MODE_SHIFT)
188 1945dbc1 Alexander Graf
#define IPVP_POLARITY_SHIFT   23
189 1945dbc1 Alexander Graf
#define IPVP_POLARITY_MASK    (1 << IPVP_POLARITY_SHIFT)
190 1945dbc1 Alexander Graf
#define IPVP_SENSE_SHIFT      22
191 1945dbc1 Alexander Graf
#define IPVP_SENSE_MASK       (1 << IPVP_SENSE_SHIFT)
192 1945dbc1 Alexander Graf
193 dbda808a bellard
#define IPVP_PRIORITY_MASK     (0x1F << 16)
194 611493d9 bellard
#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
195 dbda808a bellard
#define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
196 dbda808a bellard
#define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
197 dbda808a bellard
198 c227f099 Anthony Liguori
typedef struct IRQ_dst_t {
199 dbda808a bellard
    uint32_t pctp; /* CPU current task priority */
200 dbda808a bellard
    uint32_t pcsr; /* CPU sensitivity register */
201 c227f099 Anthony Liguori
    IRQ_queue_t raised;
202 c227f099 Anthony Liguori
    IRQ_queue_t servicing;
203 e9df014c j_mayer
    qemu_irq *irqs;
204 c227f099 Anthony Liguori
} IRQ_dst_t;
205 dbda808a bellard
206 6d544ee8 Alexander Graf
typedef struct OpenPICState {
207 d0b72631 Alexander Graf
    SysBusDevice busdev;
208 23c5e4ca Avi Kivity
    MemoryRegion mem;
209 71cf9e62 Fabien Chouteau
210 5861a338 Alexander Graf
    /* Behavior control */
211 d0b72631 Alexander Graf
    uint32_t model;
212 5861a338 Alexander Graf
    uint32_t flags;
213 825463b3 Alexander Graf
    uint32_t nb_irqs;
214 825463b3 Alexander Graf
    uint32_t vid;
215 825463b3 Alexander Graf
    uint32_t veni; /* Vendor identification register */
216 825463b3 Alexander Graf
    uint32_t spve_mask;
217 825463b3 Alexander Graf
    uint32_t tifr_reset;
218 825463b3 Alexander Graf
    uint32_t ipvp_reset;
219 825463b3 Alexander Graf
    uint32_t ide_reset;
220 dbbbfd60 Alexander Graf
    uint32_t brr1;
221 5861a338 Alexander Graf
222 71cf9e62 Fabien Chouteau
    /* Sub-regions */
223 732aa6ec Alexander Graf
    MemoryRegion sub_io_mem[5];
224 71cf9e62 Fabien Chouteau
225 dbda808a bellard
    /* Global registers */
226 dbda808a bellard
    uint32_t frep; /* Feature reporting register */
227 dbda808a bellard
    uint32_t glbc; /* Global configuration register  */
228 e9df014c j_mayer
    uint32_t pint; /* Processor initialization register */
229 dbda808a bellard
    uint32_t spve; /* Spurious vector register */
230 dbda808a bellard
    uint32_t tifr; /* Timer frequency reporting register */
231 dbda808a bellard
    /* Source registers */
232 c227f099 Anthony Liguori
    IRQ_src_t src[MAX_IRQ];
233 dbda808a bellard
    /* Local registers per output pin */
234 c227f099 Anthony Liguori
    IRQ_dst_t dst[MAX_CPU];
235 d0b72631 Alexander Graf
    uint32_t nb_cpus;
236 dbda808a bellard
    /* Timer registers */
237 dbda808a bellard
    struct {
238 060fbfe1 Aurelien Jarno
        uint32_t ticc;  /* Global timer current count register */
239 060fbfe1 Aurelien Jarno
        uint32_t tibc;  /* Global timer base count register */
240 dbda808a bellard
    } timers[MAX_TMR];
241 732aa6ec Alexander Graf
    /* Shared MSI registers */
242 732aa6ec Alexander Graf
    struct {
243 732aa6ec Alexander Graf
        uint32_t msir;   /* Shared Message Signaled Interrupt Register */
244 732aa6ec Alexander Graf
    } msi[MAX_MSI];
245 d0b72631 Alexander Graf
    uint32_t max_irq;
246 d0b72631 Alexander Graf
    uint32_t irq_ipi0;
247 d0b72631 Alexander Graf
    uint32_t irq_tim0;
248 732aa6ec Alexander Graf
    uint32_t irq_msi;
249 6d544ee8 Alexander Graf
} OpenPICState;
250 dbda808a bellard
251 6d544ee8 Alexander Graf
static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src);
252 5861a338 Alexander Graf
253 dbe30e13 Alexander Graf
static inline void IRQ_setbit(IRQ_queue_t *q, int n_IRQ)
254 dbda808a bellard
{
255 76aec1f8 Alexander Graf
    q->pending++;
256 dbda808a bellard
    set_bit(q->queue, n_IRQ);
257 dbda808a bellard
}
258 dbda808a bellard
259 dbe30e13 Alexander Graf
static inline void IRQ_resetbit(IRQ_queue_t *q, int n_IRQ)
260 dbda808a bellard
{
261 76aec1f8 Alexander Graf
    q->pending--;
262 dbda808a bellard
    reset_bit(q->queue, n_IRQ);
263 dbda808a bellard
}
264 dbda808a bellard
265 dbe30e13 Alexander Graf
static inline int IRQ_testbit(IRQ_queue_t *q, int n_IRQ)
266 dbda808a bellard
{
267 dbda808a bellard
    return test_bit(q->queue, n_IRQ);
268 dbda808a bellard
}
269 dbda808a bellard
270 6d544ee8 Alexander Graf
static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q)
271 dbda808a bellard
{
272 dbda808a bellard
    int next, i;
273 dbda808a bellard
    int priority;
274 dbda808a bellard
275 dbda808a bellard
    next = -1;
276 dbda808a bellard
    priority = -1;
277 76aec1f8 Alexander Graf
278 76aec1f8 Alexander Graf
    if (!q->pending) {
279 76aec1f8 Alexander Graf
        /* IRQ bitmap is empty */
280 76aec1f8 Alexander Graf
        goto out;
281 76aec1f8 Alexander Graf
    }
282 76aec1f8 Alexander Graf
283 b7169916 aurel32
    for (i = 0; i < opp->max_irq; i++) {
284 060fbfe1 Aurelien Jarno
        if (IRQ_testbit(q, i)) {
285 5fafdf24 ths
            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
286 611493d9 bellard
                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
287 060fbfe1 Aurelien Jarno
            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
288 060fbfe1 Aurelien Jarno
                next = i;
289 060fbfe1 Aurelien Jarno
                priority = IPVP_PRIORITY(opp->src[i].ipvp);
290 060fbfe1 Aurelien Jarno
            }
291 060fbfe1 Aurelien Jarno
        }
292 dbda808a bellard
    }
293 76aec1f8 Alexander Graf
294 76aec1f8 Alexander Graf
out:
295 dbda808a bellard
    q->next = next;
296 dbda808a bellard
    q->priority = priority;
297 dbda808a bellard
}
298 dbda808a bellard
299 6d544ee8 Alexander Graf
static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
300 dbda808a bellard
{
301 dbda808a bellard
    if (q->next == -1) {
302 611493d9 bellard
        /* XXX: optimize */
303 060fbfe1 Aurelien Jarno
        IRQ_check(opp, q);
304 dbda808a bellard
    }
305 dbda808a bellard
306 dbda808a bellard
    return q->next;
307 dbda808a bellard
}
308 dbda808a bellard
309 6d544ee8 Alexander Graf
static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
310 dbda808a bellard
{
311 c227f099 Anthony Liguori
    IRQ_dst_t *dst;
312 c227f099 Anthony Liguori
    IRQ_src_t *src;
313 dbda808a bellard
    int priority;
314 dbda808a bellard
315 dbda808a bellard
    dst = &opp->dst[n_CPU];
316 dbda808a bellard
    src = &opp->src[n_IRQ];
317 dbda808a bellard
    priority = IPVP_PRIORITY(src->ipvp);
318 dbda808a bellard
    if (priority <= dst->pctp) {
319 060fbfe1 Aurelien Jarno
        /* Too low priority */
320 e9df014c j_mayer
        DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
321 e9df014c j_mayer
                __func__, n_IRQ, n_CPU);
322 060fbfe1 Aurelien Jarno
        return;
323 dbda808a bellard
    }
324 dbda808a bellard
    if (IRQ_testbit(&dst->raised, n_IRQ)) {
325 060fbfe1 Aurelien Jarno
        /* Interrupt miss */
326 e9df014c j_mayer
        DPRINTF("%s: IRQ %d was missed on CPU %d\n",
327 e9df014c j_mayer
                __func__, n_IRQ, n_CPU);
328 060fbfe1 Aurelien Jarno
        return;
329 dbda808a bellard
    }
330 1945dbc1 Alexander Graf
    src->ipvp |= IPVP_ACTIVITY_MASK;
331 dbda808a bellard
    IRQ_setbit(&dst->raised, n_IRQ);
332 e9df014c j_mayer
    if (priority < dst->raised.priority) {
333 e9df014c j_mayer
        /* An higher priority IRQ is already raised */
334 e9df014c j_mayer
        DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
335 e9df014c j_mayer
                __func__, n_IRQ, dst->raised.next, n_CPU);
336 e9df014c j_mayer
        return;
337 e9df014c j_mayer
    }
338 e9df014c j_mayer
    IRQ_get_next(opp, &dst->raised);
339 e9df014c j_mayer
    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
340 24865167 aliguori
        priority <= dst->servicing.priority) {
341 e9df014c j_mayer
        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
342 e9df014c j_mayer
                __func__, n_IRQ, dst->servicing.next, n_CPU);
343 e9df014c j_mayer
        /* Already servicing a higher priority IRQ */
344 e9df014c j_mayer
        return;
345 dbda808a bellard
    }
346 e9df014c j_mayer
    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
347 5861a338 Alexander Graf
    openpic_irq_raise(opp, n_CPU, src);
348 dbda808a bellard
}
349 dbda808a bellard
350 611493d9 bellard
/* update pic state because registers for n_IRQ have changed value */
351 6d544ee8 Alexander Graf
static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
352 dbda808a bellard
{
353 c227f099 Anthony Liguori
    IRQ_src_t *src;
354 dbda808a bellard
    int i;
355 dbda808a bellard
356 dbda808a bellard
    src = &opp->src[n_IRQ];
357 611493d9 bellard
358 611493d9 bellard
    if (!src->pending) {
359 611493d9 bellard
        /* no irq pending */
360 e9df014c j_mayer
        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
361 611493d9 bellard
        return;
362 611493d9 bellard
    }
363 1945dbc1 Alexander Graf
    if (src->ipvp & IPVP_MASK_MASK) {
364 060fbfe1 Aurelien Jarno
        /* Interrupt source is disabled */
365 e9df014c j_mayer
        DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
366 060fbfe1 Aurelien Jarno
        return;
367 dbda808a bellard
    }
368 dbda808a bellard
    if (IPVP_PRIORITY(src->ipvp) == 0) {
369 060fbfe1 Aurelien Jarno
        /* Priority set to zero */
370 e9df014c j_mayer
        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
371 060fbfe1 Aurelien Jarno
        return;
372 dbda808a bellard
    }
373 1945dbc1 Alexander Graf
    if (src->ipvp & IPVP_ACTIVITY_MASK) {
374 611493d9 bellard
        /* IRQ already active */
375 e9df014c j_mayer
        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
376 611493d9 bellard
        return;
377 611493d9 bellard
    }
378 dbda808a bellard
    if (src->ide == 0x00000000) {
379 060fbfe1 Aurelien Jarno
        /* No target */
380 e9df014c j_mayer
        DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
381 060fbfe1 Aurelien Jarno
        return;
382 dbda808a bellard
    }
383 611493d9 bellard
384 e9df014c j_mayer
    if (src->ide == (1 << src->last_cpu)) {
385 e9df014c j_mayer
        /* Only one CPU is allowed to receive this IRQ */
386 e9df014c j_mayer
        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
387 1945dbc1 Alexander Graf
    } else if (!(src->ipvp & IPVP_MODE_MASK)) {
388 611493d9 bellard
        /* Directed delivery mode */
389 611493d9 bellard
        for (i = 0; i < opp->nb_cpus; i++) {
390 1945dbc1 Alexander Graf
            if (src->ide & (1 << i)) {
391 611493d9 bellard
                IRQ_local_pipe(opp, i, n_IRQ);
392 1945dbc1 Alexander Graf
            }
393 611493d9 bellard
        }
394 dbda808a bellard
    } else {
395 611493d9 bellard
        /* Distributed delivery mode */
396 e9df014c j_mayer
        for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
397 e9df014c j_mayer
            if (i == opp->nb_cpus)
398 611493d9 bellard
                i = 0;
399 1945dbc1 Alexander Graf
            if (src->ide & (1 << i)) {
400 611493d9 bellard
                IRQ_local_pipe(opp, i, n_IRQ);
401 611493d9 bellard
                src->last_cpu = i;
402 611493d9 bellard
                break;
403 611493d9 bellard
            }
404 611493d9 bellard
        }
405 611493d9 bellard
    }
406 611493d9 bellard
}
407 611493d9 bellard
408 d537cf6c pbrook
static void openpic_set_irq(void *opaque, int n_IRQ, int level)
409 611493d9 bellard
{
410 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
411 c227f099 Anthony Liguori
    IRQ_src_t *src;
412 611493d9 bellard
413 611493d9 bellard
    src = &opp->src[n_IRQ];
414 5fafdf24 ths
    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
415 611493d9 bellard
            n_IRQ, level, src->ipvp);
416 1945dbc1 Alexander Graf
    if (src->ipvp & IPVP_SENSE_MASK) {
417 611493d9 bellard
        /* level-sensitive irq */
418 611493d9 bellard
        src->pending = level;
419 1945dbc1 Alexander Graf
        if (!level) {
420 1945dbc1 Alexander Graf
            src->ipvp &= ~IPVP_ACTIVITY_MASK;
421 1945dbc1 Alexander Graf
        }
422 611493d9 bellard
    } else {
423 611493d9 bellard
        /* edge-sensitive irq */
424 611493d9 bellard
        if (level)
425 611493d9 bellard
            src->pending = 1;
426 dbda808a bellard
    }
427 611493d9 bellard
    openpic_update_irq(opp, n_IRQ);
428 dbda808a bellard
}
429 dbda808a bellard
430 d0b72631 Alexander Graf
static void openpic_reset(DeviceState *d)
431 dbda808a bellard
{
432 d0b72631 Alexander Graf
    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
433 dbda808a bellard
    int i;
434 dbda808a bellard
435 dbda808a bellard
    opp->glbc = 0x80000000;
436 f8407028 bellard
    /* Initialise controller registers */
437 825463b3 Alexander Graf
    opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
438 825463b3 Alexander Graf
                ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
439 825463b3 Alexander Graf
                (opp->vid << FREP_VID_SHIFT);
440 825463b3 Alexander Graf
441 e9df014c j_mayer
    opp->pint = 0x00000000;
442 825463b3 Alexander Graf
    opp->spve = -1 & opp->spve_mask;
443 825463b3 Alexander Graf
    opp->tifr = opp->tifr_reset;
444 dbda808a bellard
    /* Initialise IRQ sources */
445 b7169916 aurel32
    for (i = 0; i < opp->max_irq; i++) {
446 825463b3 Alexander Graf
        opp->src[i].ipvp = opp->ipvp_reset;
447 825463b3 Alexander Graf
        opp->src[i].ide  = opp->ide_reset;
448 dbda808a bellard
    }
449 dbda808a bellard
    /* Initialise IRQ destinations */
450 e9df014c j_mayer
    for (i = 0; i < MAX_CPU; i++) {
451 060fbfe1 Aurelien Jarno
        opp->dst[i].pctp      = 0x0000000F;
452 060fbfe1 Aurelien Jarno
        opp->dst[i].pcsr      = 0x00000000;
453 060fbfe1 Aurelien Jarno
        memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
454 d14ed254 Alexander Graf
        opp->dst[i].raised.next = -1;
455 060fbfe1 Aurelien Jarno
        memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
456 d14ed254 Alexander Graf
        opp->dst[i].servicing.next = -1;
457 dbda808a bellard
    }
458 dbda808a bellard
    /* Initialise timers */
459 dbda808a bellard
    for (i = 0; i < MAX_TMR; i++) {
460 060fbfe1 Aurelien Jarno
        opp->timers[i].ticc = 0x00000000;
461 060fbfe1 Aurelien Jarno
        opp->timers[i].tibc = 0x80000000;
462 dbda808a bellard
    }
463 dbda808a bellard
    /* Go out of RESET state */
464 dbda808a bellard
    opp->glbc = 0x00000000;
465 dbda808a bellard
}
466 dbda808a bellard
467 6d544ee8 Alexander Graf
static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
468 dbda808a bellard
{
469 8d3a8c1e Alexander Graf
    return opp->src[n_IRQ].ide;
470 8d3a8c1e Alexander Graf
}
471 dbda808a bellard
472 6d544ee8 Alexander Graf
static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ)
473 8d3a8c1e Alexander Graf
{
474 8d3a8c1e Alexander Graf
    return opp->src[n_IRQ].ipvp;
475 dbda808a bellard
}
476 dbda808a bellard
477 6d544ee8 Alexander Graf
static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
478 dbda808a bellard
{
479 dbda808a bellard
    uint32_t tmp;
480 dbda808a bellard
481 11de8b71 Alexander Graf
    tmp = val & 0xC0000000;
482 11de8b71 Alexander Graf
    tmp |= val & ((1ULL << MAX_CPU) - 1);
483 11de8b71 Alexander Graf
    opp->src[n_IRQ].ide = tmp;
484 11de8b71 Alexander Graf
    DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
485 11de8b71 Alexander Graf
}
486 11de8b71 Alexander Graf
487 6d544ee8 Alexander Graf
static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
488 11de8b71 Alexander Graf
{
489 11de8b71 Alexander Graf
    /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
490 11de8b71 Alexander Graf
    /* ACTIVITY bit is read-only */
491 11de8b71 Alexander Graf
    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
492 11de8b71 Alexander Graf
                         | (val & 0x800F00FF);
493 11de8b71 Alexander Graf
    openpic_update_irq(opp, n_IRQ);
494 11de8b71 Alexander Graf
    DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
495 11de8b71 Alexander Graf
            opp->src[n_IRQ].ipvp);
496 dbda808a bellard
}
497 dbda808a bellard
498 b9b2aaa3 Alexander Graf
static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
499 b9b2aaa3 Alexander Graf
                              unsigned len)
500 dbda808a bellard
{
501 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
502 c227f099 Anthony Liguori
    IRQ_dst_t *dst;
503 e9df014c j_mayer
    int idx;
504 dbda808a bellard
505 0bf9e31a Blue Swirl
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
506 dbda808a bellard
    if (addr & 0xF)
507 dbda808a bellard
        return;
508 dbda808a bellard
    switch (addr) {
509 3e772232 Bharat Bhushan
    case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
510 3e772232 Bharat Bhushan
        break;
511 704c7e5d Alexander Graf
    case 0x40:
512 704c7e5d Alexander Graf
    case 0x50:
513 704c7e5d Alexander Graf
    case 0x60:
514 704c7e5d Alexander Graf
    case 0x70:
515 704c7e5d Alexander Graf
    case 0x80:
516 704c7e5d Alexander Graf
    case 0x90:
517 704c7e5d Alexander Graf
    case 0xA0:
518 704c7e5d Alexander Graf
    case 0xB0:
519 704c7e5d Alexander Graf
        openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
520 dbda808a bellard
        break;
521 704c7e5d Alexander Graf
    case 0x1000: /* FREP */
522 dbda808a bellard
        break;
523 704c7e5d Alexander Graf
    case 0x1020: /* GLBC */
524 825463b3 Alexander Graf
        if (val & 0x80000000) {
525 d0b72631 Alexander Graf
            openpic_reset(&opp->busdev.qdev);
526 825463b3 Alexander Graf
        }
527 060fbfe1 Aurelien Jarno
        break;
528 704c7e5d Alexander Graf
    case 0x1080: /* VENI */
529 060fbfe1 Aurelien Jarno
        break;
530 704c7e5d Alexander Graf
    case 0x1090: /* PINT */
531 e9df014c j_mayer
        for (idx = 0; idx < opp->nb_cpus; idx++) {
532 e9df014c j_mayer
            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
533 e9df014c j_mayer
                DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
534 e9df014c j_mayer
                dst = &opp->dst[idx];
535 e9df014c j_mayer
                qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
536 e9df014c j_mayer
            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
537 e9df014c j_mayer
                DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
538 e9df014c j_mayer
                dst = &opp->dst[idx];
539 e9df014c j_mayer
                qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
540 e9df014c j_mayer
            }
541 dbda808a bellard
        }
542 e9df014c j_mayer
        opp->pint = val;
543 060fbfe1 Aurelien Jarno
        break;
544 704c7e5d Alexander Graf
    case 0x10A0: /* IPI_IPVP */
545 704c7e5d Alexander Graf
    case 0x10B0:
546 704c7e5d Alexander Graf
    case 0x10C0:
547 704c7e5d Alexander Graf
    case 0x10D0:
548 dbda808a bellard
        {
549 dbda808a bellard
            int idx;
550 704c7e5d Alexander Graf
            idx = (addr - 0x10A0) >> 4;
551 11de8b71 Alexander Graf
            write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
552 dbda808a bellard
        }
553 dbda808a bellard
        break;
554 704c7e5d Alexander Graf
    case 0x10E0: /* SPVE */
555 825463b3 Alexander Graf
        opp->spve = val & opp->spve_mask;
556 dbda808a bellard
        break;
557 dbda808a bellard
    default:
558 dbda808a bellard
        break;
559 dbda808a bellard
    }
560 dbda808a bellard
}
561 dbda808a bellard
562 b9b2aaa3 Alexander Graf
static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
563 dbda808a bellard
{
564 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
565 dbda808a bellard
    uint32_t retval;
566 dbda808a bellard
567 0bf9e31a Blue Swirl
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
568 dbda808a bellard
    retval = 0xFFFFFFFF;
569 dbda808a bellard
    if (addr & 0xF)
570 dbda808a bellard
        return retval;
571 dbda808a bellard
    switch (addr) {
572 704c7e5d Alexander Graf
    case 0x1000: /* FREP */
573 dbda808a bellard
        retval = opp->frep;
574 dbda808a bellard
        break;
575 704c7e5d Alexander Graf
    case 0x1020: /* GLBC */
576 dbda808a bellard
        retval = opp->glbc;
577 060fbfe1 Aurelien Jarno
        break;
578 704c7e5d Alexander Graf
    case 0x1080: /* VENI */
579 dbda808a bellard
        retval = opp->veni;
580 060fbfe1 Aurelien Jarno
        break;
581 704c7e5d Alexander Graf
    case 0x1090: /* PINT */
582 dbda808a bellard
        retval = 0x00000000;
583 060fbfe1 Aurelien Jarno
        break;
584 3e772232 Bharat Bhushan
    case 0x00: /* Block Revision Register1 (BRR1) */
585 704c7e5d Alexander Graf
    case 0x40:
586 704c7e5d Alexander Graf
    case 0x50:
587 704c7e5d Alexander Graf
    case 0x60:
588 704c7e5d Alexander Graf
    case 0x70:
589 704c7e5d Alexander Graf
    case 0x80:
590 704c7e5d Alexander Graf
    case 0x90:
591 704c7e5d Alexander Graf
    case 0xA0:
592 dbda808a bellard
    case 0xB0:
593 704c7e5d Alexander Graf
        retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
594 704c7e5d Alexander Graf
        break;
595 704c7e5d Alexander Graf
    case 0x10A0: /* IPI_IPVP */
596 704c7e5d Alexander Graf
    case 0x10B0:
597 704c7e5d Alexander Graf
    case 0x10C0:
598 704c7e5d Alexander Graf
    case 0x10D0:
599 dbda808a bellard
        {
600 dbda808a bellard
            int idx;
601 704c7e5d Alexander Graf
            idx = (addr - 0x10A0) >> 4;
602 8d3a8c1e Alexander Graf
            retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
603 dbda808a bellard
        }
604 060fbfe1 Aurelien Jarno
        break;
605 704c7e5d Alexander Graf
    case 0x10E0: /* SPVE */
606 dbda808a bellard
        retval = opp->spve;
607 dbda808a bellard
        break;
608 dbda808a bellard
    default:
609 dbda808a bellard
        break;
610 dbda808a bellard
    }
611 dbda808a bellard
    DPRINTF("%s: => %08x\n", __func__, retval);
612 dbda808a bellard
613 dbda808a bellard
    return retval;
614 dbda808a bellard
}
615 dbda808a bellard
616 6d544ee8 Alexander Graf
static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
617 b9b2aaa3 Alexander Graf
                                unsigned len)
618 dbda808a bellard
{
619 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
620 dbda808a bellard
    int idx;
621 dbda808a bellard
622 dbda808a bellard
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
623 dbda808a bellard
    if (addr & 0xF)
624 dbda808a bellard
        return;
625 c38c0b8a Alexander Graf
    idx = (addr >> 6) & 0x3;
626 dbda808a bellard
    addr = addr & 0x30;
627 c38c0b8a Alexander Graf
628 c38c0b8a Alexander Graf
    if (addr == 0x0) {
629 c38c0b8a Alexander Graf
        /* TIFR (TFRR) */
630 c38c0b8a Alexander Graf
        opp->tifr = val;
631 c38c0b8a Alexander Graf
        return;
632 c38c0b8a Alexander Graf
    }
633 c38c0b8a Alexander Graf
    switch (addr & 0x30) {
634 c38c0b8a Alexander Graf
    case 0x00: /* TICC (GTCCR) */
635 dbda808a bellard
        break;
636 c38c0b8a Alexander Graf
    case 0x10: /* TIBC (GTBCR) */
637 060fbfe1 Aurelien Jarno
        if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
638 060fbfe1 Aurelien Jarno
            (val & 0x80000000) == 0 &&
639 dbda808a bellard
            (opp->timers[idx].tibc & 0x80000000) != 0)
640 060fbfe1 Aurelien Jarno
            opp->timers[idx].ticc &= ~0x80000000;
641 060fbfe1 Aurelien Jarno
        opp->timers[idx].tibc = val;
642 060fbfe1 Aurelien Jarno
        break;
643 c38c0b8a Alexander Graf
    case 0x20: /* TIVP (GTIVPR) */
644 11de8b71 Alexander Graf
        write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
645 060fbfe1 Aurelien Jarno
        break;
646 c38c0b8a Alexander Graf
    case 0x30: /* TIDE (GTIDR) */
647 11de8b71 Alexander Graf
        write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
648 060fbfe1 Aurelien Jarno
        break;
649 dbda808a bellard
    }
650 dbda808a bellard
}
651 dbda808a bellard
652 6d544ee8 Alexander Graf
static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
653 dbda808a bellard
{
654 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
655 c38c0b8a Alexander Graf
    uint32_t retval = -1;
656 dbda808a bellard
    int idx;
657 dbda808a bellard
658 dbda808a bellard
    DPRINTF("%s: addr %08x\n", __func__, addr);
659 c38c0b8a Alexander Graf
    if (addr & 0xF) {
660 c38c0b8a Alexander Graf
        goto out;
661 c38c0b8a Alexander Graf
    }
662 c38c0b8a Alexander Graf
    idx = (addr >> 6) & 0x3;
663 c38c0b8a Alexander Graf
    if (addr == 0x0) {
664 c38c0b8a Alexander Graf
        /* TIFR (TFRR) */
665 c38c0b8a Alexander Graf
        retval = opp->tifr;
666 c38c0b8a Alexander Graf
        goto out;
667 c38c0b8a Alexander Graf
    }
668 c38c0b8a Alexander Graf
    switch (addr & 0x30) {
669 c38c0b8a Alexander Graf
    case 0x00: /* TICC (GTCCR) */
670 060fbfe1 Aurelien Jarno
        retval = opp->timers[idx].ticc;
671 dbda808a bellard
        break;
672 c38c0b8a Alexander Graf
    case 0x10: /* TIBC (GTBCR) */
673 060fbfe1 Aurelien Jarno
        retval = opp->timers[idx].tibc;
674 060fbfe1 Aurelien Jarno
        break;
675 c38c0b8a Alexander Graf
    case 0x20: /* TIPV (TIPV) */
676 8d3a8c1e Alexander Graf
        retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
677 060fbfe1 Aurelien Jarno
        break;
678 c38c0b8a Alexander Graf
    case 0x30: /* TIDE (TIDR) */
679 8d3a8c1e Alexander Graf
        retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
680 060fbfe1 Aurelien Jarno
        break;
681 dbda808a bellard
    }
682 c38c0b8a Alexander Graf
683 c38c0b8a Alexander Graf
out:
684 dbda808a bellard
    DPRINTF("%s: => %08x\n", __func__, retval);
685 dbda808a bellard
686 dbda808a bellard
    return retval;
687 dbda808a bellard
}
688 dbda808a bellard
689 b9b2aaa3 Alexander Graf
static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
690 b9b2aaa3 Alexander Graf
                              unsigned len)
691 dbda808a bellard
{
692 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
693 dbda808a bellard
    int idx;
694 dbda808a bellard
695 dbda808a bellard
    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
696 dbda808a bellard
    if (addr & 0xF)
697 dbda808a bellard
        return;
698 dbda808a bellard
    addr = addr & 0xFFF0;
699 dbda808a bellard
    idx = addr >> 5;
700 dbda808a bellard
    if (addr & 0x10) {
701 dbda808a bellard
        /* EXDE / IFEDE / IEEDE */
702 11de8b71 Alexander Graf
        write_IRQreg_ide(opp, idx, val);
703 dbda808a bellard
    } else {
704 dbda808a bellard
        /* EXVP / IFEVP / IEEVP */
705 11de8b71 Alexander Graf
        write_IRQreg_ipvp(opp, idx, val);
706 dbda808a bellard
    }
707 dbda808a bellard
}
708 dbda808a bellard
709 b9b2aaa3 Alexander Graf
static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
710 dbda808a bellard
{
711 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
712 dbda808a bellard
    uint32_t retval;
713 dbda808a bellard
    int idx;
714 dbda808a bellard
715 dbda808a bellard
    DPRINTF("%s: addr %08x\n", __func__, addr);
716 dbda808a bellard
    retval = 0xFFFFFFFF;
717 dbda808a bellard
    if (addr & 0xF)
718 dbda808a bellard
        return retval;
719 dbda808a bellard
    addr = addr & 0xFFF0;
720 dbda808a bellard
    idx = addr >> 5;
721 dbda808a bellard
    if (addr & 0x10) {
722 dbda808a bellard
        /* EXDE / IFEDE / IEEDE */
723 8d3a8c1e Alexander Graf
        retval = read_IRQreg_ide(opp, idx);
724 dbda808a bellard
    } else {
725 dbda808a bellard
        /* EXVP / IFEVP / IEEVP */
726 8d3a8c1e Alexander Graf
        retval = read_IRQreg_ipvp(opp, idx);
727 dbda808a bellard
    }
728 dbda808a bellard
    DPRINTF("%s: => %08x\n", __func__, retval);
729 dbda808a bellard
730 dbda808a bellard
    return retval;
731 dbda808a bellard
}
732 dbda808a bellard
733 732aa6ec Alexander Graf
static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
734 732aa6ec Alexander Graf
                              unsigned size)
735 732aa6ec Alexander Graf
{
736 732aa6ec Alexander Graf
    OpenPICState *opp = opaque;
737 732aa6ec Alexander Graf
    int idx = opp->irq_msi;
738 732aa6ec Alexander Graf
    int srs, ibs;
739 732aa6ec Alexander Graf
740 732aa6ec Alexander Graf
    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
741 732aa6ec Alexander Graf
    if (addr & 0xF) {
742 732aa6ec Alexander Graf
        return;
743 732aa6ec Alexander Graf
    }
744 732aa6ec Alexander Graf
745 732aa6ec Alexander Graf
    switch (addr) {
746 732aa6ec Alexander Graf
    case MSIIR_OFFSET:
747 732aa6ec Alexander Graf
        srs = val >> MSIIR_SRS_SHIFT;
748 732aa6ec Alexander Graf
        idx += srs;
749 732aa6ec Alexander Graf
        ibs = (val & MSIIR_IBS_MASK) >> MSIIR_IBS_SHIFT;
750 732aa6ec Alexander Graf
        opp->msi[srs].msir |= 1 << ibs;
751 732aa6ec Alexander Graf
        openpic_set_irq(opp, idx, 1);
752 732aa6ec Alexander Graf
        break;
753 732aa6ec Alexander Graf
    default:
754 732aa6ec Alexander Graf
        /* most registers are read-only, thus ignored */
755 732aa6ec Alexander Graf
        break;
756 732aa6ec Alexander Graf
    }
757 732aa6ec Alexander Graf
}
758 732aa6ec Alexander Graf
759 732aa6ec Alexander Graf
static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
760 732aa6ec Alexander Graf
{
761 732aa6ec Alexander Graf
    OpenPICState *opp = opaque;
762 732aa6ec Alexander Graf
    uint64_t r = 0;
763 732aa6ec Alexander Graf
    int i, srs;
764 732aa6ec Alexander Graf
765 732aa6ec Alexander Graf
    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
766 732aa6ec Alexander Graf
    if (addr & 0xF) {
767 732aa6ec Alexander Graf
        return -1;
768 732aa6ec Alexander Graf
    }
769 732aa6ec Alexander Graf
770 732aa6ec Alexander Graf
    srs = addr >> 4;
771 732aa6ec Alexander Graf
772 732aa6ec Alexander Graf
    switch (addr) {
773 732aa6ec Alexander Graf
    case 0x00:
774 732aa6ec Alexander Graf
    case 0x10:
775 732aa6ec Alexander Graf
    case 0x20:
776 732aa6ec Alexander Graf
    case 0x30:
777 732aa6ec Alexander Graf
    case 0x40:
778 732aa6ec Alexander Graf
    case 0x50:
779 732aa6ec Alexander Graf
    case 0x60:
780 732aa6ec Alexander Graf
    case 0x70: /* MSIRs */
781 732aa6ec Alexander Graf
        r = opp->msi[srs].msir;
782 732aa6ec Alexander Graf
        /* Clear on read */
783 732aa6ec Alexander Graf
        opp->msi[srs].msir = 0;
784 732aa6ec Alexander Graf
        break;
785 732aa6ec Alexander Graf
    case 0x120: /* MSISR */
786 732aa6ec Alexander Graf
        for (i = 0; i < MAX_MSI; i++) {
787 732aa6ec Alexander Graf
            r |= (opp->msi[i].msir ? 1 : 0) << i;
788 732aa6ec Alexander Graf
        }
789 732aa6ec Alexander Graf
        break;
790 732aa6ec Alexander Graf
    }
791 732aa6ec Alexander Graf
792 732aa6ec Alexander Graf
    return r;
793 732aa6ec Alexander Graf
}
794 732aa6ec Alexander Graf
795 a8170e5e Avi Kivity
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
796 704c7e5d Alexander Graf
                                       uint32_t val, int idx)
797 dbda808a bellard
{
798 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
799 c227f099 Anthony Liguori
    IRQ_src_t *src;
800 c227f099 Anthony Liguori
    IRQ_dst_t *dst;
801 704c7e5d Alexander Graf
    int s_IRQ, n_IRQ;
802 dbda808a bellard
803 704c7e5d Alexander Graf
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
804 704c7e5d Alexander Graf
            addr, val);
805 dbda808a bellard
    if (addr & 0xF)
806 dbda808a bellard
        return;
807 dbda808a bellard
    dst = &opp->dst[idx];
808 dbda808a bellard
    addr &= 0xFF0;
809 dbda808a bellard
    switch (addr) {
810 704c7e5d Alexander Graf
    case 0x40: /* IPIDR */
811 dbda808a bellard
    case 0x50:
812 dbda808a bellard
    case 0x60:
813 dbda808a bellard
    case 0x70:
814 dbda808a bellard
        idx = (addr - 0x40) >> 4;
815 a675155e Alexander Graf
        /* we use IDE as mask which CPUs to deliver the IPI to still. */
816 11de8b71 Alexander Graf
        write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
817 11de8b71 Alexander Graf
                         opp->src[opp->irq_ipi0 + idx].ide | val);
818 b7169916 aurel32
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
819 b7169916 aurel32
        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
820 dbda808a bellard
        break;
821 dbda808a bellard
    case 0x80: /* PCTP */
822 060fbfe1 Aurelien Jarno
        dst->pctp = val & 0x0000000F;
823 060fbfe1 Aurelien Jarno
        break;
824 dbda808a bellard
    case 0x90: /* WHOAMI */
825 060fbfe1 Aurelien Jarno
        /* Read-only register */
826 060fbfe1 Aurelien Jarno
        break;
827 dbda808a bellard
    case 0xA0: /* PIAC */
828 060fbfe1 Aurelien Jarno
        /* Read-only register */
829 060fbfe1 Aurelien Jarno
        break;
830 dbda808a bellard
    case 0xB0: /* PEOI */
831 dbda808a bellard
        DPRINTF("PEOI\n");
832 060fbfe1 Aurelien Jarno
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
833 060fbfe1 Aurelien Jarno
        IRQ_resetbit(&dst->servicing, s_IRQ);
834 060fbfe1 Aurelien Jarno
        dst->servicing.next = -1;
835 060fbfe1 Aurelien Jarno
        /* Set up next servicing IRQ */
836 060fbfe1 Aurelien Jarno
        s_IRQ = IRQ_get_next(opp, &dst->servicing);
837 e9df014c j_mayer
        /* Check queued interrupts. */
838 e9df014c j_mayer
        n_IRQ = IRQ_get_next(opp, &dst->raised);
839 e9df014c j_mayer
        src = &opp->src[n_IRQ];
840 e9df014c j_mayer
        if (n_IRQ != -1 &&
841 e9df014c j_mayer
            (s_IRQ == -1 ||
842 e9df014c j_mayer
             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
843 e9df014c j_mayer
            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
844 e9df014c j_mayer
                    idx, n_IRQ);
845 5861a338 Alexander Graf
            openpic_irq_raise(opp, idx, src);
846 e9df014c j_mayer
        }
847 060fbfe1 Aurelien Jarno
        break;
848 dbda808a bellard
    default:
849 dbda808a bellard
        break;
850 dbda808a bellard
    }
851 dbda808a bellard
}
852 dbda808a bellard
853 b9b2aaa3 Alexander Graf
static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
854 b9b2aaa3 Alexander Graf
                              unsigned len)
855 704c7e5d Alexander Graf
{
856 704c7e5d Alexander Graf
    openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
857 704c7e5d Alexander Graf
}
858 704c7e5d Alexander Graf
859 a8170e5e Avi Kivity
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
860 704c7e5d Alexander Graf
                                          int idx)
861 dbda808a bellard
{
862 6d544ee8 Alexander Graf
    OpenPICState *opp = opaque;
863 c227f099 Anthony Liguori
    IRQ_src_t *src;
864 c227f099 Anthony Liguori
    IRQ_dst_t *dst;
865 dbda808a bellard
    uint32_t retval;
866 704c7e5d Alexander Graf
    int n_IRQ;
867 3b46e624 ths
868 704c7e5d Alexander Graf
    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
869 dbda808a bellard
    retval = 0xFFFFFFFF;
870 dbda808a bellard
    if (addr & 0xF)
871 dbda808a bellard
        return retval;
872 dbda808a bellard
    dst = &opp->dst[idx];
873 dbda808a bellard
    addr &= 0xFF0;
874 dbda808a bellard
    switch (addr) {
875 3e772232 Bharat Bhushan
    case 0x00: /* Block Revision Register1 (BRR1) */
876 dbbbfd60 Alexander Graf
        retval = opp->brr1;
877 3e772232 Bharat Bhushan
        break;
878 dbda808a bellard
    case 0x80: /* PCTP */
879 060fbfe1 Aurelien Jarno
        retval = dst->pctp;
880 060fbfe1 Aurelien Jarno
        break;
881 dbda808a bellard
    case 0x90: /* WHOAMI */
882 060fbfe1 Aurelien Jarno
        retval = idx;
883 060fbfe1 Aurelien Jarno
        break;
884 dbda808a bellard
    case 0xA0: /* PIAC */
885 e9df014c j_mayer
        DPRINTF("Lower OpenPIC INT output\n");
886 e9df014c j_mayer
        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
887 060fbfe1 Aurelien Jarno
        n_IRQ = IRQ_get_next(opp, &dst->raised);
888 dbda808a bellard
        DPRINTF("PIAC: irq=%d\n", n_IRQ);
889 060fbfe1 Aurelien Jarno
        if (n_IRQ == -1) {
890 060fbfe1 Aurelien Jarno
            /* No more interrupt pending */
891 e9df014c j_mayer
            retval = IPVP_VECTOR(opp->spve);
892 060fbfe1 Aurelien Jarno
        } else {
893 060fbfe1 Aurelien Jarno
            src = &opp->src[n_IRQ];
894 1945dbc1 Alexander Graf
            if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
895 060fbfe1 Aurelien Jarno
                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
896 060fbfe1 Aurelien Jarno
                /* - Spurious level-sensitive IRQ
897 060fbfe1 Aurelien Jarno
                 * - Priorities has been changed
898 060fbfe1 Aurelien Jarno
                 *   and the pending IRQ isn't allowed anymore
899 060fbfe1 Aurelien Jarno
                 */
900 1945dbc1 Alexander Graf
                src->ipvp &= ~IPVP_ACTIVITY_MASK;
901 060fbfe1 Aurelien Jarno
                retval = IPVP_VECTOR(opp->spve);
902 060fbfe1 Aurelien Jarno
            } else {
903 060fbfe1 Aurelien Jarno
                /* IRQ enter servicing state */
904 060fbfe1 Aurelien Jarno
                IRQ_setbit(&dst->servicing, n_IRQ);
905 060fbfe1 Aurelien Jarno
                retval = IPVP_VECTOR(src->ipvp);
906 060fbfe1 Aurelien Jarno
            }
907 060fbfe1 Aurelien Jarno
            IRQ_resetbit(&dst->raised, n_IRQ);
908 060fbfe1 Aurelien Jarno
            dst->raised.next = -1;
909 1945dbc1 Alexander Graf
            if (!(src->ipvp & IPVP_SENSE_MASK)) {
910 611493d9 bellard
                /* edge-sensitive IRQ */
911 1945dbc1 Alexander Graf
                src->ipvp &= ~IPVP_ACTIVITY_MASK;
912 611493d9 bellard
                src->pending = 0;
913 611493d9 bellard
            }
914 a675155e Alexander Graf
915 a675155e Alexander Graf
            if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
916 a675155e Alexander Graf
                src->ide &= ~(1 << idx);
917 1945dbc1 Alexander Graf
                if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) {
918 a675155e Alexander Graf
                    /* trigger on CPUs that didn't know about it yet */
919 a675155e Alexander Graf
                    openpic_set_irq(opp, n_IRQ, 1);
920 a675155e Alexander Graf
                    openpic_set_irq(opp, n_IRQ, 0);
921 a675155e Alexander Graf
                    /* if all CPUs knew about it, set active bit again */
922 1945dbc1 Alexander Graf
                    src->ipvp |= IPVP_ACTIVITY_MASK;
923 a675155e Alexander Graf
                }
924 a675155e Alexander Graf
            }
925 060fbfe1 Aurelien Jarno
        }
926 060fbfe1 Aurelien Jarno
        break;
927 dbda808a bellard
    case 0xB0: /* PEOI */
928 060fbfe1 Aurelien Jarno
        retval = 0;
929 060fbfe1 Aurelien Jarno
        break;
930 dbda808a bellard
    default:
931 dbda808a bellard
        break;
932 dbda808a bellard
    }
933 dbda808a bellard
    DPRINTF("%s: => %08x\n", __func__, retval);
934 dbda808a bellard
935 dbda808a bellard
    return retval;
936 dbda808a bellard
}
937 dbda808a bellard
938 b9b2aaa3 Alexander Graf
static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
939 704c7e5d Alexander Graf
{
940 704c7e5d Alexander Graf
    return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
941 704c7e5d Alexander Graf
}
942 704c7e5d Alexander Graf
943 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_glb_ops_le = {
944 780d16b7 Alexander Graf
    .write = openpic_gbl_write,
945 780d16b7 Alexander Graf
    .read  = openpic_gbl_read,
946 780d16b7 Alexander Graf
    .endianness = DEVICE_LITTLE_ENDIAN,
947 780d16b7 Alexander Graf
    .impl = {
948 780d16b7 Alexander Graf
        .min_access_size = 4,
949 780d16b7 Alexander Graf
        .max_access_size = 4,
950 780d16b7 Alexander Graf
    },
951 780d16b7 Alexander Graf
};
952 dbda808a bellard
953 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_glb_ops_be = {
954 35732cb4 Alexander Graf
    .write = openpic_gbl_write,
955 35732cb4 Alexander Graf
    .read  = openpic_gbl_read,
956 35732cb4 Alexander Graf
    .endianness = DEVICE_BIG_ENDIAN,
957 35732cb4 Alexander Graf
    .impl = {
958 35732cb4 Alexander Graf
        .min_access_size = 4,
959 35732cb4 Alexander Graf
        .max_access_size = 4,
960 35732cb4 Alexander Graf
    },
961 35732cb4 Alexander Graf
};
962 35732cb4 Alexander Graf
963 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_tmr_ops_le = {
964 6d544ee8 Alexander Graf
    .write = openpic_tmr_write,
965 6d544ee8 Alexander Graf
    .read  = openpic_tmr_read,
966 780d16b7 Alexander Graf
    .endianness = DEVICE_LITTLE_ENDIAN,
967 780d16b7 Alexander Graf
    .impl = {
968 780d16b7 Alexander Graf
        .min_access_size = 4,
969 780d16b7 Alexander Graf
        .max_access_size = 4,
970 780d16b7 Alexander Graf
    },
971 780d16b7 Alexander Graf
};
972 dbda808a bellard
973 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_tmr_ops_be = {
974 6d544ee8 Alexander Graf
    .write = openpic_tmr_write,
975 6d544ee8 Alexander Graf
    .read  = openpic_tmr_read,
976 35732cb4 Alexander Graf
    .endianness = DEVICE_BIG_ENDIAN,
977 35732cb4 Alexander Graf
    .impl = {
978 35732cb4 Alexander Graf
        .min_access_size = 4,
979 35732cb4 Alexander Graf
        .max_access_size = 4,
980 35732cb4 Alexander Graf
    },
981 35732cb4 Alexander Graf
};
982 35732cb4 Alexander Graf
983 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_cpu_ops_le = {
984 780d16b7 Alexander Graf
    .write = openpic_cpu_write,
985 780d16b7 Alexander Graf
    .read  = openpic_cpu_read,
986 780d16b7 Alexander Graf
    .endianness = DEVICE_LITTLE_ENDIAN,
987 780d16b7 Alexander Graf
    .impl = {
988 780d16b7 Alexander Graf
        .min_access_size = 4,
989 780d16b7 Alexander Graf
        .max_access_size = 4,
990 780d16b7 Alexander Graf
    },
991 780d16b7 Alexander Graf
};
992 dbda808a bellard
993 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_cpu_ops_be = {
994 35732cb4 Alexander Graf
    .write = openpic_cpu_write,
995 35732cb4 Alexander Graf
    .read  = openpic_cpu_read,
996 35732cb4 Alexander Graf
    .endianness = DEVICE_BIG_ENDIAN,
997 35732cb4 Alexander Graf
    .impl = {
998 35732cb4 Alexander Graf
        .min_access_size = 4,
999 35732cb4 Alexander Graf
        .max_access_size = 4,
1000 35732cb4 Alexander Graf
    },
1001 35732cb4 Alexander Graf
};
1002 35732cb4 Alexander Graf
1003 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_src_ops_le = {
1004 780d16b7 Alexander Graf
    .write = openpic_src_write,
1005 780d16b7 Alexander Graf
    .read  = openpic_src_read,
1006 23c5e4ca Avi Kivity
    .endianness = DEVICE_LITTLE_ENDIAN,
1007 b9b2aaa3 Alexander Graf
    .impl = {
1008 b9b2aaa3 Alexander Graf
        .min_access_size = 4,
1009 b9b2aaa3 Alexander Graf
        .max_access_size = 4,
1010 b9b2aaa3 Alexander Graf
    },
1011 23c5e4ca Avi Kivity
};
1012 23c5e4ca Avi Kivity
1013 35732cb4 Alexander Graf
static const MemoryRegionOps openpic_src_ops_be = {
1014 35732cb4 Alexander Graf
    .write = openpic_src_write,
1015 35732cb4 Alexander Graf
    .read  = openpic_src_read,
1016 35732cb4 Alexander Graf
    .endianness = DEVICE_BIG_ENDIAN,
1017 35732cb4 Alexander Graf
    .impl = {
1018 35732cb4 Alexander Graf
        .min_access_size = 4,
1019 35732cb4 Alexander Graf
        .max_access_size = 4,
1020 35732cb4 Alexander Graf
    },
1021 35732cb4 Alexander Graf
};
1022 35732cb4 Alexander Graf
1023 732aa6ec Alexander Graf
static const MemoryRegionOps openpic_msi_ops_le = {
1024 732aa6ec Alexander Graf
    .read = openpic_msi_read,
1025 732aa6ec Alexander Graf
    .write = openpic_msi_write,
1026 732aa6ec Alexander Graf
    .endianness = DEVICE_LITTLE_ENDIAN,
1027 732aa6ec Alexander Graf
    .impl = {
1028 732aa6ec Alexander Graf
        .min_access_size = 4,
1029 732aa6ec Alexander Graf
        .max_access_size = 4,
1030 732aa6ec Alexander Graf
    },
1031 732aa6ec Alexander Graf
};
1032 732aa6ec Alexander Graf
1033 732aa6ec Alexander Graf
static const MemoryRegionOps openpic_msi_ops_be = {
1034 732aa6ec Alexander Graf
    .read = openpic_msi_read,
1035 732aa6ec Alexander Graf
    .write = openpic_msi_write,
1036 732aa6ec Alexander Graf
    .endianness = DEVICE_BIG_ENDIAN,
1037 732aa6ec Alexander Graf
    .impl = {
1038 732aa6ec Alexander Graf
        .min_access_size = 4,
1039 732aa6ec Alexander Graf
        .max_access_size = 4,
1040 732aa6ec Alexander Graf
    },
1041 732aa6ec Alexander Graf
};
1042 732aa6ec Alexander Graf
1043 c227f099 Anthony Liguori
static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1044 67b55785 blueswir1
{
1045 67b55785 blueswir1
    unsigned int i;
1046 67b55785 blueswir1
1047 67b55785 blueswir1
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1048 67b55785 blueswir1
        qemu_put_be32s(f, &q->queue[i]);
1049 67b55785 blueswir1
1050 67b55785 blueswir1
    qemu_put_sbe32s(f, &q->next);
1051 67b55785 blueswir1
    qemu_put_sbe32s(f, &q->priority);
1052 67b55785 blueswir1
}
1053 67b55785 blueswir1
1054 67b55785 blueswir1
static void openpic_save(QEMUFile* f, void *opaque)
1055 67b55785 blueswir1
{
1056 6d544ee8 Alexander Graf
    OpenPICState *opp = (OpenPICState *)opaque;
1057 67b55785 blueswir1
    unsigned int i;
1058 67b55785 blueswir1
1059 67b55785 blueswir1
    qemu_put_be32s(f, &opp->glbc);
1060 67b55785 blueswir1
    qemu_put_be32s(f, &opp->veni);
1061 67b55785 blueswir1
    qemu_put_be32s(f, &opp->pint);
1062 67b55785 blueswir1
    qemu_put_be32s(f, &opp->spve);
1063 67b55785 blueswir1
    qemu_put_be32s(f, &opp->tifr);
1064 67b55785 blueswir1
1065 b7169916 aurel32
    for (i = 0; i < opp->max_irq; i++) {
1066 67b55785 blueswir1
        qemu_put_be32s(f, &opp->src[i].ipvp);
1067 67b55785 blueswir1
        qemu_put_be32s(f, &opp->src[i].ide);
1068 67b55785 blueswir1
        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
1069 67b55785 blueswir1
        qemu_put_sbe32s(f, &opp->src[i].pending);
1070 67b55785 blueswir1
    }
1071 67b55785 blueswir1
1072 d0b72631 Alexander Graf
    qemu_put_be32s(f, &opp->nb_cpus);
1073 b7169916 aurel32
1074 b7169916 aurel32
    for (i = 0; i < opp->nb_cpus; i++) {
1075 67b55785 blueswir1
        qemu_put_be32s(f, &opp->dst[i].pctp);
1076 67b55785 blueswir1
        qemu_put_be32s(f, &opp->dst[i].pcsr);
1077 67b55785 blueswir1
        openpic_save_IRQ_queue(f, &opp->dst[i].raised);
1078 67b55785 blueswir1
        openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
1079 67b55785 blueswir1
    }
1080 67b55785 blueswir1
1081 67b55785 blueswir1
    for (i = 0; i < MAX_TMR; i++) {
1082 67b55785 blueswir1
        qemu_put_be32s(f, &opp->timers[i].ticc);
1083 67b55785 blueswir1
        qemu_put_be32s(f, &opp->timers[i].tibc);
1084 67b55785 blueswir1
    }
1085 67b55785 blueswir1
}
1086 67b55785 blueswir1
1087 c227f099 Anthony Liguori
static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
1088 67b55785 blueswir1
{
1089 67b55785 blueswir1
    unsigned int i;
1090 67b55785 blueswir1
1091 67b55785 blueswir1
    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
1092 67b55785 blueswir1
        qemu_get_be32s(f, &q->queue[i]);
1093 67b55785 blueswir1
1094 67b55785 blueswir1
    qemu_get_sbe32s(f, &q->next);
1095 67b55785 blueswir1
    qemu_get_sbe32s(f, &q->priority);
1096 67b55785 blueswir1
}
1097 67b55785 blueswir1
1098 67b55785 blueswir1
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
1099 67b55785 blueswir1
{
1100 6d544ee8 Alexander Graf
    OpenPICState *opp = (OpenPICState *)opaque;
1101 67b55785 blueswir1
    unsigned int i;
1102 67b55785 blueswir1
1103 67b55785 blueswir1
    if (version_id != 1)
1104 67b55785 blueswir1
        return -EINVAL;
1105 67b55785 blueswir1
1106 67b55785 blueswir1
    qemu_get_be32s(f, &opp->glbc);
1107 67b55785 blueswir1
    qemu_get_be32s(f, &opp->veni);
1108 67b55785 blueswir1
    qemu_get_be32s(f, &opp->pint);
1109 67b55785 blueswir1
    qemu_get_be32s(f, &opp->spve);
1110 67b55785 blueswir1
    qemu_get_be32s(f, &opp->tifr);
1111 67b55785 blueswir1
1112 b7169916 aurel32
    for (i = 0; i < opp->max_irq; i++) {
1113 67b55785 blueswir1
        qemu_get_be32s(f, &opp->src[i].ipvp);
1114 67b55785 blueswir1
        qemu_get_be32s(f, &opp->src[i].ide);
1115 67b55785 blueswir1
        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
1116 67b55785 blueswir1
        qemu_get_sbe32s(f, &opp->src[i].pending);
1117 67b55785 blueswir1
    }
1118 67b55785 blueswir1
1119 d0b72631 Alexander Graf
    qemu_get_be32s(f, &opp->nb_cpus);
1120 b7169916 aurel32
1121 b7169916 aurel32
    for (i = 0; i < opp->nb_cpus; i++) {
1122 67b55785 blueswir1
        qemu_get_be32s(f, &opp->dst[i].pctp);
1123 67b55785 blueswir1
        qemu_get_be32s(f, &opp->dst[i].pcsr);
1124 67b55785 blueswir1
        openpic_load_IRQ_queue(f, &opp->dst[i].raised);
1125 67b55785 blueswir1
        openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
1126 67b55785 blueswir1
    }
1127 67b55785 blueswir1
1128 67b55785 blueswir1
    for (i = 0; i < MAX_TMR; i++) {
1129 67b55785 blueswir1
        qemu_get_be32s(f, &opp->timers[i].ticc);
1130 67b55785 blueswir1
        qemu_get_be32s(f, &opp->timers[i].tibc);
1131 67b55785 blueswir1
    }
1132 67b55785 blueswir1
1133 d0b72631 Alexander Graf
    return 0;
1134 67b55785 blueswir1
}
1135 67b55785 blueswir1
1136 6d544ee8 Alexander Graf
static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
1137 b7169916 aurel32
{
1138 1945dbc1 Alexander Graf
    int n_ci = IDR_CI0_SHIFT - n_CPU;
1139 5861a338 Alexander Graf
1140 1945dbc1 Alexander Graf
    if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) {
1141 5861a338 Alexander Graf
        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
1142 5861a338 Alexander Graf
    } else {
1143 5861a338 Alexander Graf
        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
1144 5861a338 Alexander Graf
    }
1145 b7169916 aurel32
}
1146 b7169916 aurel32
1147 d0b72631 Alexander Graf
struct memreg {
1148 d0b72631 Alexander Graf
    const char             *name;
1149 d0b72631 Alexander Graf
    MemoryRegionOps const  *ops;
1150 732aa6ec Alexander Graf
    bool                   map;
1151 d0b72631 Alexander Graf
    hwaddr      start_addr;
1152 d0b72631 Alexander Graf
    ram_addr_t              size;
1153 d0b72631 Alexander Graf
};
1154 d0b72631 Alexander Graf
1155 d0b72631 Alexander Graf
static int openpic_init(SysBusDevice *dev)
1156 dbda808a bellard
{
1157 d0b72631 Alexander Graf
    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
1158 d0b72631 Alexander Graf
    int i, j;
1159 732aa6ec Alexander Graf
    struct memreg list_le[] = {
1160 732aa6ec Alexander Graf
        {"glb", &openpic_glb_ops_le, true,
1161 732aa6ec Alexander Graf
                OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1162 732aa6ec Alexander Graf
        {"tmr", &openpic_tmr_ops_le, true,
1163 732aa6ec Alexander Graf
                OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1164 732aa6ec Alexander Graf
        {"msi", &openpic_msi_ops_le, true,
1165 732aa6ec Alexander Graf
                OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1166 732aa6ec Alexander Graf
        {"src", &openpic_src_ops_le, true,
1167 732aa6ec Alexander Graf
                OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1168 732aa6ec Alexander Graf
        {"cpu", &openpic_cpu_ops_le, true,
1169 732aa6ec Alexander Graf
                OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1170 780d16b7 Alexander Graf
    };
1171 732aa6ec Alexander Graf
    struct memreg list_be[] = {
1172 732aa6ec Alexander Graf
        {"glb", &openpic_glb_ops_be, true,
1173 732aa6ec Alexander Graf
                OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1174 732aa6ec Alexander Graf
        {"tmr", &openpic_tmr_ops_be, true,
1175 732aa6ec Alexander Graf
                OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1176 732aa6ec Alexander Graf
        {"msi", &openpic_msi_ops_be, true,
1177 732aa6ec Alexander Graf
                OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1178 732aa6ec Alexander Graf
        {"src", &openpic_src_ops_be, true,
1179 732aa6ec Alexander Graf
                OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1180 732aa6ec Alexander Graf
        {"cpu", &openpic_cpu_ops_be, true,
1181 732aa6ec Alexander Graf
                OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1182 d0b72631 Alexander Graf
    };
1183 732aa6ec Alexander Graf
    struct memreg *list;
1184 3b46e624 ths
1185 d0b72631 Alexander Graf
    switch (opp->model) {
1186 d0b72631 Alexander Graf
    case OPENPIC_MODEL_FSL_MPIC_20:
1187 d0b72631 Alexander Graf
    default:
1188 d0b72631 Alexander Graf
        opp->flags |= OPENPIC_FLAG_IDE_CRIT;
1189 d0b72631 Alexander Graf
        opp->nb_irqs = 80;
1190 d0b72631 Alexander Graf
        opp->vid = VID_REVISION_1_2;
1191 d0b72631 Alexander Graf
        opp->veni = VENI_GENERIC;
1192 d0b72631 Alexander Graf
        opp->spve_mask = 0xFFFF;
1193 d0b72631 Alexander Graf
        opp->tifr_reset = 0x00000000;
1194 d0b72631 Alexander Graf
        opp->ipvp_reset = 0x80000000;
1195 d0b72631 Alexander Graf
        opp->ide_reset = 0x00000001;
1196 d0b72631 Alexander Graf
        opp->max_irq = FSL_MPIC_20_MAX_IRQ;
1197 d0b72631 Alexander Graf
        opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
1198 d0b72631 Alexander Graf
        opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
1199 732aa6ec Alexander Graf
        opp->irq_msi = FSL_MPIC_20_MSI_IRQ;
1200 dbbbfd60 Alexander Graf
        opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
1201 732aa6ec Alexander Graf
        msi_supported = true;
1202 d0b72631 Alexander Graf
        list = list_be;
1203 d0b72631 Alexander Graf
        break;
1204 d0b72631 Alexander Graf
    case OPENPIC_MODEL_RAVEN:
1205 d0b72631 Alexander Graf
        opp->nb_irqs = RAVEN_MAX_EXT;
1206 d0b72631 Alexander Graf
        opp->vid = VID_REVISION_1_3;
1207 d0b72631 Alexander Graf
        opp->veni = VENI_GENERIC;
1208 d0b72631 Alexander Graf
        opp->spve_mask = 0xFF;
1209 d0b72631 Alexander Graf
        opp->tifr_reset = 0x003F7A00;
1210 d0b72631 Alexander Graf
        opp->ipvp_reset = 0xA0000000;
1211 d0b72631 Alexander Graf
        opp->ide_reset = 0x00000000;
1212 d0b72631 Alexander Graf
        opp->max_irq = RAVEN_MAX_IRQ;
1213 d0b72631 Alexander Graf
        opp->irq_ipi0 = RAVEN_IPI_IRQ;
1214 d0b72631 Alexander Graf
        opp->irq_tim0 = RAVEN_TMR_IRQ;
1215 dbbbfd60 Alexander Graf
        opp->brr1 = -1;
1216 d0b72631 Alexander Graf
        list = list_le;
1217 732aa6ec Alexander Graf
        /* Don't map MSI region */
1218 732aa6ec Alexander Graf
        list[2].map = false;
1219 d0b72631 Alexander Graf
1220 d0b72631 Alexander Graf
        /* Only UP supported today */
1221 d0b72631 Alexander Graf
        if (opp->nb_cpus != 1) {
1222 d0b72631 Alexander Graf
            return -EINVAL;
1223 d0b72631 Alexander Graf
        }
1224 d0b72631 Alexander Graf
        break;
1225 d0b72631 Alexander Graf
    }
1226 780d16b7 Alexander Graf
1227 780d16b7 Alexander Graf
    memory_region_init(&opp->mem, "openpic", 0x40000);
1228 780d16b7 Alexander Graf
1229 d0b72631 Alexander Graf
    for (i = 0; i < ARRAY_SIZE(list_le); i++) {
1230 732aa6ec Alexander Graf
        if (!list[i].map) {
1231 732aa6ec Alexander Graf
            continue;
1232 732aa6ec Alexander Graf
        }
1233 732aa6ec Alexander Graf
1234 780d16b7 Alexander Graf
        memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
1235 780d16b7 Alexander Graf
                              list[i].name, list[i].size);
1236 780d16b7 Alexander Graf
1237 780d16b7 Alexander Graf
        memory_region_add_subregion(&opp->mem, list[i].start_addr,
1238 780d16b7 Alexander Graf
                                    &opp->sub_io_mem[i]);
1239 780d16b7 Alexander Graf
    }
1240 3b46e624 ths
1241 d0b72631 Alexander Graf
    for (i = 0; i < opp->nb_cpus; i++) {
1242 d0b72631 Alexander Graf
        opp->dst[i].irqs = g_new(qemu_irq, OPENPIC_OUTPUT_NB);
1243 d0b72631 Alexander Graf
        for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
1244 d0b72631 Alexander Graf
            sysbus_init_irq(dev, &opp->dst[i].irqs[j]);
1245 d0b72631 Alexander Graf
        }
1246 d0b72631 Alexander Graf
    }
1247 d0b72631 Alexander Graf
1248 d0b72631 Alexander Graf
    register_savevm(&opp->busdev.qdev, "openpic", 0, 2,
1249 0be71e32 Alex Williamson
                    openpic_save, openpic_load, opp);
1250 b7169916 aurel32
1251 d0b72631 Alexander Graf
    sysbus_init_mmio(dev, &opp->mem);
1252 d0b72631 Alexander Graf
    qdev_init_gpio_in(&dev->qdev, openpic_set_irq, opp->max_irq);
1253 e9df014c j_mayer
1254 d0b72631 Alexander Graf
    return 0;
1255 b7169916 aurel32
}
1256 b7169916 aurel32
1257 d0b72631 Alexander Graf
static Property openpic_properties[] = {
1258 d0b72631 Alexander Graf
    DEFINE_PROP_UINT32("model", OpenPICState, model, OPENPIC_MODEL_FSL_MPIC_20),
1259 d0b72631 Alexander Graf
    DEFINE_PROP_UINT32("nb_cpus", OpenPICState, nb_cpus, 1),
1260 d0b72631 Alexander Graf
    DEFINE_PROP_END_OF_LIST(),
1261 d0b72631 Alexander Graf
};
1262 71cf9e62 Fabien Chouteau
1263 d0b72631 Alexander Graf
static void openpic_class_init(ObjectClass *klass, void *data)
1264 d0b72631 Alexander Graf
{
1265 d0b72631 Alexander Graf
    DeviceClass *dc = DEVICE_CLASS(klass);
1266 d0b72631 Alexander Graf
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1267 b7169916 aurel32
1268 d0b72631 Alexander Graf
    k->init = openpic_init;
1269 d0b72631 Alexander Graf
    dc->props = openpic_properties;
1270 d0b72631 Alexander Graf
    dc->reset = openpic_reset;
1271 d0b72631 Alexander Graf
}
1272 71cf9e62 Fabien Chouteau
1273 d0b72631 Alexander Graf
static TypeInfo openpic_info = {
1274 d0b72631 Alexander Graf
    .name          = "openpic",
1275 d0b72631 Alexander Graf
    .parent        = TYPE_SYS_BUS_DEVICE,
1276 d0b72631 Alexander Graf
    .instance_size = sizeof(OpenPICState),
1277 d0b72631 Alexander Graf
    .class_init    = openpic_class_init,
1278 d0b72631 Alexander Graf
};
1279 b7169916 aurel32
1280 d0b72631 Alexander Graf
static void openpic_register_types(void)
1281 d0b72631 Alexander Graf
{
1282 d0b72631 Alexander Graf
    type_register_static(&openpic_info);
1283 dbda808a bellard
}
1284 d0b72631 Alexander Graf
1285 d0b72631 Alexander Graf
type_init(openpic_register_types)