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 static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic, 66 uint32_t reg) 67 { 68 int i; 69 70 for (i = 0; i < aic->irq_table_count; i++) { 71 if (aic->irq_table[i].enable_reg == reg || 72 aic->irq_table[i].status_reg == reg) { 73 return &aic->irq_table[i]; 74 } 75 } 76 77 /* 78 * Invalid reg. 79 */ 80 g_assert_not_reached(); 81 } 82 83 /* 84 * Update the state of an interrupt controller pin by setting 85 * the specified output pin to the given level. 86 * The input pin index should be between 0 and the number of input pins. 87 * The output pin index should be between 0 and the number of output pins. 88 */ 89 static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx, 90 int outpin_idx, int level) 91 { 92 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 93 const char *name = object_get_typename(OBJECT(s)); 94 95 assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins)); 96 97 trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level); 98 qemu_set_irq(s->output_pins[outpin_idx], level); 99 } 100 101 static void aspeed_intc_set_irq_handler(AspeedINTCState *s, 102 const AspeedINTCIRQ *intc_irq, 103 uint32_t select) 104 { 105 const char *name = object_get_typename(OBJECT(s)); 106 uint32_t status_reg; 107 int outpin_idx; 108 int inpin_idx; 109 110 status_reg = intc_irq->status_reg; 111 outpin_idx = intc_irq->outpin_idx; 112 inpin_idx = intc_irq->inpin_idx; 113 114 if ((s->mask[inpin_idx] & select) || (s->regs[status_reg] & select)) { 115 /* 116 * a. mask is not 0 means in ISR mode 117 * sources interrupt routine are executing. 118 * b. status register value is not 0 means previous 119 * source interrupt does not be executed, yet. 120 * 121 * save source interrupt to pending variable. 122 */ 123 s->pending[inpin_idx] |= select; 124 trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]); 125 } else { 126 /* 127 * notify firmware which source interrupt are coming 128 * by setting status register 129 */ 130 s->regs[status_reg] = select; 131 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx, 132 s->regs[status_reg]); 133 aspeed_intc_update(s, inpin_idx, outpin_idx, 1); 134 } 135 } 136 137 static void aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState *s, 138 const AspeedINTCIRQ *intc_irq, uint32_t select) 139 { 140 const char *name = object_get_typename(OBJECT(s)); 141 uint32_t status_reg; 142 int num_outpins; 143 int outpin_idx; 144 int inpin_idx; 145 int i; 146 147 num_outpins = intc_irq->num_outpins; 148 status_reg = intc_irq->status_reg; 149 outpin_idx = intc_irq->outpin_idx; 150 inpin_idx = intc_irq->inpin_idx; 151 152 for (i = 0; i < num_outpins; i++) { 153 if (select & BIT(i)) { 154 if (s->mask[inpin_idx] & BIT(i) || 155 s->regs[status_reg] & BIT(i)) { 156 /* 157 * a. mask bit is not 0 means in ISR mode sources interrupt 158 * routine are executing. 159 * b. status bit is not 0 means previous source interrupt 160 * does not be executed, yet. 161 * 162 * save source interrupt to pending bit. 163 */ 164 s->pending[inpin_idx] |= BIT(i); 165 trace_aspeed_intc_pending_irq(name, inpin_idx, 166 s->pending[inpin_idx]); 167 } else { 168 /* 169 * notify firmware which source interrupt are coming 170 * by setting status bit 171 */ 172 s->regs[status_reg] |= BIT(i); 173 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i, 174 s->regs[status_reg]); 175 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1); 176 } 177 } 178 } 179 } 180 181 /* 182 * GICINT192_201 maps 1:10 to input IRQ 0 and output IRQs 0 to 9. 183 * GICINT128 to GICINT136 map 1:1 to input IRQs 1 to 9 and output 184 * IRQs 10 to 18. The value of input IRQ should be between 0 and 185 * the number of input pins. 186 */ 187 static void aspeed_intc_set_irq(void *opaque, int irq, int level) 188 { 189 AspeedINTCState *s = (AspeedINTCState *)opaque; 190 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 191 const char *name = object_get_typename(OBJECT(s)); 192 const AspeedINTCIRQ *intc_irq; 193 uint32_t select = 0; 194 uint32_t enable; 195 int num_outpins; 196 int inpin_idx; 197 int i; 198 199 assert(irq < aic->num_inpins); 200 201 intc_irq = &aic->irq_table[irq]; 202 num_outpins = intc_irq->num_outpins; 203 inpin_idx = intc_irq->inpin_idx; 204 trace_aspeed_intc_set_irq(name, inpin_idx, level); 205 enable = s->enable[inpin_idx]; 206 207 if (!level) { 208 return; 209 } 210 211 for (i = 0; i < aic->num_lines; i++) { 212 if (s->orgates[inpin_idx].levels[i]) { 213 if (enable & BIT(i)) { 214 select |= BIT(i); 215 } 216 } 217 } 218 219 if (!select) { 220 return; 221 } 222 223 trace_aspeed_intc_select(name, select); 224 if (num_outpins > 1) { 225 aspeed_intc_set_irq_handler_multi_outpins(s, intc_irq, select); 226 } else { 227 aspeed_intc_set_irq_handler(s, intc_irq, select); 228 } 229 } 230 231 static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset, 232 uint64_t data) 233 { 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 reg = offset >> 2; 238 uint32_t old_enable; 239 uint32_t change; 240 int inpin_idx; 241 242 intc_irq = aspeed_intc_get_irq(aic, reg); 243 inpin_idx = intc_irq->inpin_idx; 244 245 assert(inpin_idx < aic->num_inpins); 246 247 /* 248 * The enable registers are used to enable source interrupts. 249 * They also handle masking and unmasking of source interrupts 250 * during the execution of the source ISR. 251 */ 252 253 /* disable all source interrupt */ 254 if (!data && !s->enable[inpin_idx]) { 255 s->regs[reg] = data; 256 return; 257 } 258 259 old_enable = s->enable[inpin_idx]; 260 s->enable[inpin_idx] |= data; 261 262 /* enable new source interrupt */ 263 if (old_enable != s->enable[inpin_idx]) { 264 trace_aspeed_intc_enable(name, s->enable[inpin_idx]); 265 s->regs[reg] = data; 266 return; 267 } 268 269 /* mask and unmask source interrupt */ 270 change = s->regs[reg] ^ data; 271 if (change & data) { 272 s->mask[inpin_idx] &= ~change; 273 trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]); 274 } else { 275 s->mask[inpin_idx] |= change; 276 trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]); 277 } 278 279 s->regs[reg] = data; 280 } 281 282 static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset, 283 uint64_t data) 284 { 285 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 286 const char *name = object_get_typename(OBJECT(s)); 287 const AspeedINTCIRQ *intc_irq; 288 uint32_t reg = offset >> 2; 289 int outpin_idx; 290 int inpin_idx; 291 292 if (!data) { 293 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__); 294 return; 295 } 296 297 intc_irq = aspeed_intc_get_irq(aic, reg); 298 outpin_idx = intc_irq->outpin_idx; 299 inpin_idx = intc_irq->inpin_idx; 300 301 assert(inpin_idx < aic->num_inpins); 302 303 /* clear status */ 304 s->regs[reg] &= ~data; 305 306 /* 307 * These status registers are used for notify sources ISR are executed. 308 * If one source ISR is executed, it will clear one bit. 309 * If it clear all bits, it means to initialize this register status 310 * rather than sources ISR are executed. 311 */ 312 if (data == 0xffffffff) { 313 return; 314 } 315 316 /* All source ISR execution are done */ 317 if (!s->regs[reg]) { 318 trace_aspeed_intc_all_isr_done(name, inpin_idx); 319 if (s->pending[inpin_idx]) { 320 /* 321 * handle pending source interrupt 322 * notify firmware which source interrupt are pending 323 * by setting status register 324 */ 325 s->regs[reg] = s->pending[inpin_idx]; 326 s->pending[inpin_idx] = 0; 327 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx, 328 s->regs[reg]); 329 aspeed_intc_update(s, inpin_idx, outpin_idx, 1); 330 } else { 331 /* clear irq */ 332 trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx, 0); 333 aspeed_intc_update(s, inpin_idx, outpin_idx, 0); 334 } 335 } 336 } 337 338 static void aspeed_intc_status_handler_multi_outpins(AspeedINTCState *s, 339 hwaddr offset, uint64_t data) 340 { 341 const char *name = object_get_typename(OBJECT(s)); 342 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 343 const AspeedINTCIRQ *intc_irq; 344 uint32_t reg = offset >> 2; 345 int num_outpins; 346 int outpin_idx; 347 int inpin_idx; 348 int i; 349 350 if (!data) { 351 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__); 352 return; 353 } 354 355 intc_irq = aspeed_intc_get_irq(aic, reg); 356 num_outpins = intc_irq->num_outpins; 357 outpin_idx = intc_irq->outpin_idx; 358 inpin_idx = intc_irq->inpin_idx; 359 assert(inpin_idx < aic->num_inpins); 360 361 /* clear status */ 362 s->regs[reg] &= ~data; 363 364 /* 365 * The status registers are used for notify sources ISR are executed. 366 * If one source ISR is executed, it will clear one bit. 367 * If it clear all bits, it means to initialize this register status 368 * rather than sources ISR are executed. 369 */ 370 if (data == 0xffffffff) { 371 return; 372 } 373 374 for (i = 0; i < num_outpins; i++) { 375 /* All source ISR executions are done from a specific bit */ 376 if (data & BIT(i)) { 377 trace_aspeed_intc_all_isr_done_bit(name, inpin_idx, i); 378 if (s->pending[inpin_idx] & BIT(i)) { 379 /* 380 * Handle pending source interrupt. 381 * Notify firmware which source interrupt is pending 382 * by setting the status bit. 383 */ 384 s->regs[reg] |= BIT(i); 385 s->pending[inpin_idx] &= ~BIT(i); 386 trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i, 387 s->regs[reg]); 388 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1); 389 } else { 390 /* clear irq for the specific bit */ 391 trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx + i, 0); 392 aspeed_intc_update(s, inpin_idx, outpin_idx + i, 0); 393 } 394 } 395 } 396 } 397 398 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size) 399 { 400 AspeedINTCState *s = ASPEED_INTC(opaque); 401 const char *name = object_get_typename(OBJECT(s)); 402 uint32_t reg = offset >> 2; 403 uint32_t value = 0; 404 405 value = s->regs[reg]; 406 trace_aspeed_intc_read(name, offset, size, value); 407 408 return value; 409 } 410 411 static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data, 412 unsigned size) 413 { 414 AspeedINTCState *s = ASPEED_INTC(opaque); 415 const char *name = object_get_typename(OBJECT(s)); 416 uint32_t reg = offset >> 2; 417 418 trace_aspeed_intc_write(name, offset, size, data); 419 420 switch (reg) { 421 case R_GICINT128_EN: 422 case R_GICINT129_EN: 423 case R_GICINT130_EN: 424 case R_GICINT131_EN: 425 case R_GICINT132_EN: 426 case R_GICINT133_EN: 427 case R_GICINT134_EN: 428 case R_GICINT135_EN: 429 case R_GICINT136_EN: 430 case R_GICINT192_201_EN: 431 aspeed_intc_enable_handler(s, offset, data); 432 break; 433 case R_GICINT128_STATUS: 434 case R_GICINT129_STATUS: 435 case R_GICINT130_STATUS: 436 case R_GICINT131_STATUS: 437 case R_GICINT132_STATUS: 438 case R_GICINT133_STATUS: 439 case R_GICINT134_STATUS: 440 case R_GICINT135_STATUS: 441 case R_GICINT136_STATUS: 442 aspeed_intc_status_handler(s, offset, data); 443 break; 444 case R_GICINT192_201_STATUS: 445 aspeed_intc_status_handler_multi_outpins(s, offset, data); 446 break; 447 default: 448 s->regs[reg] = data; 449 break; 450 } 451 452 return; 453 } 454 455 static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset, 456 unsigned int size) 457 { 458 AspeedINTCState *s = ASPEED_INTC(opaque); 459 const char *name = object_get_typename(OBJECT(s)); 460 uint32_t reg = offset >> 2; 461 uint32_t value = 0; 462 463 value = s->regs[reg]; 464 trace_aspeed_intc_read(name, offset, size, value); 465 466 return value; 467 } 468 469 static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data, 470 unsigned size) 471 { 472 AspeedINTCState *s = ASPEED_INTC(opaque); 473 const char *name = object_get_typename(OBJECT(s)); 474 uint32_t reg = offset >> 2; 475 476 trace_aspeed_intc_write(name, offset, size, data); 477 478 switch (reg) { 479 case R_GICINT192_EN: 480 case R_GICINT193_EN: 481 case R_GICINT194_EN: 482 case R_GICINT195_EN: 483 case R_GICINT196_EN: 484 case R_GICINT197_EN: 485 aspeed_intc_enable_handler(s, offset, data); 486 break; 487 case R_GICINT192_STATUS: 488 case R_GICINT193_STATUS: 489 case R_GICINT194_STATUS: 490 case R_GICINT195_STATUS: 491 case R_GICINT196_STATUS: 492 case R_GICINT197_STATUS: 493 aspeed_intc_status_handler(s, offset, data); 494 break; 495 default: 496 s->regs[reg] = data; 497 break; 498 } 499 500 return; 501 } 502 503 504 static const MemoryRegionOps aspeed_intc_ops = { 505 .read = aspeed_intc_read, 506 .write = aspeed_intc_write, 507 .endianness = DEVICE_LITTLE_ENDIAN, 508 .valid = { 509 .min_access_size = 4, 510 .max_access_size = 4, 511 } 512 }; 513 514 static const MemoryRegionOps aspeed_intcio_ops = { 515 .read = aspeed_intcio_read, 516 .write = aspeed_intcio_write, 517 .endianness = DEVICE_LITTLE_ENDIAN, 518 .valid = { 519 .min_access_size = 4, 520 .max_access_size = 4, 521 } 522 }; 523 524 static void aspeed_intc_instance_init(Object *obj) 525 { 526 AspeedINTCState *s = ASPEED_INTC(obj); 527 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 528 int i; 529 530 assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS); 531 for (i = 0; i < aic->num_inpins; i++) { 532 object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i], 533 TYPE_OR_IRQ); 534 object_property_set_int(OBJECT(&s->orgates[i]), "num-lines", 535 aic->num_lines, &error_abort); 536 } 537 } 538 539 static void aspeed_intc_reset(DeviceState *dev) 540 { 541 AspeedINTCState *s = ASPEED_INTC(dev); 542 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 543 544 memset(s->regs, 0, aic->nr_regs << 2); 545 memset(s->enable, 0, sizeof(s->enable)); 546 memset(s->mask, 0, sizeof(s->mask)); 547 memset(s->pending, 0, sizeof(s->pending)); 548 } 549 550 static void aspeed_intc_realize(DeviceState *dev, Error **errp) 551 { 552 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 553 AspeedINTCState *s = ASPEED_INTC(dev); 554 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 555 int i; 556 557 memory_region_init(&s->iomem_container, OBJECT(s), 558 TYPE_ASPEED_INTC ".container", aic->mem_size); 559 560 sysbus_init_mmio(sbd, &s->iomem_container); 561 562 s->regs = g_new(uint32_t, aic->nr_regs); 563 memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s, 564 TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2); 565 566 memory_region_add_subregion(&s->iomem_container, aic->reg_offset, 567 &s->iomem); 568 569 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins); 570 571 for (i = 0; i < aic->num_inpins; i++) { 572 if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) { 573 return; 574 } 575 } 576 577 for (i = 0; i < aic->num_outpins; i++) { 578 sysbus_init_irq(sbd, &s->output_pins[i]); 579 } 580 } 581 582 static void aspeed_intc_unrealize(DeviceState *dev) 583 { 584 AspeedINTCState *s = ASPEED_INTC(dev); 585 586 g_free(s->regs); 587 s->regs = NULL; 588 } 589 590 static void aspeed_intc_class_init(ObjectClass *klass, void *data) 591 { 592 DeviceClass *dc = DEVICE_CLASS(klass); 593 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 594 595 dc->desc = "ASPEED INTC Controller"; 596 dc->realize = aspeed_intc_realize; 597 dc->unrealize = aspeed_intc_unrealize; 598 device_class_set_legacy_reset(dc, aspeed_intc_reset); 599 dc->vmsd = NULL; 600 601 aic->reg_ops = &aspeed_intc_ops; 602 } 603 604 static const TypeInfo aspeed_intc_info = { 605 .name = TYPE_ASPEED_INTC, 606 .parent = TYPE_SYS_BUS_DEVICE, 607 .instance_init = aspeed_intc_instance_init, 608 .instance_size = sizeof(AspeedINTCState), 609 .class_init = aspeed_intc_class_init, 610 .class_size = sizeof(AspeedINTCClass), 611 .abstract = true, 612 }; 613 614 static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = { 615 {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS}, 616 {1, 10, 1, R_GICINT128_EN, R_GICINT128_STATUS}, 617 {2, 11, 1, R_GICINT129_EN, R_GICINT129_STATUS}, 618 {3, 12, 1, R_GICINT130_EN, R_GICINT130_STATUS}, 619 {4, 13, 1, R_GICINT131_EN, R_GICINT131_STATUS}, 620 {5, 14, 1, R_GICINT132_EN, R_GICINT132_STATUS}, 621 {6, 15, 1, R_GICINT133_EN, R_GICINT133_STATUS}, 622 {7, 16, 1, R_GICINT134_EN, R_GICINT134_STATUS}, 623 {8, 17, 1, R_GICINT135_EN, R_GICINT135_STATUS}, 624 {9, 18, 1, R_GICINT136_EN, R_GICINT136_STATUS}, 625 }; 626 627 static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data) 628 { 629 DeviceClass *dc = DEVICE_CLASS(klass); 630 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 631 632 dc->desc = "ASPEED 2700 INTC Controller"; 633 aic->num_lines = 32; 634 aic->num_inpins = 10; 635 aic->num_outpins = 19; 636 aic->mem_size = 0x4000; 637 aic->nr_regs = 0xB08 >> 2; 638 aic->reg_offset = 0x1000; 639 aic->irq_table = aspeed_2700_intc_irqs; 640 aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc_irqs); 641 } 642 643 static const TypeInfo aspeed_2700_intc_info = { 644 .name = TYPE_ASPEED_2700_INTC, 645 .parent = TYPE_ASPEED_INTC, 646 .class_init = aspeed_2700_intc_class_init, 647 }; 648 649 static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { 650 {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS}, 651 {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS}, 652 {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS}, 653 {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS}, 654 {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS}, 655 {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS}, 656 }; 657 658 static void aspeed_2700_intcio_class_init(ObjectClass *klass, void *data) 659 { 660 DeviceClass *dc = DEVICE_CLASS(klass); 661 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 662 663 dc->desc = "ASPEED 2700 INTC IO Controller"; 664 aic->num_lines = 32; 665 aic->num_inpins = 6; 666 aic->num_outpins = 6; 667 aic->mem_size = 0x400; 668 aic->nr_regs = 0x58 >> 2; 669 aic->reg_offset = 0x100; 670 aic->reg_ops = &aspeed_intcio_ops; 671 aic->irq_table = aspeed_2700_intcio_irqs; 672 aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcio_irqs); 673 } 674 675 static const TypeInfo aspeed_2700_intcio_info = { 676 .name = TYPE_ASPEED_2700_INTCIO, 677 .parent = TYPE_ASPEED_INTC, 678 .class_init = aspeed_2700_intcio_class_init, 679 }; 680 681 static void aspeed_intc_register_types(void) 682 { 683 type_register_static(&aspeed_intc_info); 684 type_register_static(&aspeed_2700_intc_info); 685 type_register_static(&aspeed_2700_intcio_info); 686 } 687 688 type_init(aspeed_intc_register_types); 689