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