xref: /qemu/hw/intc/aspeed_intc.c (revision 80db93b2b88f9b3ed8927ae7ac74ca30e643a83e)
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 /*
110  * TSP INTC Registers
111  */
112 REG32(TSPINT128_EN,             0x3000)
113 REG32(TSPINT128_STATUS,         0x3004)
114 REG32(TSPINT129_EN,             0x3100)
115 REG32(TSPINT129_STATUS,         0x3104)
116 REG32(TSPINT130_EN,             0x3200)
117 REG32(TSPINT130_STATUS,         0x3204)
118 REG32(TSPINT131_EN,             0x3300)
119 REG32(TSPINT131_STATUS,         0x3304)
120 REG32(TSPINT132_EN,             0x3400)
121 REG32(TSPINT132_STATUS,         0x3404)
122 REG32(TSPINT133_EN,             0x3500)
123 REG32(TSPINT133_STATUS,         0x3504)
124 REG32(TSPINT134_EN,             0x3600)
125 REG32(TSPINT134_STATUS,         0x3604)
126 REG32(TSPINT135_EN,             0x3700)
127 REG32(TSPINT135_STATUS,         0x3704)
128 REG32(TSPINT136_EN,             0x3800)
129 REG32(TSPINT136_STATUS,         0x3804)
130 REG32(TSPINT137_EN,             0x3900)
131 REG32(TSPINT137_STATUS,         0x3904)
132 REG32(TSPINT138_EN,             0x3A00)
133 REG32(TSPINT138_STATUS,         0x3A04)
134 REG32(TSPINT160_169_EN,         0x3B00)
135 REG32(TSPINT160_169_STATUS,     0x3B04)
136 
137 /*
138  * TSP INTCIO Registers
139  */
140 
141 REG32(TSPINT160_EN,         0x200)
142 REG32(TSPINT160_STATUS,     0x204)
143 REG32(TSPINT161_EN,         0x210)
144 REG32(TSPINT161_STATUS,     0x214)
145 REG32(TSPINT162_EN,         0x220)
146 REG32(TSPINT162_STATUS,     0x224)
147 REG32(TSPINT163_EN,         0x230)
148 REG32(TSPINT163_STATUS,     0x234)
149 REG32(TSPINT164_EN,         0x240)
150 REG32(TSPINT164_STATUS,     0x244)
151 REG32(TSPINT165_EN,         0x250)
152 REG32(TSPINT165_STATUS,     0x254)
153 
aspeed_intc_get_irq(AspeedINTCClass * aic,uint32_t reg)154 static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
155                                                 uint32_t reg)
156 {
157     int i;
158 
159     for (i = 0; i < aic->irq_table_count; i++) {
160         if (aic->irq_table[i].enable_reg == reg ||
161             aic->irq_table[i].status_reg == reg) {
162             return &aic->irq_table[i];
163         }
164     }
165 
166     /*
167      * Invalid reg.
168      */
169     g_assert_not_reached();
170 }
171 
172 /*
173  * Update the state of an interrupt controller pin by setting
174  * the specified output pin to the given level.
175  * The input pin index should be between 0 and the number of input pins.
176  * The output pin index should be between 0 and the number of output pins.
177  */
aspeed_intc_update(AspeedINTCState * s,int inpin_idx,int outpin_idx,int level)178 static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
179                                int outpin_idx, int level)
180 {
181     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
182     const char *name = object_get_typename(OBJECT(s));
183 
184     assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins));
185 
186     trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level);
187     qemu_set_irq(s->output_pins[outpin_idx], level);
188 }
189 
aspeed_intc_set_irq_handler(AspeedINTCState * s,const AspeedINTCIRQ * intc_irq,uint32_t select)190 static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
191                                         const AspeedINTCIRQ *intc_irq,
192                                         uint32_t select)
193 {
194     const char *name = object_get_typename(OBJECT(s));
195     uint32_t status_reg;
196     int outpin_idx;
197     int inpin_idx;
198 
199     status_reg = intc_irq->status_reg;
200     outpin_idx = intc_irq->outpin_idx;
201     inpin_idx = intc_irq->inpin_idx;
202 
203     if ((s->mask[inpin_idx] & select) || (s->regs[status_reg] & select)) {
204         /*
205          * a. mask is not 0 means in ISR mode
206          * sources interrupt routine are executing.
207          * b. status register value is not 0 means previous
208          * source interrupt does not be executed, yet.
209          *
210          * save source interrupt to pending variable.
211          */
212         s->pending[inpin_idx] |= select;
213         trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
214     } else {
215         /*
216          * notify firmware which source interrupt are coming
217          * by setting status register
218          */
219         s->regs[status_reg] = select;
220         trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
221                                       s->regs[status_reg]);
222         aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
223     }
224 }
225 
aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState * s,const AspeedINTCIRQ * intc_irq,uint32_t select)226 static void aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState *s,
227                                  const AspeedINTCIRQ *intc_irq, uint32_t select)
228 {
229     const char *name = object_get_typename(OBJECT(s));
230     uint32_t status_reg;
231     int num_outpins;
232     int outpin_idx;
233     int inpin_idx;
234     int i;
235 
236     num_outpins = intc_irq->num_outpins;
237     status_reg = intc_irq->status_reg;
238     outpin_idx = intc_irq->outpin_idx;
239     inpin_idx = intc_irq->inpin_idx;
240 
241     for (i = 0; i < num_outpins; i++) {
242         if (select & BIT(i)) {
243             if (s->mask[inpin_idx] & BIT(i) ||
244                 s->regs[status_reg] & BIT(i)) {
245                 /*
246                  * a. mask bit is not 0 means in ISR mode sources interrupt
247                  * routine are executing.
248                  * b. status bit is not 0 means previous source interrupt
249                  * does not be executed, yet.
250                  *
251                  * save source interrupt to pending bit.
252                  */
253                  s->pending[inpin_idx] |= BIT(i);
254                  trace_aspeed_intc_pending_irq(name, inpin_idx,
255                                                s->pending[inpin_idx]);
256             } else {
257                 /*
258                  * notify firmware which source interrupt are coming
259                  * by setting status bit
260                  */
261                 s->regs[status_reg] |= BIT(i);
262                 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
263                                               s->regs[status_reg]);
264                 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
265             }
266         }
267     }
268 }
269 
270 /*
271  * GICINT192_201 maps 1:10 to input IRQ 0 and output IRQs 0 to 9.
272  * GICINT128 to GICINT136 map 1:1 to input IRQs 1 to 9 and output
273  * IRQs 10 to 18. The value of input IRQ should be between 0 and
274  * the number of input pins.
275  */
aspeed_intc_set_irq(void * opaque,int irq,int level)276 static void aspeed_intc_set_irq(void *opaque, int irq, int level)
277 {
278     AspeedINTCState *s = (AspeedINTCState *)opaque;
279     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
280     const char *name = object_get_typename(OBJECT(s));
281     const AspeedINTCIRQ *intc_irq;
282     uint32_t select = 0;
283     uint32_t enable;
284     int num_outpins;
285     int inpin_idx;
286     int i;
287 
288     assert(irq < aic->num_inpins);
289 
290     intc_irq = &aic->irq_table[irq];
291     num_outpins = intc_irq->num_outpins;
292     inpin_idx = intc_irq->inpin_idx;
293     trace_aspeed_intc_set_irq(name, inpin_idx, level);
294     enable = s->enable[inpin_idx];
295 
296     if (!level) {
297         return;
298     }
299 
300     for (i = 0; i < aic->num_lines; i++) {
301         if (s->orgates[inpin_idx].levels[i]) {
302             if (enable & BIT(i)) {
303                 select |= BIT(i);
304             }
305         }
306     }
307 
308     if (!select) {
309         return;
310     }
311 
312     trace_aspeed_intc_select(name, select);
313     if (num_outpins > 1) {
314         aspeed_intc_set_irq_handler_multi_outpins(s, intc_irq, select);
315     } else {
316         aspeed_intc_set_irq_handler(s, intc_irq, select);
317     }
318 }
319 
aspeed_intc_enable_handler(AspeedINTCState * s,hwaddr offset,uint64_t data)320 static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
321                                        uint64_t data)
322 {
323     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
324     const char *name = object_get_typename(OBJECT(s));
325     const AspeedINTCIRQ *intc_irq;
326     uint32_t reg = offset >> 2;
327     uint32_t old_enable;
328     uint32_t change;
329     int inpin_idx;
330 
331     intc_irq = aspeed_intc_get_irq(aic, reg);
332     inpin_idx = intc_irq->inpin_idx;
333 
334     assert(inpin_idx < aic->num_inpins);
335 
336     /*
337      * The enable registers are used to enable source interrupts.
338      * They also handle masking and unmasking of source interrupts
339      * during the execution of the source ISR.
340      */
341 
342     /* disable all source interrupt */
343     if (!data && !s->enable[inpin_idx]) {
344         s->regs[reg] = data;
345         return;
346     }
347 
348     old_enable = s->enable[inpin_idx];
349     s->enable[inpin_idx] |= data;
350 
351     /* enable new source interrupt */
352     if (old_enable != s->enable[inpin_idx]) {
353         trace_aspeed_intc_enable(name, s->enable[inpin_idx]);
354         s->regs[reg] = data;
355         return;
356     }
357 
358     /* mask and unmask source interrupt */
359     change = s->regs[reg] ^ data;
360     if (change & data) {
361         s->mask[inpin_idx] &= ~change;
362         trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]);
363     } else {
364         s->mask[inpin_idx] |= change;
365         trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]);
366     }
367 
368     s->regs[reg] = data;
369 }
370 
aspeed_intc_status_handler(AspeedINTCState * s,hwaddr offset,uint64_t data)371 static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
372                                        uint64_t data)
373 {
374     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
375     const char *name = object_get_typename(OBJECT(s));
376     const AspeedINTCIRQ *intc_irq;
377     uint32_t reg = offset >> 2;
378     int outpin_idx;
379     int inpin_idx;
380 
381     if (!data) {
382         qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
383         return;
384     }
385 
386     intc_irq = aspeed_intc_get_irq(aic, reg);
387     outpin_idx = intc_irq->outpin_idx;
388     inpin_idx = intc_irq->inpin_idx;
389 
390     assert(inpin_idx < aic->num_inpins);
391 
392     /* clear status */
393     s->regs[reg] &= ~data;
394 
395     /*
396      * These status registers are used for notify sources ISR are executed.
397      * If one source ISR is executed, it will clear one bit.
398      * If it clear all bits, it means to initialize this register status
399      * rather than sources ISR are executed.
400      */
401     if (data == 0xffffffff) {
402         return;
403     }
404 
405     /* All source ISR execution are done */
406     if (!s->regs[reg]) {
407         trace_aspeed_intc_all_isr_done(name, inpin_idx);
408         if (s->pending[inpin_idx]) {
409             /*
410              * handle pending source interrupt
411              * notify firmware which source interrupt are pending
412              * by setting status register
413              */
414             s->regs[reg] = s->pending[inpin_idx];
415             s->pending[inpin_idx] = 0;
416             trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
417                                           s->regs[reg]);
418             aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
419         } else {
420             /* clear irq */
421             trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx, 0);
422             aspeed_intc_update(s, inpin_idx, outpin_idx, 0);
423         }
424     }
425 }
426 
aspeed_intc_status_handler_multi_outpins(AspeedINTCState * s,hwaddr offset,uint64_t data)427 static void aspeed_intc_status_handler_multi_outpins(AspeedINTCState *s,
428                                                 hwaddr offset, uint64_t data)
429 {
430     const char *name = object_get_typename(OBJECT(s));
431     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
432     const AspeedINTCIRQ *intc_irq;
433     uint32_t reg = offset >> 2;
434     int num_outpins;
435     int outpin_idx;
436     int inpin_idx;
437     int i;
438 
439     if (!data) {
440         qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
441         return;
442     }
443 
444     intc_irq = aspeed_intc_get_irq(aic, reg);
445     num_outpins = intc_irq->num_outpins;
446     outpin_idx = intc_irq->outpin_idx;
447     inpin_idx = intc_irq->inpin_idx;
448     assert(inpin_idx < aic->num_inpins);
449 
450     /* clear status */
451     s->regs[reg] &= ~data;
452 
453     /*
454      * The status registers are used for notify sources ISR are executed.
455      * If one source ISR is executed, it will clear one bit.
456      * If it clear all bits, it means to initialize this register status
457      * rather than sources ISR are executed.
458      */
459     if (data == 0xffffffff) {
460         return;
461     }
462 
463     for (i = 0; i < num_outpins; i++) {
464         /* All source ISR executions are done from a specific bit */
465         if (data & BIT(i)) {
466             trace_aspeed_intc_all_isr_done_bit(name, inpin_idx, i);
467             if (s->pending[inpin_idx] & BIT(i)) {
468                 /*
469                  * Handle pending source interrupt.
470                  * Notify firmware which source interrupt is pending
471                  * by setting the status bit.
472                  */
473                 s->regs[reg] |= BIT(i);
474                 s->pending[inpin_idx] &= ~BIT(i);
475                 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
476                                               s->regs[reg]);
477                 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
478             } else {
479                 /* clear irq for the specific bit */
480                 trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx + i, 0);
481                 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 0);
482             }
483         }
484     }
485 }
486 
aspeed_intc_read(void * opaque,hwaddr offset,unsigned int size)487 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size)
488 {
489     AspeedINTCState *s = ASPEED_INTC(opaque);
490     const char *name = object_get_typename(OBJECT(s));
491     uint32_t reg = offset >> 2;
492     uint32_t value = 0;
493 
494     value = s->regs[reg];
495     trace_aspeed_intc_read(name, offset, size, value);
496 
497     return value;
498 }
499 
aspeed_intc_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)500 static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
501                                         unsigned size)
502 {
503     AspeedINTCState *s = ASPEED_INTC(opaque);
504     const char *name = object_get_typename(OBJECT(s));
505     uint32_t reg = offset >> 2;
506 
507     trace_aspeed_intc_write(name, offset, size, data);
508 
509     switch (reg) {
510     case R_GICINT128_EN:
511     case R_GICINT129_EN:
512     case R_GICINT130_EN:
513     case R_GICINT131_EN:
514     case R_GICINT132_EN:
515     case R_GICINT133_EN:
516     case R_GICINT134_EN:
517     case R_GICINT135_EN:
518     case R_GICINT136_EN:
519     case R_GICINT192_201_EN:
520         aspeed_intc_enable_handler(s, offset, data);
521         break;
522     case R_GICINT128_STATUS:
523     case R_GICINT129_STATUS:
524     case R_GICINT130_STATUS:
525     case R_GICINT131_STATUS:
526     case R_GICINT132_STATUS:
527     case R_GICINT133_STATUS:
528     case R_GICINT134_STATUS:
529     case R_GICINT135_STATUS:
530     case R_GICINT136_STATUS:
531         aspeed_intc_status_handler(s, offset, data);
532         break;
533     case R_GICINT192_201_STATUS:
534         aspeed_intc_status_handler_multi_outpins(s, offset, data);
535         break;
536     default:
537         s->regs[reg] = data;
538         break;
539     }
540 }
541 
aspeed_ssp_intc_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)542 static void aspeed_ssp_intc_write(void *opaque, hwaddr offset, uint64_t data,
543                                         unsigned size)
544 {
545     AspeedINTCState *s = ASPEED_INTC(opaque);
546     const char *name = object_get_typename(OBJECT(s));
547     uint32_t reg = offset >> 2;
548 
549     trace_aspeed_intc_write(name, offset, size, data);
550 
551     switch (reg) {
552     case R_SSPINT128_EN:
553     case R_SSPINT129_EN:
554     case R_SSPINT130_EN:
555     case R_SSPINT131_EN:
556     case R_SSPINT132_EN:
557     case R_SSPINT133_EN:
558     case R_SSPINT134_EN:
559     case R_SSPINT135_EN:
560     case R_SSPINT136_EN:
561     case R_SSPINT160_169_EN:
562         aspeed_intc_enable_handler(s, offset, data);
563         break;
564     case R_SSPINT128_STATUS:
565     case R_SSPINT129_STATUS:
566     case R_SSPINT130_STATUS:
567     case R_SSPINT131_STATUS:
568     case R_SSPINT132_STATUS:
569     case R_SSPINT133_STATUS:
570     case R_SSPINT134_STATUS:
571     case R_SSPINT135_STATUS:
572     case R_SSPINT136_STATUS:
573         aspeed_intc_status_handler(s, offset, data);
574         break;
575     case R_SSPINT160_169_STATUS:
576         aspeed_intc_status_handler_multi_outpins(s, offset, data);
577         break;
578     default:
579         s->regs[reg] = data;
580         break;
581     }
582 }
583 
aspeed_tsp_intc_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)584 static void aspeed_tsp_intc_write(void *opaque, hwaddr offset, uint64_t data,
585                                         unsigned size)
586 {
587     AspeedINTCState *s = ASPEED_INTC(opaque);
588     const char *name = object_get_typename(OBJECT(s));
589     uint32_t reg = offset >> 2;
590 
591     trace_aspeed_intc_write(name, offset, size, data);
592 
593     switch (reg) {
594     case R_TSPINT128_EN:
595     case R_TSPINT129_EN:
596     case R_TSPINT130_EN:
597     case R_TSPINT131_EN:
598     case R_TSPINT132_EN:
599     case R_TSPINT133_EN:
600     case R_TSPINT134_EN:
601     case R_TSPINT135_EN:
602     case R_TSPINT136_EN:
603     case R_TSPINT160_169_EN:
604         aspeed_intc_enable_handler(s, offset, data);
605         break;
606     case R_TSPINT128_STATUS:
607     case R_TSPINT129_STATUS:
608     case R_TSPINT130_STATUS:
609     case R_TSPINT131_STATUS:
610     case R_TSPINT132_STATUS:
611     case R_TSPINT133_STATUS:
612     case R_TSPINT134_STATUS:
613     case R_TSPINT135_STATUS:
614     case R_TSPINT136_STATUS:
615         aspeed_intc_status_handler(s, offset, data);
616         break;
617     case R_TSPINT160_169_STATUS:
618         aspeed_intc_status_handler_multi_outpins(s, offset, data);
619         break;
620     default:
621         s->regs[reg] = data;
622         break;
623     }
624 }
625 
aspeed_intcio_read(void * opaque,hwaddr offset,unsigned int size)626 static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset,
627                                    unsigned int size)
628 {
629     AspeedINTCState *s = ASPEED_INTC(opaque);
630     const char *name = object_get_typename(OBJECT(s));
631     uint32_t reg = offset >> 2;
632     uint32_t value = 0;
633 
634     value = s->regs[reg];
635     trace_aspeed_intc_read(name, offset, size, value);
636 
637     return value;
638 }
639 
aspeed_intcio_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)640 static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data,
641                                 unsigned size)
642 {
643     AspeedINTCState *s = ASPEED_INTC(opaque);
644     const char *name = object_get_typename(OBJECT(s));
645     uint32_t reg = offset >> 2;
646 
647     trace_aspeed_intc_write(name, offset, size, data);
648 
649     switch (reg) {
650     case R_GICINT192_EN:
651     case R_GICINT193_EN:
652     case R_GICINT194_EN:
653     case R_GICINT195_EN:
654     case R_GICINT196_EN:
655     case R_GICINT197_EN:
656         aspeed_intc_enable_handler(s, offset, data);
657         break;
658     case R_GICINT192_STATUS:
659     case R_GICINT193_STATUS:
660     case R_GICINT194_STATUS:
661     case R_GICINT195_STATUS:
662     case R_GICINT196_STATUS:
663     case R_GICINT197_STATUS:
664         aspeed_intc_status_handler(s, offset, data);
665         break;
666     default:
667         s->regs[reg] = data;
668         break;
669     }
670 }
671 
aspeed_ssp_intcio_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)672 static void aspeed_ssp_intcio_write(void *opaque, hwaddr offset, uint64_t data,
673                                 unsigned size)
674 {
675     AspeedINTCState *s = ASPEED_INTC(opaque);
676     const char *name = object_get_typename(OBJECT(s));
677     uint32_t reg = offset >> 2;
678 
679     trace_aspeed_intc_write(name, offset, size, data);
680 
681     switch (reg) {
682     case R_SSPINT160_EN:
683     case R_SSPINT161_EN:
684     case R_SSPINT162_EN:
685     case R_SSPINT163_EN:
686     case R_SSPINT164_EN:
687     case R_SSPINT165_EN:
688         aspeed_intc_enable_handler(s, offset, data);
689         break;
690     case R_SSPINT160_STATUS:
691     case R_SSPINT161_STATUS:
692     case R_SSPINT162_STATUS:
693     case R_SSPINT163_STATUS:
694     case R_SSPINT164_STATUS:
695     case R_SSPINT165_STATUS:
696         aspeed_intc_status_handler(s, offset, data);
697         break;
698     default:
699         s->regs[reg] = data;
700         break;
701     }
702 }
703 
aspeed_tsp_intcio_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)704 static void aspeed_tsp_intcio_write(void *opaque, hwaddr offset, uint64_t data,
705                                 unsigned size)
706 {
707     AspeedINTCState *s = ASPEED_INTC(opaque);
708     const char *name = object_get_typename(OBJECT(s));
709     uint32_t reg = offset >> 2;
710 
711     trace_aspeed_intc_write(name, offset, size, data);
712 
713     switch (reg) {
714     case R_TSPINT160_EN:
715     case R_TSPINT161_EN:
716     case R_TSPINT162_EN:
717     case R_TSPINT163_EN:
718     case R_TSPINT164_EN:
719     case R_TSPINT165_EN:
720         aspeed_intc_enable_handler(s, offset, data);
721         break;
722     case R_TSPINT160_STATUS:
723     case R_TSPINT161_STATUS:
724     case R_TSPINT162_STATUS:
725     case R_TSPINT163_STATUS:
726     case R_TSPINT164_STATUS:
727     case R_TSPINT165_STATUS:
728         aspeed_intc_status_handler(s, offset, data);
729         break;
730     default:
731         s->regs[reg] = data;
732         break;
733     }
734 }
735 
736 static const MemoryRegionOps aspeed_intc_ops = {
737     .read = aspeed_intc_read,
738     .write = aspeed_intc_write,
739     .endianness = DEVICE_LITTLE_ENDIAN,
740     .impl.min_access_size = 4,
741     .valid = {
742         .min_access_size = 4,
743         .max_access_size = 4,
744     }
745 };
746 
747 static const MemoryRegionOps aspeed_intcio_ops = {
748     .read = aspeed_intcio_read,
749     .write = aspeed_intcio_write,
750     .endianness = DEVICE_LITTLE_ENDIAN,
751     .impl.min_access_size = 4,
752     .valid = {
753         .min_access_size = 4,
754         .max_access_size = 4,
755     }
756 };
757 
758 static const MemoryRegionOps aspeed_ssp_intc_ops = {
759     .read = aspeed_intc_read,
760     .write = aspeed_ssp_intc_write,
761     .endianness = DEVICE_LITTLE_ENDIAN,
762     .impl.min_access_size = 4,
763     .valid = {
764         .min_access_size = 4,
765         .max_access_size = 4,
766     }
767 };
768 
769 static const MemoryRegionOps aspeed_ssp_intcio_ops = {
770     .read = aspeed_intcio_read,
771     .write = aspeed_ssp_intcio_write,
772     .endianness = DEVICE_LITTLE_ENDIAN,
773     .impl.min_access_size = 4,
774     .valid = {
775         .min_access_size = 4,
776         .max_access_size = 4,
777     }
778 };
779 
780 static const MemoryRegionOps aspeed_tsp_intc_ops = {
781     .read = aspeed_intc_read,
782     .write = aspeed_tsp_intc_write,
783     .endianness = DEVICE_LITTLE_ENDIAN,
784     .impl.min_access_size = 4,
785     .valid = {
786         .min_access_size = 4,
787         .max_access_size = 4,
788     }
789 };
790 
791 static const MemoryRegionOps aspeed_tsp_intcio_ops = {
792     .read = aspeed_intcio_read,
793     .write = aspeed_tsp_intcio_write,
794     .endianness = DEVICE_LITTLE_ENDIAN,
795     .impl.min_access_size = 4,
796     .valid = {
797         .min_access_size = 4,
798         .max_access_size = 4,
799     }
800 };
801 
aspeed_intc_instance_init(Object * obj)802 static void aspeed_intc_instance_init(Object *obj)
803 {
804     AspeedINTCState *s = ASPEED_INTC(obj);
805     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
806     int i;
807 
808     assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS);
809     for (i = 0; i < aic->num_inpins; i++) {
810         object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
811                                 TYPE_OR_IRQ);
812         object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
813                                 aic->num_lines, &error_abort);
814     }
815 }
816 
aspeed_intc_reset(DeviceState * dev)817 static void aspeed_intc_reset(DeviceState *dev)
818 {
819     AspeedINTCState *s = ASPEED_INTC(dev);
820     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
821 
822     memset(s->regs, 0, aic->nr_regs << 2);
823     memset(s->enable, 0, sizeof(s->enable));
824     memset(s->mask, 0, sizeof(s->mask));
825     memset(s->pending, 0, sizeof(s->pending));
826 }
827 
aspeed_intc_realize(DeviceState * dev,Error ** errp)828 static void aspeed_intc_realize(DeviceState *dev, Error **errp)
829 {
830     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
831     AspeedINTCState *s = ASPEED_INTC(dev);
832     AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
833     int i;
834 
835     memory_region_init(&s->iomem_container, OBJECT(s),
836             TYPE_ASPEED_INTC ".container", aic->mem_size);
837 
838     sysbus_init_mmio(sbd, &s->iomem_container);
839 
840     s->regs = g_new(uint32_t, aic->nr_regs);
841     memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s,
842                           TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
843 
844     memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
845                                 &s->iomem);
846 
847     qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins);
848 
849     for (i = 0; i < aic->num_inpins; i++) {
850         if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
851             return;
852         }
853     }
854 
855     for (i = 0; i < aic->num_outpins; i++) {
856         sysbus_init_irq(sbd, &s->output_pins[i]);
857     }
858 }
859 
aspeed_intc_unrealize(DeviceState * dev)860 static void aspeed_intc_unrealize(DeviceState *dev)
861 {
862     AspeedINTCState *s = ASPEED_INTC(dev);
863 
864     g_free(s->regs);
865     s->regs = NULL;
866 }
867 
aspeed_intc_class_init(ObjectClass * klass,const void * data)868 static void aspeed_intc_class_init(ObjectClass *klass, const void *data)
869 {
870     DeviceClass *dc = DEVICE_CLASS(klass);
871     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
872 
873     dc->desc = "ASPEED INTC Controller";
874     dc->realize = aspeed_intc_realize;
875     dc->unrealize = aspeed_intc_unrealize;
876     device_class_set_legacy_reset(dc, aspeed_intc_reset);
877     dc->vmsd = NULL;
878 
879     aic->reg_ops = &aspeed_intc_ops;
880 }
881 
882 static const TypeInfo aspeed_intc_info = {
883     .name = TYPE_ASPEED_INTC,
884     .parent = TYPE_SYS_BUS_DEVICE,
885     .instance_init = aspeed_intc_instance_init,
886     .instance_size = sizeof(AspeedINTCState),
887     .class_init = aspeed_intc_class_init,
888     .class_size = sizeof(AspeedINTCClass),
889     .abstract = true,
890 };
891 
892 static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = {
893     {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS},
894     {1, 10, 1, R_GICINT128_EN, R_GICINT128_STATUS},
895     {2, 11, 1, R_GICINT129_EN, R_GICINT129_STATUS},
896     {3, 12, 1, R_GICINT130_EN, R_GICINT130_STATUS},
897     {4, 13, 1, R_GICINT131_EN, R_GICINT131_STATUS},
898     {5, 14, 1, R_GICINT132_EN, R_GICINT132_STATUS},
899     {6, 15, 1, R_GICINT133_EN, R_GICINT133_STATUS},
900     {7, 16, 1, R_GICINT134_EN, R_GICINT134_STATUS},
901     {8, 17, 1, R_GICINT135_EN, R_GICINT135_STATUS},
902     {9, 18, 1, R_GICINT136_EN, R_GICINT136_STATUS},
903 };
904 
aspeed_2700_intc_class_init(ObjectClass * klass,const void * data)905 static void aspeed_2700_intc_class_init(ObjectClass *klass, const void *data)
906 {
907     DeviceClass *dc = DEVICE_CLASS(klass);
908     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
909 
910     dc->desc = "ASPEED 2700 INTC Controller";
911     aic->num_lines = 32;
912     aic->num_inpins = 10;
913     aic->num_outpins = 19;
914     aic->mem_size = 0x4000;
915     aic->nr_regs = 0xB08 >> 2;
916     aic->reg_offset = 0x1000;
917     aic->irq_table = aspeed_2700_intc_irqs;
918     aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc_irqs);
919 }
920 
921 static const TypeInfo aspeed_2700_intc_info = {
922     .name = TYPE_ASPEED_2700_INTC,
923     .parent = TYPE_ASPEED_INTC,
924     .class_init = aspeed_2700_intc_class_init,
925 };
926 
927 static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
928     {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS},
929     {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS},
930     {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS},
931     {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS},
932     {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS},
933     {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS},
934 };
935 
aspeed_2700_intcio_class_init(ObjectClass * klass,const void * data)936 static void aspeed_2700_intcio_class_init(ObjectClass *klass, const void *data)
937 {
938     DeviceClass *dc = DEVICE_CLASS(klass);
939     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
940 
941     dc->desc = "ASPEED 2700 INTC IO Controller";
942     aic->num_lines = 32;
943     aic->num_inpins = 6;
944     aic->num_outpins = 6;
945     aic->mem_size = 0x400;
946     aic->nr_regs = 0x58 >> 2;
947     aic->reg_offset = 0x100;
948     aic->reg_ops = &aspeed_intcio_ops;
949     aic->irq_table = aspeed_2700_intcio_irqs;
950     aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcio_irqs);
951 }
952 
953 static const TypeInfo aspeed_2700_intcio_info = {
954     .name = TYPE_ASPEED_2700_INTCIO,
955     .parent = TYPE_ASPEED_INTC,
956     .class_init = aspeed_2700_intcio_class_init,
957 };
958 
959 static AspeedINTCIRQ aspeed_2700ssp_intc_irqs[ASPEED_INTC_MAX_INPINS] = {
960     {0, 0, 10, R_SSPINT160_169_EN, R_SSPINT160_169_STATUS},
961     {1, 10, 1, R_SSPINT128_EN, R_SSPINT128_STATUS},
962     {2, 11, 1, R_SSPINT129_EN, R_SSPINT129_STATUS},
963     {3, 12, 1, R_SSPINT130_EN, R_SSPINT130_STATUS},
964     {4, 13, 1, R_SSPINT131_EN, R_SSPINT131_STATUS},
965     {5, 14, 1, R_SSPINT132_EN, R_SSPINT132_STATUS},
966     {6, 15, 1, R_SSPINT133_EN, R_SSPINT133_STATUS},
967     {7, 16, 1, R_SSPINT134_EN, R_SSPINT134_STATUS},
968     {8, 17, 1, R_SSPINT135_EN, R_SSPINT135_STATUS},
969     {9, 18, 1, R_SSPINT136_EN, R_SSPINT136_STATUS},
970 };
971 
aspeed_2700ssp_intc_class_init(ObjectClass * klass,const void * data)972 static void aspeed_2700ssp_intc_class_init(ObjectClass *klass, const void *data)
973 {
974     DeviceClass *dc = DEVICE_CLASS(klass);
975     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
976 
977     dc->desc = "ASPEED 2700 SSP INTC Controller";
978     aic->num_lines = 32;
979     aic->num_inpins = 10;
980     aic->num_outpins = 19;
981     aic->mem_size = 0x4000;
982     aic->nr_regs = 0x2B08 >> 2;
983     aic->reg_offset = 0x0;
984     aic->reg_ops = &aspeed_ssp_intc_ops;
985     aic->irq_table = aspeed_2700ssp_intc_irqs;
986     aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intc_irqs);
987 }
988 
989 static const TypeInfo aspeed_2700ssp_intc_info = {
990     .name = TYPE_ASPEED_2700SSP_INTC,
991     .parent = TYPE_ASPEED_INTC,
992     .class_init = aspeed_2700ssp_intc_class_init,
993 };
994 
995 static AspeedINTCIRQ aspeed_2700ssp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
996     {0, 0, 1, R_SSPINT160_EN, R_SSPINT160_STATUS},
997     {1, 1, 1, R_SSPINT161_EN, R_SSPINT161_STATUS},
998     {2, 2, 1, R_SSPINT162_EN, R_SSPINT162_STATUS},
999     {3, 3, 1, R_SSPINT163_EN, R_SSPINT163_STATUS},
1000     {4, 4, 1, R_SSPINT164_EN, R_SSPINT164_STATUS},
1001     {5, 5, 1, R_SSPINT165_EN, R_SSPINT165_STATUS},
1002 };
1003 
aspeed_2700ssp_intcio_class_init(ObjectClass * klass,const void * data)1004 static void aspeed_2700ssp_intcio_class_init(ObjectClass *klass,
1005                                              const void *data)
1006 {
1007     DeviceClass *dc = DEVICE_CLASS(klass);
1008     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
1009 
1010     dc->desc = "ASPEED 2700 SSP INTC IO Controller";
1011     aic->num_lines = 32;
1012     aic->num_inpins = 6;
1013     aic->num_outpins = 6;
1014     aic->mem_size = 0x400;
1015     aic->nr_regs = 0x1d8 >> 2;
1016     aic->reg_offset = 0;
1017     aic->reg_ops = &aspeed_ssp_intcio_ops;
1018     aic->irq_table = aspeed_2700ssp_intcio_irqs;
1019     aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intcio_irqs);
1020 }
1021 
1022 static const TypeInfo aspeed_2700ssp_intcio_info = {
1023     .name = TYPE_ASPEED_2700SSP_INTCIO,
1024     .parent = TYPE_ASPEED_INTC,
1025     .class_init = aspeed_2700ssp_intcio_class_init,
1026 };
1027 
1028 static AspeedINTCIRQ aspeed_2700tsp_intc_irqs[ASPEED_INTC_MAX_INPINS] = {
1029     {0, 0, 10, R_TSPINT160_169_EN, R_TSPINT160_169_STATUS},
1030     {1, 10, 1, R_TSPINT128_EN, R_TSPINT128_STATUS},
1031     {2, 11, 1, R_TSPINT129_EN, R_TSPINT129_STATUS},
1032     {3, 12, 1, R_TSPINT130_EN, R_TSPINT130_STATUS},
1033     {4, 13, 1, R_TSPINT131_EN, R_TSPINT131_STATUS},
1034     {5, 14, 1, R_TSPINT132_EN, R_TSPINT132_STATUS},
1035     {6, 15, 1, R_TSPINT133_EN, R_TSPINT133_STATUS},
1036     {7, 16, 1, R_TSPINT134_EN, R_TSPINT134_STATUS},
1037     {8, 17, 1, R_TSPINT135_EN, R_TSPINT135_STATUS},
1038     {9, 18, 1, R_TSPINT136_EN, R_TSPINT136_STATUS},
1039 };
1040 
aspeed_2700tsp_intc_class_init(ObjectClass * klass,const void * data)1041 static void aspeed_2700tsp_intc_class_init(ObjectClass *klass, const void *data)
1042 {
1043     DeviceClass *dc = DEVICE_CLASS(klass);
1044     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
1045 
1046     dc->desc = "ASPEED 2700 TSP INTC Controller";
1047     aic->num_lines = 32;
1048     aic->num_inpins = 10;
1049     aic->num_outpins = 19;
1050     aic->mem_size = 0x4000;
1051     aic->nr_regs = 0x3B08 >> 2;
1052     aic->reg_offset = 0;
1053     aic->reg_ops = &aspeed_tsp_intc_ops;
1054     aic->irq_table = aspeed_2700tsp_intc_irqs;
1055     aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intc_irqs);
1056 }
1057 
1058 static const TypeInfo aspeed_2700tsp_intc_info = {
1059     .name = TYPE_ASPEED_2700TSP_INTC,
1060     .parent = TYPE_ASPEED_INTC,
1061     .class_init = aspeed_2700tsp_intc_class_init,
1062 };
1063 
1064 static AspeedINTCIRQ aspeed_2700tsp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
1065     {0, 0, 1, R_TSPINT160_EN, R_TSPINT160_STATUS},
1066     {1, 1, 1, R_TSPINT161_EN, R_TSPINT161_STATUS},
1067     {2, 2, 1, R_TSPINT162_EN, R_TSPINT162_STATUS},
1068     {3, 3, 1, R_TSPINT163_EN, R_TSPINT163_STATUS},
1069     {4, 4, 1, R_TSPINT164_EN, R_TSPINT164_STATUS},
1070     {5, 5, 1, R_TSPINT165_EN, R_TSPINT165_STATUS},
1071 };
1072 
aspeed_2700tsp_intcio_class_init(ObjectClass * klass,const void * data)1073 static void aspeed_2700tsp_intcio_class_init(ObjectClass *klass,
1074                                              const void *data)
1075 {
1076     DeviceClass *dc = DEVICE_CLASS(klass);
1077     AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
1078 
1079     dc->desc = "ASPEED 2700 TSP INTC IO Controller";
1080     aic->num_lines = 32;
1081     aic->num_inpins = 6;
1082     aic->num_outpins = 6;
1083     aic->mem_size = 0x400;
1084     aic->nr_regs = 0x258 >> 2;
1085     aic->reg_offset = 0x0;
1086     aic->reg_ops = &aspeed_tsp_intcio_ops;
1087     aic->irq_table = aspeed_2700tsp_intcio_irqs;
1088     aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intcio_irqs);
1089 }
1090 
1091 static const TypeInfo aspeed_2700tsp_intcio_info = {
1092     .name = TYPE_ASPEED_2700TSP_INTCIO,
1093     .parent = TYPE_ASPEED_INTC,
1094     .class_init = aspeed_2700tsp_intcio_class_init,
1095 };
1096 
aspeed_intc_register_types(void)1097 static void aspeed_intc_register_types(void)
1098 {
1099     type_register_static(&aspeed_intc_info);
1100     type_register_static(&aspeed_2700_intc_info);
1101     type_register_static(&aspeed_2700_intcio_info);
1102     type_register_static(&aspeed_2700ssp_intc_info);
1103     type_register_static(&aspeed_2700ssp_intcio_info);
1104     type_register_static(&aspeed_2700tsp_intc_info);
1105     type_register_static(&aspeed_2700tsp_intcio_info);
1106 }
1107 
1108 type_init(aspeed_intc_register_types);
1109