1d831c5fdSJamin Lin /* 2d831c5fdSJamin Lin * ASPEED INTC Controller 3d831c5fdSJamin Lin * 4d831c5fdSJamin Lin * Copyright (C) 2024 ASPEED Technology Inc. 5d831c5fdSJamin Lin * 6d831c5fdSJamin Lin * SPDX-License-Identifier: GPL-2.0-or-later 7d831c5fdSJamin Lin */ 8d831c5fdSJamin Lin 9d831c5fdSJamin Lin #include "qemu/osdep.h" 10d831c5fdSJamin Lin #include "hw/intc/aspeed_intc.h" 11d831c5fdSJamin Lin #include "hw/irq.h" 12d831c5fdSJamin Lin #include "qemu/log.h" 13d831c5fdSJamin Lin #include "trace.h" 14d831c5fdSJamin Lin #include "hw/registerfields.h" 15d831c5fdSJamin Lin #include "qapi/error.h" 16d831c5fdSJamin Lin 177ffee511SJamin Lin /* 187ffee511SJamin Lin * INTC Registers 197ffee511SJamin Lin * 207ffee511SJamin Lin * values below are offset by - 0x1000 from datasheet 217ffee511SJamin Lin * because its memory region is start at 0x1000 227ffee511SJamin Lin * 237ffee511SJamin Lin */ 247ffee511SJamin Lin REG32(GICINT128_EN, 0x000) 257ffee511SJamin Lin REG32(GICINT128_STATUS, 0x004) 267ffee511SJamin Lin REG32(GICINT129_EN, 0x100) 277ffee511SJamin Lin REG32(GICINT129_STATUS, 0x104) 287ffee511SJamin Lin REG32(GICINT130_EN, 0x200) 297ffee511SJamin Lin REG32(GICINT130_STATUS, 0x204) 307ffee511SJamin Lin REG32(GICINT131_EN, 0x300) 317ffee511SJamin Lin REG32(GICINT131_STATUS, 0x304) 327ffee511SJamin Lin REG32(GICINT132_EN, 0x400) 337ffee511SJamin Lin REG32(GICINT132_STATUS, 0x404) 347ffee511SJamin Lin REG32(GICINT133_EN, 0x500) 357ffee511SJamin Lin REG32(GICINT133_STATUS, 0x504) 367ffee511SJamin Lin REG32(GICINT134_EN, 0x600) 377ffee511SJamin Lin REG32(GICINT134_STATUS, 0x604) 387ffee511SJamin Lin REG32(GICINT135_EN, 0x700) 397ffee511SJamin Lin REG32(GICINT135_STATUS, 0x704) 407ffee511SJamin Lin REG32(GICINT136_EN, 0x800) 417ffee511SJamin Lin REG32(GICINT136_STATUS, 0x804) 429178ff91SJamin Lin REG32(GICINT192_201_EN, 0xB00) 439178ff91SJamin Lin REG32(GICINT192_201_STATUS, 0xB04) 44d831c5fdSJamin Lin 4538ba38d8SJamin Lin /* 4638ba38d8SJamin Lin * INTCIO Registers 4738ba38d8SJamin Lin * 4838ba38d8SJamin Lin * values below are offset by - 0x100 from datasheet 4938ba38d8SJamin Lin * because its memory region is start at 0x100 5038ba38d8SJamin Lin * 5138ba38d8SJamin Lin */ 5238ba38d8SJamin Lin REG32(GICINT192_EN, 0x00) 5338ba38d8SJamin Lin REG32(GICINT192_STATUS, 0x04) 5438ba38d8SJamin Lin REG32(GICINT193_EN, 0x10) 5538ba38d8SJamin Lin REG32(GICINT193_STATUS, 0x14) 5638ba38d8SJamin Lin REG32(GICINT194_EN, 0x20) 5738ba38d8SJamin Lin REG32(GICINT194_STATUS, 0x24) 5838ba38d8SJamin Lin REG32(GICINT195_EN, 0x30) 5938ba38d8SJamin Lin REG32(GICINT195_STATUS, 0x34) 6038ba38d8SJamin Lin REG32(GICINT196_EN, 0x40) 6138ba38d8SJamin Lin REG32(GICINT196_STATUS, 0x44) 6238ba38d8SJamin Lin REG32(GICINT197_EN, 0x50) 6338ba38d8SJamin Lin REG32(GICINT197_STATUS, 0x54) 6438ba38d8SJamin Lin 658872b671SSteven Lee /* 668872b671SSteven Lee * SSP INTC Registers 678872b671SSteven Lee */ 688872b671SSteven Lee REG32(SSPINT128_EN, 0x2000) 698872b671SSteven Lee REG32(SSPINT128_STATUS, 0x2004) 708872b671SSteven Lee REG32(SSPINT129_EN, 0x2100) 718872b671SSteven Lee REG32(SSPINT129_STATUS, 0x2104) 728872b671SSteven Lee REG32(SSPINT130_EN, 0x2200) 738872b671SSteven Lee REG32(SSPINT130_STATUS, 0x2204) 748872b671SSteven Lee REG32(SSPINT131_EN, 0x2300) 758872b671SSteven Lee REG32(SSPINT131_STATUS, 0x2304) 768872b671SSteven Lee REG32(SSPINT132_EN, 0x2400) 778872b671SSteven Lee REG32(SSPINT132_STATUS, 0x2404) 788872b671SSteven Lee REG32(SSPINT133_EN, 0x2500) 798872b671SSteven Lee REG32(SSPINT133_STATUS, 0x2504) 808872b671SSteven Lee REG32(SSPINT134_EN, 0x2600) 818872b671SSteven Lee REG32(SSPINT134_STATUS, 0x2604) 828872b671SSteven Lee REG32(SSPINT135_EN, 0x2700) 838872b671SSteven Lee REG32(SSPINT135_STATUS, 0x2704) 848872b671SSteven Lee REG32(SSPINT136_EN, 0x2800) 858872b671SSteven Lee REG32(SSPINT136_STATUS, 0x2804) 868872b671SSteven Lee REG32(SSPINT137_EN, 0x2900) 878872b671SSteven Lee REG32(SSPINT137_STATUS, 0x2904) 888872b671SSteven Lee REG32(SSPINT138_EN, 0x2A00) 898872b671SSteven Lee REG32(SSPINT138_STATUS, 0x2A04) 908872b671SSteven Lee REG32(SSPINT160_169_EN, 0x2B00) 918872b671SSteven Lee REG32(SSPINT160_169_STATUS, 0x2B04) 928872b671SSteven Lee 938872b671SSteven Lee /* 948872b671SSteven Lee * SSP INTCIO Registers 958872b671SSteven Lee */ 968872b671SSteven Lee REG32(SSPINT160_EN, 0x180) 978872b671SSteven Lee REG32(SSPINT160_STATUS, 0x184) 988872b671SSteven Lee REG32(SSPINT161_EN, 0x190) 998872b671SSteven Lee REG32(SSPINT161_STATUS, 0x194) 1008872b671SSteven Lee REG32(SSPINT162_EN, 0x1A0) 1018872b671SSteven Lee REG32(SSPINT162_STATUS, 0x1A4) 1028872b671SSteven Lee REG32(SSPINT163_EN, 0x1B0) 1038872b671SSteven Lee REG32(SSPINT163_STATUS, 0x1B4) 1048872b671SSteven Lee REG32(SSPINT164_EN, 0x1C0) 1058872b671SSteven Lee REG32(SSPINT164_STATUS, 0x1C4) 1068872b671SSteven Lee REG32(SSPINT165_EN, 0x1D0) 1078872b671SSteven Lee REG32(SSPINT165_STATUS, 0x1D4) 1088872b671SSteven Lee 109c528f10dSSteven Lee /* 110c528f10dSSteven Lee * TSP INTC Registers 111c528f10dSSteven Lee */ 112c528f10dSSteven Lee REG32(TSPINT128_EN, 0x3000) 113c528f10dSSteven Lee REG32(TSPINT128_STATUS, 0x3004) 114c528f10dSSteven Lee REG32(TSPINT129_EN, 0x3100) 115c528f10dSSteven Lee REG32(TSPINT129_STATUS, 0x3104) 116c528f10dSSteven Lee REG32(TSPINT130_EN, 0x3200) 117c528f10dSSteven Lee REG32(TSPINT130_STATUS, 0x3204) 118c528f10dSSteven Lee REG32(TSPINT131_EN, 0x3300) 119c528f10dSSteven Lee REG32(TSPINT131_STATUS, 0x3304) 120c528f10dSSteven Lee REG32(TSPINT132_EN, 0x3400) 121c528f10dSSteven Lee REG32(TSPINT132_STATUS, 0x3404) 122c528f10dSSteven Lee REG32(TSPINT133_EN, 0x3500) 123c528f10dSSteven Lee REG32(TSPINT133_STATUS, 0x3504) 124c528f10dSSteven Lee REG32(TSPINT134_EN, 0x3600) 125c528f10dSSteven Lee REG32(TSPINT134_STATUS, 0x3604) 126c528f10dSSteven Lee REG32(TSPINT135_EN, 0x3700) 127c528f10dSSteven Lee REG32(TSPINT135_STATUS, 0x3704) 128c528f10dSSteven Lee REG32(TSPINT136_EN, 0x3800) 129c528f10dSSteven Lee REG32(TSPINT136_STATUS, 0x3804) 130c528f10dSSteven Lee REG32(TSPINT137_EN, 0x3900) 131c528f10dSSteven Lee REG32(TSPINT137_STATUS, 0x3904) 132c528f10dSSteven Lee REG32(TSPINT138_EN, 0x3A00) 133c528f10dSSteven Lee REG32(TSPINT138_STATUS, 0x3A04) 134c528f10dSSteven Lee REG32(TSPINT160_169_EN, 0x3B00) 135c528f10dSSteven Lee REG32(TSPINT160_169_STATUS, 0x3B04) 136c528f10dSSteven Lee 137c528f10dSSteven Lee /* 138c528f10dSSteven Lee * TSP INTCIO Registers 139c528f10dSSteven Lee */ 140c528f10dSSteven Lee 141c528f10dSSteven Lee REG32(TSPINT160_EN, 0x200) 142c528f10dSSteven Lee REG32(TSPINT160_STATUS, 0x204) 143c528f10dSSteven Lee REG32(TSPINT161_EN, 0x210) 144c528f10dSSteven Lee REG32(TSPINT161_STATUS, 0x214) 145c528f10dSSteven Lee REG32(TSPINT162_EN, 0x220) 146c528f10dSSteven Lee REG32(TSPINT162_STATUS, 0x224) 147c528f10dSSteven Lee REG32(TSPINT163_EN, 0x230) 148c528f10dSSteven Lee REG32(TSPINT163_STATUS, 0x234) 149c528f10dSSteven Lee REG32(TSPINT164_EN, 0x240) 150c528f10dSSteven Lee REG32(TSPINT164_STATUS, 0x244) 151c528f10dSSteven Lee REG32(TSPINT165_EN, 0x250) 152c528f10dSSteven Lee REG32(TSPINT165_STATUS, 0x254) 153c528f10dSSteven Lee 154ab24c6a2SJamin Lin static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic, 155ab24c6a2SJamin Lin uint32_t reg) 156ab24c6a2SJamin Lin { 157ab24c6a2SJamin Lin int i; 158ab24c6a2SJamin Lin 159ab24c6a2SJamin Lin for (i = 0; i < aic->irq_table_count; i++) { 160ab24c6a2SJamin Lin if (aic->irq_table[i].enable_reg == reg || 161ab24c6a2SJamin Lin aic->irq_table[i].status_reg == reg) { 162ab24c6a2SJamin Lin return &aic->irq_table[i]; 163ab24c6a2SJamin Lin } 164ab24c6a2SJamin Lin } 165ab24c6a2SJamin Lin 166ab24c6a2SJamin Lin /* 167ab24c6a2SJamin Lin * Invalid reg. 168ab24c6a2SJamin Lin */ 169ab24c6a2SJamin Lin g_assert_not_reached(); 170ab24c6a2SJamin Lin } 171d831c5fdSJamin Lin 172c6c5e63dSJamin Lin /* 173c6c5e63dSJamin Lin * Update the state of an interrupt controller pin by setting 174c6c5e63dSJamin Lin * the specified output pin to the given level. 175c6c5e63dSJamin Lin * The input pin index should be between 0 and the number of input pins. 176c6c5e63dSJamin Lin * The output pin index should be between 0 and the number of output pins. 177c6c5e63dSJamin Lin */ 178c6c5e63dSJamin Lin static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx, 179c6c5e63dSJamin Lin int outpin_idx, int level) 180d831c5fdSJamin Lin { 181d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 18249da40cfSJamin Lin const char *name = object_get_typename(OBJECT(s)); 183d831c5fdSJamin Lin 184ab24c6a2SJamin Lin assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins)); 185c6c5e63dSJamin Lin 186c6c5e63dSJamin Lin trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level); 187c6c5e63dSJamin Lin qemu_set_irq(s->output_pins[outpin_idx], level); 188d831c5fdSJamin Lin } 189d831c5fdSJamin Lin 1905824e8bfSJamin Lin static void aspeed_intc_set_irq_handler(AspeedINTCState *s, 1915824e8bfSJamin Lin const AspeedINTCIRQ *intc_irq, 1925824e8bfSJamin Lin uint32_t select) 193d831c5fdSJamin Lin { 19449da40cfSJamin Lin const char *name = object_get_typename(OBJECT(s)); 195ab24c6a2SJamin Lin uint32_t status_reg; 196c6c5e63dSJamin Lin int outpin_idx; 197c6c5e63dSJamin Lin int inpin_idx; 198d831c5fdSJamin Lin 199ab24c6a2SJamin Lin status_reg = intc_irq->status_reg; 200ab24c6a2SJamin Lin outpin_idx = intc_irq->outpin_idx; 201ab24c6a2SJamin Lin inpin_idx = intc_irq->inpin_idx; 202d831c5fdSJamin Lin 2037b8cbe51SSteven Lee if ((s->mask[inpin_idx] & select) || (s->regs[status_reg] & select)) { 204d831c5fdSJamin Lin /* 205d831c5fdSJamin Lin * a. mask is not 0 means in ISR mode 206d831c5fdSJamin Lin * sources interrupt routine are executing. 207d831c5fdSJamin Lin * b. status register value is not 0 means previous 208d831c5fdSJamin Lin * source interrupt does not be executed, yet. 209d831c5fdSJamin Lin * 210d831c5fdSJamin Lin * save source interrupt to pending variable. 211d831c5fdSJamin Lin */ 212c6c5e63dSJamin Lin s->pending[inpin_idx] |= select; 213c6c5e63dSJamin Lin trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]); 214d831c5fdSJamin Lin } else { 215d831c5fdSJamin Lin /* 216d831c5fdSJamin Lin * notify firmware which source interrupt are coming 217d831c5fdSJamin Lin * by setting status register 218d831c5fdSJamin Lin */ 2190cffaaceSJamin Lin s->regs[status_reg] = select; 220c6c5e63dSJamin Lin trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx, 221c6c5e63dSJamin Lin s->regs[status_reg]); 222c6c5e63dSJamin Lin aspeed_intc_update(s, inpin_idx, outpin_idx, 1); 223d831c5fdSJamin Lin } 224d831c5fdSJamin Lin } 225d831c5fdSJamin Lin 2269178ff91SJamin Lin static void aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState *s, 2279178ff91SJamin Lin const AspeedINTCIRQ *intc_irq, uint32_t select) 2289178ff91SJamin Lin { 2299178ff91SJamin Lin const char *name = object_get_typename(OBJECT(s)); 2309178ff91SJamin Lin uint32_t status_reg; 2319178ff91SJamin Lin int num_outpins; 2329178ff91SJamin Lin int outpin_idx; 2339178ff91SJamin Lin int inpin_idx; 2349178ff91SJamin Lin int i; 2359178ff91SJamin Lin 2369178ff91SJamin Lin num_outpins = intc_irq->num_outpins; 2379178ff91SJamin Lin status_reg = intc_irq->status_reg; 2389178ff91SJamin Lin outpin_idx = intc_irq->outpin_idx; 2399178ff91SJamin Lin inpin_idx = intc_irq->inpin_idx; 2409178ff91SJamin Lin 2419178ff91SJamin Lin for (i = 0; i < num_outpins; i++) { 2429178ff91SJamin Lin if (select & BIT(i)) { 2439178ff91SJamin Lin if (s->mask[inpin_idx] & BIT(i) || 2449178ff91SJamin Lin s->regs[status_reg] & BIT(i)) { 2455824e8bfSJamin Lin /* 2469178ff91SJamin Lin * a. mask bit is not 0 means in ISR mode sources interrupt 2479178ff91SJamin Lin * routine are executing. 2489178ff91SJamin Lin * b. status bit is not 0 means previous source interrupt 2499178ff91SJamin Lin * does not be executed, yet. 2509178ff91SJamin Lin * 2519178ff91SJamin Lin * save source interrupt to pending bit. 2529178ff91SJamin Lin */ 2539178ff91SJamin Lin s->pending[inpin_idx] |= BIT(i); 2549178ff91SJamin Lin trace_aspeed_intc_pending_irq(name, inpin_idx, 2559178ff91SJamin Lin s->pending[inpin_idx]); 2569178ff91SJamin Lin } else { 2579178ff91SJamin Lin /* 2589178ff91SJamin Lin * notify firmware which source interrupt are coming 2599178ff91SJamin Lin * by setting status bit 2609178ff91SJamin Lin */ 2619178ff91SJamin Lin s->regs[status_reg] |= BIT(i); 2629178ff91SJamin Lin trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i, 2639178ff91SJamin Lin s->regs[status_reg]); 2649178ff91SJamin Lin aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1); 2659178ff91SJamin Lin } 2669178ff91SJamin Lin } 2679178ff91SJamin Lin } 2689178ff91SJamin Lin } 2699178ff91SJamin Lin 2709178ff91SJamin Lin /* 2719178ff91SJamin Lin * GICINT192_201 maps 1:10 to input IRQ 0 and output IRQs 0 to 9. 2729178ff91SJamin Lin * GICINT128 to GICINT136 map 1:1 to input IRQs 1 to 9 and output 2739178ff91SJamin Lin * IRQs 10 to 18. The value of input IRQ should be between 0 and 2749178ff91SJamin Lin * the number of input pins. 2755824e8bfSJamin Lin */ 2765824e8bfSJamin Lin static void aspeed_intc_set_irq(void *opaque, int irq, int level) 2775824e8bfSJamin Lin { 2785824e8bfSJamin Lin AspeedINTCState *s = (AspeedINTCState *)opaque; 2795824e8bfSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 2805824e8bfSJamin Lin const char *name = object_get_typename(OBJECT(s)); 2815824e8bfSJamin Lin const AspeedINTCIRQ *intc_irq; 2825824e8bfSJamin Lin uint32_t select = 0; 2835824e8bfSJamin Lin uint32_t enable; 2849178ff91SJamin Lin int num_outpins; 2855824e8bfSJamin Lin int inpin_idx; 2865824e8bfSJamin Lin int i; 2875824e8bfSJamin Lin 2885824e8bfSJamin Lin assert(irq < aic->num_inpins); 2895824e8bfSJamin Lin 2905824e8bfSJamin Lin intc_irq = &aic->irq_table[irq]; 2919178ff91SJamin Lin num_outpins = intc_irq->num_outpins; 2925824e8bfSJamin Lin inpin_idx = intc_irq->inpin_idx; 2935824e8bfSJamin Lin trace_aspeed_intc_set_irq(name, inpin_idx, level); 2945824e8bfSJamin Lin enable = s->enable[inpin_idx]; 2955824e8bfSJamin Lin 2965824e8bfSJamin Lin if (!level) { 2975824e8bfSJamin Lin return; 2985824e8bfSJamin Lin } 2995824e8bfSJamin Lin 3005824e8bfSJamin Lin for (i = 0; i < aic->num_lines; i++) { 3015824e8bfSJamin Lin if (s->orgates[inpin_idx].levels[i]) { 3025824e8bfSJamin Lin if (enable & BIT(i)) { 3035824e8bfSJamin Lin select |= BIT(i); 3045824e8bfSJamin Lin } 3055824e8bfSJamin Lin } 3065824e8bfSJamin Lin } 3075824e8bfSJamin Lin 3085824e8bfSJamin Lin if (!select) { 3095824e8bfSJamin Lin return; 3105824e8bfSJamin Lin } 3115824e8bfSJamin Lin 3125824e8bfSJamin Lin trace_aspeed_intc_select(name, select); 3139178ff91SJamin Lin if (num_outpins > 1) { 3149178ff91SJamin Lin aspeed_intc_set_irq_handler_multi_outpins(s, intc_irq, select); 3159178ff91SJamin Lin } else { 3165824e8bfSJamin Lin aspeed_intc_set_irq_handler(s, intc_irq, select); 3175824e8bfSJamin Lin } 3189178ff91SJamin Lin } 3195824e8bfSJamin Lin 3203d6e15eaSJamin Lin static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset, 3213d6e15eaSJamin Lin uint64_t data) 322d831c5fdSJamin Lin { 323d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 32449da40cfSJamin Lin const char *name = object_get_typename(OBJECT(s)); 325ab24c6a2SJamin Lin const AspeedINTCIRQ *intc_irq; 3260cffaaceSJamin Lin uint32_t reg = offset >> 2; 327d831c5fdSJamin Lin uint32_t old_enable; 328d831c5fdSJamin Lin uint32_t change; 329c6c5e63dSJamin Lin int inpin_idx; 330d831c5fdSJamin Lin 331ab24c6a2SJamin Lin intc_irq = aspeed_intc_get_irq(aic, reg); 332ab24c6a2SJamin Lin inpin_idx = intc_irq->inpin_idx; 333d831c5fdSJamin Lin 334ab24c6a2SJamin Lin assert(inpin_idx < aic->num_inpins); 335d831c5fdSJamin Lin 336d831c5fdSJamin Lin /* 3373d6e15eaSJamin Lin * The enable registers are used to enable source interrupts. 3383d6e15eaSJamin Lin * They also handle masking and unmasking of source interrupts 3393d6e15eaSJamin Lin * during the execution of the source ISR. 340d831c5fdSJamin Lin */ 341d831c5fdSJamin Lin 342d831c5fdSJamin Lin /* disable all source interrupt */ 343c6c5e63dSJamin Lin if (!data && !s->enable[inpin_idx]) { 3440cffaaceSJamin Lin s->regs[reg] = data; 345d831c5fdSJamin Lin return; 346d831c5fdSJamin Lin } 347d831c5fdSJamin Lin 348c6c5e63dSJamin Lin old_enable = s->enable[inpin_idx]; 349c6c5e63dSJamin Lin s->enable[inpin_idx] |= data; 350d831c5fdSJamin Lin 351d831c5fdSJamin Lin /* enable new source interrupt */ 352c6c5e63dSJamin Lin if (old_enable != s->enable[inpin_idx]) { 353c6c5e63dSJamin Lin trace_aspeed_intc_enable(name, s->enable[inpin_idx]); 3540cffaaceSJamin Lin s->regs[reg] = data; 355d831c5fdSJamin Lin return; 356d831c5fdSJamin Lin } 357d831c5fdSJamin Lin 358d831c5fdSJamin Lin /* mask and unmask source interrupt */ 3590cffaaceSJamin Lin change = s->regs[reg] ^ data; 360d831c5fdSJamin Lin if (change & data) { 361c6c5e63dSJamin Lin s->mask[inpin_idx] &= ~change; 362c6c5e63dSJamin Lin trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]); 363d831c5fdSJamin Lin } else { 364c6c5e63dSJamin Lin s->mask[inpin_idx] |= change; 365c6c5e63dSJamin Lin trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]); 366d831c5fdSJamin Lin } 3673d6e15eaSJamin Lin 3680cffaaceSJamin Lin s->regs[reg] = data; 3693d6e15eaSJamin Lin } 3703d6e15eaSJamin Lin 3713d6e15eaSJamin Lin static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset, 3723d6e15eaSJamin Lin uint64_t data) 3733d6e15eaSJamin Lin { 3743d6e15eaSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 37549da40cfSJamin Lin const char *name = object_get_typename(OBJECT(s)); 376ab24c6a2SJamin Lin const AspeedINTCIRQ *intc_irq; 3773d6e15eaSJamin Lin uint32_t reg = offset >> 2; 378c6c5e63dSJamin Lin int outpin_idx; 379c6c5e63dSJamin Lin int inpin_idx; 3803d6e15eaSJamin Lin 3813d6e15eaSJamin Lin if (!data) { 3823d6e15eaSJamin Lin qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__); 3833d6e15eaSJamin Lin return; 3843d6e15eaSJamin Lin } 3853d6e15eaSJamin Lin 386ab24c6a2SJamin Lin intc_irq = aspeed_intc_get_irq(aic, reg); 387ab24c6a2SJamin Lin outpin_idx = intc_irq->outpin_idx; 388ab24c6a2SJamin Lin inpin_idx = intc_irq->inpin_idx; 389d831c5fdSJamin Lin 390ab24c6a2SJamin Lin assert(inpin_idx < aic->num_inpins); 391d831c5fdSJamin Lin 392d831c5fdSJamin Lin /* clear status */ 3930cffaaceSJamin Lin s->regs[reg] &= ~data; 394d831c5fdSJamin Lin 395d831c5fdSJamin Lin /* 396d831c5fdSJamin Lin * These status registers are used for notify sources ISR are executed. 397d831c5fdSJamin Lin * If one source ISR is executed, it will clear one bit. 398d831c5fdSJamin Lin * If it clear all bits, it means to initialize this register status 399d831c5fdSJamin Lin * rather than sources ISR are executed. 400d831c5fdSJamin Lin */ 401d831c5fdSJamin Lin if (data == 0xffffffff) { 402d831c5fdSJamin Lin return; 403d831c5fdSJamin Lin } 404d831c5fdSJamin Lin 405d831c5fdSJamin Lin /* All source ISR execution are done */ 4060cffaaceSJamin Lin if (!s->regs[reg]) { 407c6c5e63dSJamin Lin trace_aspeed_intc_all_isr_done(name, inpin_idx); 408c6c5e63dSJamin Lin if (s->pending[inpin_idx]) { 409d831c5fdSJamin Lin /* 410d831c5fdSJamin Lin * handle pending source interrupt 411d831c5fdSJamin Lin * notify firmware which source interrupt are pending 412d831c5fdSJamin Lin * by setting status register 413d831c5fdSJamin Lin */ 414c6c5e63dSJamin Lin s->regs[reg] = s->pending[inpin_idx]; 415c6c5e63dSJamin Lin s->pending[inpin_idx] = 0; 416c6c5e63dSJamin Lin trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx, 417c6c5e63dSJamin Lin s->regs[reg]); 418c6c5e63dSJamin Lin aspeed_intc_update(s, inpin_idx, outpin_idx, 1); 419d831c5fdSJamin Lin } else { 420d831c5fdSJamin Lin /* clear irq */ 421c6c5e63dSJamin Lin trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx, 0); 422c6c5e63dSJamin Lin aspeed_intc_update(s, inpin_idx, outpin_idx, 0); 423d831c5fdSJamin Lin } 424d831c5fdSJamin Lin } 4253d6e15eaSJamin Lin } 4263d6e15eaSJamin Lin 4279178ff91SJamin Lin static void aspeed_intc_status_handler_multi_outpins(AspeedINTCState *s, 4289178ff91SJamin Lin hwaddr offset, uint64_t data) 4299178ff91SJamin Lin { 4309178ff91SJamin Lin const char *name = object_get_typename(OBJECT(s)); 4319178ff91SJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 4329178ff91SJamin Lin const AspeedINTCIRQ *intc_irq; 4339178ff91SJamin Lin uint32_t reg = offset >> 2; 4349178ff91SJamin Lin int num_outpins; 4359178ff91SJamin Lin int outpin_idx; 4369178ff91SJamin Lin int inpin_idx; 4379178ff91SJamin Lin int i; 4389178ff91SJamin Lin 4399178ff91SJamin Lin if (!data) { 4409178ff91SJamin Lin qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__); 4419178ff91SJamin Lin return; 4429178ff91SJamin Lin } 4439178ff91SJamin Lin 4449178ff91SJamin Lin intc_irq = aspeed_intc_get_irq(aic, reg); 4459178ff91SJamin Lin num_outpins = intc_irq->num_outpins; 4469178ff91SJamin Lin outpin_idx = intc_irq->outpin_idx; 4479178ff91SJamin Lin inpin_idx = intc_irq->inpin_idx; 4489178ff91SJamin Lin assert(inpin_idx < aic->num_inpins); 4499178ff91SJamin Lin 4509178ff91SJamin Lin /* clear status */ 4519178ff91SJamin Lin s->regs[reg] &= ~data; 4529178ff91SJamin Lin 4539178ff91SJamin Lin /* 4549178ff91SJamin Lin * The status registers are used for notify sources ISR are executed. 4559178ff91SJamin Lin * If one source ISR is executed, it will clear one bit. 4569178ff91SJamin Lin * If it clear all bits, it means to initialize this register status 4579178ff91SJamin Lin * rather than sources ISR are executed. 4589178ff91SJamin Lin */ 4599178ff91SJamin Lin if (data == 0xffffffff) { 4609178ff91SJamin Lin return; 4619178ff91SJamin Lin } 4629178ff91SJamin Lin 4639178ff91SJamin Lin for (i = 0; i < num_outpins; i++) { 4649178ff91SJamin Lin /* All source ISR executions are done from a specific bit */ 4659178ff91SJamin Lin if (data & BIT(i)) { 4669178ff91SJamin Lin trace_aspeed_intc_all_isr_done_bit(name, inpin_idx, i); 4679178ff91SJamin Lin if (s->pending[inpin_idx] & BIT(i)) { 4689178ff91SJamin Lin /* 4699178ff91SJamin Lin * Handle pending source interrupt. 4709178ff91SJamin Lin * Notify firmware which source interrupt is pending 4719178ff91SJamin Lin * by setting the status bit. 4729178ff91SJamin Lin */ 4739178ff91SJamin Lin s->regs[reg] |= BIT(i); 4749178ff91SJamin Lin s->pending[inpin_idx] &= ~BIT(i); 4759178ff91SJamin Lin trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i, 4769178ff91SJamin Lin s->regs[reg]); 4779178ff91SJamin Lin aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1); 4789178ff91SJamin Lin } else { 4799178ff91SJamin Lin /* clear irq for the specific bit */ 4809178ff91SJamin Lin trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx + i, 0); 4819178ff91SJamin Lin aspeed_intc_update(s, inpin_idx, outpin_idx + i, 0); 4829178ff91SJamin Lin } 4839178ff91SJamin Lin } 4849178ff91SJamin Lin } 4859178ff91SJamin Lin } 4869178ff91SJamin Lin 4873d6e15eaSJamin Lin static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size) 4883d6e15eaSJamin Lin { 4893d6e15eaSJamin Lin AspeedINTCState *s = ASPEED_INTC(opaque); 49049da40cfSJamin Lin const char *name = object_get_typename(OBJECT(s)); 4913d6e15eaSJamin Lin uint32_t reg = offset >> 2; 4923d6e15eaSJamin Lin uint32_t value = 0; 4933d6e15eaSJamin Lin 4943d6e15eaSJamin Lin value = s->regs[reg]; 49549da40cfSJamin Lin trace_aspeed_intc_read(name, offset, size, value); 4963d6e15eaSJamin Lin 4973d6e15eaSJamin Lin return value; 4983d6e15eaSJamin Lin } 4993d6e15eaSJamin Lin 5003d6e15eaSJamin Lin static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data, 5013d6e15eaSJamin Lin unsigned size) 5023d6e15eaSJamin Lin { 5033d6e15eaSJamin Lin AspeedINTCState *s = ASPEED_INTC(opaque); 50449da40cfSJamin Lin const char *name = object_get_typename(OBJECT(s)); 5053d6e15eaSJamin Lin uint32_t reg = offset >> 2; 5063d6e15eaSJamin Lin 50749da40cfSJamin Lin trace_aspeed_intc_write(name, offset, size, data); 5083d6e15eaSJamin Lin 5093d6e15eaSJamin Lin switch (reg) { 5103d6e15eaSJamin Lin case R_GICINT128_EN: 5113d6e15eaSJamin Lin case R_GICINT129_EN: 5123d6e15eaSJamin Lin case R_GICINT130_EN: 5133d6e15eaSJamin Lin case R_GICINT131_EN: 5143d6e15eaSJamin Lin case R_GICINT132_EN: 5153d6e15eaSJamin Lin case R_GICINT133_EN: 5163d6e15eaSJamin Lin case R_GICINT134_EN: 5173d6e15eaSJamin Lin case R_GICINT135_EN: 5183d6e15eaSJamin Lin case R_GICINT136_EN: 5199178ff91SJamin Lin case R_GICINT192_201_EN: 5203d6e15eaSJamin Lin aspeed_intc_enable_handler(s, offset, data); 5213d6e15eaSJamin Lin break; 5223d6e15eaSJamin Lin case R_GICINT128_STATUS: 5233d6e15eaSJamin Lin case R_GICINT129_STATUS: 5243d6e15eaSJamin Lin case R_GICINT130_STATUS: 5253d6e15eaSJamin Lin case R_GICINT131_STATUS: 5263d6e15eaSJamin Lin case R_GICINT132_STATUS: 5273d6e15eaSJamin Lin case R_GICINT133_STATUS: 5283d6e15eaSJamin Lin case R_GICINT134_STATUS: 5293d6e15eaSJamin Lin case R_GICINT135_STATUS: 5303d6e15eaSJamin Lin case R_GICINT136_STATUS: 5313d6e15eaSJamin Lin aspeed_intc_status_handler(s, offset, data); 532d831c5fdSJamin Lin break; 5339178ff91SJamin Lin case R_GICINT192_201_STATUS: 5349178ff91SJamin Lin aspeed_intc_status_handler_multi_outpins(s, offset, data); 5359178ff91SJamin Lin break; 536d831c5fdSJamin Lin default: 5370cffaaceSJamin Lin s->regs[reg] = data; 538d831c5fdSJamin Lin break; 539d831c5fdSJamin Lin } 540d831c5fdSJamin Lin } 541d831c5fdSJamin Lin 5428872b671SSteven Lee static void aspeed_ssp_intc_write(void *opaque, hwaddr offset, uint64_t data, 5438872b671SSteven Lee unsigned size) 5448872b671SSteven Lee { 5458872b671SSteven Lee AspeedINTCState *s = ASPEED_INTC(opaque); 5468872b671SSteven Lee const char *name = object_get_typename(OBJECT(s)); 5478872b671SSteven Lee uint32_t reg = offset >> 2; 5488872b671SSteven Lee 5498872b671SSteven Lee trace_aspeed_intc_write(name, offset, size, data); 5508872b671SSteven Lee 5518872b671SSteven Lee switch (reg) { 5528872b671SSteven Lee case R_SSPINT128_EN: 5538872b671SSteven Lee case R_SSPINT129_EN: 5548872b671SSteven Lee case R_SSPINT130_EN: 5558872b671SSteven Lee case R_SSPINT131_EN: 5568872b671SSteven Lee case R_SSPINT132_EN: 5578872b671SSteven Lee case R_SSPINT133_EN: 5588872b671SSteven Lee case R_SSPINT134_EN: 5598872b671SSteven Lee case R_SSPINT135_EN: 5608872b671SSteven Lee case R_SSPINT136_EN: 5618872b671SSteven Lee case R_SSPINT160_169_EN: 5628872b671SSteven Lee aspeed_intc_enable_handler(s, offset, data); 5638872b671SSteven Lee break; 5648872b671SSteven Lee case R_SSPINT128_STATUS: 5658872b671SSteven Lee case R_SSPINT129_STATUS: 5668872b671SSteven Lee case R_SSPINT130_STATUS: 5678872b671SSteven Lee case R_SSPINT131_STATUS: 5688872b671SSteven Lee case R_SSPINT132_STATUS: 5698872b671SSteven Lee case R_SSPINT133_STATUS: 5708872b671SSteven Lee case R_SSPINT134_STATUS: 5718872b671SSteven Lee case R_SSPINT135_STATUS: 5728872b671SSteven Lee case R_SSPINT136_STATUS: 5738872b671SSteven Lee aspeed_intc_status_handler(s, offset, data); 5748872b671SSteven Lee break; 5758872b671SSteven Lee case R_SSPINT160_169_STATUS: 5768872b671SSteven Lee aspeed_intc_status_handler_multi_outpins(s, offset, data); 5778872b671SSteven Lee break; 5788872b671SSteven Lee default: 5798872b671SSteven Lee s->regs[reg] = data; 5808872b671SSteven Lee break; 5818872b671SSteven Lee } 582c528f10dSSteven Lee } 5838872b671SSteven Lee 584c528f10dSSteven Lee static void aspeed_tsp_intc_write(void *opaque, hwaddr offset, uint64_t data, 585c528f10dSSteven Lee unsigned size) 586c528f10dSSteven Lee { 587c528f10dSSteven Lee AspeedINTCState *s = ASPEED_INTC(opaque); 588c528f10dSSteven Lee const char *name = object_get_typename(OBJECT(s)); 589c528f10dSSteven Lee uint32_t reg = offset >> 2; 590c528f10dSSteven Lee 591c528f10dSSteven Lee trace_aspeed_intc_write(name, offset, size, data); 592c528f10dSSteven Lee 593c528f10dSSteven Lee switch (reg) { 594c528f10dSSteven Lee case R_TSPINT128_EN: 595c528f10dSSteven Lee case R_TSPINT129_EN: 596c528f10dSSteven Lee case R_TSPINT130_EN: 597c528f10dSSteven Lee case R_TSPINT131_EN: 598c528f10dSSteven Lee case R_TSPINT132_EN: 599c528f10dSSteven Lee case R_TSPINT133_EN: 600c528f10dSSteven Lee case R_TSPINT134_EN: 601c528f10dSSteven Lee case R_TSPINT135_EN: 602c528f10dSSteven Lee case R_TSPINT136_EN: 603c528f10dSSteven Lee case R_TSPINT160_169_EN: 604c528f10dSSteven Lee aspeed_intc_enable_handler(s, offset, data); 605c528f10dSSteven Lee break; 606c528f10dSSteven Lee case R_TSPINT128_STATUS: 607c528f10dSSteven Lee case R_TSPINT129_STATUS: 608c528f10dSSteven Lee case R_TSPINT130_STATUS: 609c528f10dSSteven Lee case R_TSPINT131_STATUS: 610c528f10dSSteven Lee case R_TSPINT132_STATUS: 611c528f10dSSteven Lee case R_TSPINT133_STATUS: 612c528f10dSSteven Lee case R_TSPINT134_STATUS: 613c528f10dSSteven Lee case R_TSPINT135_STATUS: 614c528f10dSSteven Lee case R_TSPINT136_STATUS: 615c528f10dSSteven Lee aspeed_intc_status_handler(s, offset, data); 616c528f10dSSteven Lee break; 617c528f10dSSteven Lee case R_TSPINT160_169_STATUS: 618c528f10dSSteven Lee aspeed_intc_status_handler_multi_outpins(s, offset, data); 619c528f10dSSteven Lee break; 620c528f10dSSteven Lee default: 621c528f10dSSteven Lee s->regs[reg] = data; 622c528f10dSSteven Lee break; 623c528f10dSSteven Lee } 6248872b671SSteven Lee } 6258872b671SSteven Lee 62638ba38d8SJamin Lin static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset, 62738ba38d8SJamin Lin unsigned int size) 62838ba38d8SJamin Lin { 62938ba38d8SJamin Lin AspeedINTCState *s = ASPEED_INTC(opaque); 63038ba38d8SJamin Lin const char *name = object_get_typename(OBJECT(s)); 63138ba38d8SJamin Lin uint32_t reg = offset >> 2; 63238ba38d8SJamin Lin uint32_t value = 0; 63338ba38d8SJamin Lin 63438ba38d8SJamin Lin value = s->regs[reg]; 63538ba38d8SJamin Lin trace_aspeed_intc_read(name, offset, size, value); 63638ba38d8SJamin Lin 63738ba38d8SJamin Lin return value; 63838ba38d8SJamin Lin } 63938ba38d8SJamin Lin 64038ba38d8SJamin Lin static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data, 64138ba38d8SJamin Lin unsigned size) 64238ba38d8SJamin Lin { 64338ba38d8SJamin Lin AspeedINTCState *s = ASPEED_INTC(opaque); 64438ba38d8SJamin Lin const char *name = object_get_typename(OBJECT(s)); 64538ba38d8SJamin Lin uint32_t reg = offset >> 2; 64638ba38d8SJamin Lin 64738ba38d8SJamin Lin trace_aspeed_intc_write(name, offset, size, data); 64838ba38d8SJamin Lin 64938ba38d8SJamin Lin switch (reg) { 65038ba38d8SJamin Lin case R_GICINT192_EN: 65138ba38d8SJamin Lin case R_GICINT193_EN: 65238ba38d8SJamin Lin case R_GICINT194_EN: 65338ba38d8SJamin Lin case R_GICINT195_EN: 65438ba38d8SJamin Lin case R_GICINT196_EN: 65538ba38d8SJamin Lin case R_GICINT197_EN: 65638ba38d8SJamin Lin aspeed_intc_enable_handler(s, offset, data); 65738ba38d8SJamin Lin break; 65838ba38d8SJamin Lin case R_GICINT192_STATUS: 65938ba38d8SJamin Lin case R_GICINT193_STATUS: 66038ba38d8SJamin Lin case R_GICINT194_STATUS: 66138ba38d8SJamin Lin case R_GICINT195_STATUS: 66238ba38d8SJamin Lin case R_GICINT196_STATUS: 66338ba38d8SJamin Lin case R_GICINT197_STATUS: 66438ba38d8SJamin Lin aspeed_intc_status_handler(s, offset, data); 66538ba38d8SJamin Lin break; 66638ba38d8SJamin Lin default: 66738ba38d8SJamin Lin s->regs[reg] = data; 66838ba38d8SJamin Lin break; 66938ba38d8SJamin Lin } 67038ba38d8SJamin Lin } 67138ba38d8SJamin Lin 6728872b671SSteven Lee static void aspeed_ssp_intcio_write(void *opaque, hwaddr offset, uint64_t data, 6738872b671SSteven Lee unsigned size) 6748872b671SSteven Lee { 6758872b671SSteven Lee AspeedINTCState *s = ASPEED_INTC(opaque); 6768872b671SSteven Lee const char *name = object_get_typename(OBJECT(s)); 6778872b671SSteven Lee uint32_t reg = offset >> 2; 6788872b671SSteven Lee 6798872b671SSteven Lee trace_aspeed_intc_write(name, offset, size, data); 6808872b671SSteven Lee 6818872b671SSteven Lee switch (reg) { 6828872b671SSteven Lee case R_SSPINT160_EN: 6838872b671SSteven Lee case R_SSPINT161_EN: 6848872b671SSteven Lee case R_SSPINT162_EN: 6858872b671SSteven Lee case R_SSPINT163_EN: 6868872b671SSteven Lee case R_SSPINT164_EN: 6878872b671SSteven Lee case R_SSPINT165_EN: 6888872b671SSteven Lee aspeed_intc_enable_handler(s, offset, data); 6898872b671SSteven Lee break; 6908872b671SSteven Lee case R_SSPINT160_STATUS: 6918872b671SSteven Lee case R_SSPINT161_STATUS: 6928872b671SSteven Lee case R_SSPINT162_STATUS: 6938872b671SSteven Lee case R_SSPINT163_STATUS: 6948872b671SSteven Lee case R_SSPINT164_STATUS: 6958872b671SSteven Lee case R_SSPINT165_STATUS: 6968872b671SSteven Lee aspeed_intc_status_handler(s, offset, data); 6978872b671SSteven Lee break; 6988872b671SSteven Lee default: 6998872b671SSteven Lee s->regs[reg] = data; 7008872b671SSteven Lee break; 7018872b671SSteven Lee } 702c528f10dSSteven Lee } 7038872b671SSteven Lee 704c528f10dSSteven Lee static void aspeed_tsp_intcio_write(void *opaque, hwaddr offset, uint64_t data, 705c528f10dSSteven Lee unsigned size) 706c528f10dSSteven Lee { 707c528f10dSSteven Lee AspeedINTCState *s = ASPEED_INTC(opaque); 708c528f10dSSteven Lee const char *name = object_get_typename(OBJECT(s)); 709c528f10dSSteven Lee uint32_t reg = offset >> 2; 710c528f10dSSteven Lee 711c528f10dSSteven Lee trace_aspeed_intc_write(name, offset, size, data); 712c528f10dSSteven Lee 713c528f10dSSteven Lee switch (reg) { 714c528f10dSSteven Lee case R_TSPINT160_EN: 715c528f10dSSteven Lee case R_TSPINT161_EN: 716c528f10dSSteven Lee case R_TSPINT162_EN: 717c528f10dSSteven Lee case R_TSPINT163_EN: 718c528f10dSSteven Lee case R_TSPINT164_EN: 719c528f10dSSteven Lee case R_TSPINT165_EN: 720c528f10dSSteven Lee aspeed_intc_enable_handler(s, offset, data); 721c528f10dSSteven Lee break; 722c528f10dSSteven Lee case R_TSPINT160_STATUS: 723c528f10dSSteven Lee case R_TSPINT161_STATUS: 724c528f10dSSteven Lee case R_TSPINT162_STATUS: 725c528f10dSSteven Lee case R_TSPINT163_STATUS: 726c528f10dSSteven Lee case R_TSPINT164_STATUS: 727c528f10dSSteven Lee case R_TSPINT165_STATUS: 728c528f10dSSteven Lee aspeed_intc_status_handler(s, offset, data); 729c528f10dSSteven Lee break; 730c528f10dSSteven Lee default: 731c528f10dSSteven Lee s->regs[reg] = data; 732c528f10dSSteven Lee break; 733c528f10dSSteven Lee } 7348872b671SSteven Lee } 73538ba38d8SJamin Lin 736d831c5fdSJamin Lin static const MemoryRegionOps aspeed_intc_ops = { 737d831c5fdSJamin Lin .read = aspeed_intc_read, 738d831c5fdSJamin Lin .write = aspeed_intc_write, 739d831c5fdSJamin Lin .endianness = DEVICE_LITTLE_ENDIAN, 740*5c14d7cbSJamin Lin .impl.min_access_size = 4, 741d831c5fdSJamin Lin .valid = { 742d831c5fdSJamin Lin .min_access_size = 4, 743d831c5fdSJamin Lin .max_access_size = 4, 744d831c5fdSJamin Lin } 745d831c5fdSJamin Lin }; 746d831c5fdSJamin Lin 74738ba38d8SJamin Lin static const MemoryRegionOps aspeed_intcio_ops = { 74838ba38d8SJamin Lin .read = aspeed_intcio_read, 74938ba38d8SJamin Lin .write = aspeed_intcio_write, 75038ba38d8SJamin Lin .endianness = DEVICE_LITTLE_ENDIAN, 751*5c14d7cbSJamin Lin .impl.min_access_size = 4, 75238ba38d8SJamin Lin .valid = { 75338ba38d8SJamin Lin .min_access_size = 4, 75438ba38d8SJamin Lin .max_access_size = 4, 75538ba38d8SJamin Lin } 75638ba38d8SJamin Lin }; 75738ba38d8SJamin Lin 7588872b671SSteven Lee static const MemoryRegionOps aspeed_ssp_intc_ops = { 7598872b671SSteven Lee .read = aspeed_intc_read, 7608872b671SSteven Lee .write = aspeed_ssp_intc_write, 7618872b671SSteven Lee .endianness = DEVICE_LITTLE_ENDIAN, 762*5c14d7cbSJamin Lin .impl.min_access_size = 4, 7638872b671SSteven Lee .valid = { 7648872b671SSteven Lee .min_access_size = 4, 7658872b671SSteven Lee .max_access_size = 4, 7668872b671SSteven Lee } 7678872b671SSteven Lee }; 7688872b671SSteven Lee 7698872b671SSteven Lee static const MemoryRegionOps aspeed_ssp_intcio_ops = { 7708872b671SSteven Lee .read = aspeed_intcio_read, 7718872b671SSteven Lee .write = aspeed_ssp_intcio_write, 7728872b671SSteven Lee .endianness = DEVICE_LITTLE_ENDIAN, 773*5c14d7cbSJamin Lin .impl.min_access_size = 4, 7748872b671SSteven Lee .valid = { 7758872b671SSteven Lee .min_access_size = 4, 7768872b671SSteven Lee .max_access_size = 4, 7778872b671SSteven Lee } 7788872b671SSteven Lee }; 7798872b671SSteven Lee 780c528f10dSSteven Lee static const MemoryRegionOps aspeed_tsp_intc_ops = { 781c528f10dSSteven Lee .read = aspeed_intc_read, 782c528f10dSSteven Lee .write = aspeed_tsp_intc_write, 783c528f10dSSteven Lee .endianness = DEVICE_LITTLE_ENDIAN, 784*5c14d7cbSJamin Lin .impl.min_access_size = 4, 785c528f10dSSteven Lee .valid = { 786c528f10dSSteven Lee .min_access_size = 4, 787c528f10dSSteven Lee .max_access_size = 4, 788c528f10dSSteven Lee } 789c528f10dSSteven Lee }; 790c528f10dSSteven Lee 791c528f10dSSteven Lee static const MemoryRegionOps aspeed_tsp_intcio_ops = { 792c528f10dSSteven Lee .read = aspeed_intcio_read, 793c528f10dSSteven Lee .write = aspeed_tsp_intcio_write, 794c528f10dSSteven Lee .endianness = DEVICE_LITTLE_ENDIAN, 795*5c14d7cbSJamin Lin .impl.min_access_size = 4, 796c528f10dSSteven Lee .valid = { 797c528f10dSSteven Lee .min_access_size = 4, 798c528f10dSSteven Lee .max_access_size = 4, 799c528f10dSSteven Lee } 800c528f10dSSteven Lee }; 801c528f10dSSteven Lee 802d831c5fdSJamin Lin static void aspeed_intc_instance_init(Object *obj) 803d831c5fdSJamin Lin { 804d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(obj); 805d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 806d831c5fdSJamin Lin int i; 807d831c5fdSJamin Lin 80863f3618fSJamin Lin assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS); 80963f3618fSJamin Lin for (i = 0; i < aic->num_inpins; i++) { 810d831c5fdSJamin Lin object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i], 811d831c5fdSJamin Lin TYPE_OR_IRQ); 812d831c5fdSJamin Lin object_property_set_int(OBJECT(&s->orgates[i]), "num-lines", 813d831c5fdSJamin Lin aic->num_lines, &error_abort); 814d831c5fdSJamin Lin } 815d831c5fdSJamin Lin } 816d831c5fdSJamin Lin 817d831c5fdSJamin Lin static void aspeed_intc_reset(DeviceState *dev) 818d831c5fdSJamin Lin { 819d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(dev); 820b008465dSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 821d831c5fdSJamin Lin 822b008465dSJamin Lin memset(s->regs, 0, aic->nr_regs << 2); 823d831c5fdSJamin Lin memset(s->enable, 0, sizeof(s->enable)); 824d831c5fdSJamin Lin memset(s->mask, 0, sizeof(s->mask)); 825d831c5fdSJamin Lin memset(s->pending, 0, sizeof(s->pending)); 826d831c5fdSJamin Lin } 827d831c5fdSJamin Lin 828d831c5fdSJamin Lin static void aspeed_intc_realize(DeviceState *dev, Error **errp) 829d831c5fdSJamin Lin { 830d831c5fdSJamin Lin SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 831d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(dev); 832d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s); 833d831c5fdSJamin Lin int i; 834d831c5fdSJamin Lin 835c5728c34SJamin Lin memory_region_init(&s->iomem_container, OBJECT(s), 836c5728c34SJamin Lin TYPE_ASPEED_INTC ".container", aic->mem_size); 837c5728c34SJamin Lin 838c5728c34SJamin Lin sysbus_init_mmio(sbd, &s->iomem_container); 839c5728c34SJamin Lin 840b008465dSJamin Lin s->regs = g_new(uint32_t, aic->nr_regs); 84128194d5dSJamin Lin memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s, 842b008465dSJamin Lin TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2); 843d831c5fdSJamin Lin 8447ffee511SJamin Lin memory_region_add_subregion(&s->iomem_container, aic->reg_offset, 8457ffee511SJamin Lin &s->iomem); 846c5728c34SJamin Lin 84763f3618fSJamin Lin qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins); 848d831c5fdSJamin Lin 84963f3618fSJamin Lin for (i = 0; i < aic->num_inpins; i++) { 850d831c5fdSJamin Lin if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) { 851d831c5fdSJamin Lin return; 852d831c5fdSJamin Lin } 85335c909cdSJamin Lin } 85435c909cdSJamin Lin 85535c909cdSJamin Lin for (i = 0; i < aic->num_outpins; i++) { 856d831c5fdSJamin Lin sysbus_init_irq(sbd, &s->output_pins[i]); 857d831c5fdSJamin Lin } 858d831c5fdSJamin Lin } 859d831c5fdSJamin Lin 860563afea0SJamin Lin static void aspeed_intc_unrealize(DeviceState *dev) 861563afea0SJamin Lin { 862563afea0SJamin Lin AspeedINTCState *s = ASPEED_INTC(dev); 863563afea0SJamin Lin 864563afea0SJamin Lin g_free(s->regs); 865563afea0SJamin Lin s->regs = NULL; 866563afea0SJamin Lin } 867563afea0SJamin Lin 86812d1a768SPhilippe Mathieu-Daudé static void aspeed_intc_class_init(ObjectClass *klass, const void *data) 869d831c5fdSJamin Lin { 870d831c5fdSJamin Lin DeviceClass *dc = DEVICE_CLASS(klass); 87128194d5dSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 872d831c5fdSJamin Lin 873d831c5fdSJamin Lin dc->desc = "ASPEED INTC Controller"; 874d831c5fdSJamin Lin dc->realize = aspeed_intc_realize; 875563afea0SJamin Lin dc->unrealize = aspeed_intc_unrealize; 876e3d08143SPeter Maydell device_class_set_legacy_reset(dc, aspeed_intc_reset); 877d831c5fdSJamin Lin dc->vmsd = NULL; 87828194d5dSJamin Lin 87928194d5dSJamin Lin aic->reg_ops = &aspeed_intc_ops; 880d831c5fdSJamin Lin } 881d831c5fdSJamin Lin 882d831c5fdSJamin Lin static const TypeInfo aspeed_intc_info = { 883d831c5fdSJamin Lin .name = TYPE_ASPEED_INTC, 884d831c5fdSJamin Lin .parent = TYPE_SYS_BUS_DEVICE, 885d831c5fdSJamin Lin .instance_init = aspeed_intc_instance_init, 886d831c5fdSJamin Lin .instance_size = sizeof(AspeedINTCState), 887d831c5fdSJamin Lin .class_init = aspeed_intc_class_init, 888d831c5fdSJamin Lin .class_size = sizeof(AspeedINTCClass), 889d831c5fdSJamin Lin .abstract = true, 890d831c5fdSJamin Lin }; 891d831c5fdSJamin Lin 892ab24c6a2SJamin Lin static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = { 8939178ff91SJamin Lin {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS}, 8949178ff91SJamin Lin {1, 10, 1, R_GICINT128_EN, R_GICINT128_STATUS}, 8959178ff91SJamin Lin {2, 11, 1, R_GICINT129_EN, R_GICINT129_STATUS}, 8969178ff91SJamin Lin {3, 12, 1, R_GICINT130_EN, R_GICINT130_STATUS}, 8979178ff91SJamin Lin {4, 13, 1, R_GICINT131_EN, R_GICINT131_STATUS}, 8989178ff91SJamin Lin {5, 14, 1, R_GICINT132_EN, R_GICINT132_STATUS}, 8999178ff91SJamin Lin {6, 15, 1, R_GICINT133_EN, R_GICINT133_STATUS}, 9009178ff91SJamin Lin {7, 16, 1, R_GICINT134_EN, R_GICINT134_STATUS}, 9019178ff91SJamin Lin {8, 17, 1, R_GICINT135_EN, R_GICINT135_STATUS}, 9029178ff91SJamin Lin {9, 18, 1, R_GICINT136_EN, R_GICINT136_STATUS}, 903ab24c6a2SJamin Lin }; 904ab24c6a2SJamin Lin 90512d1a768SPhilippe Mathieu-Daudé static void aspeed_2700_intc_class_init(ObjectClass *klass, const void *data) 906d831c5fdSJamin Lin { 907d831c5fdSJamin Lin DeviceClass *dc = DEVICE_CLASS(klass); 908d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 909d831c5fdSJamin Lin 910d831c5fdSJamin Lin dc->desc = "ASPEED 2700 INTC Controller"; 911d831c5fdSJamin Lin aic->num_lines = 32; 9129178ff91SJamin Lin aic->num_inpins = 10; 9139178ff91SJamin Lin aic->num_outpins = 19; 914c5728c34SJamin Lin aic->mem_size = 0x4000; 9159178ff91SJamin Lin aic->nr_regs = 0xB08 >> 2; 9167ffee511SJamin Lin aic->reg_offset = 0x1000; 917ab24c6a2SJamin Lin aic->irq_table = aspeed_2700_intc_irqs; 918ab24c6a2SJamin Lin aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc_irqs); 919d831c5fdSJamin Lin } 920d831c5fdSJamin Lin 921d831c5fdSJamin Lin static const TypeInfo aspeed_2700_intc_info = { 922d831c5fdSJamin Lin .name = TYPE_ASPEED_2700_INTC, 923d831c5fdSJamin Lin .parent = TYPE_ASPEED_INTC, 924d831c5fdSJamin Lin .class_init = aspeed_2700_intc_class_init, 925d831c5fdSJamin Lin }; 926d831c5fdSJamin Lin 92738ba38d8SJamin Lin static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { 92838ba38d8SJamin Lin {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS}, 92938ba38d8SJamin Lin {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS}, 93038ba38d8SJamin Lin {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS}, 93138ba38d8SJamin Lin {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS}, 93238ba38d8SJamin Lin {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS}, 93338ba38d8SJamin Lin {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS}, 93438ba38d8SJamin Lin }; 93538ba38d8SJamin Lin 93612d1a768SPhilippe Mathieu-Daudé static void aspeed_2700_intcio_class_init(ObjectClass *klass, const void *data) 93738ba38d8SJamin Lin { 93838ba38d8SJamin Lin DeviceClass *dc = DEVICE_CLASS(klass); 93938ba38d8SJamin Lin AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 94038ba38d8SJamin Lin 94138ba38d8SJamin Lin dc->desc = "ASPEED 2700 INTC IO Controller"; 94238ba38d8SJamin Lin aic->num_lines = 32; 94338ba38d8SJamin Lin aic->num_inpins = 6; 94438ba38d8SJamin Lin aic->num_outpins = 6; 94538ba38d8SJamin Lin aic->mem_size = 0x400; 94638ba38d8SJamin Lin aic->nr_regs = 0x58 >> 2; 94738ba38d8SJamin Lin aic->reg_offset = 0x100; 94838ba38d8SJamin Lin aic->reg_ops = &aspeed_intcio_ops; 94938ba38d8SJamin Lin aic->irq_table = aspeed_2700_intcio_irqs; 95038ba38d8SJamin Lin aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcio_irqs); 95138ba38d8SJamin Lin } 95238ba38d8SJamin Lin 95338ba38d8SJamin Lin static const TypeInfo aspeed_2700_intcio_info = { 95438ba38d8SJamin Lin .name = TYPE_ASPEED_2700_INTCIO, 95538ba38d8SJamin Lin .parent = TYPE_ASPEED_INTC, 95638ba38d8SJamin Lin .class_init = aspeed_2700_intcio_class_init, 95738ba38d8SJamin Lin }; 95838ba38d8SJamin Lin 9598872b671SSteven Lee static AspeedINTCIRQ aspeed_2700ssp_intc_irqs[ASPEED_INTC_MAX_INPINS] = { 9608872b671SSteven Lee {0, 0, 10, R_SSPINT160_169_EN, R_SSPINT160_169_STATUS}, 9618872b671SSteven Lee {1, 10, 1, R_SSPINT128_EN, R_SSPINT128_STATUS}, 9628872b671SSteven Lee {2, 11, 1, R_SSPINT129_EN, R_SSPINT129_STATUS}, 9638872b671SSteven Lee {3, 12, 1, R_SSPINT130_EN, R_SSPINT130_STATUS}, 9648872b671SSteven Lee {4, 13, 1, R_SSPINT131_EN, R_SSPINT131_STATUS}, 9658872b671SSteven Lee {5, 14, 1, R_SSPINT132_EN, R_SSPINT132_STATUS}, 9668872b671SSteven Lee {6, 15, 1, R_SSPINT133_EN, R_SSPINT133_STATUS}, 9678872b671SSteven Lee {7, 16, 1, R_SSPINT134_EN, R_SSPINT134_STATUS}, 9688872b671SSteven Lee {8, 17, 1, R_SSPINT135_EN, R_SSPINT135_STATUS}, 9698872b671SSteven Lee {9, 18, 1, R_SSPINT136_EN, R_SSPINT136_STATUS}, 9708872b671SSteven Lee }; 9718872b671SSteven Lee 9728872b671SSteven Lee static void aspeed_2700ssp_intc_class_init(ObjectClass *klass, const void *data) 9738872b671SSteven Lee { 9748872b671SSteven Lee DeviceClass *dc = DEVICE_CLASS(klass); 9758872b671SSteven Lee AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 9768872b671SSteven Lee 9778872b671SSteven Lee dc->desc = "ASPEED 2700 SSP INTC Controller"; 9788872b671SSteven Lee aic->num_lines = 32; 9798872b671SSteven Lee aic->num_inpins = 10; 9808872b671SSteven Lee aic->num_outpins = 19; 9818872b671SSteven Lee aic->mem_size = 0x4000; 9828872b671SSteven Lee aic->nr_regs = 0x2B08 >> 2; 9838872b671SSteven Lee aic->reg_offset = 0x0; 9848872b671SSteven Lee aic->reg_ops = &aspeed_ssp_intc_ops; 9858872b671SSteven Lee aic->irq_table = aspeed_2700ssp_intc_irqs; 9868872b671SSteven Lee aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intc_irqs); 9878872b671SSteven Lee } 9888872b671SSteven Lee 9898872b671SSteven Lee static const TypeInfo aspeed_2700ssp_intc_info = { 9908872b671SSteven Lee .name = TYPE_ASPEED_2700SSP_INTC, 9918872b671SSteven Lee .parent = TYPE_ASPEED_INTC, 9928872b671SSteven Lee .class_init = aspeed_2700ssp_intc_class_init, 9938872b671SSteven Lee }; 9948872b671SSteven Lee 9958872b671SSteven Lee static AspeedINTCIRQ aspeed_2700ssp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { 9968872b671SSteven Lee {0, 0, 1, R_SSPINT160_EN, R_SSPINT160_STATUS}, 9978872b671SSteven Lee {1, 1, 1, R_SSPINT161_EN, R_SSPINT161_STATUS}, 9988872b671SSteven Lee {2, 2, 1, R_SSPINT162_EN, R_SSPINT162_STATUS}, 9998872b671SSteven Lee {3, 3, 1, R_SSPINT163_EN, R_SSPINT163_STATUS}, 10008872b671SSteven Lee {4, 4, 1, R_SSPINT164_EN, R_SSPINT164_STATUS}, 10018872b671SSteven Lee {5, 5, 1, R_SSPINT165_EN, R_SSPINT165_STATUS}, 10028872b671SSteven Lee }; 10038872b671SSteven Lee 10048872b671SSteven Lee static void aspeed_2700ssp_intcio_class_init(ObjectClass *klass, const void *data) 10058872b671SSteven Lee { 10068872b671SSteven Lee DeviceClass *dc = DEVICE_CLASS(klass); 10078872b671SSteven Lee AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 10088872b671SSteven Lee 10098872b671SSteven Lee dc->desc = "ASPEED 2700 SSP INTC IO Controller"; 10108872b671SSteven Lee aic->num_lines = 32; 10118872b671SSteven Lee aic->num_inpins = 6; 10128872b671SSteven Lee aic->num_outpins = 6; 10138872b671SSteven Lee aic->mem_size = 0x400; 10148872b671SSteven Lee aic->nr_regs = 0x1d8 >> 2; 10158872b671SSteven Lee aic->reg_offset = 0; 10168872b671SSteven Lee aic->reg_ops = &aspeed_ssp_intcio_ops; 10178872b671SSteven Lee aic->irq_table = aspeed_2700ssp_intcio_irqs; 10188872b671SSteven Lee aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intcio_irqs); 10198872b671SSteven Lee } 10208872b671SSteven Lee 10218872b671SSteven Lee static const TypeInfo aspeed_2700ssp_intcio_info = { 10228872b671SSteven Lee .name = TYPE_ASPEED_2700SSP_INTCIO, 10238872b671SSteven Lee .parent = TYPE_ASPEED_INTC, 10248872b671SSteven Lee .class_init = aspeed_2700ssp_intcio_class_init, 10258872b671SSteven Lee }; 10268872b671SSteven Lee 1027c528f10dSSteven Lee static AspeedINTCIRQ aspeed_2700tsp_intc_irqs[ASPEED_INTC_MAX_INPINS] = { 1028c528f10dSSteven Lee {0, 0, 10, R_TSPINT160_169_EN, R_TSPINT160_169_STATUS}, 1029c528f10dSSteven Lee {1, 10, 1, R_TSPINT128_EN, R_TSPINT128_STATUS}, 1030c528f10dSSteven Lee {2, 11, 1, R_TSPINT129_EN, R_TSPINT129_STATUS}, 1031c528f10dSSteven Lee {3, 12, 1, R_TSPINT130_EN, R_TSPINT130_STATUS}, 1032c528f10dSSteven Lee {4, 13, 1, R_TSPINT131_EN, R_TSPINT131_STATUS}, 1033c528f10dSSteven Lee {5, 14, 1, R_TSPINT132_EN, R_TSPINT132_STATUS}, 1034c528f10dSSteven Lee {6, 15, 1, R_TSPINT133_EN, R_TSPINT133_STATUS}, 1035c528f10dSSteven Lee {7, 16, 1, R_TSPINT134_EN, R_TSPINT134_STATUS}, 1036c528f10dSSteven Lee {8, 17, 1, R_TSPINT135_EN, R_TSPINT135_STATUS}, 1037c528f10dSSteven Lee {9, 18, 1, R_TSPINT136_EN, R_TSPINT136_STATUS}, 1038c528f10dSSteven Lee }; 1039c528f10dSSteven Lee 1040c528f10dSSteven Lee static void aspeed_2700tsp_intc_class_init(ObjectClass *klass, const void *data) 1041c528f10dSSteven Lee { 1042c528f10dSSteven Lee DeviceClass *dc = DEVICE_CLASS(klass); 1043c528f10dSSteven Lee AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 1044c528f10dSSteven Lee 1045c528f10dSSteven Lee dc->desc = "ASPEED 2700 TSP INTC Controller"; 1046c528f10dSSteven Lee aic->num_lines = 32; 1047c528f10dSSteven Lee aic->num_inpins = 10; 1048c528f10dSSteven Lee aic->num_outpins = 19; 1049c528f10dSSteven Lee aic->mem_size = 0x4000; 1050c528f10dSSteven Lee aic->nr_regs = 0x3B08 >> 2; 1051c528f10dSSteven Lee aic->reg_offset = 0; 1052c528f10dSSteven Lee aic->reg_ops = &aspeed_tsp_intc_ops; 1053c528f10dSSteven Lee aic->irq_table = aspeed_2700tsp_intc_irqs; 1054c528f10dSSteven Lee aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intc_irqs); 1055c528f10dSSteven Lee } 1056c528f10dSSteven Lee 1057c528f10dSSteven Lee static const TypeInfo aspeed_2700tsp_intc_info = { 1058c528f10dSSteven Lee .name = TYPE_ASPEED_2700TSP_INTC, 1059c528f10dSSteven Lee .parent = TYPE_ASPEED_INTC, 1060c528f10dSSteven Lee .class_init = aspeed_2700tsp_intc_class_init, 1061c528f10dSSteven Lee }; 1062c528f10dSSteven Lee 1063c528f10dSSteven Lee static AspeedINTCIRQ aspeed_2700tsp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { 1064c528f10dSSteven Lee {0, 0, 1, R_TSPINT160_EN, R_TSPINT160_STATUS}, 1065c528f10dSSteven Lee {1, 1, 1, R_TSPINT161_EN, R_TSPINT161_STATUS}, 1066c528f10dSSteven Lee {2, 2, 1, R_TSPINT162_EN, R_TSPINT162_STATUS}, 1067c528f10dSSteven Lee {3, 3, 1, R_TSPINT163_EN, R_TSPINT163_STATUS}, 1068c528f10dSSteven Lee {4, 4, 1, R_TSPINT164_EN, R_TSPINT164_STATUS}, 1069c528f10dSSteven Lee {5, 5, 1, R_TSPINT165_EN, R_TSPINT165_STATUS}, 1070c528f10dSSteven Lee }; 1071c528f10dSSteven Lee 1072c528f10dSSteven Lee static void aspeed_2700tsp_intcio_class_init(ObjectClass *klass, const void *data) 1073c528f10dSSteven Lee { 1074c528f10dSSteven Lee DeviceClass *dc = DEVICE_CLASS(klass); 1075c528f10dSSteven Lee AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); 1076c528f10dSSteven Lee 1077c528f10dSSteven Lee dc->desc = "ASPEED 2700 TSP INTC IO Controller"; 1078c528f10dSSteven Lee aic->num_lines = 32; 1079c528f10dSSteven Lee aic->num_inpins = 6; 1080c528f10dSSteven Lee aic->num_outpins = 6; 1081c528f10dSSteven Lee aic->mem_size = 0x400; 1082c528f10dSSteven Lee aic->nr_regs = 0x258 >> 2; 1083c528f10dSSteven Lee aic->reg_offset = 0x0; 1084c528f10dSSteven Lee aic->reg_ops = &aspeed_tsp_intcio_ops; 1085c528f10dSSteven Lee aic->irq_table = aspeed_2700tsp_intcio_irqs; 1086c528f10dSSteven Lee aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intcio_irqs); 1087c528f10dSSteven Lee } 1088c528f10dSSteven Lee 1089c528f10dSSteven Lee static const TypeInfo aspeed_2700tsp_intcio_info = { 1090c528f10dSSteven Lee .name = TYPE_ASPEED_2700TSP_INTCIO, 1091c528f10dSSteven Lee .parent = TYPE_ASPEED_INTC, 1092c528f10dSSteven Lee .class_init = aspeed_2700tsp_intcio_class_init, 1093c528f10dSSteven Lee }; 1094c528f10dSSteven Lee 1095d831c5fdSJamin Lin static void aspeed_intc_register_types(void) 1096d831c5fdSJamin Lin { 1097d831c5fdSJamin Lin type_register_static(&aspeed_intc_info); 1098d831c5fdSJamin Lin type_register_static(&aspeed_2700_intc_info); 109938ba38d8SJamin Lin type_register_static(&aspeed_2700_intcio_info); 11008872b671SSteven Lee type_register_static(&aspeed_2700ssp_intc_info); 11018872b671SSteven Lee type_register_static(&aspeed_2700ssp_intcio_info); 1102c528f10dSSteven Lee type_register_static(&aspeed_2700tsp_intc_info); 1103c528f10dSSteven Lee type_register_static(&aspeed_2700tsp_intcio_info); 1104d831c5fdSJamin Lin } 1105d831c5fdSJamin Lin 1106d831c5fdSJamin Lin type_init(aspeed_intc_register_types); 1107