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