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 43 #define GICINT_STATUS_BASE R_GICINT128_STATUS 44 45 static void aspeed_intc_update(AspeedINTCState *s, int irq, int level) 46 { 47 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 48 const char *name = object_get_typename(OBJECT(s)); 49 50 if (irq >= aic->num_inpins) { 51 qemu_log_mask(LOG_GUEST_ERROR, 52 "%s: Invalid input pin index: %d\n", 53 __func__, irq); 54 return; 55 } 56 57 trace_aspeed_intc_update_irq(name, irq, level); 58 qemu_set_irq(s->output_pins[irq], level); 59 } 60 61 /* 62 * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804. 63 * Utilize "address & 0x0f00" to get the irq and irq output pin index 64 * The value of irq should be 0 to num_inpins. 65 * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on. 66 */ 67 static void aspeed_intc_set_irq(void *opaque, int irq, int level) 68 { 69 AspeedINTCState *s = (AspeedINTCState *)opaque; 70 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 71 const char *name = object_get_typename(OBJECT(s)); 72 uint32_t status_reg = GICINT_STATUS_BASE + ((0x100 * irq) >> 2); 73 uint32_t select = 0; 74 uint32_t enable; 75 int i; 76 77 if (irq >= aic->num_inpins) { 78 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid input pin index: %d\n", 79 __func__, irq); 80 return; 81 } 82 83 trace_aspeed_intc_set_irq(name, irq, level); 84 enable = s->enable[irq]; 85 86 if (!level) { 87 return; 88 } 89 90 for (i = 0; i < aic->num_lines; i++) { 91 if (s->orgates[irq].levels[i]) { 92 if (enable & BIT(i)) { 93 select |= BIT(i); 94 } 95 } 96 } 97 98 if (!select) { 99 return; 100 } 101 102 trace_aspeed_intc_select(name, select); 103 104 if (s->mask[irq] || s->regs[status_reg]) { 105 /* 106 * a. mask is not 0 means in ISR mode 107 * sources interrupt routine are executing. 108 * b. status register value is not 0 means previous 109 * source interrupt does not be executed, yet. 110 * 111 * save source interrupt to pending variable. 112 */ 113 s->pending[irq] |= select; 114 trace_aspeed_intc_pending_irq(name, irq, s->pending[irq]); 115 } else { 116 /* 117 * notify firmware which source interrupt are coming 118 * by setting status register 119 */ 120 s->regs[status_reg] = select; 121 trace_aspeed_intc_trigger_irq(name, irq, s->regs[status_reg]); 122 aspeed_intc_update(s, irq, 1); 123 } 124 } 125 126 static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset, 127 uint64_t data) 128 { 129 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 130 const char *name = object_get_typename(OBJECT(s)); 131 uint32_t reg = offset >> 2; 132 uint32_t old_enable; 133 uint32_t change; 134 uint32_t irq; 135 136 irq = (offset & 0x0f00) >> 8; 137 138 if (irq >= aic->num_inpins) { 139 qemu_log_mask(LOG_GUEST_ERROR, 140 "%s: Invalid input pin index: %d\n", 141 __func__, irq); 142 return; 143 } 144 145 /* 146 * The enable registers are used to enable source interrupts. 147 * They also handle masking and unmasking of source interrupts 148 * during the execution of the source ISR. 149 */ 150 151 /* disable all source interrupt */ 152 if (!data && !s->enable[irq]) { 153 s->regs[reg] = data; 154 return; 155 } 156 157 old_enable = s->enable[irq]; 158 s->enable[irq] |= data; 159 160 /* enable new source interrupt */ 161 if (old_enable != s->enable[irq]) { 162 trace_aspeed_intc_enable(name, s->enable[irq]); 163 s->regs[reg] = data; 164 return; 165 } 166 167 /* mask and unmask source interrupt */ 168 change = s->regs[reg] ^ data; 169 if (change & data) { 170 s->mask[irq] &= ~change; 171 trace_aspeed_intc_unmask(name, change, s->mask[irq]); 172 } else { 173 s->mask[irq] |= change; 174 trace_aspeed_intc_mask(name, change, s->mask[irq]); 175 } 176 177 s->regs[reg] = data; 178 } 179 180 static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset, 181 uint64_t data) 182 { 183 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 184 const char *name = object_get_typename(OBJECT(s)); 185 uint32_t reg = offset >> 2; 186 uint32_t irq; 187 188 if (!data) { 189 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__); 190 return; 191 } 192 193 irq = (offset & 0x0f00) >> 8; 194 195 if (irq >= aic->num_inpins) { 196 qemu_log_mask(LOG_GUEST_ERROR, 197 "%s: Invalid input pin index: %d\n", 198 __func__, irq); 199 return; 200 } 201 202 /* clear status */ 203 s->regs[reg] &= ~data; 204 205 /* 206 * These status registers are used for notify sources ISR are executed. 207 * If one source ISR is executed, it will clear one bit. 208 * If it clear all bits, it means to initialize this register status 209 * rather than sources ISR are executed. 210 */ 211 if (data == 0xffffffff) { 212 return; 213 } 214 215 /* All source ISR execution are done */ 216 if (!s->regs[reg]) { 217 trace_aspeed_intc_all_isr_done(name, irq); 218 if (s->pending[irq]) { 219 /* 220 * handle pending source interrupt 221 * notify firmware which source interrupt are pending 222 * by setting status register 223 */ 224 s->regs[reg] = s->pending[irq]; 225 s->pending[irq] = 0; 226 trace_aspeed_intc_trigger_irq(name, irq, s->regs[reg]); 227 aspeed_intc_update(s, irq, 1); 228 } else { 229 /* clear irq */ 230 trace_aspeed_intc_clear_irq(name, irq, 0); 231 aspeed_intc_update(s, irq, 0); 232 } 233 } 234 } 235 236 static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size) 237 { 238 AspeedINTCState *s = ASPEED_INTC(opaque); 239 const char *name = object_get_typename(OBJECT(s)); 240 uint32_t reg = offset >> 2; 241 uint32_t value = 0; 242 243 value = s->regs[reg]; 244 trace_aspeed_intc_read(name, offset, size, value); 245 246 return value; 247 } 248 249 static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data, 250 unsigned size) 251 { 252 AspeedINTCState *s = ASPEED_INTC(opaque); 253 const char *name = object_get_typename(OBJECT(s)); 254 uint32_t reg = offset >> 2; 255 256 trace_aspeed_intc_write(name, offset, size, data); 257 258 switch (reg) { 259 case R_GICINT128_EN: 260 case R_GICINT129_EN: 261 case R_GICINT130_EN: 262 case R_GICINT131_EN: 263 case R_GICINT132_EN: 264 case R_GICINT133_EN: 265 case R_GICINT134_EN: 266 case R_GICINT135_EN: 267 case R_GICINT136_EN: 268 aspeed_intc_enable_handler(s, offset, data); 269 break; 270 case R_GICINT128_STATUS: 271 case R_GICINT129_STATUS: 272 case R_GICINT130_STATUS: 273 case R_GICINT131_STATUS: 274 case R_GICINT132_STATUS: 275 case R_GICINT133_STATUS: 276 case R_GICINT134_STATUS: 277 case R_GICINT135_STATUS: 278 case R_GICINT136_STATUS: 279 aspeed_intc_status_handler(s, offset, data); 280 break; 281 default: 282 s->regs[reg] = data; 283 break; 284 } 285 286 return; 287 } 288 289 static const MemoryRegionOps aspeed_intc_ops = { 290 .read = aspeed_intc_read, 291 .write = aspeed_intc_write, 292 .endianness = DEVICE_LITTLE_ENDIAN, 293 .valid = { 294 .min_access_size = 4, 295 .max_access_size = 4, 296 } 297 }; 298 299 static void aspeed_intc_instance_init(Object *obj) 300 { 301 AspeedINTCState *s = ASPEED_INTC(obj); 302 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 303 int i; 304 305 assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS); 306 for (i = 0; i < aic->num_inpins; i++) { 307 object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i], 308 TYPE_OR_IRQ); 309 object_property_set_int(OBJECT(&s->orgates[i]), "num-lines", 310 aic->num_lines, &error_abort); 311 } 312 } 313 314 static void aspeed_intc_reset(DeviceState *dev) 315 { 316 AspeedINTCState *s = ASPEED_INTC(dev); 317 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 318 319 memset(s->regs, 0, aic->nr_regs << 2); 320 memset(s->enable, 0, sizeof(s->enable)); 321 memset(s->mask, 0, sizeof(s->mask)); 322 memset(s->pending, 0, sizeof(s->pending)); 323 } 324 325 static void aspeed_intc_realize(DeviceState *dev, Error **errp) 326 { 327 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 328 AspeedINTCState *s = ASPEED_INTC(dev); 329 AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 330 int i; 331 332 memory_region_init(&s->iomem_container, OBJECT(s), 333 TYPE_ASPEED_INTC ".container", aic->mem_size); 334 335 sysbus_init_mmio(sbd, &s->iomem_container); 336 337 s->regs = g_new(uint32_t, aic->nr_regs); 338 memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s, 339 TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2); 340 341 memory_region_add_subregion(&s->iomem_container, aic->reg_offset, 342 &s->iomem); 343 344 qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins); 345 346 for (i = 0; i < aic->num_inpins; i++) { 347 if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) { 348 return; 349 } 350 sysbus_init_irq(sbd, &s->output_pins[i]); 351 } 352 } 353 354 static void aspeed_intc_unrealize(DeviceState *dev) 355 { 356 AspeedINTCState *s = ASPEED_INTC(dev); 357 358 g_free(s->regs); 359 s->regs = NULL; 360 } 361 362 static void aspeed_intc_class_init(ObjectClass *klass, void *data) 363 { 364 DeviceClass *dc = DEVICE_CLASS(klass); 365 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 366 367 dc->desc = "ASPEED INTC Controller"; 368 dc->realize = aspeed_intc_realize; 369 dc->unrealize = aspeed_intc_unrealize; 370 device_class_set_legacy_reset(dc, aspeed_intc_reset); 371 dc->vmsd = NULL; 372 373 aic->reg_ops = &aspeed_intc_ops; 374 } 375 376 static const TypeInfo aspeed_intc_info = { 377 .name = TYPE_ASPEED_INTC, 378 .parent = TYPE_SYS_BUS_DEVICE, 379 .instance_init = aspeed_intc_instance_init, 380 .instance_size = sizeof(AspeedINTCState), 381 .class_init = aspeed_intc_class_init, 382 .class_size = sizeof(AspeedINTCClass), 383 .abstract = true, 384 }; 385 386 static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data) 387 { 388 DeviceClass *dc = DEVICE_CLASS(klass); 389 AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 390 391 dc->desc = "ASPEED 2700 INTC Controller"; 392 aic->num_lines = 32; 393 aic->num_inpins = 9; 394 aic->mem_size = 0x4000; 395 aic->nr_regs = 0x808 >> 2; 396 aic->reg_offset = 0x1000; 397 } 398 399 static const TypeInfo aspeed_2700_intc_info = { 400 .name = TYPE_ASPEED_2700_INTC, 401 .parent = TYPE_ASPEED_INTC, 402 .class_init = aspeed_2700_intc_class_init, 403 }; 404 405 static void aspeed_intc_register_types(void) 406 { 407 type_register_static(&aspeed_intc_info); 408 type_register_static(&aspeed_2700_intc_info); 409 } 410 411 type_init(aspeed_intc_register_types); 412