1*d831c5fdSJamin Lin /*
2*d831c5fdSJamin Lin * ASPEED INTC Controller
3*d831c5fdSJamin Lin *
4*d831c5fdSJamin Lin * Copyright (C) 2024 ASPEED Technology Inc.
5*d831c5fdSJamin Lin *
6*d831c5fdSJamin Lin * SPDX-License-Identifier: GPL-2.0-or-later
7*d831c5fdSJamin Lin */
8*d831c5fdSJamin Lin
9*d831c5fdSJamin Lin #include "qemu/osdep.h"
10*d831c5fdSJamin Lin #include "hw/intc/aspeed_intc.h"
11*d831c5fdSJamin Lin #include "hw/irq.h"
12*d831c5fdSJamin Lin #include "qemu/log.h"
13*d831c5fdSJamin Lin #include "trace.h"
14*d831c5fdSJamin Lin #include "hw/registerfields.h"
15*d831c5fdSJamin Lin #include "qapi/error.h"
16*d831c5fdSJamin Lin
17*d831c5fdSJamin Lin /* INTC Registers */
18*d831c5fdSJamin Lin REG32(GICINT128_EN, 0x1000)
19*d831c5fdSJamin Lin REG32(GICINT128_STATUS, 0x1004)
20*d831c5fdSJamin Lin REG32(GICINT129_EN, 0x1100)
21*d831c5fdSJamin Lin REG32(GICINT129_STATUS, 0x1104)
22*d831c5fdSJamin Lin REG32(GICINT130_EN, 0x1200)
23*d831c5fdSJamin Lin REG32(GICINT130_STATUS, 0x1204)
24*d831c5fdSJamin Lin REG32(GICINT131_EN, 0x1300)
25*d831c5fdSJamin Lin REG32(GICINT131_STATUS, 0x1304)
26*d831c5fdSJamin Lin REG32(GICINT132_EN, 0x1400)
27*d831c5fdSJamin Lin REG32(GICINT132_STATUS, 0x1404)
28*d831c5fdSJamin Lin REG32(GICINT133_EN, 0x1500)
29*d831c5fdSJamin Lin REG32(GICINT133_STATUS, 0x1504)
30*d831c5fdSJamin Lin REG32(GICINT134_EN, 0x1600)
31*d831c5fdSJamin Lin REG32(GICINT134_STATUS, 0x1604)
32*d831c5fdSJamin Lin REG32(GICINT135_EN, 0x1700)
33*d831c5fdSJamin Lin REG32(GICINT135_STATUS, 0x1704)
34*d831c5fdSJamin Lin REG32(GICINT136_EN, 0x1800)
35*d831c5fdSJamin Lin REG32(GICINT136_STATUS, 0x1804)
36*d831c5fdSJamin Lin
37*d831c5fdSJamin Lin #define GICINT_STATUS_BASE R_GICINT128_STATUS
38*d831c5fdSJamin Lin
aspeed_intc_update(AspeedINTCState * s,int irq,int level)39*d831c5fdSJamin Lin static void aspeed_intc_update(AspeedINTCState *s, int irq, int level)
40*d831c5fdSJamin Lin {
41*d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
42*d831c5fdSJamin Lin
43*d831c5fdSJamin Lin if (irq >= aic->num_ints) {
44*d831c5fdSJamin Lin qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
45*d831c5fdSJamin Lin __func__, irq);
46*d831c5fdSJamin Lin return;
47*d831c5fdSJamin Lin }
48*d831c5fdSJamin Lin
49*d831c5fdSJamin Lin trace_aspeed_intc_update_irq(irq, level);
50*d831c5fdSJamin Lin qemu_set_irq(s->output_pins[irq], level);
51*d831c5fdSJamin Lin }
52*d831c5fdSJamin Lin
53*d831c5fdSJamin Lin /*
54*d831c5fdSJamin Lin * The address of GICINT128 to GICINT136 are from 0x1000 to 0x1804.
55*d831c5fdSJamin Lin * Utilize "address & 0x0f00" to get the irq and irq output pin index
56*d831c5fdSJamin Lin * The value of irq should be 0 to num_ints.
57*d831c5fdSJamin Lin * The irq 0 indicates GICINT128, irq 1 indicates GICINT129 and so on.
58*d831c5fdSJamin Lin */
aspeed_intc_set_irq(void * opaque,int irq,int level)59*d831c5fdSJamin Lin static void aspeed_intc_set_irq(void *opaque, int irq, int level)
60*d831c5fdSJamin Lin {
61*d831c5fdSJamin Lin AspeedINTCState *s = (AspeedINTCState *)opaque;
62*d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
63*d831c5fdSJamin Lin uint32_t status_addr = GICINT_STATUS_BASE + ((0x100 * irq) >> 2);
64*d831c5fdSJamin Lin uint32_t select = 0;
65*d831c5fdSJamin Lin uint32_t enable;
66*d831c5fdSJamin Lin int i;
67*d831c5fdSJamin Lin
68*d831c5fdSJamin Lin if (irq >= aic->num_ints) {
69*d831c5fdSJamin Lin qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
70*d831c5fdSJamin Lin __func__, irq);
71*d831c5fdSJamin Lin return;
72*d831c5fdSJamin Lin }
73*d831c5fdSJamin Lin
74*d831c5fdSJamin Lin trace_aspeed_intc_set_irq(irq, level);
75*d831c5fdSJamin Lin enable = s->enable[irq];
76*d831c5fdSJamin Lin
77*d831c5fdSJamin Lin if (!level) {
78*d831c5fdSJamin Lin return;
79*d831c5fdSJamin Lin }
80*d831c5fdSJamin Lin
81*d831c5fdSJamin Lin for (i = 0; i < aic->num_lines; i++) {
82*d831c5fdSJamin Lin if (s->orgates[irq].levels[i]) {
83*d831c5fdSJamin Lin if (enable & BIT(i)) {
84*d831c5fdSJamin Lin select |= BIT(i);
85*d831c5fdSJamin Lin }
86*d831c5fdSJamin Lin }
87*d831c5fdSJamin Lin }
88*d831c5fdSJamin Lin
89*d831c5fdSJamin Lin if (!select) {
90*d831c5fdSJamin Lin return;
91*d831c5fdSJamin Lin }
92*d831c5fdSJamin Lin
93*d831c5fdSJamin Lin trace_aspeed_intc_select(select);
94*d831c5fdSJamin Lin
95*d831c5fdSJamin Lin if (s->mask[irq] || s->regs[status_addr]) {
96*d831c5fdSJamin Lin /*
97*d831c5fdSJamin Lin * a. mask is not 0 means in ISR mode
98*d831c5fdSJamin Lin * sources interrupt routine are executing.
99*d831c5fdSJamin Lin * b. status register value is not 0 means previous
100*d831c5fdSJamin Lin * source interrupt does not be executed, yet.
101*d831c5fdSJamin Lin *
102*d831c5fdSJamin Lin * save source interrupt to pending variable.
103*d831c5fdSJamin Lin */
104*d831c5fdSJamin Lin s->pending[irq] |= select;
105*d831c5fdSJamin Lin trace_aspeed_intc_pending_irq(irq, s->pending[irq]);
106*d831c5fdSJamin Lin } else {
107*d831c5fdSJamin Lin /*
108*d831c5fdSJamin Lin * notify firmware which source interrupt are coming
109*d831c5fdSJamin Lin * by setting status register
110*d831c5fdSJamin Lin */
111*d831c5fdSJamin Lin s->regs[status_addr] = select;
112*d831c5fdSJamin Lin trace_aspeed_intc_trigger_irq(irq, s->regs[status_addr]);
113*d831c5fdSJamin Lin aspeed_intc_update(s, irq, 1);
114*d831c5fdSJamin Lin }
115*d831c5fdSJamin Lin }
116*d831c5fdSJamin Lin
aspeed_intc_read(void * opaque,hwaddr offset,unsigned int size)117*d831c5fdSJamin Lin static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size)
118*d831c5fdSJamin Lin {
119*d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(opaque);
120*d831c5fdSJamin Lin uint32_t addr = offset >> 2;
121*d831c5fdSJamin Lin uint32_t value = 0;
122*d831c5fdSJamin Lin
123*d831c5fdSJamin Lin if (addr >= ASPEED_INTC_NR_REGS) {
124*d831c5fdSJamin Lin qemu_log_mask(LOG_GUEST_ERROR,
125*d831c5fdSJamin Lin "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
126*d831c5fdSJamin Lin __func__, offset);
127*d831c5fdSJamin Lin return 0;
128*d831c5fdSJamin Lin }
129*d831c5fdSJamin Lin
130*d831c5fdSJamin Lin value = s->regs[addr];
131*d831c5fdSJamin Lin trace_aspeed_intc_read(offset, size, value);
132*d831c5fdSJamin Lin
133*d831c5fdSJamin Lin return value;
134*d831c5fdSJamin Lin }
135*d831c5fdSJamin Lin
aspeed_intc_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)136*d831c5fdSJamin Lin static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
137*d831c5fdSJamin Lin unsigned size)
138*d831c5fdSJamin Lin {
139*d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(opaque);
140*d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
141*d831c5fdSJamin Lin uint32_t addr = offset >> 2;
142*d831c5fdSJamin Lin uint32_t old_enable;
143*d831c5fdSJamin Lin uint32_t change;
144*d831c5fdSJamin Lin uint32_t irq;
145*d831c5fdSJamin Lin
146*d831c5fdSJamin Lin if (addr >= ASPEED_INTC_NR_REGS) {
147*d831c5fdSJamin Lin qemu_log_mask(LOG_GUEST_ERROR,
148*d831c5fdSJamin Lin "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
149*d831c5fdSJamin Lin __func__, offset);
150*d831c5fdSJamin Lin return;
151*d831c5fdSJamin Lin }
152*d831c5fdSJamin Lin
153*d831c5fdSJamin Lin trace_aspeed_intc_write(offset, size, data);
154*d831c5fdSJamin Lin
155*d831c5fdSJamin Lin switch (addr) {
156*d831c5fdSJamin Lin case R_GICINT128_EN:
157*d831c5fdSJamin Lin case R_GICINT129_EN:
158*d831c5fdSJamin Lin case R_GICINT130_EN:
159*d831c5fdSJamin Lin case R_GICINT131_EN:
160*d831c5fdSJamin Lin case R_GICINT132_EN:
161*d831c5fdSJamin Lin case R_GICINT133_EN:
162*d831c5fdSJamin Lin case R_GICINT134_EN:
163*d831c5fdSJamin Lin case R_GICINT135_EN:
164*d831c5fdSJamin Lin case R_GICINT136_EN:
165*d831c5fdSJamin Lin irq = (offset & 0x0f00) >> 8;
166*d831c5fdSJamin Lin
167*d831c5fdSJamin Lin if (irq >= aic->num_ints) {
168*d831c5fdSJamin Lin qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
169*d831c5fdSJamin Lin __func__, irq);
170*d831c5fdSJamin Lin return;
171*d831c5fdSJamin Lin }
172*d831c5fdSJamin Lin
173*d831c5fdSJamin Lin /*
174*d831c5fdSJamin Lin * These registers are used for enable sources interrupt and
175*d831c5fdSJamin Lin * mask and unmask source interrupt while executing source ISR.
176*d831c5fdSJamin Lin */
177*d831c5fdSJamin Lin
178*d831c5fdSJamin Lin /* disable all source interrupt */
179*d831c5fdSJamin Lin if (!data && !s->enable[irq]) {
180*d831c5fdSJamin Lin s->regs[addr] = data;
181*d831c5fdSJamin Lin return;
182*d831c5fdSJamin Lin }
183*d831c5fdSJamin Lin
184*d831c5fdSJamin Lin old_enable = s->enable[irq];
185*d831c5fdSJamin Lin s->enable[irq] |= data;
186*d831c5fdSJamin Lin
187*d831c5fdSJamin Lin /* enable new source interrupt */
188*d831c5fdSJamin Lin if (old_enable != s->enable[irq]) {
189*d831c5fdSJamin Lin trace_aspeed_intc_enable(s->enable[irq]);
190*d831c5fdSJamin Lin s->regs[addr] = data;
191*d831c5fdSJamin Lin return;
192*d831c5fdSJamin Lin }
193*d831c5fdSJamin Lin
194*d831c5fdSJamin Lin /* mask and unmask source interrupt */
195*d831c5fdSJamin Lin change = s->regs[addr] ^ data;
196*d831c5fdSJamin Lin if (change & data) {
197*d831c5fdSJamin Lin s->mask[irq] &= ~change;
198*d831c5fdSJamin Lin trace_aspeed_intc_unmask(change, s->mask[irq]);
199*d831c5fdSJamin Lin } else {
200*d831c5fdSJamin Lin s->mask[irq] |= change;
201*d831c5fdSJamin Lin trace_aspeed_intc_mask(change, s->mask[irq]);
202*d831c5fdSJamin Lin }
203*d831c5fdSJamin Lin s->regs[addr] = data;
204*d831c5fdSJamin Lin break;
205*d831c5fdSJamin Lin case R_GICINT128_STATUS:
206*d831c5fdSJamin Lin case R_GICINT129_STATUS:
207*d831c5fdSJamin Lin case R_GICINT130_STATUS:
208*d831c5fdSJamin Lin case R_GICINT131_STATUS:
209*d831c5fdSJamin Lin case R_GICINT132_STATUS:
210*d831c5fdSJamin Lin case R_GICINT133_STATUS:
211*d831c5fdSJamin Lin case R_GICINT134_STATUS:
212*d831c5fdSJamin Lin case R_GICINT135_STATUS:
213*d831c5fdSJamin Lin case R_GICINT136_STATUS:
214*d831c5fdSJamin Lin irq = (offset & 0x0f00) >> 8;
215*d831c5fdSJamin Lin
216*d831c5fdSJamin Lin if (irq >= aic->num_ints) {
217*d831c5fdSJamin Lin qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
218*d831c5fdSJamin Lin __func__, irq);
219*d831c5fdSJamin Lin return;
220*d831c5fdSJamin Lin }
221*d831c5fdSJamin Lin
222*d831c5fdSJamin Lin /* clear status */
223*d831c5fdSJamin Lin s->regs[addr] &= ~data;
224*d831c5fdSJamin Lin
225*d831c5fdSJamin Lin /*
226*d831c5fdSJamin Lin * These status registers are used for notify sources ISR are executed.
227*d831c5fdSJamin Lin * If one source ISR is executed, it will clear one bit.
228*d831c5fdSJamin Lin * If it clear all bits, it means to initialize this register status
229*d831c5fdSJamin Lin * rather than sources ISR are executed.
230*d831c5fdSJamin Lin */
231*d831c5fdSJamin Lin if (data == 0xffffffff) {
232*d831c5fdSJamin Lin return;
233*d831c5fdSJamin Lin }
234*d831c5fdSJamin Lin
235*d831c5fdSJamin Lin /* All source ISR execution are done */
236*d831c5fdSJamin Lin if (!s->regs[addr]) {
237*d831c5fdSJamin Lin trace_aspeed_intc_all_isr_done(irq);
238*d831c5fdSJamin Lin if (s->pending[irq]) {
239*d831c5fdSJamin Lin /*
240*d831c5fdSJamin Lin * handle pending source interrupt
241*d831c5fdSJamin Lin * notify firmware which source interrupt are pending
242*d831c5fdSJamin Lin * by setting status register
243*d831c5fdSJamin Lin */
244*d831c5fdSJamin Lin s->regs[addr] = s->pending[irq];
245*d831c5fdSJamin Lin s->pending[irq] = 0;
246*d831c5fdSJamin Lin trace_aspeed_intc_trigger_irq(irq, s->regs[addr]);
247*d831c5fdSJamin Lin aspeed_intc_update(s, irq, 1);
248*d831c5fdSJamin Lin } else {
249*d831c5fdSJamin Lin /* clear irq */
250*d831c5fdSJamin Lin trace_aspeed_intc_clear_irq(irq, 0);
251*d831c5fdSJamin Lin aspeed_intc_update(s, irq, 0);
252*d831c5fdSJamin Lin }
253*d831c5fdSJamin Lin }
254*d831c5fdSJamin Lin break;
255*d831c5fdSJamin Lin default:
256*d831c5fdSJamin Lin s->regs[addr] = data;
257*d831c5fdSJamin Lin break;
258*d831c5fdSJamin Lin }
259*d831c5fdSJamin Lin
260*d831c5fdSJamin Lin return;
261*d831c5fdSJamin Lin }
262*d831c5fdSJamin Lin
263*d831c5fdSJamin Lin static const MemoryRegionOps aspeed_intc_ops = {
264*d831c5fdSJamin Lin .read = aspeed_intc_read,
265*d831c5fdSJamin Lin .write = aspeed_intc_write,
266*d831c5fdSJamin Lin .endianness = DEVICE_LITTLE_ENDIAN,
267*d831c5fdSJamin Lin .valid = {
268*d831c5fdSJamin Lin .min_access_size = 4,
269*d831c5fdSJamin Lin .max_access_size = 4,
270*d831c5fdSJamin Lin }
271*d831c5fdSJamin Lin };
272*d831c5fdSJamin Lin
aspeed_intc_instance_init(Object * obj)273*d831c5fdSJamin Lin static void aspeed_intc_instance_init(Object *obj)
274*d831c5fdSJamin Lin {
275*d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(obj);
276*d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
277*d831c5fdSJamin Lin int i;
278*d831c5fdSJamin Lin
279*d831c5fdSJamin Lin assert(aic->num_ints <= ASPEED_INTC_NR_INTS);
280*d831c5fdSJamin Lin for (i = 0; i < aic->num_ints; i++) {
281*d831c5fdSJamin Lin object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
282*d831c5fdSJamin Lin TYPE_OR_IRQ);
283*d831c5fdSJamin Lin object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
284*d831c5fdSJamin Lin aic->num_lines, &error_abort);
285*d831c5fdSJamin Lin }
286*d831c5fdSJamin Lin }
287*d831c5fdSJamin Lin
aspeed_intc_reset(DeviceState * dev)288*d831c5fdSJamin Lin static void aspeed_intc_reset(DeviceState *dev)
289*d831c5fdSJamin Lin {
290*d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(dev);
291*d831c5fdSJamin Lin
292*d831c5fdSJamin Lin memset(s->regs, 0, sizeof(s->regs));
293*d831c5fdSJamin Lin memset(s->enable, 0, sizeof(s->enable));
294*d831c5fdSJamin Lin memset(s->mask, 0, sizeof(s->mask));
295*d831c5fdSJamin Lin memset(s->pending, 0, sizeof(s->pending));
296*d831c5fdSJamin Lin }
297*d831c5fdSJamin Lin
aspeed_intc_realize(DeviceState * dev,Error ** errp)298*d831c5fdSJamin Lin static void aspeed_intc_realize(DeviceState *dev, Error **errp)
299*d831c5fdSJamin Lin {
300*d831c5fdSJamin Lin SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
301*d831c5fdSJamin Lin AspeedINTCState *s = ASPEED_INTC(dev);
302*d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
303*d831c5fdSJamin Lin int i;
304*d831c5fdSJamin Lin
305*d831c5fdSJamin Lin memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_intc_ops, s,
306*d831c5fdSJamin Lin TYPE_ASPEED_INTC ".regs", ASPEED_INTC_NR_REGS << 2);
307*d831c5fdSJamin Lin
308*d831c5fdSJamin Lin sysbus_init_mmio(sbd, &s->iomem);
309*d831c5fdSJamin Lin qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
310*d831c5fdSJamin Lin
311*d831c5fdSJamin Lin for (i = 0; i < aic->num_ints; i++) {
312*d831c5fdSJamin Lin if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
313*d831c5fdSJamin Lin return;
314*d831c5fdSJamin Lin }
315*d831c5fdSJamin Lin sysbus_init_irq(sbd, &s->output_pins[i]);
316*d831c5fdSJamin Lin }
317*d831c5fdSJamin Lin }
318*d831c5fdSJamin Lin
aspeed_intc_class_init(ObjectClass * klass,void * data)319*d831c5fdSJamin Lin static void aspeed_intc_class_init(ObjectClass *klass, void *data)
320*d831c5fdSJamin Lin {
321*d831c5fdSJamin Lin DeviceClass *dc = DEVICE_CLASS(klass);
322*d831c5fdSJamin Lin
323*d831c5fdSJamin Lin dc->desc = "ASPEED INTC Controller";
324*d831c5fdSJamin Lin dc->realize = aspeed_intc_realize;
325*d831c5fdSJamin Lin dc->reset = aspeed_intc_reset;
326*d831c5fdSJamin Lin dc->vmsd = NULL;
327*d831c5fdSJamin Lin }
328*d831c5fdSJamin Lin
329*d831c5fdSJamin Lin static const TypeInfo aspeed_intc_info = {
330*d831c5fdSJamin Lin .name = TYPE_ASPEED_INTC,
331*d831c5fdSJamin Lin .parent = TYPE_SYS_BUS_DEVICE,
332*d831c5fdSJamin Lin .instance_init = aspeed_intc_instance_init,
333*d831c5fdSJamin Lin .instance_size = sizeof(AspeedINTCState),
334*d831c5fdSJamin Lin .class_init = aspeed_intc_class_init,
335*d831c5fdSJamin Lin .class_size = sizeof(AspeedINTCClass),
336*d831c5fdSJamin Lin .abstract = true,
337*d831c5fdSJamin Lin };
338*d831c5fdSJamin Lin
aspeed_2700_intc_class_init(ObjectClass * klass,void * data)339*d831c5fdSJamin Lin static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data)
340*d831c5fdSJamin Lin {
341*d831c5fdSJamin Lin DeviceClass *dc = DEVICE_CLASS(klass);
342*d831c5fdSJamin Lin AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
343*d831c5fdSJamin Lin
344*d831c5fdSJamin Lin dc->desc = "ASPEED 2700 INTC Controller";
345*d831c5fdSJamin Lin aic->num_lines = 32;
346*d831c5fdSJamin Lin aic->num_ints = 9;
347*d831c5fdSJamin Lin }
348*d831c5fdSJamin Lin
349*d831c5fdSJamin Lin static const TypeInfo aspeed_2700_intc_info = {
350*d831c5fdSJamin Lin .name = TYPE_ASPEED_2700_INTC,
351*d831c5fdSJamin Lin .parent = TYPE_ASPEED_INTC,
352*d831c5fdSJamin Lin .class_init = aspeed_2700_intc_class_init,
353*d831c5fdSJamin Lin };
354*d831c5fdSJamin Lin
aspeed_intc_register_types(void)355*d831c5fdSJamin Lin static void aspeed_intc_register_types(void)
356*d831c5fdSJamin Lin {
357*d831c5fdSJamin Lin type_register_static(&aspeed_intc_info);
358*d831c5fdSJamin Lin type_register_static(&aspeed_2700_intc_info);
359*d831c5fdSJamin Lin }
360*d831c5fdSJamin Lin
361*d831c5fdSJamin Lin type_init(aspeed_intc_register_types);
362