1 | /* |
2 | * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c |
3 | * |
4 | * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. |
5 | * All rights reserved. |
6 | * |
7 | * Evgeny Voevodin <e.voevodin@samsung.com> |
8 | * |
9 | * This program is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU General Public License as published by the |
11 | * Free Software Foundation; either version 2 of the License, or (at your |
12 | * option) any later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | * See the GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License along |
20 | * with this program; if not, see <http://www.gnu.org/licenses/>. |
21 | */ |
22 | |
23 | #include "qemu/osdep.h" |
24 | #include "hw/sysbus.h" |
25 | #include "migration/vmstate.h" |
26 | #include "qemu/module.h" |
27 | #include "hw/irq.h" |
28 | #include "hw/qdev-properties.h" |
29 | #include "hw/arm/exynos4210.h" |
30 | |
31 | enum ExtGicId { |
32 | EXT_GIC_ID_MDMA_LCD0 = 66, |
33 | EXT_GIC_ID_PDMA0, |
34 | EXT_GIC_ID_PDMA1, |
35 | EXT_GIC_ID_TIMER0, |
36 | EXT_GIC_ID_TIMER1, |
37 | EXT_GIC_ID_TIMER2, |
38 | EXT_GIC_ID_TIMER3, |
39 | EXT_GIC_ID_TIMER4, |
40 | EXT_GIC_ID_MCT_L0, |
41 | EXT_GIC_ID_WDT, |
42 | EXT_GIC_ID_RTC_ALARM, |
43 | EXT_GIC_ID_RTC_TIC, |
44 | EXT_GIC_ID_GPIO_XB, |
45 | EXT_GIC_ID_GPIO_XA, |
46 | EXT_GIC_ID_MCT_L1, |
47 | EXT_GIC_ID_IEM_APC, |
48 | EXT_GIC_ID_IEM_IEC, |
49 | EXT_GIC_ID_NFC, |
50 | EXT_GIC_ID_UART0, |
51 | EXT_GIC_ID_UART1, |
52 | EXT_GIC_ID_UART2, |
53 | EXT_GIC_ID_UART3, |
54 | EXT_GIC_ID_UART4, |
55 | EXT_GIC_ID_MCT_G0, |
56 | EXT_GIC_ID_I2C0, |
57 | EXT_GIC_ID_I2C1, |
58 | EXT_GIC_ID_I2C2, |
59 | EXT_GIC_ID_I2C3, |
60 | EXT_GIC_ID_I2C4, |
61 | EXT_GIC_ID_I2C5, |
62 | EXT_GIC_ID_I2C6, |
63 | EXT_GIC_ID_I2C7, |
64 | EXT_GIC_ID_SPI0, |
65 | EXT_GIC_ID_SPI1, |
66 | EXT_GIC_ID_SPI2, |
67 | EXT_GIC_ID_MCT_G1, |
68 | EXT_GIC_ID_USB_HOST, |
69 | EXT_GIC_ID_USB_DEVICE, |
70 | EXT_GIC_ID_MODEMIF, |
71 | EXT_GIC_ID_HSMMC0, |
72 | EXT_GIC_ID_HSMMC1, |
73 | EXT_GIC_ID_HSMMC2, |
74 | EXT_GIC_ID_HSMMC3, |
75 | EXT_GIC_ID_SDMMC, |
76 | EXT_GIC_ID_MIPI_CSI_4LANE, |
77 | EXT_GIC_ID_MIPI_DSI_4LANE, |
78 | EXT_GIC_ID_MIPI_CSI_2LANE, |
79 | EXT_GIC_ID_MIPI_DSI_2LANE, |
80 | EXT_GIC_ID_ONENAND_AUDI, |
81 | EXT_GIC_ID_ROTATOR, |
82 | EXT_GIC_ID_FIMC0, |
83 | EXT_GIC_ID_FIMC1, |
84 | EXT_GIC_ID_FIMC2, |
85 | EXT_GIC_ID_FIMC3, |
86 | EXT_GIC_ID_JPEG, |
87 | EXT_GIC_ID_2D, |
88 | EXT_GIC_ID_PCIe, |
89 | EXT_GIC_ID_MIXER, |
90 | EXT_GIC_ID_HDMI, |
91 | EXT_GIC_ID_HDMI_I2C, |
92 | EXT_GIC_ID_MFC, |
93 | EXT_GIC_ID_TVENC, |
94 | }; |
95 | |
96 | enum ExtInt { |
97 | EXT_GIC_ID_EXTINT0 = 48, |
98 | EXT_GIC_ID_EXTINT1, |
99 | EXT_GIC_ID_EXTINT2, |
100 | EXT_GIC_ID_EXTINT3, |
101 | EXT_GIC_ID_EXTINT4, |
102 | EXT_GIC_ID_EXTINT5, |
103 | EXT_GIC_ID_EXTINT6, |
104 | EXT_GIC_ID_EXTINT7, |
105 | EXT_GIC_ID_EXTINT8, |
106 | EXT_GIC_ID_EXTINT9, |
107 | EXT_GIC_ID_EXTINT10, |
108 | EXT_GIC_ID_EXTINT11, |
109 | EXT_GIC_ID_EXTINT12, |
110 | EXT_GIC_ID_EXTINT13, |
111 | EXT_GIC_ID_EXTINT14, |
112 | EXT_GIC_ID_EXTINT15 |
113 | }; |
114 | |
115 | /* |
116 | * External GIC sources which are not from External Interrupt Combiner or |
117 | * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ, |
118 | * which is INTG16 in Internal Interrupt Combiner. |
119 | */ |
120 | |
121 | static const uint32_t |
122 | combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = { |
123 | /* int combiner groups 16-19 */ |
124 | { }, { }, { }, { }, |
125 | /* int combiner group 20 */ |
126 | { 0, EXT_GIC_ID_MDMA_LCD0 }, |
127 | /* int combiner group 21 */ |
128 | { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 }, |
129 | /* int combiner group 22 */ |
130 | { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2, |
131 | EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 }, |
132 | /* int combiner group 23 */ |
133 | { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC }, |
134 | /* int combiner group 24 */ |
135 | { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA }, |
136 | /* int combiner group 25 */ |
137 | { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC }, |
138 | /* int combiner group 26 */ |
139 | { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3, |
140 | EXT_GIC_ID_UART4 }, |
141 | /* int combiner group 27 */ |
142 | { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3, |
143 | EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6, |
144 | EXT_GIC_ID_I2C7 }, |
145 | /* int combiner group 28 */ |
146 | { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST}, |
147 | /* int combiner group 29 */ |
148 | { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2, |
149 | EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC }, |
150 | /* int combiner group 30 */ |
151 | { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE }, |
152 | /* int combiner group 31 */ |
153 | { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE }, |
154 | /* int combiner group 32 */ |
155 | { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 }, |
156 | /* int combiner group 33 */ |
157 | { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 }, |
158 | /* int combiner group 34 */ |
159 | { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC }, |
160 | /* int combiner group 35 */ |
161 | { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 }, |
162 | /* int combiner group 36 */ |
163 | { EXT_GIC_ID_MIXER }, |
164 | /* int combiner group 37 */ |
165 | { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6, |
166 | EXT_GIC_ID_EXTINT7 }, |
167 | /* groups 38-50 */ |
168 | { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, |
169 | /* int combiner group 51 */ |
170 | { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 }, |
171 | /* group 52 */ |
172 | { }, |
173 | /* int combiner group 53 */ |
174 | { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 }, |
175 | /* groups 54-63 */ |
176 | { }, { }, { }, { }, { }, { }, { }, { }, { }, { } |
177 | }; |
178 | |
179 | #define EXYNOS4210_GIC_NIRQ 160 |
180 | |
181 | #define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000 |
182 | #define EXYNOS4210_EXT_GIC_DIST_REGION_SIZE 0x10000 |
183 | |
184 | #define EXYNOS4210_EXT_GIC_PER_CPU_OFFSET 0x8000 |
185 | #define EXYNOS4210_EXT_GIC_CPU_GET_OFFSET(n) \ |
186 | ((n) * EXYNOS4210_EXT_GIC_PER_CPU_OFFSET) |
187 | #define EXYNOS4210_EXT_GIC_DIST_GET_OFFSET(n) \ |
188 | ((n) * EXYNOS4210_EXT_GIC_PER_CPU_OFFSET) |
189 | |
190 | #define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100 |
191 | #define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000 |
192 | |
193 | static void exynos4210_irq_handler(void *opaque, int irq, int level) |
194 | { |
195 | Exynos4210Irq *s = (Exynos4210Irq *)opaque; |
196 | |
197 | /* Bypass */ |
198 | qemu_set_irq(s->board_irqs[irq], level); |
199 | } |
200 | |
201 | /* |
202 | * Initialize exynos4210 IRQ subsystem stub. |
203 | */ |
204 | qemu_irq *exynos4210_init_irq(Exynos4210Irq *s) |
205 | { |
206 | return qemu_allocate_irqs(exynos4210_irq_handler, s, |
207 | EXYNOS4210_MAX_INT_COMBINER_IN_IRQ); |
208 | } |
209 | |
210 | /* |
211 | * Initialize board IRQs. |
212 | * These IRQs contain splitted Int/External Combiner and External Gic IRQs. |
213 | */ |
214 | void exynos4210_init_board_irqs(Exynos4210Irq *s) |
215 | { |
216 | uint32_t grp, bit, irq_id, n; |
217 | |
218 | for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) { |
219 | irq_id = 0; |
220 | if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) || |
221 | n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) { |
222 | /* MCT_G0 is passed to External GIC */ |
223 | irq_id = EXT_GIC_ID_MCT_G0; |
224 | } |
225 | if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) || |
226 | n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) { |
227 | /* MCT_G1 is passed to External and GIC */ |
228 | irq_id = EXT_GIC_ID_MCT_G1; |
229 | } |
230 | if (irq_id) { |
231 | s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n], |
232 | s->ext_gic_irq[irq_id-32]); |
233 | } else { |
234 | s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n], |
235 | s->ext_combiner_irq[n]); |
236 | } |
237 | } |
238 | for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) { |
239 | /* these IDs are passed to Internal Combiner and External GIC */ |
240 | grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n); |
241 | bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n); |
242 | irq_id = combiner_grp_to_gic_id[grp - |
243 | EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit]; |
244 | |
245 | if (irq_id) { |
246 | s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n], |
247 | s->ext_gic_irq[irq_id-32]); |
248 | } |
249 | } |
250 | } |
251 | |
252 | /* |
253 | * Get IRQ number from exynos4210 IRQ subsystem stub. |
254 | * To identify IRQ source use internal combiner group and bit number |
255 | * grp - group number |
256 | * bit - bit number inside group |
257 | */ |
258 | uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit) |
259 | { |
260 | return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit); |
261 | } |
262 | |
263 | /********* GIC part *********/ |
264 | |
265 | #define TYPE_EXYNOS4210_GIC "exynos4210.gic" |
266 | #define EXYNOS4210_GIC(obj) \ |
267 | OBJECT_CHECK(Exynos4210GicState, (obj), TYPE_EXYNOS4210_GIC) |
268 | |
269 | typedef struct { |
270 | SysBusDevice parent_obj; |
271 | |
272 | MemoryRegion cpu_container; |
273 | MemoryRegion dist_container; |
274 | MemoryRegion cpu_alias[EXYNOS4210_NCPUS]; |
275 | MemoryRegion dist_alias[EXYNOS4210_NCPUS]; |
276 | uint32_t num_cpu; |
277 | DeviceState *gic; |
278 | } Exynos4210GicState; |
279 | |
280 | static void exynos4210_gic_set_irq(void *opaque, int irq, int level) |
281 | { |
282 | Exynos4210GicState *s = (Exynos4210GicState *)opaque; |
283 | qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); |
284 | } |
285 | |
286 | static void exynos4210_gic_realize(DeviceState *dev, Error **errp) |
287 | { |
288 | Object *obj = OBJECT(dev); |
289 | Exynos4210GicState *s = EXYNOS4210_GIC(obj); |
290 | SysBusDevice *sbd = SYS_BUS_DEVICE(obj); |
291 | const char cpu_prefix[] = "exynos4210-gic-alias_cpu" ; |
292 | const char dist_prefix[] = "exynos4210-gic-alias_dist" ; |
293 | char cpu_alias_name[sizeof(cpu_prefix) + 3]; |
294 | char dist_alias_name[sizeof(cpu_prefix) + 3]; |
295 | SysBusDevice *gicbusdev; |
296 | uint32_t i; |
297 | |
298 | s->gic = qdev_create(NULL, "arm_gic" ); |
299 | qdev_prop_set_uint32(s->gic, "num-cpu" , s->num_cpu); |
300 | qdev_prop_set_uint32(s->gic, "num-irq" , EXYNOS4210_GIC_NIRQ); |
301 | qdev_init_nofail(s->gic); |
302 | gicbusdev = SYS_BUS_DEVICE(s->gic); |
303 | |
304 | /* Pass through outbound IRQ lines from the GIC */ |
305 | sysbus_pass_irq(sbd, gicbusdev); |
306 | |
307 | /* Pass through inbound GPIO lines to the GIC */ |
308 | qdev_init_gpio_in(dev, exynos4210_gic_set_irq, |
309 | EXYNOS4210_GIC_NIRQ - 32); |
310 | |
311 | memory_region_init(&s->cpu_container, obj, "exynos4210-cpu-container" , |
312 | EXYNOS4210_EXT_GIC_CPU_REGION_SIZE); |
313 | memory_region_init(&s->dist_container, obj, "exynos4210-dist-container" , |
314 | EXYNOS4210_EXT_GIC_DIST_REGION_SIZE); |
315 | |
316 | for (i = 0; i < s->num_cpu; i++) { |
317 | /* Map CPU interface per SMP Core */ |
318 | sprintf(cpu_alias_name, "%s%x" , cpu_prefix, i); |
319 | memory_region_init_alias(&s->cpu_alias[i], obj, |
320 | cpu_alias_name, |
321 | sysbus_mmio_get_region(gicbusdev, 1), |
322 | 0, |
323 | EXYNOS4210_GIC_CPU_REGION_SIZE); |
324 | memory_region_add_subregion(&s->cpu_container, |
325 | EXYNOS4210_EXT_GIC_CPU_GET_OFFSET(i), &s->cpu_alias[i]); |
326 | |
327 | /* Map Distributor per SMP Core */ |
328 | sprintf(dist_alias_name, "%s%x" , dist_prefix, i); |
329 | memory_region_init_alias(&s->dist_alias[i], obj, |
330 | dist_alias_name, |
331 | sysbus_mmio_get_region(gicbusdev, 0), |
332 | 0, |
333 | EXYNOS4210_GIC_DIST_REGION_SIZE); |
334 | memory_region_add_subregion(&s->dist_container, |
335 | EXYNOS4210_EXT_GIC_DIST_GET_OFFSET(i), &s->dist_alias[i]); |
336 | } |
337 | |
338 | sysbus_init_mmio(sbd, &s->cpu_container); |
339 | sysbus_init_mmio(sbd, &s->dist_container); |
340 | } |
341 | |
342 | static Property exynos4210_gic_properties[] = { |
343 | DEFINE_PROP_UINT32("num-cpu" , Exynos4210GicState, num_cpu, 1), |
344 | DEFINE_PROP_END_OF_LIST(), |
345 | }; |
346 | |
347 | static void exynos4210_gic_class_init(ObjectClass *klass, void *data) |
348 | { |
349 | DeviceClass *dc = DEVICE_CLASS(klass); |
350 | |
351 | dc->props = exynos4210_gic_properties; |
352 | dc->realize = exynos4210_gic_realize; |
353 | } |
354 | |
355 | static const TypeInfo exynos4210_gic_info = { |
356 | .name = TYPE_EXYNOS4210_GIC, |
357 | .parent = TYPE_SYS_BUS_DEVICE, |
358 | .instance_size = sizeof(Exynos4210GicState), |
359 | .class_init = exynos4210_gic_class_init, |
360 | }; |
361 | |
362 | static void exynos4210_gic_register_types(void) |
363 | { |
364 | type_register_static(&exynos4210_gic_info); |
365 | } |
366 | |
367 | type_init(exynos4210_gic_register_types) |
368 | |
369 | /* IRQ OR Gate struct. |
370 | * |
371 | * This device models an OR gate. There are n_in input qdev gpio lines and one |
372 | * output sysbus IRQ line. The output IRQ level is formed as OR between all |
373 | * gpio inputs. |
374 | */ |
375 | |
376 | #define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate" |
377 | #define EXYNOS4210_IRQ_GATE(obj) \ |
378 | OBJECT_CHECK(Exynos4210IRQGateState, (obj), TYPE_EXYNOS4210_IRQ_GATE) |
379 | |
380 | typedef struct Exynos4210IRQGateState { |
381 | SysBusDevice parent_obj; |
382 | |
383 | uint32_t n_in; /* inputs amount */ |
384 | uint32_t *level; /* input levels */ |
385 | qemu_irq out; /* output IRQ */ |
386 | } Exynos4210IRQGateState; |
387 | |
388 | static Property exynos4210_irq_gate_properties[] = { |
389 | DEFINE_PROP_UINT32("n_in" , Exynos4210IRQGateState, n_in, 1), |
390 | DEFINE_PROP_END_OF_LIST(), |
391 | }; |
392 | |
393 | static const VMStateDescription vmstate_exynos4210_irq_gate = { |
394 | .name = "exynos4210.irq_gate" , |
395 | .version_id = 2, |
396 | .minimum_version_id = 2, |
397 | .fields = (VMStateField[]) { |
398 | VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in), |
399 | VMSTATE_END_OF_LIST() |
400 | } |
401 | }; |
402 | |
403 | /* Process a change in IRQ input. */ |
404 | static void exynos4210_irq_gate_handler(void *opaque, int irq, int level) |
405 | { |
406 | Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque; |
407 | uint32_t i; |
408 | |
409 | assert(irq < s->n_in); |
410 | |
411 | s->level[irq] = level; |
412 | |
413 | for (i = 0; i < s->n_in; i++) { |
414 | if (s->level[i] >= 1) { |
415 | qemu_irq_raise(s->out); |
416 | return; |
417 | } |
418 | } |
419 | |
420 | qemu_irq_lower(s->out); |
421 | } |
422 | |
423 | static void exynos4210_irq_gate_reset(DeviceState *d) |
424 | { |
425 | Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d); |
426 | |
427 | memset(s->level, 0, s->n_in * sizeof(*s->level)); |
428 | } |
429 | |
430 | /* |
431 | * IRQ Gate initialization. |
432 | */ |
433 | static void exynos4210_irq_gate_init(Object *obj) |
434 | { |
435 | Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj); |
436 | SysBusDevice *sbd = SYS_BUS_DEVICE(obj); |
437 | |
438 | sysbus_init_irq(sbd, &s->out); |
439 | } |
440 | |
441 | static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp) |
442 | { |
443 | Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev); |
444 | |
445 | /* Allocate general purpose input signals and connect a handler to each of |
446 | * them */ |
447 | qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in); |
448 | |
449 | s->level = g_malloc0(s->n_in * sizeof(*s->level)); |
450 | } |
451 | |
452 | static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data) |
453 | { |
454 | DeviceClass *dc = DEVICE_CLASS(klass); |
455 | |
456 | dc->reset = exynos4210_irq_gate_reset; |
457 | dc->vmsd = &vmstate_exynos4210_irq_gate; |
458 | dc->props = exynos4210_irq_gate_properties; |
459 | dc->realize = exynos4210_irq_gate_realize; |
460 | } |
461 | |
462 | static const TypeInfo exynos4210_irq_gate_info = { |
463 | .name = TYPE_EXYNOS4210_IRQ_GATE, |
464 | .parent = TYPE_SYS_BUS_DEVICE, |
465 | .instance_size = sizeof(Exynos4210IRQGateState), |
466 | .instance_init = exynos4210_irq_gate_init, |
467 | .class_init = exynos4210_irq_gate_class_init, |
468 | }; |
469 | |
470 | static void exynos4210_irq_gate_register_types(void) |
471 | { |
472 | type_register_static(&exynos4210_irq_gate_info); |
473 | } |
474 | |
475 | type_init(exynos4210_irq_gate_register_types) |
476 | |