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 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 */ 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 .valid = { 741 .min_access_size = 4, 742 .max_access_size = 4, 743 } 744 }; 745 746 static const MemoryRegionOps aspeed_intcio_ops = { 747 .read = aspeed_intcio_read, 748 .write = aspeed_intcio_write, 749 .endianness = DEVICE_LITTLE_ENDIAN, 750 .valid = { 751 .min_access_size = 4, 752 .max_access_size = 4, 753 } 754 }; 755 756 static const MemoryRegionOps aspeed_ssp_intc_ops = { 757 .read = aspeed_intc_read, 758 .write = aspeed_ssp_intc_write, 759 .endianness = DEVICE_LITTLE_ENDIAN, 760 .valid = { 761 .min_access_size = 4, 762 .max_access_size = 4, 763 } 764 }; 765 766 static const MemoryRegionOps aspeed_ssp_intcio_ops = { 767 .read = aspeed_intcio_read, 768 .write = aspeed_ssp_intcio_write, 769 .endianness = DEVICE_LITTLE_ENDIAN, 770 .valid = { 771 .min_access_size = 4, 772 .max_access_size = 4, 773 } 774 }; 775 776 static const MemoryRegionOps aspeed_tsp_intc_ops = { 777 .read = aspeed_intc_read, 778 .write = aspeed_tsp_intc_write, 779 .endianness = DEVICE_LITTLE_ENDIAN, 780 .valid = { 781 .min_access_size = 4, 782 .max_access_size = 4, 783 } 784 }; 785 786 static const MemoryRegionOps aspeed_tsp_intcio_ops = { 787 .read = aspeed_intcio_read, 788 .write = aspeed_tsp_intcio_write, 789 .endianness = DEVICE_LITTLE_ENDIAN, 790 .valid = { 791 .min_access_size = 4, 792 .max_access_size = 4, 793 } 794 }; 795 796 static void aspeed_intc_instance_init(Object *obj) 797 { 798 AspeedINTCState *s = ASPEED_INTC(obj); 799 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 800 int i; 801 802 assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS); 803 for (i = 0; i < aic->num_inpins; i++) { 804 object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i], 805 TYPE_OR_IRQ); 806 object_property_set_int(OBJECT(&s->orgates[i]), "num-lines", 807 aic->num_lines, &error_abort); 808 } 809 } 810 811 static void aspeed_intc_reset(DeviceState *dev) 812 { 813 AspeedINTCState *s = ASPEED_INTC(dev); 814 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 815 816 memset(s->regs, 0, aic->nr_regs << 2); 817 memset(s->enable, 0, sizeof(s->enable)); 818 memset(s->mask, 0, sizeof(s->mask)); 819 memset(s->pending, 0, sizeof(s->pending)); 820 } 821 822 static void aspeed_intc_realize(DeviceState *dev, Error **errp) 823 { 824 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 825 AspeedINTCState *s = ASPEED_INTC(dev); 826 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 827 int i; 828 829 memory_region_init(&s->iomem_container, OBJECT(s), 830 TYPE_ASPEED_INTC ".container", aic->mem_size); 831 832 sysbus_init_mmio(sbd, &s->iomem_container); 833 834 s->regs = g_new(uint32_t, aic->nr_regs); 835 memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s, 836 TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2); 837 838 memory_region_add_subregion(&s->iomem_container, aic->reg_offset, 839 &s->iomem); 840 841 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins); 842 843 for (i = 0; i < aic->num_inpins; i++) { 844 if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) { 845 return; 846 } 847 } 848 849 for (i = 0; i < aic->num_outpins; i++) { 850 sysbus_init_irq(sbd, &s->output_pins[i]); 851 } 852 } 853 854 static void aspeed_intc_unrealize(DeviceState *dev) 855 { 856 AspeedINTCState *s = ASPEED_INTC(dev); 857 858 g_free(s->regs); 859 s->regs = NULL; 860 } 861 862 static void aspeed_intc_class_init(ObjectClass *klass, const void *data) 863 { 864 DeviceClass *dc = DEVICE_CLASS(klass); 865 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 866 867 dc->desc = "ASPEED INTC Controller"; 868 dc->realize = aspeed_intc_realize; 869 dc->unrealize = aspeed_intc_unrealize; 870 device_class_set_legacy_reset(dc, aspeed_intc_reset); 871 dc->vmsd = NULL; 872 873 aic->reg_ops = &aspeed_intc_ops; 874 } 875 876 static const TypeInfo aspeed_intc_info = { 877 .name = TYPE_ASPEED_INTC, 878 .parent = TYPE_SYS_BUS_DEVICE, 879 .instance_init = aspeed_intc_instance_init, 880 .instance_size = sizeof(AspeedINTCState), 881 .class_init = aspeed_intc_class_init, 882 .class_size = sizeof(AspeedINTCClass), 883 .abstract = true, 884 }; 885 886 static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = { 887 {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS}, 888 {1, 10, 1, R_GICINT128_EN, R_GICINT128_STATUS}, 889 {2, 11, 1, R_GICINT129_EN, R_GICINT129_STATUS}, 890 {3, 12, 1, R_GICINT130_EN, R_GICINT130_STATUS}, 891 {4, 13, 1, R_GICINT131_EN, R_GICINT131_STATUS}, 892 {5, 14, 1, R_GICINT132_EN, R_GICINT132_STATUS}, 893 {6, 15, 1, R_GICINT133_EN, R_GICINT133_STATUS}, 894 {7, 16, 1, R_GICINT134_EN, R_GICINT134_STATUS}, 895 {8, 17, 1, R_GICINT135_EN, R_GICINT135_STATUS}, 896 {9, 18, 1, R_GICINT136_EN, R_GICINT136_STATUS}, 897 }; 898 899 static void aspeed_2700_intc_class_init(ObjectClass *klass, const void *data) 900 { 901 DeviceClass *dc = DEVICE_CLASS(klass); 902 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 903 904 dc->desc = "ASPEED 2700 INTC Controller"; 905 aic->num_lines = 32; 906 aic->num_inpins = 10; 907 aic->num_outpins = 19; 908 aic->mem_size = 0x4000; 909 aic->nr_regs = 0xB08 >> 2; 910 aic->reg_offset = 0x1000; 911 aic->irq_table = aspeed_2700_intc_irqs; 912 aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc_irqs); 913 } 914 915 static const TypeInfo aspeed_2700_intc_info = { 916 .name = TYPE_ASPEED_2700_INTC, 917 .parent = TYPE_ASPEED_INTC, 918 .class_init = aspeed_2700_intc_class_init, 919 }; 920 921 static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { 922 {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS}, 923 {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS}, 924 {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS}, 925 {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS}, 926 {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS}, 927 {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS}, 928 }; 929 930 static void aspeed_2700_intcio_class_init(ObjectClass *klass, const void *data) 931 { 932 DeviceClass *dc = DEVICE_CLASS(klass); 933 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 934 935 dc->desc = "ASPEED 2700 INTC IO Controller"; 936 aic->num_lines = 32; 937 aic->num_inpins = 6; 938 aic->num_outpins = 6; 939 aic->mem_size = 0x400; 940 aic->nr_regs = 0x58 >> 2; 941 aic->reg_offset = 0x100; 942 aic->reg_ops = &aspeed_intcio_ops; 943 aic->irq_table = aspeed_2700_intcio_irqs; 944 aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcio_irqs); 945 } 946 947 static const TypeInfo aspeed_2700_intcio_info = { 948 .name = TYPE_ASPEED_2700_INTCIO, 949 .parent = TYPE_ASPEED_INTC, 950 .class_init = aspeed_2700_intcio_class_init, 951 }; 952 953 static AspeedINTCIRQ aspeed_2700ssp_intc_irqs[ASPEED_INTC_MAX_INPINS] = { 954 {0, 0, 10, R_SSPINT160_169_EN, R_SSPINT160_169_STATUS}, 955 {1, 10, 1, R_SSPINT128_EN, R_SSPINT128_STATUS}, 956 {2, 11, 1, R_SSPINT129_EN, R_SSPINT129_STATUS}, 957 {3, 12, 1, R_SSPINT130_EN, R_SSPINT130_STATUS}, 958 {4, 13, 1, R_SSPINT131_EN, R_SSPINT131_STATUS}, 959 {5, 14, 1, R_SSPINT132_EN, R_SSPINT132_STATUS}, 960 {6, 15, 1, R_SSPINT133_EN, R_SSPINT133_STATUS}, 961 {7, 16, 1, R_SSPINT134_EN, R_SSPINT134_STATUS}, 962 {8, 17, 1, R_SSPINT135_EN, R_SSPINT135_STATUS}, 963 {9, 18, 1, R_SSPINT136_EN, R_SSPINT136_STATUS}, 964 }; 965 966 static void aspeed_2700ssp_intc_class_init(ObjectClass *klass, const void *data) 967 { 968 DeviceClass *dc = DEVICE_CLASS(klass); 969 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 970 971 dc->desc = "ASPEED 2700 SSP INTC Controller"; 972 aic->num_lines = 32; 973 aic->num_inpins = 10; 974 aic->num_outpins = 19; 975 aic->mem_size = 0x4000; 976 aic->nr_regs = 0x2B08 >> 2; 977 aic->reg_offset = 0x0; 978 aic->reg_ops = &aspeed_ssp_intc_ops; 979 aic->irq_table = aspeed_2700ssp_intc_irqs; 980 aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intc_irqs); 981 } 982 983 static const TypeInfo aspeed_2700ssp_intc_info = { 984 .name = TYPE_ASPEED_2700SSP_INTC, 985 .parent = TYPE_ASPEED_INTC, 986 .class_init = aspeed_2700ssp_intc_class_init, 987 }; 988 989 static AspeedINTCIRQ aspeed_2700ssp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { 990 {0, 0, 1, R_SSPINT160_EN, R_SSPINT160_STATUS}, 991 {1, 1, 1, R_SSPINT161_EN, R_SSPINT161_STATUS}, 992 {2, 2, 1, R_SSPINT162_EN, R_SSPINT162_STATUS}, 993 {3, 3, 1, R_SSPINT163_EN, R_SSPINT163_STATUS}, 994 {4, 4, 1, R_SSPINT164_EN, R_SSPINT164_STATUS}, 995 {5, 5, 1, R_SSPINT165_EN, R_SSPINT165_STATUS}, 996 }; 997 998 static void aspeed_2700ssp_intcio_class_init(ObjectClass *klass, const void *data) 999 { 1000 DeviceClass *dc = DEVICE_CLASS(klass); 1001 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 1002 1003 dc->desc = "ASPEED 2700 SSP INTC IO Controller"; 1004 aic->num_lines = 32; 1005 aic->num_inpins = 6; 1006 aic->num_outpins = 6; 1007 aic->mem_size = 0x400; 1008 aic->nr_regs = 0x1d8 >> 2; 1009 aic->reg_offset = 0; 1010 aic->reg_ops = &aspeed_ssp_intcio_ops; 1011 aic->irq_table = aspeed_2700ssp_intcio_irqs; 1012 aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intcio_irqs); 1013 } 1014 1015 static const TypeInfo aspeed_2700ssp_intcio_info = { 1016 .name = TYPE_ASPEED_2700SSP_INTCIO, 1017 .parent = TYPE_ASPEED_INTC, 1018 .class_init = aspeed_2700ssp_intcio_class_init, 1019 }; 1020 1021 static AspeedINTCIRQ aspeed_2700tsp_intc_irqs[ASPEED_INTC_MAX_INPINS] = { 1022 {0, 0, 10, R_TSPINT160_169_EN, R_TSPINT160_169_STATUS}, 1023 {1, 10, 1, R_TSPINT128_EN, R_TSPINT128_STATUS}, 1024 {2, 11, 1, R_TSPINT129_EN, R_TSPINT129_STATUS}, 1025 {3, 12, 1, R_TSPINT130_EN, R_TSPINT130_STATUS}, 1026 {4, 13, 1, R_TSPINT131_EN, R_TSPINT131_STATUS}, 1027 {5, 14, 1, R_TSPINT132_EN, R_TSPINT132_STATUS}, 1028 {6, 15, 1, R_TSPINT133_EN, R_TSPINT133_STATUS}, 1029 {7, 16, 1, R_TSPINT134_EN, R_TSPINT134_STATUS}, 1030 {8, 17, 1, R_TSPINT135_EN, R_TSPINT135_STATUS}, 1031 {9, 18, 1, R_TSPINT136_EN, R_TSPINT136_STATUS}, 1032 }; 1033 1034 static void aspeed_2700tsp_intc_class_init(ObjectClass *klass, const void *data) 1035 { 1036 DeviceClass *dc = DEVICE_CLASS(klass); 1037 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 1038 1039 dc->desc = "ASPEED 2700 TSP INTC Controller"; 1040 aic->num_lines = 32; 1041 aic->num_inpins = 10; 1042 aic->num_outpins = 19; 1043 aic->mem_size = 0x4000; 1044 aic->nr_regs = 0x3B08 >> 2; 1045 aic->reg_offset = 0; 1046 aic->reg_ops = &aspeed_tsp_intc_ops; 1047 aic->irq_table = aspeed_2700tsp_intc_irqs; 1048 aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intc_irqs); 1049 } 1050 1051 static const TypeInfo aspeed_2700tsp_intc_info = { 1052 .name = TYPE_ASPEED_2700TSP_INTC, 1053 .parent = TYPE_ASPEED_INTC, 1054 .class_init = aspeed_2700tsp_intc_class_init, 1055 }; 1056 1057 static AspeedINTCIRQ aspeed_2700tsp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { 1058 {0, 0, 1, R_TSPINT160_EN, R_TSPINT160_STATUS}, 1059 {1, 1, 1, R_TSPINT161_EN, R_TSPINT161_STATUS}, 1060 {2, 2, 1, R_TSPINT162_EN, R_TSPINT162_STATUS}, 1061 {3, 3, 1, R_TSPINT163_EN, R_TSPINT163_STATUS}, 1062 {4, 4, 1, R_TSPINT164_EN, R_TSPINT164_STATUS}, 1063 {5, 5, 1, R_TSPINT165_EN, R_TSPINT165_STATUS}, 1064 }; 1065 1066 static void aspeed_2700tsp_intcio_class_init(ObjectClass *klass, const void *data) 1067 { 1068 DeviceClass *dc = DEVICE_CLASS(klass); 1069 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 1070 1071 dc->desc = "ASPEED 2700 TSP INTC IO Controller"; 1072 aic->num_lines = 32; 1073 aic->num_inpins = 6; 1074 aic->num_outpins = 6; 1075 aic->mem_size = 0x400; 1076 aic->nr_regs = 0x258 >> 2; 1077 aic->reg_offset = 0x0; 1078 aic->reg_ops = &aspeed_tsp_intcio_ops; 1079 aic->irq_table = aspeed_2700tsp_intcio_irqs; 1080 aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intcio_irqs); 1081 } 1082 1083 static const TypeInfo aspeed_2700tsp_intcio_info = { 1084 .name = TYPE_ASPEED_2700TSP_INTCIO, 1085 .parent = TYPE_ASPEED_INTC, 1086 .class_init = aspeed_2700tsp_intcio_class_init, 1087 }; 1088 1089 static void aspeed_intc_register_types(void) 1090 { 1091 type_register_static(&aspeed_intc_info); 1092 type_register_static(&aspeed_2700_intc_info); 1093 type_register_static(&aspeed_2700_intcio_info); 1094 type_register_static(&aspeed_2700ssp_intc_info); 1095 type_register_static(&aspeed_2700ssp_intcio_info); 1096 type_register_static(&aspeed_2700tsp_intc_info); 1097 type_register_static(&aspeed_2700tsp_intcio_info); 1098 } 1099 1100 type_init(aspeed_intc_register_types); 1101