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 .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 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 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 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 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 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 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 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 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 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 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 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 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