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