xref: /openbmc/qemu/hw/intc/aspeed_intc.c (revision 8872b6717c37001e8f2e6c4ed0af20b1811d8f58)
1 /*
2  * ASPEED INTC Controller
3  *
4  * Copyright (C) 2024 ASPEED Technology Inc.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include "hw/intc/aspeed_intc.h"
11 #include "hw/irq.h"
12 #include "qemu/log.h"
13 #include "trace.h"
14 #include "hw/registerfields.h"
15 #include "qapi/error.h"
16 
17 /*
18  * INTC Registers
19  *
20  * values below are offset by - 0x1000 from datasheet
21  * because its memory region is start at 0x1000
22  *
23  */
24 REG32(GICINT128_EN,         0x000)
25 REG32(GICINT128_STATUS,     0x004)
26 REG32(GICINT129_EN,         0x100)
27 REG32(GICINT129_STATUS,     0x104)
28 REG32(GICINT130_EN,         0x200)
29 REG32(GICINT130_STATUS,     0x204)
30 REG32(GICINT131_EN,         0x300)
31 REG32(GICINT131_STATUS,     0x304)
32 REG32(GICINT132_EN,         0x400)
33 REG32(GICINT132_STATUS,     0x404)
34 REG32(GICINT133_EN,         0x500)
35 REG32(GICINT133_STATUS,     0x504)
36 REG32(GICINT134_EN,         0x600)
37 REG32(GICINT134_STATUS,     0x604)
38 REG32(GICINT135_EN,         0x700)
39 REG32(GICINT135_STATUS,     0x704)
40 REG32(GICINT136_EN,         0x800)
41 REG32(GICINT136_STATUS,     0x804)
42 REG32(GICINT192_201_EN,         0xB00)
43 REG32(GICINT192_201_STATUS,     0xB04)
44 
45 /*
46  * INTCIO Registers
47  *
48  * values below are offset by - 0x100 from datasheet
49  * because its memory region is start at 0x100
50  *
51  */
52 REG32(GICINT192_EN,         0x00)
53 REG32(GICINT192_STATUS,     0x04)
54 REG32(GICINT193_EN,         0x10)
55 REG32(GICINT193_STATUS,     0x14)
56 REG32(GICINT194_EN,         0x20)
57 REG32(GICINT194_STATUS,     0x24)
58 REG32(GICINT195_EN,         0x30)
59 REG32(GICINT195_STATUS,     0x34)
60 REG32(GICINT196_EN,         0x40)
61 REG32(GICINT196_STATUS,     0x44)
62 REG32(GICINT197_EN,         0x50)
63 REG32(GICINT197_STATUS,     0x54)
64 
65 /*
66  * SSP INTC Registers
67  */
68 REG32(SSPINT128_EN,             0x2000)
69 REG32(SSPINT128_STATUS,         0x2004)
70 REG32(SSPINT129_EN,             0x2100)
71 REG32(SSPINT129_STATUS,         0x2104)
72 REG32(SSPINT130_EN,             0x2200)
73 REG32(SSPINT130_STATUS,         0x2204)
74 REG32(SSPINT131_EN,             0x2300)
75 REG32(SSPINT131_STATUS,         0x2304)
76 REG32(SSPINT132_EN,             0x2400)
77 REG32(SSPINT132_STATUS,         0x2404)
78 REG32(SSPINT133_EN,             0x2500)
79 REG32(SSPINT133_STATUS,         0x2504)
80 REG32(SSPINT134_EN,             0x2600)
81 REG32(SSPINT134_STATUS,         0x2604)
82 REG32(SSPINT135_EN,             0x2700)
83 REG32(SSPINT135_STATUS,         0x2704)
84 REG32(SSPINT136_EN,             0x2800)
85 REG32(SSPINT136_STATUS,         0x2804)
86 REG32(SSPINT137_EN,             0x2900)
87 REG32(SSPINT137_STATUS,         0x2904)
88 REG32(SSPINT138_EN,             0x2A00)
89 REG32(SSPINT138_STATUS,         0x2A04)
90 REG32(SSPINT160_169_EN,         0x2B00)
91 REG32(SSPINT160_169_STATUS,     0x2B04)
92 
93 /*
94  * SSP INTCIO Registers
95  */
96 REG32(SSPINT160_EN,         0x180)
97 REG32(SSPINT160_STATUS,     0x184)
98 REG32(SSPINT161_EN,         0x190)
99 REG32(SSPINT161_STATUS,     0x194)
100 REG32(SSPINT162_EN,         0x1A0)
101 REG32(SSPINT162_STATUS,     0x1A4)
102 REG32(SSPINT163_EN,         0x1B0)
103 REG32(SSPINT163_STATUS,     0x1B4)
104 REG32(SSPINT164_EN,         0x1C0)
105 REG32(SSPINT164_STATUS,     0x1C4)
106 REG32(SSPINT165_EN,         0x1D0)
107 REG32(SSPINT165_STATUS,     0x1D4)
108 
109 static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
110                                                 uint32_t reg)
111 {
112     int i;
113 
114     for (i = 0; i < aic->irq_table_count; i++) {
115         if (aic->irq_table[i].enable_reg == reg ||
116             aic->irq_table[i].status_reg == reg) {
117             return &aic->irq_table[i];
118         }
119     }
120 
121     /*
122      * Invalid reg.
123      */
124     g_assert_not_reached();
125 }
126 
127 /*
128  * Update the state of an interrupt controller pin by setting
129  * the specified output pin to the given level.
130  * The input pin index should be between 0 and the number of input pins.
131  * The output pin index should be between 0 and the number of output pins.
132  */
133 static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
134                                int outpin_idx, int level)
135 {
136     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
137     const char *name = object_get_typename(OBJECT(s));
138 
139     assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins));
140 
141     trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level);
142     qemu_set_irq(s->output_pins[outpin_idx], level);
143 }
144 
145 static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
146                                         const AspeedINTCIRQ *intc_irq,
147                                         uint32_t select)
148 {
149     const char *name = object_get_typename(OBJECT(s));
150     uint32_t status_reg;
151     int outpin_idx;
152     int inpin_idx;
153 
154     status_reg = intc_irq->status_reg;
155     outpin_idx = intc_irq->outpin_idx;
156     inpin_idx = intc_irq->inpin_idx;
157 
158     if ((s->mask[inpin_idx] & select) || (s->regs[status_reg] & select)) {
159         /*
160          * a. mask is not 0 means in ISR mode
161          * sources interrupt routine are executing.
162          * b. status register value is not 0 means previous
163          * source interrupt does not be executed, yet.
164          *
165          * save source interrupt to pending variable.
166          */
167         s->pending[inpin_idx] |= select;
168         trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
169     } else {
170         /*
171          * notify firmware which source interrupt are coming
172          * by setting status register
173          */
174         s->regs[status_reg] = select;
175         trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
176                                       s->regs[status_reg]);
177         aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
178     }
179 }
180 
181 static void aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState *s,
182                                  const AspeedINTCIRQ *intc_irq, uint32_t select)
183 {
184     const char *name = object_get_typename(OBJECT(s));
185     uint32_t status_reg;
186     int num_outpins;
187     int outpin_idx;
188     int inpin_idx;
189     int i;
190 
191     num_outpins = intc_irq->num_outpins;
192     status_reg = intc_irq->status_reg;
193     outpin_idx = intc_irq->outpin_idx;
194     inpin_idx = intc_irq->inpin_idx;
195 
196     for (i = 0; i < num_outpins; i++) {
197         if (select & BIT(i)) {
198             if (s->mask[inpin_idx] & BIT(i) ||
199                 s->regs[status_reg] & BIT(i)) {
200                 /*
201                  * a. mask bit is not 0 means in ISR mode sources interrupt
202                  * routine are executing.
203                  * b. status bit is not 0 means previous source interrupt
204                  * does not be executed, yet.
205                  *
206                  * save source interrupt to pending bit.
207                  */
208                  s->pending[inpin_idx] |= BIT(i);
209                  trace_aspeed_intc_pending_irq(name, inpin_idx,
210                                                s->pending[inpin_idx]);
211             } else {
212                 /*
213                  * notify firmware which source interrupt are coming
214                  * by setting status bit
215                  */
216                 s->regs[status_reg] |= BIT(i);
217                 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
218                                               s->regs[status_reg]);
219                 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
220             }
221         }
222     }
223 }
224 
225 /*
226  * GICINT192_201 maps 1:10 to input IRQ 0 and output IRQs 0 to 9.
227  * GICINT128 to GICINT136 map 1:1 to input IRQs 1 to 9 and output
228  * IRQs 10 to 18. The value of input IRQ should be between 0 and
229  * the number of input pins.
230  */
231 static void aspeed_intc_set_irq(void *opaque, int irq, int level)
232 {
233     AspeedINTCState *s = (AspeedINTCState *)opaque;
234     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
235     const char *name = object_get_typename(OBJECT(s));
236     const AspeedINTCIRQ *intc_irq;
237     uint32_t select = 0;
238     uint32_t enable;
239     int num_outpins;
240     int inpin_idx;
241     int i;
242 
243     assert(irq < aic->num_inpins);
244 
245     intc_irq = &aic->irq_table[irq];
246     num_outpins = intc_irq->num_outpins;
247     inpin_idx = intc_irq->inpin_idx;
248     trace_aspeed_intc_set_irq(name, inpin_idx, level);
249     enable = s->enable[inpin_idx];
250 
251     if (!level) {
252         return;
253     }
254 
255     for (i = 0; i < aic->num_lines; i++) {
256         if (s->orgates[inpin_idx].levels[i]) {
257             if (enable & BIT(i)) {
258                 select |= BIT(i);
259             }
260         }
261     }
262 
263     if (!select) {
264         return;
265     }
266 
267     trace_aspeed_intc_select(name, select);
268     if (num_outpins > 1) {
269         aspeed_intc_set_irq_handler_multi_outpins(s, intc_irq, select);
270     } else {
271         aspeed_intc_set_irq_handler(s, intc_irq, select);
272     }
273 }
274 
275 static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
276                                        uint64_t data)
277 {
278     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
279     const char *name = object_get_typename(OBJECT(s));
280     const AspeedINTCIRQ *intc_irq;
281     uint32_t reg = offset >> 2;
282     uint32_t old_enable;
283     uint32_t change;
284     int inpin_idx;
285 
286     intc_irq = aspeed_intc_get_irq(aic, reg);
287     inpin_idx = intc_irq->inpin_idx;
288 
289     assert(inpin_idx < aic->num_inpins);
290 
291     /*
292      * The enable registers are used to enable source interrupts.
293      * They also handle masking and unmasking of source interrupts
294      * during the execution of the source ISR.
295      */
296 
297     /* disable all source interrupt */
298     if (!data && !s->enable[inpin_idx]) {
299         s->regs[reg] = data;
300         return;
301     }
302 
303     old_enable = s->enable[inpin_idx];
304     s->enable[inpin_idx] |= data;
305 
306     /* enable new source interrupt */
307     if (old_enable != s->enable[inpin_idx]) {
308         trace_aspeed_intc_enable(name, s->enable[inpin_idx]);
309         s->regs[reg] = data;
310         return;
311     }
312 
313     /* mask and unmask source interrupt */
314     change = s->regs[reg] ^ data;
315     if (change & data) {
316         s->mask[inpin_idx] &= ~change;
317         trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]);
318     } else {
319         s->mask[inpin_idx] |= change;
320         trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]);
321     }
322 
323     s->regs[reg] = data;
324 }
325 
326 static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
327                                        uint64_t data)
328 {
329     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
330     const char *name = object_get_typename(OBJECT(s));
331     const AspeedINTCIRQ *intc_irq;
332     uint32_t reg = offset >> 2;
333     int outpin_idx;
334     int inpin_idx;
335 
336     if (!data) {
337         qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
338         return;
339     }
340 
341     intc_irq = aspeed_intc_get_irq(aic, reg);
342     outpin_idx = intc_irq->outpin_idx;
343     inpin_idx = intc_irq->inpin_idx;
344 
345     assert(inpin_idx < aic->num_inpins);
346 
347     /* clear status */
348     s->regs[reg] &= ~data;
349 
350     /*
351      * These status registers are used for notify sources ISR are executed.
352      * If one source ISR is executed, it will clear one bit.
353      * If it clear all bits, it means to initialize this register status
354      * rather than sources ISR are executed.
355      */
356     if (data == 0xffffffff) {
357         return;
358     }
359 
360     /* All source ISR execution are done */
361     if (!s->regs[reg]) {
362         trace_aspeed_intc_all_isr_done(name, inpin_idx);
363         if (s->pending[inpin_idx]) {
364             /*
365              * handle pending source interrupt
366              * notify firmware which source interrupt are pending
367              * by setting status register
368              */
369             s->regs[reg] = s->pending[inpin_idx];
370             s->pending[inpin_idx] = 0;
371             trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
372                                           s->regs[reg]);
373             aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
374         } else {
375             /* clear irq */
376             trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx, 0);
377             aspeed_intc_update(s, inpin_idx, outpin_idx, 0);
378         }
379     }
380 }
381 
382 static void aspeed_intc_status_handler_multi_outpins(AspeedINTCState *s,
383                                                 hwaddr offset, uint64_t data)
384 {
385     const char *name = object_get_typename(OBJECT(s));
386     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
387     const AspeedINTCIRQ *intc_irq;
388     uint32_t reg = offset >> 2;
389     int num_outpins;
390     int outpin_idx;
391     int inpin_idx;
392     int i;
393 
394     if (!data) {
395         qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
396         return;
397     }
398 
399     intc_irq = aspeed_intc_get_irq(aic, reg);
400     num_outpins = intc_irq->num_outpins;
401     outpin_idx = intc_irq->outpin_idx;
402     inpin_idx = intc_irq->inpin_idx;
403     assert(inpin_idx < aic->num_inpins);
404 
405     /* clear status */
406     s->regs[reg] &= ~data;
407 
408     /*
409      * The status registers are used for notify sources ISR are executed.
410      * If one source ISR is executed, it will clear one bit.
411      * If it clear all bits, it means to initialize this register status
412      * rather than sources ISR are executed.
413      */
414     if (data == 0xffffffff) {
415         return;
416     }
417 
418     for (i = 0; i < num_outpins; i++) {
419         /* All source ISR executions are done from a specific bit */
420         if (data & BIT(i)) {
421             trace_aspeed_intc_all_isr_done_bit(name, inpin_idx, i);
422             if (s->pending[inpin_idx] & BIT(i)) {
423                 /*
424                  * Handle pending source interrupt.
425                  * Notify firmware which source interrupt is pending
426                  * by setting the status bit.
427                  */
428                 s->regs[reg] |= BIT(i);
429                 s->pending[inpin_idx] &= ~BIT(i);
430                 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
431                                               s->regs[reg]);
432                 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
433             } else {
434                 /* clear irq for the specific bit */
435                 trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx + i, 0);
436                 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 0);
437             }
438         }
439     }
440 }
441 
442 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size)
443 {
444     AspeedINTCState *s = ASPEED_INTC(opaque);
445     const char *name = object_get_typename(OBJECT(s));
446     uint32_t reg = offset >> 2;
447     uint32_t value = 0;
448 
449     value = s->regs[reg];
450     trace_aspeed_intc_read(name, offset, size, value);
451 
452     return value;
453 }
454 
455 static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
456                                         unsigned size)
457 {
458     AspeedINTCState *s = ASPEED_INTC(opaque);
459     const char *name = object_get_typename(OBJECT(s));
460     uint32_t reg = offset >> 2;
461 
462     trace_aspeed_intc_write(name, offset, size, data);
463 
464     switch (reg) {
465     case R_GICINT128_EN:
466     case R_GICINT129_EN:
467     case R_GICINT130_EN:
468     case R_GICINT131_EN:
469     case R_GICINT132_EN:
470     case R_GICINT133_EN:
471     case R_GICINT134_EN:
472     case R_GICINT135_EN:
473     case R_GICINT136_EN:
474     case R_GICINT192_201_EN:
475         aspeed_intc_enable_handler(s, offset, data);
476         break;
477     case R_GICINT128_STATUS:
478     case R_GICINT129_STATUS:
479     case R_GICINT130_STATUS:
480     case R_GICINT131_STATUS:
481     case R_GICINT132_STATUS:
482     case R_GICINT133_STATUS:
483     case R_GICINT134_STATUS:
484     case R_GICINT135_STATUS:
485     case R_GICINT136_STATUS:
486         aspeed_intc_status_handler(s, offset, data);
487         break;
488     case R_GICINT192_201_STATUS:
489         aspeed_intc_status_handler_multi_outpins(s, offset, data);
490         break;
491     default:
492         s->regs[reg] = data;
493         break;
494     }
495 }
496 
497 static void aspeed_ssp_intc_write(void *opaque, hwaddr offset, uint64_t data,
498                                         unsigned size)
499 {
500     AspeedINTCState *s = ASPEED_INTC(opaque);
501     const char *name = object_get_typename(OBJECT(s));
502     uint32_t reg = offset >> 2;
503 
504     trace_aspeed_intc_write(name, offset, size, data);
505 
506     switch (reg) {
507     case R_SSPINT128_EN:
508     case R_SSPINT129_EN:
509     case R_SSPINT130_EN:
510     case R_SSPINT131_EN:
511     case R_SSPINT132_EN:
512     case R_SSPINT133_EN:
513     case R_SSPINT134_EN:
514     case R_SSPINT135_EN:
515     case R_SSPINT136_EN:
516     case R_SSPINT160_169_EN:
517         aspeed_intc_enable_handler(s, offset, data);
518         break;
519     case R_SSPINT128_STATUS:
520     case R_SSPINT129_STATUS:
521     case R_SSPINT130_STATUS:
522     case R_SSPINT131_STATUS:
523     case R_SSPINT132_STATUS:
524     case R_SSPINT133_STATUS:
525     case R_SSPINT134_STATUS:
526     case R_SSPINT135_STATUS:
527     case R_SSPINT136_STATUS:
528         aspeed_intc_status_handler(s, offset, data);
529         break;
530     case R_SSPINT160_169_STATUS:
531         aspeed_intc_status_handler_multi_outpins(s, offset, data);
532         break;
533     default:
534         s->regs[reg] = data;
535         break;
536     }
537 
538     return;
539 }
540 
541 static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset,
542                                    unsigned int size)
543 {
544     AspeedINTCState *s = ASPEED_INTC(opaque);
545     const char *name = object_get_typename(OBJECT(s));
546     uint32_t reg = offset >> 2;
547     uint32_t value = 0;
548 
549     value = s->regs[reg];
550     trace_aspeed_intc_read(name, offset, size, value);
551 
552     return value;
553 }
554 
555 static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data,
556                                 unsigned size)
557 {
558     AspeedINTCState *s = ASPEED_INTC(opaque);
559     const char *name = object_get_typename(OBJECT(s));
560     uint32_t reg = offset >> 2;
561 
562     trace_aspeed_intc_write(name, offset, size, data);
563 
564     switch (reg) {
565     case R_GICINT192_EN:
566     case R_GICINT193_EN:
567     case R_GICINT194_EN:
568     case R_GICINT195_EN:
569     case R_GICINT196_EN:
570     case R_GICINT197_EN:
571         aspeed_intc_enable_handler(s, offset, data);
572         break;
573     case R_GICINT192_STATUS:
574     case R_GICINT193_STATUS:
575     case R_GICINT194_STATUS:
576     case R_GICINT195_STATUS:
577     case R_GICINT196_STATUS:
578     case R_GICINT197_STATUS:
579         aspeed_intc_status_handler(s, offset, data);
580         break;
581     default:
582         s->regs[reg] = data;
583         break;
584     }
585 }
586 
587 static void aspeed_ssp_intcio_write(void *opaque, hwaddr offset, uint64_t data,
588                                 unsigned size)
589 {
590     AspeedINTCState *s = ASPEED_INTC(opaque);
591     const char *name = object_get_typename(OBJECT(s));
592     uint32_t reg = offset >> 2;
593 
594     trace_aspeed_intc_write(name, offset, size, data);
595 
596     switch (reg) {
597     case R_SSPINT160_EN:
598     case R_SSPINT161_EN:
599     case R_SSPINT162_EN:
600     case R_SSPINT163_EN:
601     case R_SSPINT164_EN:
602     case R_SSPINT165_EN:
603         aspeed_intc_enable_handler(s, offset, data);
604         break;
605     case R_SSPINT160_STATUS:
606     case R_SSPINT161_STATUS:
607     case R_SSPINT162_STATUS:
608     case R_SSPINT163_STATUS:
609     case R_SSPINT164_STATUS:
610     case R_SSPINT165_STATUS:
611         aspeed_intc_status_handler(s, offset, data);
612         break;
613     default:
614         s->regs[reg] = data;
615         break;
616     }
617 
618     return;
619 }
620 
621 static const MemoryRegionOps aspeed_intc_ops = {
622     .read = aspeed_intc_read,
623     .write = aspeed_intc_write,
624     .endianness = DEVICE_LITTLE_ENDIAN,
625     .valid = {
626         .min_access_size = 4,
627         .max_access_size = 4,
628     }
629 };
630 
631 static const MemoryRegionOps aspeed_intcio_ops = {
632     .read = aspeed_intcio_read,
633     .write = aspeed_intcio_write,
634     .endianness = DEVICE_LITTLE_ENDIAN,
635     .valid = {
636         .min_access_size = 4,
637         .max_access_size = 4,
638     }
639 };
640 
641 static const MemoryRegionOps aspeed_ssp_intc_ops = {
642     .read = aspeed_intc_read,
643     .write = aspeed_ssp_intc_write,
644     .endianness = DEVICE_LITTLE_ENDIAN,
645     .valid = {
646         .min_access_size = 4,
647         .max_access_size = 4,
648     }
649 };
650 
651 static const MemoryRegionOps aspeed_ssp_intcio_ops = {
652     .read = aspeed_intcio_read,
653     .write = aspeed_ssp_intcio_write,
654     .endianness = DEVICE_LITTLE_ENDIAN,
655     .valid = {
656         .min_access_size = 4,
657         .max_access_size = 4,
658     }
659 };
660 
661 static void aspeed_intc_instance_init(Object *obj)
662 {
663     AspeedINTCState *s = ASPEED_INTC(obj);
664     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
665     int i;
666 
667     assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS);
668     for (i = 0; i < aic->num_inpins; i++) {
669         object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
670                                 TYPE_OR_IRQ);
671         object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
672                                 aic->num_lines, &error_abort);
673     }
674 }
675 
676 static void aspeed_intc_reset(DeviceState *dev)
677 {
678     AspeedINTCState *s = ASPEED_INTC(dev);
679     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
680 
681     memset(s->regs, 0, aic->nr_regs << 2);
682     memset(s->enable, 0, sizeof(s->enable));
683     memset(s->mask, 0, sizeof(s->mask));
684     memset(s->pending, 0, sizeof(s->pending));
685 }
686 
687 static void aspeed_intc_realize(DeviceState *dev, Error **errp)
688 {
689     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
690     AspeedINTCState *s = ASPEED_INTC(dev);
691     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
692     int i;
693 
694     memory_region_init(&s->iomem_container, OBJECT(s),
695             TYPE_ASPEED_INTC ".container", aic->mem_size);
696 
697     sysbus_init_mmio(sbd, &s->iomem_container);
698 
699     s->regs = g_new(uint32_t, aic->nr_regs);
700     memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s,
701                           TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
702 
703     memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
704                                 &s->iomem);
705 
706     qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins);
707 
708     for (i = 0; i < aic->num_inpins; i++) {
709         if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
710             return;
711         }
712     }
713 
714     for (i = 0; i < aic->num_outpins; i++) {
715         sysbus_init_irq(sbd, &s->output_pins[i]);
716     }
717 }
718 
719 static void aspeed_intc_unrealize(DeviceState *dev)
720 {
721     AspeedINTCState *s = ASPEED_INTC(dev);
722 
723     g_free(s->regs);
724     s->regs = NULL;
725 }
726 
727 static void aspeed_intc_class_init(ObjectClass *klass, const void *data)
728 {
729     DeviceClass *dc = DEVICE_CLASS(klass);
730     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
731 
732     dc->desc = "ASPEED INTC Controller";
733     dc->realize = aspeed_intc_realize;
734     dc->unrealize = aspeed_intc_unrealize;
735     device_class_set_legacy_reset(dc, aspeed_intc_reset);
736     dc->vmsd = NULL;
737 
738     aic->reg_ops = &aspeed_intc_ops;
739 }
740 
741 static const TypeInfo aspeed_intc_info = {
742     .name = TYPE_ASPEED_INTC,
743     .parent = TYPE_SYS_BUS_DEVICE,
744     .instance_init = aspeed_intc_instance_init,
745     .instance_size = sizeof(AspeedINTCState),
746     .class_init = aspeed_intc_class_init,
747     .class_size = sizeof(AspeedINTCClass),
748     .abstract = true,
749 };
750 
751 static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = {
752     {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS},
753     {1, 10, 1, R_GICINT128_EN, R_GICINT128_STATUS},
754     {2, 11, 1, R_GICINT129_EN, R_GICINT129_STATUS},
755     {3, 12, 1, R_GICINT130_EN, R_GICINT130_STATUS},
756     {4, 13, 1, R_GICINT131_EN, R_GICINT131_STATUS},
757     {5, 14, 1, R_GICINT132_EN, R_GICINT132_STATUS},
758     {6, 15, 1, R_GICINT133_EN, R_GICINT133_STATUS},
759     {7, 16, 1, R_GICINT134_EN, R_GICINT134_STATUS},
760     {8, 17, 1, R_GICINT135_EN, R_GICINT135_STATUS},
761     {9, 18, 1, R_GICINT136_EN, R_GICINT136_STATUS},
762 };
763 
764 static void aspeed_2700_intc_class_init(ObjectClass *klass, const void *data)
765 {
766     DeviceClass *dc = DEVICE_CLASS(klass);
767     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
768 
769     dc->desc = "ASPEED 2700 INTC Controller";
770     aic->num_lines = 32;
771     aic->num_inpins = 10;
772     aic->num_outpins = 19;
773     aic->mem_size = 0x4000;
774     aic->nr_regs = 0xB08 >> 2;
775     aic->reg_offset = 0x1000;
776     aic->irq_table = aspeed_2700_intc_irqs;
777     aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc_irqs);
778 }
779 
780 static const TypeInfo aspeed_2700_intc_info = {
781     .name = TYPE_ASPEED_2700_INTC,
782     .parent = TYPE_ASPEED_INTC,
783     .class_init = aspeed_2700_intc_class_init,
784 };
785 
786 static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
787     {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS},
788     {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS},
789     {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS},
790     {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS},
791     {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS},
792     {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS},
793 };
794 
795 static void aspeed_2700_intcio_class_init(ObjectClass *klass, const void *data)
796 {
797     DeviceClass *dc = DEVICE_CLASS(klass);
798     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
799 
800     dc->desc = "ASPEED 2700 INTC IO Controller";
801     aic->num_lines = 32;
802     aic->num_inpins = 6;
803     aic->num_outpins = 6;
804     aic->mem_size = 0x400;
805     aic->nr_regs = 0x58 >> 2;
806     aic->reg_offset = 0x100;
807     aic->reg_ops = &aspeed_intcio_ops;
808     aic->irq_table = aspeed_2700_intcio_irqs;
809     aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcio_irqs);
810 }
811 
812 static const TypeInfo aspeed_2700_intcio_info = {
813     .name = TYPE_ASPEED_2700_INTCIO,
814     .parent = TYPE_ASPEED_INTC,
815     .class_init = aspeed_2700_intcio_class_init,
816 };
817 
818 static AspeedINTCIRQ aspeed_2700ssp_intc_irqs[ASPEED_INTC_MAX_INPINS] = {
819     {0, 0, 10, R_SSPINT160_169_EN, R_SSPINT160_169_STATUS},
820     {1, 10, 1, R_SSPINT128_EN, R_SSPINT128_STATUS},
821     {2, 11, 1, R_SSPINT129_EN, R_SSPINT129_STATUS},
822     {3, 12, 1, R_SSPINT130_EN, R_SSPINT130_STATUS},
823     {4, 13, 1, R_SSPINT131_EN, R_SSPINT131_STATUS},
824     {5, 14, 1, R_SSPINT132_EN, R_SSPINT132_STATUS},
825     {6, 15, 1, R_SSPINT133_EN, R_SSPINT133_STATUS},
826     {7, 16, 1, R_SSPINT134_EN, R_SSPINT134_STATUS},
827     {8, 17, 1, R_SSPINT135_EN, R_SSPINT135_STATUS},
828     {9, 18, 1, R_SSPINT136_EN, R_SSPINT136_STATUS},
829 };
830 
831 static void aspeed_2700ssp_intc_class_init(ObjectClass *klass, const void *data)
832 {
833     DeviceClass *dc = DEVICE_CLASS(klass);
834     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
835 
836     dc->desc = "ASPEED 2700 SSP INTC Controller";
837     aic->num_lines = 32;
838     aic->num_inpins = 10;
839     aic->num_outpins = 19;
840     aic->mem_size = 0x4000;
841     aic->nr_regs = 0x2B08 >> 2;
842     aic->reg_offset = 0x0;
843     aic->reg_ops = &aspeed_ssp_intc_ops;
844     aic->irq_table = aspeed_2700ssp_intc_irqs;
845     aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intc_irqs);
846 }
847 
848 static const TypeInfo aspeed_2700ssp_intc_info = {
849     .name = TYPE_ASPEED_2700SSP_INTC,
850     .parent = TYPE_ASPEED_INTC,
851     .class_init = aspeed_2700ssp_intc_class_init,
852 };
853 
854 static AspeedINTCIRQ aspeed_2700ssp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
855     {0, 0, 1, R_SSPINT160_EN, R_SSPINT160_STATUS},
856     {1, 1, 1, R_SSPINT161_EN, R_SSPINT161_STATUS},
857     {2, 2, 1, R_SSPINT162_EN, R_SSPINT162_STATUS},
858     {3, 3, 1, R_SSPINT163_EN, R_SSPINT163_STATUS},
859     {4, 4, 1, R_SSPINT164_EN, R_SSPINT164_STATUS},
860     {5, 5, 1, R_SSPINT165_EN, R_SSPINT165_STATUS},
861 };
862 
863 static void aspeed_2700ssp_intcio_class_init(ObjectClass *klass, const void *data)
864 {
865     DeviceClass *dc = DEVICE_CLASS(klass);
866     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
867 
868     dc->desc = "ASPEED 2700 SSP INTC IO Controller";
869     aic->num_lines = 32;
870     aic->num_inpins = 6;
871     aic->num_outpins = 6;
872     aic->mem_size = 0x400;
873     aic->nr_regs = 0x1d8 >> 2;
874     aic->reg_offset = 0;
875     aic->reg_ops = &aspeed_ssp_intcio_ops;
876     aic->irq_table = aspeed_2700ssp_intcio_irqs;
877     aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intcio_irqs);
878 }
879 
880 static const TypeInfo aspeed_2700ssp_intcio_info = {
881     .name = TYPE_ASPEED_2700SSP_INTCIO,
882     .parent = TYPE_ASPEED_INTC,
883     .class_init = aspeed_2700ssp_intcio_class_init,
884 };
885 
886 static void aspeed_intc_register_types(void)
887 {
888     type_register_static(&aspeed_intc_info);
889     type_register_static(&aspeed_2700_intc_info);
890     type_register_static(&aspeed_2700_intcio_info);
891     type_register_static(&aspeed_2700ssp_intc_info);
892     type_register_static(&aspeed_2700ssp_intcio_info);
893 }
894 
895 type_init(aspeed_intc_register_types);
896