1dd73185bSPeter Maydell /* 2dd73185bSPeter Maydell * ARM MPS2 SCC emulation 3dd73185bSPeter Maydell * 4dd73185bSPeter Maydell * Copyright (c) 2017 Linaro Limited 5dd73185bSPeter Maydell * Written by Peter Maydell 6dd73185bSPeter Maydell * 7dd73185bSPeter Maydell * This program is free software; you can redistribute it and/or modify 8dd73185bSPeter Maydell * it under the terms of the GNU General Public License version 2 or 9dd73185bSPeter Maydell * (at your option) any later version. 10dd73185bSPeter Maydell */ 11dd73185bSPeter Maydell 12dd73185bSPeter Maydell /* This is a model of the SCC (Serial Communication Controller) 13dd73185bSPeter Maydell * found in the FPGA images of MPS2 development boards. 14dd73185bSPeter Maydell * 15dd73185bSPeter Maydell * Documentation of it can be found in the MPS2 TRM: 16*50b52b18SPeter Maydell * https://developer.arm.com/documentation/100112/latest/ 17dd73185bSPeter Maydell * and also in the Application Notes documenting individual FPGA images. 18dd73185bSPeter Maydell */ 19dd73185bSPeter Maydell 20dd73185bSPeter Maydell #include "qemu/osdep.h" 21dd73185bSPeter Maydell #include "qemu/log.h" 220b8fa32fSMarkus Armbruster #include "qemu/module.h" 23435db7ebSPhilippe Mathieu-Daudé #include "qemu/bitops.h" 24dd73185bSPeter Maydell #include "trace.h" 25dd73185bSPeter Maydell #include "hw/sysbus.h" 26d6454270SMarkus Armbruster #include "migration/vmstate.h" 27dd73185bSPeter Maydell #include "hw/registerfields.h" 28dd73185bSPeter Maydell #include "hw/misc/mps2-scc.h" 29435db7ebSPhilippe Mathieu-Daudé #include "hw/misc/led.h" 30a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 31dd73185bSPeter Maydell 32dd73185bSPeter Maydell REG32(CFG0, 0) 33dd73185bSPeter Maydell REG32(CFG1, 4) 348e4b4c1cSPeter Maydell REG32(CFG2, 8) 35dd73185bSPeter Maydell REG32(CFG3, 0xc) 36dd73185bSPeter Maydell REG32(CFG4, 0x10) 378e4b4c1cSPeter Maydell REG32(CFG5, 0x14) 388e4b4c1cSPeter Maydell REG32(CFG6, 0x18) 39dd73185bSPeter Maydell REG32(CFGDATA_RTN, 0xa0) 40dd73185bSPeter Maydell REG32(CFGDATA_OUT, 0xa4) 41dd73185bSPeter Maydell REG32(CFGCTRL, 0xa8) 42dd73185bSPeter Maydell FIELD(CFGCTRL, DEVICE, 0, 12) 43dd73185bSPeter Maydell FIELD(CFGCTRL, RES1, 12, 8) 44dd73185bSPeter Maydell FIELD(CFGCTRL, FUNCTION, 20, 6) 45dd73185bSPeter Maydell FIELD(CFGCTRL, RES2, 26, 4) 46dd73185bSPeter Maydell FIELD(CFGCTRL, WRITE, 30, 1) 47dd73185bSPeter Maydell FIELD(CFGCTRL, START, 31, 1) 48dd73185bSPeter Maydell REG32(CFGSTAT, 0xac) 49dd73185bSPeter Maydell FIELD(CFGSTAT, DONE, 0, 1) 50dd73185bSPeter Maydell FIELD(CFGSTAT, ERROR, 1, 1) 51dd73185bSPeter Maydell REG32(DLL, 0x100) 52dd73185bSPeter Maydell REG32(AID, 0xFF8) 53dd73185bSPeter Maydell REG32(ID, 0xFFC) 54dd73185bSPeter Maydell 558e4b4c1cSPeter Maydell static int scc_partno(MPS2SCC *s) 568e4b4c1cSPeter Maydell { 578e4b4c1cSPeter Maydell /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */ 588e4b4c1cSPeter Maydell return extract32(s->id, 4, 8); 598e4b4c1cSPeter Maydell } 608e4b4c1cSPeter Maydell 61dd73185bSPeter Maydell /* Handle a write via the SYS_CFG channel to the specified function/device. 62dd73185bSPeter Maydell * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit). 63dd73185bSPeter Maydell */ 64dd73185bSPeter Maydell static bool scc_cfg_write(MPS2SCC *s, unsigned function, 65dd73185bSPeter Maydell unsigned device, uint32_t value) 66dd73185bSPeter Maydell { 67dd73185bSPeter Maydell trace_mps2_scc_cfg_write(function, device, value); 68dd73185bSPeter Maydell 694fb013afSPeter Maydell if (function != 1 || device >= s->num_oscclk) { 70dd73185bSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 71dd73185bSPeter Maydell "MPS2 SCC config write: bad function %d device %d\n", 72dd73185bSPeter Maydell function, device); 73dd73185bSPeter Maydell return false; 74dd73185bSPeter Maydell } 75dd73185bSPeter Maydell 76dd73185bSPeter Maydell s->oscclk[device] = value; 77dd73185bSPeter Maydell return true; 78dd73185bSPeter Maydell } 79dd73185bSPeter Maydell 80dd73185bSPeter Maydell /* Handle a read via the SYS_CFG channel to the specified function/device. 81dd73185bSPeter Maydell * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit), 82dd73185bSPeter Maydell * or set *value on success. 83dd73185bSPeter Maydell */ 84dd73185bSPeter Maydell static bool scc_cfg_read(MPS2SCC *s, unsigned function, 85dd73185bSPeter Maydell unsigned device, uint32_t *value) 86dd73185bSPeter Maydell { 874fb013afSPeter Maydell if (function != 1 || device >= s->num_oscclk) { 88dd73185bSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 89dd73185bSPeter Maydell "MPS2 SCC config read: bad function %d device %d\n", 90dd73185bSPeter Maydell function, device); 91dd73185bSPeter Maydell return false; 92dd73185bSPeter Maydell } 93dd73185bSPeter Maydell 94dd73185bSPeter Maydell *value = s->oscclk[device]; 95dd73185bSPeter Maydell 96dd73185bSPeter Maydell trace_mps2_scc_cfg_read(function, device, *value); 97dd73185bSPeter Maydell return true; 98dd73185bSPeter Maydell } 99dd73185bSPeter Maydell 100dd73185bSPeter Maydell static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size) 101dd73185bSPeter Maydell { 102dd73185bSPeter Maydell MPS2SCC *s = MPS2_SCC(opaque); 103dd73185bSPeter Maydell uint64_t r; 104dd73185bSPeter Maydell 105dd73185bSPeter Maydell switch (offset) { 106dd73185bSPeter Maydell case A_CFG0: 107dd73185bSPeter Maydell r = s->cfg0; 108dd73185bSPeter Maydell break; 109dd73185bSPeter Maydell case A_CFG1: 110dd73185bSPeter Maydell r = s->cfg1; 111dd73185bSPeter Maydell break; 1128e4b4c1cSPeter Maydell case A_CFG2: 1138e4b4c1cSPeter Maydell if (scc_partno(s) != 0x524) { 1148e4b4c1cSPeter Maydell /* CFG2 reserved on other boards */ 1158e4b4c1cSPeter Maydell goto bad_offset; 1168e4b4c1cSPeter Maydell } 1178e4b4c1cSPeter Maydell r = s->cfg2; 1188e4b4c1cSPeter Maydell break; 119dd73185bSPeter Maydell case A_CFG3: 1208e4b4c1cSPeter Maydell if (scc_partno(s) == 0x524) { 1218e4b4c1cSPeter Maydell /* CFG3 reserved on AN524 */ 1228e4b4c1cSPeter Maydell goto bad_offset; 1238e4b4c1cSPeter Maydell } 124dd73185bSPeter Maydell /* These are user-settable DIP switches on the board. We don't 125dd73185bSPeter Maydell * model that, so just return zeroes. 126dd73185bSPeter Maydell */ 127dd73185bSPeter Maydell r = 0; 128dd73185bSPeter Maydell break; 129dd73185bSPeter Maydell case A_CFG4: 130dd73185bSPeter Maydell r = s->cfg4; 131dd73185bSPeter Maydell break; 1328e4b4c1cSPeter Maydell case A_CFG5: 1338e4b4c1cSPeter Maydell if (scc_partno(s) != 0x524) { 1348e4b4c1cSPeter Maydell /* CFG5 reserved on other boards */ 1358e4b4c1cSPeter Maydell goto bad_offset; 1368e4b4c1cSPeter Maydell } 1378e4b4c1cSPeter Maydell r = s->cfg5; 1388e4b4c1cSPeter Maydell break; 1398e4b4c1cSPeter Maydell case A_CFG6: 1408e4b4c1cSPeter Maydell if (scc_partno(s) != 0x524) { 1418e4b4c1cSPeter Maydell /* CFG6 reserved on other boards */ 1428e4b4c1cSPeter Maydell goto bad_offset; 1438e4b4c1cSPeter Maydell } 1448e4b4c1cSPeter Maydell r = s->cfg6; 1458e4b4c1cSPeter Maydell break; 146dd73185bSPeter Maydell case A_CFGDATA_RTN: 147dd73185bSPeter Maydell r = s->cfgdata_rtn; 148dd73185bSPeter Maydell break; 149dd73185bSPeter Maydell case A_CFGDATA_OUT: 150dd73185bSPeter Maydell r = s->cfgdata_out; 151dd73185bSPeter Maydell break; 152dd73185bSPeter Maydell case A_CFGCTRL: 153dd73185bSPeter Maydell r = s->cfgctrl; 154dd73185bSPeter Maydell break; 155dd73185bSPeter Maydell case A_CFGSTAT: 156dd73185bSPeter Maydell r = s->cfgstat; 157dd73185bSPeter Maydell break; 158dd73185bSPeter Maydell case A_DLL: 159dd73185bSPeter Maydell r = s->dll; 160dd73185bSPeter Maydell break; 161dd73185bSPeter Maydell case A_AID: 162dd73185bSPeter Maydell r = s->aid; 163dd73185bSPeter Maydell break; 164dd73185bSPeter Maydell case A_ID: 165dd73185bSPeter Maydell r = s->id; 166dd73185bSPeter Maydell break; 167dd73185bSPeter Maydell default: 1688e4b4c1cSPeter Maydell bad_offset: 169dd73185bSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 170dd73185bSPeter Maydell "MPS2 SCC read: bad offset %x\n", (int) offset); 171dd73185bSPeter Maydell r = 0; 172dd73185bSPeter Maydell break; 173dd73185bSPeter Maydell } 174dd73185bSPeter Maydell 175dd73185bSPeter Maydell trace_mps2_scc_read(offset, r, size); 176dd73185bSPeter Maydell return r; 177dd73185bSPeter Maydell } 178dd73185bSPeter Maydell 179dd73185bSPeter Maydell static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value, 180dd73185bSPeter Maydell unsigned size) 181dd73185bSPeter Maydell { 182dd73185bSPeter Maydell MPS2SCC *s = MPS2_SCC(opaque); 183dd73185bSPeter Maydell 184dd73185bSPeter Maydell trace_mps2_scc_write(offset, value, size); 185dd73185bSPeter Maydell 186dd73185bSPeter Maydell switch (offset) { 187dd73185bSPeter Maydell case A_CFG0: 188dd73185bSPeter Maydell /* TODO on some boards bit 0 controls RAM remapping */ 189dd73185bSPeter Maydell s->cfg0 = value; 190dd73185bSPeter Maydell break; 191dd73185bSPeter Maydell case A_CFG1: 192dd73185bSPeter Maydell s->cfg1 = value; 193435db7ebSPhilippe Mathieu-Daudé for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { 194435db7ebSPhilippe Mathieu-Daudé led_set_state(s->led[i], extract32(value, i, 1)); 195435db7ebSPhilippe Mathieu-Daudé } 196dd73185bSPeter Maydell break; 1978e4b4c1cSPeter Maydell case A_CFG2: 1988e4b4c1cSPeter Maydell if (scc_partno(s) != 0x524) { 1998e4b4c1cSPeter Maydell /* CFG2 reserved on other boards */ 2008e4b4c1cSPeter Maydell goto bad_offset; 2018e4b4c1cSPeter Maydell } 2028e4b4c1cSPeter Maydell /* AN524: QSPI Select signal */ 2038e4b4c1cSPeter Maydell s->cfg2 = value; 2048e4b4c1cSPeter Maydell break; 2058e4b4c1cSPeter Maydell case A_CFG5: 2068e4b4c1cSPeter Maydell if (scc_partno(s) != 0x524) { 2078e4b4c1cSPeter Maydell /* CFG5 reserved on other boards */ 2088e4b4c1cSPeter Maydell goto bad_offset; 2098e4b4c1cSPeter Maydell } 2108e4b4c1cSPeter Maydell /* AN524: ACLK frequency in Hz */ 2118e4b4c1cSPeter Maydell s->cfg5 = value; 2128e4b4c1cSPeter Maydell break; 2138e4b4c1cSPeter Maydell case A_CFG6: 2148e4b4c1cSPeter Maydell if (scc_partno(s) != 0x524) { 2158e4b4c1cSPeter Maydell /* CFG6 reserved on other boards */ 2168e4b4c1cSPeter Maydell goto bad_offset; 2178e4b4c1cSPeter Maydell } 2188e4b4c1cSPeter Maydell /* AN524: Clock divider for BRAM */ 2198e4b4c1cSPeter Maydell s->cfg6 = value; 2208e4b4c1cSPeter Maydell break; 221dd73185bSPeter Maydell case A_CFGDATA_OUT: 222dd73185bSPeter Maydell s->cfgdata_out = value; 223dd73185bSPeter Maydell break; 224dd73185bSPeter Maydell case A_CFGCTRL: 225dd73185bSPeter Maydell /* Writing to CFGCTRL clears SYS_CFGSTAT */ 226dd73185bSPeter Maydell s->cfgstat = 0; 227dd73185bSPeter Maydell s->cfgctrl = value & ~(R_CFGCTRL_RES1_MASK | 228dd73185bSPeter Maydell R_CFGCTRL_RES2_MASK | 229dd73185bSPeter Maydell R_CFGCTRL_START_MASK); 230dd73185bSPeter Maydell 231dd73185bSPeter Maydell if (value & R_CFGCTRL_START_MASK) { 232dd73185bSPeter Maydell /* Start bit set -- do a read or write (instantaneously) */ 233dd73185bSPeter Maydell int device = extract32(s->cfgctrl, R_CFGCTRL_DEVICE_SHIFT, 234dd73185bSPeter Maydell R_CFGCTRL_DEVICE_LENGTH); 235dd73185bSPeter Maydell int function = extract32(s->cfgctrl, R_CFGCTRL_FUNCTION_SHIFT, 236dd73185bSPeter Maydell R_CFGCTRL_FUNCTION_LENGTH); 237dd73185bSPeter Maydell 238dd73185bSPeter Maydell s->cfgstat = R_CFGSTAT_DONE_MASK; 239dd73185bSPeter Maydell if (s->cfgctrl & R_CFGCTRL_WRITE_MASK) { 240dd73185bSPeter Maydell if (!scc_cfg_write(s, function, device, s->cfgdata_out)) { 241dd73185bSPeter Maydell s->cfgstat |= R_CFGSTAT_ERROR_MASK; 242dd73185bSPeter Maydell } 243dd73185bSPeter Maydell } else { 244dd73185bSPeter Maydell uint32_t result; 245dd73185bSPeter Maydell if (!scc_cfg_read(s, function, device, &result)) { 246dd73185bSPeter Maydell s->cfgstat |= R_CFGSTAT_ERROR_MASK; 247dd73185bSPeter Maydell } else { 248dd73185bSPeter Maydell s->cfgdata_rtn = result; 249dd73185bSPeter Maydell } 250dd73185bSPeter Maydell } 251dd73185bSPeter Maydell } 252dd73185bSPeter Maydell break; 253dd73185bSPeter Maydell case A_DLL: 254dd73185bSPeter Maydell /* DLL stands for Digital Locked Loop. 255dd73185bSPeter Maydell * Bits [31:24] (DLL_LOCK_MASK) are writable, and indicate a 256dd73185bSPeter Maydell * mask of which of the DLL_LOCKED bits [16:23] should be ORed 257dd73185bSPeter Maydell * together to determine the ALL_UNMASKED_DLLS_LOCKED bit [0]. 258dd73185bSPeter Maydell * For QEMU, our DLLs are always locked, so we can leave bit 0 259dd73185bSPeter Maydell * as 1 always and don't need to recalculate it. 260dd73185bSPeter Maydell */ 261dd73185bSPeter Maydell s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8)); 262dd73185bSPeter Maydell break; 263dd73185bSPeter Maydell default: 2648e4b4c1cSPeter Maydell bad_offset: 265dd73185bSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 266dd73185bSPeter Maydell "MPS2 SCC write: bad offset 0x%x\n", (int) offset); 267dd73185bSPeter Maydell break; 268dd73185bSPeter Maydell } 269dd73185bSPeter Maydell } 270dd73185bSPeter Maydell 271dd73185bSPeter Maydell static const MemoryRegionOps mps2_scc_ops = { 272dd73185bSPeter Maydell .read = mps2_scc_read, 273dd73185bSPeter Maydell .write = mps2_scc_write, 274dd73185bSPeter Maydell .endianness = DEVICE_LITTLE_ENDIAN, 275dd73185bSPeter Maydell }; 276dd73185bSPeter Maydell 277dd73185bSPeter Maydell static void mps2_scc_reset(DeviceState *dev) 278dd73185bSPeter Maydell { 279dd73185bSPeter Maydell MPS2SCC *s = MPS2_SCC(dev); 280dd73185bSPeter Maydell int i; 281dd73185bSPeter Maydell 282dd73185bSPeter Maydell trace_mps2_scc_reset(); 283dd73185bSPeter Maydell s->cfg0 = 0; 284dd73185bSPeter Maydell s->cfg1 = 0; 2858e4b4c1cSPeter Maydell s->cfg2 = 0; 2868e4b4c1cSPeter Maydell s->cfg5 = 0; 2878e4b4c1cSPeter Maydell s->cfg6 = 0; 288dd73185bSPeter Maydell s->cfgdata_rtn = 0; 289dd73185bSPeter Maydell s->cfgdata_out = 0; 290dd73185bSPeter Maydell s->cfgctrl = 0x100000; 291dd73185bSPeter Maydell s->cfgstat = 0; 292dd73185bSPeter Maydell s->dll = 0xffff0001; 2934fb013afSPeter Maydell for (i = 0; i < s->num_oscclk; i++) { 294dd73185bSPeter Maydell s->oscclk[i] = s->oscclk_reset[i]; 295dd73185bSPeter Maydell } 296435db7ebSPhilippe Mathieu-Daudé for (i = 0; i < ARRAY_SIZE(s->led); i++) { 297435db7ebSPhilippe Mathieu-Daudé device_cold_reset(DEVICE(s->led[i])); 298435db7ebSPhilippe Mathieu-Daudé } 299dd73185bSPeter Maydell } 300dd73185bSPeter Maydell 301dd73185bSPeter Maydell static void mps2_scc_init(Object *obj) 302dd73185bSPeter Maydell { 303dd73185bSPeter Maydell SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 304dd73185bSPeter Maydell MPS2SCC *s = MPS2_SCC(obj); 305dd73185bSPeter Maydell 306dd73185bSPeter Maydell memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000); 307dd73185bSPeter Maydell sysbus_init_mmio(sbd, &s->iomem); 308dd73185bSPeter Maydell } 309dd73185bSPeter Maydell 310dd73185bSPeter Maydell static void mps2_scc_realize(DeviceState *dev, Error **errp) 311dd73185bSPeter Maydell { 312435db7ebSPhilippe Mathieu-Daudé MPS2SCC *s = MPS2_SCC(dev); 313435db7ebSPhilippe Mathieu-Daudé 314435db7ebSPhilippe Mathieu-Daudé for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { 315435db7ebSPhilippe Mathieu-Daudé char *name = g_strdup_printf("SCC LED%zu", i); 316435db7ebSPhilippe Mathieu-Daudé s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, 317435db7ebSPhilippe Mathieu-Daudé LED_COLOR_GREEN, name); 318435db7ebSPhilippe Mathieu-Daudé g_free(name); 319435db7ebSPhilippe Mathieu-Daudé } 3204fb013afSPeter Maydell 3214fb013afSPeter Maydell s->oscclk = g_new0(uint32_t, s->num_oscclk); 322dd73185bSPeter Maydell } 323dd73185bSPeter Maydell 324dd73185bSPeter Maydell static const VMStateDescription mps2_scc_vmstate = { 325dd73185bSPeter Maydell .name = "mps2-scc", 3268e4b4c1cSPeter Maydell .version_id = 3, 3278e4b4c1cSPeter Maydell .minimum_version_id = 3, 328dd73185bSPeter Maydell .fields = (VMStateField[]) { 329dd73185bSPeter Maydell VMSTATE_UINT32(cfg0, MPS2SCC), 330dd73185bSPeter Maydell VMSTATE_UINT32(cfg1, MPS2SCC), 3318e4b4c1cSPeter Maydell VMSTATE_UINT32(cfg2, MPS2SCC), 3328e4b4c1cSPeter Maydell /* cfg3, cfg4 are read-only so need not be migrated */ 3338e4b4c1cSPeter Maydell VMSTATE_UINT32(cfg5, MPS2SCC), 3348e4b4c1cSPeter Maydell VMSTATE_UINT32(cfg6, MPS2SCC), 335dd73185bSPeter Maydell VMSTATE_UINT32(cfgdata_rtn, MPS2SCC), 336dd73185bSPeter Maydell VMSTATE_UINT32(cfgdata_out, MPS2SCC), 337dd73185bSPeter Maydell VMSTATE_UINT32(cfgctrl, MPS2SCC), 338dd73185bSPeter Maydell VMSTATE_UINT32(cfgstat, MPS2SCC), 339dd73185bSPeter Maydell VMSTATE_UINT32(dll, MPS2SCC), 3404fb013afSPeter Maydell VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk, 3414fb013afSPeter Maydell 0, vmstate_info_uint32, uint32_t), 342dd73185bSPeter Maydell VMSTATE_END_OF_LIST() 343dd73185bSPeter Maydell } 344dd73185bSPeter Maydell }; 345dd73185bSPeter Maydell 346dd73185bSPeter Maydell static Property mps2_scc_properties[] = { 347dd73185bSPeter Maydell /* Values for various read-only ID registers (which are specific 348dd73185bSPeter Maydell * to the board model or FPGA image) 349dd73185bSPeter Maydell */ 35089cbc377SPhilippe Mathieu-Daudé DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0), 351dd73185bSPeter Maydell DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0), 35289cbc377SPhilippe Mathieu-Daudé DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0), 3534fb013afSPeter Maydell /* 3544fb013afSPeter Maydell * These are the initial settings for the source clocks on the board. 355dd73185bSPeter Maydell * In hardware they can be configured via a config file read by the 356dd73185bSPeter Maydell * motherboard configuration controller to suit the FPGA image. 357dd73185bSPeter Maydell */ 3584fb013afSPeter Maydell DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset, 3594fb013afSPeter Maydell qdev_prop_uint32, uint32_t), 360dd73185bSPeter Maydell DEFINE_PROP_END_OF_LIST(), 361dd73185bSPeter Maydell }; 362dd73185bSPeter Maydell 363dd73185bSPeter Maydell static void mps2_scc_class_init(ObjectClass *klass, void *data) 364dd73185bSPeter Maydell { 365dd73185bSPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 366dd73185bSPeter Maydell 367dd73185bSPeter Maydell dc->realize = mps2_scc_realize; 368dd73185bSPeter Maydell dc->vmsd = &mps2_scc_vmstate; 369dd73185bSPeter Maydell dc->reset = mps2_scc_reset; 3704f67d30bSMarc-André Lureau device_class_set_props(dc, mps2_scc_properties); 371dd73185bSPeter Maydell } 372dd73185bSPeter Maydell 373dd73185bSPeter Maydell static const TypeInfo mps2_scc_info = { 374dd73185bSPeter Maydell .name = TYPE_MPS2_SCC, 375dd73185bSPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 376dd73185bSPeter Maydell .instance_size = sizeof(MPS2SCC), 377dd73185bSPeter Maydell .instance_init = mps2_scc_init, 378dd73185bSPeter Maydell .class_init = mps2_scc_class_init, 379dd73185bSPeter Maydell }; 380dd73185bSPeter Maydell 381dd73185bSPeter Maydell static void mps2_scc_register_types(void) 382dd73185bSPeter Maydell { 383dd73185bSPeter Maydell type_register_static(&mps2_scc_info); 384dd73185bSPeter Maydell } 385dd73185bSPeter Maydell 386dd73185bSPeter Maydell type_init(mps2_scc_register_types); 387