17702e47cSPaolo Bonzini /* 27702e47cSPaolo Bonzini * Samsung exynos4210 Interrupt Combiner 37702e47cSPaolo Bonzini * 47702e47cSPaolo Bonzini * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. 57702e47cSPaolo Bonzini * All rights reserved. 67702e47cSPaolo Bonzini * 77702e47cSPaolo Bonzini * Evgeny Voevodin <e.voevodin@samsung.com> 87702e47cSPaolo Bonzini * 97702e47cSPaolo Bonzini * This program is free software; you can redistribute it and/or modify it 107702e47cSPaolo Bonzini * under the terms of the GNU General Public License as published by the 117702e47cSPaolo Bonzini * Free Software Foundation; either version 2 of the License, or (at your 127702e47cSPaolo Bonzini * option) any later version. 137702e47cSPaolo Bonzini * 147702e47cSPaolo Bonzini * This program is distributed in the hope that it will be useful, 157702e47cSPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of 167702e47cSPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 177702e47cSPaolo Bonzini * See the GNU General Public License for more details. 187702e47cSPaolo Bonzini * 197702e47cSPaolo Bonzini * You should have received a copy of the GNU General Public License along 207702e47cSPaolo Bonzini * with this program; if not, see <http://www.gnu.org/licenses/>. 217702e47cSPaolo Bonzini */ 227702e47cSPaolo Bonzini 237702e47cSPaolo Bonzini /* 247702e47cSPaolo Bonzini * Exynos4210 Combiner represents an OR gate for SOC's IRQ lines. It combines 257702e47cSPaolo Bonzini * IRQ sources into groups and provides signal output to GIC from each group. It 267702e47cSPaolo Bonzini * is driven by common mask and enable/disable logic. Take a note that not all 277702e47cSPaolo Bonzini * IRQs are passed to GIC through Combiner. 287702e47cSPaolo Bonzini */ 297702e47cSPaolo Bonzini 308ef94f0bSPeter Maydell #include "qemu/osdep.h" 317702e47cSPaolo Bonzini #include "hw/sysbus.h" 32d6454270SMarkus Armbruster #include "migration/vmstate.h" 330b8fa32fSMarkus Armbruster #include "qemu/module.h" 34*cebef07dSPeter Maydell #include "hw/intc/exynos4210_combiner.h" 357702e47cSPaolo Bonzini #include "hw/arm/exynos4210.h" 36650d103dSMarkus Armbruster #include "hw/hw.h" 3764552b6bSMarkus Armbruster #include "hw/irq.h" 38a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 39db1015e9SEduardo Habkost #include "qom/object.h" 407702e47cSPaolo Bonzini 417702e47cSPaolo Bonzini //#define DEBUG_COMBINER 427702e47cSPaolo Bonzini 437702e47cSPaolo Bonzini #ifdef DEBUG_COMBINER 447702e47cSPaolo Bonzini #define DPRINTF(fmt, ...) \ 457702e47cSPaolo Bonzini do { fprintf(stdout, "COMBINER: [%s:%d] " fmt, __func__ , __LINE__, \ 467702e47cSPaolo Bonzini ## __VA_ARGS__); } while (0) 477702e47cSPaolo Bonzini #else 487702e47cSPaolo Bonzini #define DPRINTF(fmt, ...) do {} while (0) 497702e47cSPaolo Bonzini #endif 507702e47cSPaolo Bonzini 517702e47cSPaolo Bonzini #define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */ 527702e47cSPaolo Bonzini 537702e47cSPaolo Bonzini static const VMStateDescription vmstate_exynos4210_combiner_group_state = { 547702e47cSPaolo Bonzini .name = "exynos4210.combiner.groupstate", 557702e47cSPaolo Bonzini .version_id = 1, 567702e47cSPaolo Bonzini .minimum_version_id = 1, 577702e47cSPaolo Bonzini .fields = (VMStateField[]) { 587702e47cSPaolo Bonzini VMSTATE_UINT8(src_mask, CombinerGroupState), 597702e47cSPaolo Bonzini VMSTATE_UINT8(src_pending, CombinerGroupState), 607702e47cSPaolo Bonzini VMSTATE_END_OF_LIST() 617702e47cSPaolo Bonzini } 627702e47cSPaolo Bonzini }; 637702e47cSPaolo Bonzini 647702e47cSPaolo Bonzini static const VMStateDescription vmstate_exynos4210_combiner = { 657702e47cSPaolo Bonzini .name = "exynos4210.combiner", 667702e47cSPaolo Bonzini .version_id = 1, 677702e47cSPaolo Bonzini .minimum_version_id = 1, 687702e47cSPaolo Bonzini .fields = (VMStateField[]) { 697702e47cSPaolo Bonzini VMSTATE_STRUCT_ARRAY(group, Exynos4210CombinerState, IIC_NGRP, 0, 707702e47cSPaolo Bonzini vmstate_exynos4210_combiner_group_state, CombinerGroupState), 717702e47cSPaolo Bonzini VMSTATE_UINT32_ARRAY(reg_set, Exynos4210CombinerState, 727702e47cSPaolo Bonzini IIC_REGSET_SIZE), 737702e47cSPaolo Bonzini VMSTATE_UINT32_ARRAY(icipsr, Exynos4210CombinerState, 2), 747702e47cSPaolo Bonzini VMSTATE_UINT32(external, Exynos4210CombinerState), 757702e47cSPaolo Bonzini VMSTATE_END_OF_LIST() 767702e47cSPaolo Bonzini } 777702e47cSPaolo Bonzini }; 787702e47cSPaolo Bonzini 797702e47cSPaolo Bonzini static uint64_t 807702e47cSPaolo Bonzini exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size) 817702e47cSPaolo Bonzini { 827702e47cSPaolo Bonzini struct Exynos4210CombinerState *s = 837702e47cSPaolo Bonzini (struct Exynos4210CombinerState *)opaque; 847702e47cSPaolo Bonzini uint32_t req_quad_base_n; /* Base of registers quad. Multiply it by 4 and 857702e47cSPaolo Bonzini get a start of corresponding group quad */ 867702e47cSPaolo Bonzini uint32_t grp_quad_base_n; /* Base of group quad */ 877702e47cSPaolo Bonzini uint32_t reg_n; /* Register number inside the quad */ 887702e47cSPaolo Bonzini uint32_t val; 897702e47cSPaolo Bonzini 907702e47cSPaolo Bonzini req_quad_base_n = offset >> 4; 917702e47cSPaolo Bonzini grp_quad_base_n = req_quad_base_n << 2; 927702e47cSPaolo Bonzini reg_n = (offset - (req_quad_base_n << 4)) >> 2; 937702e47cSPaolo Bonzini 947702e47cSPaolo Bonzini if (req_quad_base_n >= IIC_NGRP) { 957702e47cSPaolo Bonzini /* Read of ICIPSR register */ 967702e47cSPaolo Bonzini return s->icipsr[reg_n]; 977702e47cSPaolo Bonzini } 987702e47cSPaolo Bonzini 997702e47cSPaolo Bonzini val = 0; 1007702e47cSPaolo Bonzini 1017702e47cSPaolo Bonzini switch (reg_n) { 1027702e47cSPaolo Bonzini /* IISTR */ 1037702e47cSPaolo Bonzini case 2: 1047702e47cSPaolo Bonzini val |= s->group[grp_quad_base_n].src_pending; 1057702e47cSPaolo Bonzini val |= s->group[grp_quad_base_n + 1].src_pending << 8; 1067702e47cSPaolo Bonzini val |= s->group[grp_quad_base_n + 2].src_pending << 16; 1077702e47cSPaolo Bonzini val |= s->group[grp_quad_base_n + 3].src_pending << 24; 1087702e47cSPaolo Bonzini break; 1097702e47cSPaolo Bonzini /* IIMSR */ 1107702e47cSPaolo Bonzini case 3: 1117702e47cSPaolo Bonzini val |= s->group[grp_quad_base_n].src_mask & 1127702e47cSPaolo Bonzini s->group[grp_quad_base_n].src_pending; 1137702e47cSPaolo Bonzini val |= (s->group[grp_quad_base_n + 1].src_mask & 1147702e47cSPaolo Bonzini s->group[grp_quad_base_n + 1].src_pending) << 8; 1157702e47cSPaolo Bonzini val |= (s->group[grp_quad_base_n + 2].src_mask & 1167702e47cSPaolo Bonzini s->group[grp_quad_base_n + 2].src_pending) << 16; 1177702e47cSPaolo Bonzini val |= (s->group[grp_quad_base_n + 3].src_mask & 1187702e47cSPaolo Bonzini s->group[grp_quad_base_n + 3].src_pending) << 24; 1197702e47cSPaolo Bonzini break; 1207702e47cSPaolo Bonzini default: 1217702e47cSPaolo Bonzini if (offset >> 2 >= IIC_REGSET_SIZE) { 1227702e47cSPaolo Bonzini hw_error("exynos4210.combiner: overflow of reg_set by 0x" 1237702e47cSPaolo Bonzini TARGET_FMT_plx "offset\n", offset); 1247702e47cSPaolo Bonzini } 1257702e47cSPaolo Bonzini val = s->reg_set[offset >> 2]; 1267702e47cSPaolo Bonzini } 1277702e47cSPaolo Bonzini return val; 1287702e47cSPaolo Bonzini } 1297702e47cSPaolo Bonzini 1307702e47cSPaolo Bonzini static void exynos4210_combiner_update(void *opaque, uint8_t group_n) 1317702e47cSPaolo Bonzini { 1327702e47cSPaolo Bonzini struct Exynos4210CombinerState *s = 1337702e47cSPaolo Bonzini (struct Exynos4210CombinerState *)opaque; 1347702e47cSPaolo Bonzini 1357702e47cSPaolo Bonzini /* Send interrupt if needed */ 1367702e47cSPaolo Bonzini if (s->group[group_n].src_mask & s->group[group_n].src_pending) { 1377702e47cSPaolo Bonzini #ifdef DEBUG_COMBINER 1387702e47cSPaolo Bonzini if (group_n != 26) { 1397702e47cSPaolo Bonzini /* skip uart */ 1407702e47cSPaolo Bonzini DPRINTF("%s raise IRQ[%d]\n", s->external ? "EXT" : "INT", group_n); 1417702e47cSPaolo Bonzini } 1427702e47cSPaolo Bonzini #endif 1437702e47cSPaolo Bonzini 1447702e47cSPaolo Bonzini /* Set Combiner interrupt pending status after masking */ 1457702e47cSPaolo Bonzini if (group_n >= 32) { 1467702e47cSPaolo Bonzini s->icipsr[1] |= 1 << (group_n - 32); 1477702e47cSPaolo Bonzini } else { 1487702e47cSPaolo Bonzini s->icipsr[0] |= 1 << group_n; 1497702e47cSPaolo Bonzini } 1507702e47cSPaolo Bonzini 1517702e47cSPaolo Bonzini qemu_irq_raise(s->output_irq[group_n]); 1527702e47cSPaolo Bonzini } else { 1537702e47cSPaolo Bonzini #ifdef DEBUG_COMBINER 1547702e47cSPaolo Bonzini if (group_n != 26) { 1557702e47cSPaolo Bonzini /* skip uart */ 1567702e47cSPaolo Bonzini DPRINTF("%s lower IRQ[%d]\n", s->external ? "EXT" : "INT", group_n); 1577702e47cSPaolo Bonzini } 1587702e47cSPaolo Bonzini #endif 1597702e47cSPaolo Bonzini 1607702e47cSPaolo Bonzini /* Set Combiner interrupt pending status after masking */ 1617702e47cSPaolo Bonzini if (group_n >= 32) { 1627702e47cSPaolo Bonzini s->icipsr[1] &= ~(1 << (group_n - 32)); 1637702e47cSPaolo Bonzini } else { 1647702e47cSPaolo Bonzini s->icipsr[0] &= ~(1 << group_n); 1657702e47cSPaolo Bonzini } 1667702e47cSPaolo Bonzini 1677702e47cSPaolo Bonzini qemu_irq_lower(s->output_irq[group_n]); 1687702e47cSPaolo Bonzini } 1697702e47cSPaolo Bonzini } 1707702e47cSPaolo Bonzini 1717702e47cSPaolo Bonzini static void exynos4210_combiner_write(void *opaque, hwaddr offset, 1727702e47cSPaolo Bonzini uint64_t val, unsigned size) 1737702e47cSPaolo Bonzini { 1747702e47cSPaolo Bonzini struct Exynos4210CombinerState *s = 1757702e47cSPaolo Bonzini (struct Exynos4210CombinerState *)opaque; 1767702e47cSPaolo Bonzini uint32_t req_quad_base_n; /* Base of registers quad. Multiply it by 4 and 1777702e47cSPaolo Bonzini get a start of corresponding group quad */ 1787702e47cSPaolo Bonzini uint32_t grp_quad_base_n; /* Base of group quad */ 1797702e47cSPaolo Bonzini uint32_t reg_n; /* Register number inside the quad */ 1807702e47cSPaolo Bonzini 1817702e47cSPaolo Bonzini req_quad_base_n = offset >> 4; 1827702e47cSPaolo Bonzini grp_quad_base_n = req_quad_base_n << 2; 1837702e47cSPaolo Bonzini reg_n = (offset - (req_quad_base_n << 4)) >> 2; 1847702e47cSPaolo Bonzini 1857702e47cSPaolo Bonzini if (req_quad_base_n >= IIC_NGRP) { 1867702e47cSPaolo Bonzini hw_error("exynos4210.combiner: unallowed write access at offset 0x" 1877702e47cSPaolo Bonzini TARGET_FMT_plx "\n", offset); 1887702e47cSPaolo Bonzini return; 1897702e47cSPaolo Bonzini } 1907702e47cSPaolo Bonzini 1917702e47cSPaolo Bonzini if (reg_n > 1) { 1927702e47cSPaolo Bonzini hw_error("exynos4210.combiner: unallowed write access at offset 0x" 1937702e47cSPaolo Bonzini TARGET_FMT_plx "\n", offset); 1947702e47cSPaolo Bonzini return; 1957702e47cSPaolo Bonzini } 1967702e47cSPaolo Bonzini 1977702e47cSPaolo Bonzini if (offset >> 2 >= IIC_REGSET_SIZE) { 1987702e47cSPaolo Bonzini hw_error("exynos4210.combiner: overflow of reg_set by 0x" 1997702e47cSPaolo Bonzini TARGET_FMT_plx "offset\n", offset); 2007702e47cSPaolo Bonzini } 2017702e47cSPaolo Bonzini s->reg_set[offset >> 2] = val; 2027702e47cSPaolo Bonzini 2037702e47cSPaolo Bonzini switch (reg_n) { 2047702e47cSPaolo Bonzini /* IIESR */ 2057702e47cSPaolo Bonzini case 0: 2067702e47cSPaolo Bonzini /* FIXME: what if irq is pending, allowed by mask, and we allow it 2077702e47cSPaolo Bonzini * again. Interrupt will rise again! */ 2087702e47cSPaolo Bonzini 2097702e47cSPaolo Bonzini DPRINTF("%s enable IRQ for groups %d, %d, %d, %d\n", 2107702e47cSPaolo Bonzini s->external ? "EXT" : "INT", 2117702e47cSPaolo Bonzini grp_quad_base_n, 2127702e47cSPaolo Bonzini grp_quad_base_n + 1, 2137702e47cSPaolo Bonzini grp_quad_base_n + 2, 2147702e47cSPaolo Bonzini grp_quad_base_n + 3); 2157702e47cSPaolo Bonzini 2167702e47cSPaolo Bonzini /* Enable interrupt sources */ 2177702e47cSPaolo Bonzini s->group[grp_quad_base_n].src_mask |= val & 0xFF; 2187702e47cSPaolo Bonzini s->group[grp_quad_base_n + 1].src_mask |= (val & 0xFF00) >> 8; 2197702e47cSPaolo Bonzini s->group[grp_quad_base_n + 2].src_mask |= (val & 0xFF0000) >> 16; 2207702e47cSPaolo Bonzini s->group[grp_quad_base_n + 3].src_mask |= (val & 0xFF000000) >> 24; 2217702e47cSPaolo Bonzini 2227702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n); 2237702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n + 1); 2247702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n + 2); 2257702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n + 3); 2267702e47cSPaolo Bonzini break; 2277702e47cSPaolo Bonzini /* IIECR */ 2287702e47cSPaolo Bonzini case 1: 2297702e47cSPaolo Bonzini DPRINTF("%s disable IRQ for groups %d, %d, %d, %d\n", 2307702e47cSPaolo Bonzini s->external ? "EXT" : "INT", 2317702e47cSPaolo Bonzini grp_quad_base_n, 2327702e47cSPaolo Bonzini grp_quad_base_n + 1, 2337702e47cSPaolo Bonzini grp_quad_base_n + 2, 2347702e47cSPaolo Bonzini grp_quad_base_n + 3); 2357702e47cSPaolo Bonzini 2367702e47cSPaolo Bonzini /* Disable interrupt sources */ 2377702e47cSPaolo Bonzini s->group[grp_quad_base_n].src_mask &= ~(val & 0xFF); 2387702e47cSPaolo Bonzini s->group[grp_quad_base_n + 1].src_mask &= ~((val & 0xFF00) >> 8); 2397702e47cSPaolo Bonzini s->group[grp_quad_base_n + 2].src_mask &= ~((val & 0xFF0000) >> 16); 2407702e47cSPaolo Bonzini s->group[grp_quad_base_n + 3].src_mask &= ~((val & 0xFF000000) >> 24); 2417702e47cSPaolo Bonzini 2427702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n); 2437702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n + 1); 2447702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n + 2); 2457702e47cSPaolo Bonzini exynos4210_combiner_update(s, grp_quad_base_n + 3); 2467702e47cSPaolo Bonzini break; 2477702e47cSPaolo Bonzini default: 2487702e47cSPaolo Bonzini hw_error("exynos4210.combiner: unallowed write access at offset 0x" 2497702e47cSPaolo Bonzini TARGET_FMT_plx "\n", offset); 2507702e47cSPaolo Bonzini break; 2517702e47cSPaolo Bonzini } 2527702e47cSPaolo Bonzini } 2537702e47cSPaolo Bonzini 2547702e47cSPaolo Bonzini /* Get combiner group and bit from irq number */ 2557702e47cSPaolo Bonzini static uint8_t get_combiner_group_and_bit(int irq, uint8_t *bit) 2567702e47cSPaolo Bonzini { 2577702e47cSPaolo Bonzini *bit = irq - ((irq >> 3) << 3); 2587702e47cSPaolo Bonzini return irq >> 3; 2597702e47cSPaolo Bonzini } 2607702e47cSPaolo Bonzini 2617702e47cSPaolo Bonzini /* Process a change in an external IRQ input. */ 2627702e47cSPaolo Bonzini static void exynos4210_combiner_handler(void *opaque, int irq, int level) 2637702e47cSPaolo Bonzini { 2647702e47cSPaolo Bonzini struct Exynos4210CombinerState *s = 2657702e47cSPaolo Bonzini (struct Exynos4210CombinerState *)opaque; 2667702e47cSPaolo Bonzini uint8_t bit_n, group_n; 2677702e47cSPaolo Bonzini 2687702e47cSPaolo Bonzini group_n = get_combiner_group_and_bit(irq, &bit_n); 2697702e47cSPaolo Bonzini 2707702e47cSPaolo Bonzini if (s->external && group_n >= EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ) { 2717702e47cSPaolo Bonzini DPRINTF("%s unallowed IRQ group 0x%x\n", s->external ? "EXT" : "INT" 2727702e47cSPaolo Bonzini , group_n); 2737702e47cSPaolo Bonzini return; 2747702e47cSPaolo Bonzini } 2757702e47cSPaolo Bonzini 2767702e47cSPaolo Bonzini if (level) { 2777702e47cSPaolo Bonzini s->group[group_n].src_pending |= 1 << bit_n; 2787702e47cSPaolo Bonzini } else { 2797702e47cSPaolo Bonzini s->group[group_n].src_pending &= ~(1 << bit_n); 2807702e47cSPaolo Bonzini } 2817702e47cSPaolo Bonzini 2827702e47cSPaolo Bonzini exynos4210_combiner_update(s, group_n); 2837702e47cSPaolo Bonzini } 2847702e47cSPaolo Bonzini 2857702e47cSPaolo Bonzini static void exynos4210_combiner_reset(DeviceState *d) 2867702e47cSPaolo Bonzini { 2877702e47cSPaolo Bonzini struct Exynos4210CombinerState *s = (struct Exynos4210CombinerState *)d; 2887702e47cSPaolo Bonzini 2897702e47cSPaolo Bonzini memset(&s->group, 0, sizeof(s->group)); 2907702e47cSPaolo Bonzini memset(&s->reg_set, 0, sizeof(s->reg_set)); 2917702e47cSPaolo Bonzini 2927702e47cSPaolo Bonzini s->reg_set[0xC0 >> 2] = 0x01010101; 2937702e47cSPaolo Bonzini s->reg_set[0xC4 >> 2] = 0x01010101; 2947702e47cSPaolo Bonzini s->reg_set[0xD0 >> 2] = 0x01010101; 2957702e47cSPaolo Bonzini s->reg_set[0xD4 >> 2] = 0x01010101; 2967702e47cSPaolo Bonzini } 2977702e47cSPaolo Bonzini 2987702e47cSPaolo Bonzini static const MemoryRegionOps exynos4210_combiner_ops = { 2997702e47cSPaolo Bonzini .read = exynos4210_combiner_read, 3007702e47cSPaolo Bonzini .write = exynos4210_combiner_write, 3017702e47cSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN, 3027702e47cSPaolo Bonzini }; 3037702e47cSPaolo Bonzini 3047702e47cSPaolo Bonzini /* 3057702e47cSPaolo Bonzini * Internal Combiner initialization. 3067702e47cSPaolo Bonzini */ 307d3d5a6feSxiaoqiang.zhao static void exynos4210_combiner_init(Object *obj) 3087702e47cSPaolo Bonzini { 309d3d5a6feSxiaoqiang.zhao DeviceState *dev = DEVICE(obj); 310d3d5a6feSxiaoqiang.zhao Exynos4210CombinerState *s = EXYNOS4210_COMBINER(obj); 311d3d5a6feSxiaoqiang.zhao SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 3127702e47cSPaolo Bonzini unsigned int i; 3137702e47cSPaolo Bonzini 3147702e47cSPaolo Bonzini /* Allocate general purpose input signals and connect a handler to each of 3157702e47cSPaolo Bonzini * them */ 316c03c6b9cSAndreas Färber qdev_init_gpio_in(dev, exynos4210_combiner_handler, IIC_NIRQ); 3177702e47cSPaolo Bonzini 3187702e47cSPaolo Bonzini /* Connect SysBusDev irqs to device specific irqs */ 319fce0a826SPeter Maydell for (i = 0; i < IIC_NGRP; i++) { 320c03c6b9cSAndreas Färber sysbus_init_irq(sbd, &s->output_irq[i]); 3217702e47cSPaolo Bonzini } 3227702e47cSPaolo Bonzini 323d3d5a6feSxiaoqiang.zhao memory_region_init_io(&s->iomem, obj, &exynos4210_combiner_ops, s, 3247702e47cSPaolo Bonzini "exynos4210-combiner", IIC_REGION_SIZE); 325c03c6b9cSAndreas Färber sysbus_init_mmio(sbd, &s->iomem); 3267702e47cSPaolo Bonzini } 3277702e47cSPaolo Bonzini 3287702e47cSPaolo Bonzini static Property exynos4210_combiner_properties[] = { 3297702e47cSPaolo Bonzini DEFINE_PROP_UINT32("external", Exynos4210CombinerState, external, 0), 3307702e47cSPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 3317702e47cSPaolo Bonzini }; 3327702e47cSPaolo Bonzini 3337702e47cSPaolo Bonzini static void exynos4210_combiner_class_init(ObjectClass *klass, void *data) 3347702e47cSPaolo Bonzini { 3357702e47cSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 3367702e47cSPaolo Bonzini 3377702e47cSPaolo Bonzini dc->reset = exynos4210_combiner_reset; 3384f67d30bSMarc-André Lureau device_class_set_props(dc, exynos4210_combiner_properties); 3397702e47cSPaolo Bonzini dc->vmsd = &vmstate_exynos4210_combiner; 3407702e47cSPaolo Bonzini } 3417702e47cSPaolo Bonzini 3427702e47cSPaolo Bonzini static const TypeInfo exynos4210_combiner_info = { 343c03c6b9cSAndreas Färber .name = TYPE_EXYNOS4210_COMBINER, 3447702e47cSPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE, 3457702e47cSPaolo Bonzini .instance_size = sizeof(Exynos4210CombinerState), 346d3d5a6feSxiaoqiang.zhao .instance_init = exynos4210_combiner_init, 3477702e47cSPaolo Bonzini .class_init = exynos4210_combiner_class_init, 3487702e47cSPaolo Bonzini }; 3497702e47cSPaolo Bonzini 3507702e47cSPaolo Bonzini static void exynos4210_combiner_register_types(void) 3517702e47cSPaolo Bonzini { 3527702e47cSPaolo Bonzini type_register_static(&exynos4210_combiner_info); 3537702e47cSPaolo Bonzini } 3547702e47cSPaolo Bonzini 3557702e47cSPaolo Bonzini type_init(exynos4210_combiner_register_types) 356