175750e4dSPeter Maydell /* 275750e4dSPeter Maydell * ARM IoTKit system control element 375750e4dSPeter Maydell * 475750e4dSPeter Maydell * Copyright (c) 2018 Linaro Limited 575750e4dSPeter Maydell * Written by Peter Maydell 675750e4dSPeter Maydell * 775750e4dSPeter Maydell * This program is free software; you can redistribute it and/or modify 875750e4dSPeter Maydell * it under the terms of the GNU General Public License version 2 or 975750e4dSPeter Maydell * (at your option) any later version. 1075750e4dSPeter Maydell */ 1175750e4dSPeter Maydell 1275750e4dSPeter Maydell /* 1375750e4dSPeter Maydell * This is a model of the "system control element" which is part of the 1475750e4dSPeter Maydell * Arm IoTKit and documented in 1575750e4dSPeter Maydell * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html 1675750e4dSPeter Maydell * Specifically, it implements the "system control register" blocks. 1775750e4dSPeter Maydell */ 1875750e4dSPeter Maydell 1975750e4dSPeter Maydell #include "qemu/osdep.h" 2004836414SPeter Maydell #include "qemu/bitops.h" 2175750e4dSPeter Maydell #include "qemu/log.h" 220b8fa32fSMarkus Armbruster #include "qemu/module.h" 2354d31236SMarkus Armbruster #include "sysemu/runstate.h" 2475750e4dSPeter Maydell #include "trace.h" 2575750e4dSPeter Maydell #include "qapi/error.h" 2675750e4dSPeter Maydell #include "hw/sysbus.h" 27d6454270SMarkus Armbruster #include "migration/vmstate.h" 2875750e4dSPeter Maydell #include "hw/registerfields.h" 2975750e4dSPeter Maydell #include "hw/misc/iotkit-sysctl.h" 30a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 310f862986SPeter Maydell #include "target/arm/arm-powerctl.h" 320f862986SPeter Maydell #include "target/arm/cpu.h" 3375750e4dSPeter Maydell 3475750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0) 3575750e4dSPeter Maydell REG32(SECDBGSET, 0x4) 3675750e4dSPeter Maydell REG32(SECDBGCLR, 0x8) 3704836414SPeter Maydell REG32(SCSECCTRL, 0xc) 3804836414SPeter Maydell REG32(FCLK_DIV, 0x10) 3904836414SPeter Maydell REG32(SYSCLK_DIV, 0x14) 4004836414SPeter Maydell REG32(CLOCK_FORCE, 0x18) 4175750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100) 4275750e4dSPeter Maydell REG32(RESET_MASK, 0x104) 4375750e4dSPeter Maydell REG32(SWRESET, 0x108) 4475750e4dSPeter Maydell FIELD(SWRESET, SWRESETREQ, 9, 1) 4575750e4dSPeter Maydell REG32(GRETREG, 0x10c) 46394e10d2SPeter Maydell REG32(INITSVTOR0, 0x110) 4704836414SPeter Maydell REG32(INITSVTOR1, 0x114) 4875750e4dSPeter Maydell REG32(CPUWAIT, 0x118) 4904836414SPeter Maydell REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */ 5075750e4dSPeter Maydell REG32(WICCTRL, 0x120) 5104836414SPeter Maydell REG32(EWCTRL, 0x124) 5204836414SPeter Maydell REG32(PDCM_PD_SYS_SENSE, 0x200) 5304836414SPeter Maydell REG32(PDCM_PD_SRAM0_SENSE, 0x20c) 5404836414SPeter Maydell REG32(PDCM_PD_SRAM1_SENSE, 0x210) 5504836414SPeter Maydell REG32(PDCM_PD_SRAM2_SENSE, 0x214) 5604836414SPeter Maydell REG32(PDCM_PD_SRAM3_SENSE, 0x218) 5775750e4dSPeter Maydell REG32(PID4, 0xfd0) 5875750e4dSPeter Maydell REG32(PID5, 0xfd4) 5975750e4dSPeter Maydell REG32(PID6, 0xfd8) 6075750e4dSPeter Maydell REG32(PID7, 0xfdc) 6175750e4dSPeter Maydell REG32(PID0, 0xfe0) 6275750e4dSPeter Maydell REG32(PID1, 0xfe4) 6375750e4dSPeter Maydell REG32(PID2, 0xfe8) 6475750e4dSPeter Maydell REG32(PID3, 0xfec) 6575750e4dSPeter Maydell REG32(CID0, 0xff0) 6675750e4dSPeter Maydell REG32(CID1, 0xff4) 6775750e4dSPeter Maydell REG32(CID2, 0xff8) 6875750e4dSPeter Maydell REG32(CID3, 0xffc) 6975750e4dSPeter Maydell 7075750e4dSPeter Maydell /* PID/CID values */ 7175750e4dSPeter Maydell static const int sysctl_id[] = { 7275750e4dSPeter Maydell 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ 7375750e4dSPeter Maydell 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ 7475750e4dSPeter Maydell 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 7575750e4dSPeter Maydell }; 7675750e4dSPeter Maydell 770f862986SPeter Maydell /* 780f862986SPeter Maydell * Set the initial secure vector table offset address for the core. 790f862986SPeter Maydell * This will take effect when the CPU next resets. 800f862986SPeter Maydell */ 810f862986SPeter Maydell static void set_init_vtor(uint64_t cpuid, uint32_t vtor) 820f862986SPeter Maydell { 830f862986SPeter Maydell Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid)); 840f862986SPeter Maydell 850f862986SPeter Maydell if (cpuobj) { 860f862986SPeter Maydell if (object_property_find(cpuobj, "init-svtor", NULL)) { 870f862986SPeter Maydell object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort); 880f862986SPeter Maydell } 890f862986SPeter Maydell } 900f862986SPeter Maydell } 910f862986SPeter Maydell 9275750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset, 9375750e4dSPeter Maydell unsigned size) 9475750e4dSPeter Maydell { 9575750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 9675750e4dSPeter Maydell uint64_t r; 9775750e4dSPeter Maydell 9875750e4dSPeter Maydell switch (offset) { 9975750e4dSPeter Maydell case A_SECDBGSTAT: 10075750e4dSPeter Maydell r = s->secure_debug; 10175750e4dSPeter Maydell break; 10204836414SPeter Maydell case A_SCSECCTRL: 10304836414SPeter Maydell if (!s->is_sse200) { 10404836414SPeter Maydell goto bad_offset; 10504836414SPeter Maydell } 10604836414SPeter Maydell r = s->scsecctrl; 10704836414SPeter Maydell break; 10804836414SPeter Maydell case A_FCLK_DIV: 10904836414SPeter Maydell if (!s->is_sse200) { 11004836414SPeter Maydell goto bad_offset; 11104836414SPeter Maydell } 11204836414SPeter Maydell r = s->fclk_div; 11304836414SPeter Maydell break; 11404836414SPeter Maydell case A_SYSCLK_DIV: 11504836414SPeter Maydell if (!s->is_sse200) { 11604836414SPeter Maydell goto bad_offset; 11704836414SPeter Maydell } 11804836414SPeter Maydell r = s->sysclk_div; 11904836414SPeter Maydell break; 12004836414SPeter Maydell case A_CLOCK_FORCE: 12104836414SPeter Maydell if (!s->is_sse200) { 12204836414SPeter Maydell goto bad_offset; 12304836414SPeter Maydell } 12404836414SPeter Maydell r = s->clock_force; 12504836414SPeter Maydell break; 12675750e4dSPeter Maydell case A_RESET_SYNDROME: 12775750e4dSPeter Maydell r = s->reset_syndrome; 12875750e4dSPeter Maydell break; 12975750e4dSPeter Maydell case A_RESET_MASK: 13075750e4dSPeter Maydell r = s->reset_mask; 13175750e4dSPeter Maydell break; 13275750e4dSPeter Maydell case A_GRETREG: 13375750e4dSPeter Maydell r = s->gretreg; 13475750e4dSPeter Maydell break; 135394e10d2SPeter Maydell case A_INITSVTOR0: 136394e10d2SPeter Maydell r = s->initsvtor0; 13775750e4dSPeter Maydell break; 13804836414SPeter Maydell case A_INITSVTOR1: 13904836414SPeter Maydell if (!s->is_sse200) { 14004836414SPeter Maydell goto bad_offset; 14104836414SPeter Maydell } 14204836414SPeter Maydell r = s->initsvtor1; 14304836414SPeter Maydell break; 14475750e4dSPeter Maydell case A_CPUWAIT: 14575750e4dSPeter Maydell r = s->cpuwait; 14675750e4dSPeter Maydell break; 14704836414SPeter Maydell case A_NMI_ENABLE: 14804836414SPeter Maydell /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */ 14904836414SPeter Maydell if (!s->is_sse200) { 15075750e4dSPeter Maydell r = 0; 15175750e4dSPeter Maydell break; 15204836414SPeter Maydell } 15304836414SPeter Maydell r = s->nmi_enable; 15404836414SPeter Maydell break; 15575750e4dSPeter Maydell case A_WICCTRL: 15675750e4dSPeter Maydell r = s->wicctrl; 15775750e4dSPeter Maydell break; 15804836414SPeter Maydell case A_EWCTRL: 15904836414SPeter Maydell if (!s->is_sse200) { 16004836414SPeter Maydell goto bad_offset; 16104836414SPeter Maydell } 16204836414SPeter Maydell r = s->ewctrl; 16304836414SPeter Maydell break; 16404836414SPeter Maydell case A_PDCM_PD_SYS_SENSE: 16504836414SPeter Maydell if (!s->is_sse200) { 16604836414SPeter Maydell goto bad_offset; 16704836414SPeter Maydell } 16804836414SPeter Maydell r = s->pdcm_pd_sys_sense; 16904836414SPeter Maydell break; 17004836414SPeter Maydell case A_PDCM_PD_SRAM0_SENSE: 17104836414SPeter Maydell if (!s->is_sse200) { 17204836414SPeter Maydell goto bad_offset; 17304836414SPeter Maydell } 17404836414SPeter Maydell r = s->pdcm_pd_sram0_sense; 17504836414SPeter Maydell break; 17604836414SPeter Maydell case A_PDCM_PD_SRAM1_SENSE: 17704836414SPeter Maydell if (!s->is_sse200) { 17804836414SPeter Maydell goto bad_offset; 17904836414SPeter Maydell } 18004836414SPeter Maydell r = s->pdcm_pd_sram1_sense; 18104836414SPeter Maydell break; 18204836414SPeter Maydell case A_PDCM_PD_SRAM2_SENSE: 18304836414SPeter Maydell if (!s->is_sse200) { 18404836414SPeter Maydell goto bad_offset; 18504836414SPeter Maydell } 18604836414SPeter Maydell r = s->pdcm_pd_sram2_sense; 18704836414SPeter Maydell break; 18804836414SPeter Maydell case A_PDCM_PD_SRAM3_SENSE: 18904836414SPeter Maydell if (!s->is_sse200) { 19004836414SPeter Maydell goto bad_offset; 19104836414SPeter Maydell } 19204836414SPeter Maydell r = s->pdcm_pd_sram3_sense; 19304836414SPeter Maydell break; 19475750e4dSPeter Maydell case A_PID4 ... A_CID3: 19575750e4dSPeter Maydell r = sysctl_id[(offset - A_PID4) / 4]; 19675750e4dSPeter Maydell break; 19775750e4dSPeter Maydell case A_SECDBGSET: 19875750e4dSPeter Maydell case A_SECDBGCLR: 19975750e4dSPeter Maydell case A_SWRESET: 20075750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 20175750e4dSPeter Maydell "IoTKit SysCtl read: read of WO offset %x\n", 20275750e4dSPeter Maydell (int)offset); 20375750e4dSPeter Maydell r = 0; 20475750e4dSPeter Maydell break; 20575750e4dSPeter Maydell default: 20604836414SPeter Maydell bad_offset: 20775750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 20875750e4dSPeter Maydell "IoTKit SysCtl read: bad offset %x\n", (int)offset); 20975750e4dSPeter Maydell r = 0; 21075750e4dSPeter Maydell break; 21175750e4dSPeter Maydell } 21275750e4dSPeter Maydell trace_iotkit_sysctl_read(offset, r, size); 21375750e4dSPeter Maydell return r; 21475750e4dSPeter Maydell } 21575750e4dSPeter Maydell 21675750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset, 21775750e4dSPeter Maydell uint64_t value, unsigned size) 21875750e4dSPeter Maydell { 21975750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 22075750e4dSPeter Maydell 22175750e4dSPeter Maydell trace_iotkit_sysctl_write(offset, value, size); 22275750e4dSPeter Maydell 22375750e4dSPeter Maydell /* 22475750e4dSPeter Maydell * Most of the state here has to do with control of reset and 22575750e4dSPeter Maydell * similar kinds of power up -- for instance the guest can ask 22675750e4dSPeter Maydell * what the reason for the last reset was, or forbid reset for 22775750e4dSPeter Maydell * some causes (like the non-secure watchdog). Most of this is 22875750e4dSPeter Maydell * not relevant to QEMU, which doesn't really model anything other 22975750e4dSPeter Maydell * than a full power-on reset. 23075750e4dSPeter Maydell * We just model the registers as reads-as-written. 23175750e4dSPeter Maydell */ 23275750e4dSPeter Maydell 23375750e4dSPeter Maydell switch (offset) { 23475750e4dSPeter Maydell case A_RESET_SYNDROME: 23575750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, 23675750e4dSPeter Maydell "IoTKit SysCtl RESET_SYNDROME unimplemented\n"); 23775750e4dSPeter Maydell s->reset_syndrome = value; 23875750e4dSPeter Maydell break; 23975750e4dSPeter Maydell case A_RESET_MASK: 24075750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n"); 24175750e4dSPeter Maydell s->reset_mask = value; 24275750e4dSPeter Maydell break; 24375750e4dSPeter Maydell case A_GRETREG: 24475750e4dSPeter Maydell /* 24575750e4dSPeter Maydell * General retention register, which is only reset by a power-on 24675750e4dSPeter Maydell * reset. Technically this implementation is complete, since 24775750e4dSPeter Maydell * QEMU only supports power-on resets... 24875750e4dSPeter Maydell */ 24975750e4dSPeter Maydell s->gretreg = value; 25075750e4dSPeter Maydell break; 251394e10d2SPeter Maydell case A_INITSVTOR0: 252394e10d2SPeter Maydell s->initsvtor0 = value; 2530f862986SPeter Maydell set_init_vtor(0, s->initsvtor0); 25475750e4dSPeter Maydell break; 25575750e4dSPeter Maydell case A_CPUWAIT: 2560f862986SPeter Maydell if ((s->cpuwait & 1) && !(value & 1)) { 2570f862986SPeter Maydell /* Powering up CPU 0 */ 2580f862986SPeter Maydell arm_set_cpu_on_and_reset(0); 2590f862986SPeter Maydell } 2600f862986SPeter Maydell if ((s->cpuwait & 2) && !(value & 2)) { 2610f862986SPeter Maydell /* Powering up CPU 1 */ 2620f862986SPeter Maydell arm_set_cpu_on_and_reset(1); 2630f862986SPeter Maydell } 26475750e4dSPeter Maydell s->cpuwait = value; 26575750e4dSPeter Maydell break; 26675750e4dSPeter Maydell case A_WICCTRL: 26775750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n"); 26875750e4dSPeter Maydell s->wicctrl = value; 26975750e4dSPeter Maydell break; 27075750e4dSPeter Maydell case A_SECDBGSET: 27175750e4dSPeter Maydell /* write-1-to-set */ 27275750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n"); 27375750e4dSPeter Maydell s->secure_debug |= value; 27475750e4dSPeter Maydell break; 27575750e4dSPeter Maydell case A_SECDBGCLR: 27675750e4dSPeter Maydell /* write-1-to-clear */ 27775750e4dSPeter Maydell s->secure_debug &= ~value; 27875750e4dSPeter Maydell break; 27975750e4dSPeter Maydell case A_SWRESET: 28075750e4dSPeter Maydell /* One w/o bit to request a reset; all other bits reserved */ 28175750e4dSPeter Maydell if (value & R_SWRESET_SWRESETREQ_MASK) { 28275750e4dSPeter Maydell qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 28375750e4dSPeter Maydell } 28475750e4dSPeter Maydell break; 28504836414SPeter Maydell case A_SCSECCTRL: 28604836414SPeter Maydell if (!s->is_sse200) { 28704836414SPeter Maydell goto bad_offset; 28804836414SPeter Maydell } 28904836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n"); 29004836414SPeter Maydell s->scsecctrl = value; 29104836414SPeter Maydell break; 29204836414SPeter Maydell case A_FCLK_DIV: 29304836414SPeter Maydell if (!s->is_sse200) { 29404836414SPeter Maydell goto bad_offset; 29504836414SPeter Maydell } 29604836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n"); 29704836414SPeter Maydell s->fclk_div = value; 29804836414SPeter Maydell break; 29904836414SPeter Maydell case A_SYSCLK_DIV: 30004836414SPeter Maydell if (!s->is_sse200) { 30104836414SPeter Maydell goto bad_offset; 30204836414SPeter Maydell } 30304836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n"); 30404836414SPeter Maydell s->sysclk_div = value; 30504836414SPeter Maydell break; 30604836414SPeter Maydell case A_CLOCK_FORCE: 30704836414SPeter Maydell if (!s->is_sse200) { 30804836414SPeter Maydell goto bad_offset; 30904836414SPeter Maydell } 31004836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n"); 31104836414SPeter Maydell s->clock_force = value; 31204836414SPeter Maydell break; 31304836414SPeter Maydell case A_INITSVTOR1: 31404836414SPeter Maydell if (!s->is_sse200) { 31504836414SPeter Maydell goto bad_offset; 31604836414SPeter Maydell } 31704836414SPeter Maydell s->initsvtor1 = value; 3180f862986SPeter Maydell set_init_vtor(1, s->initsvtor1); 31904836414SPeter Maydell break; 32004836414SPeter Maydell case A_EWCTRL: 32104836414SPeter Maydell if (!s->is_sse200) { 32204836414SPeter Maydell goto bad_offset; 32304836414SPeter Maydell } 32404836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n"); 32504836414SPeter Maydell s->ewctrl = value; 32604836414SPeter Maydell break; 32704836414SPeter Maydell case A_PDCM_PD_SYS_SENSE: 32804836414SPeter Maydell if (!s->is_sse200) { 32904836414SPeter Maydell goto bad_offset; 33004836414SPeter Maydell } 33104836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 33204836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n"); 33304836414SPeter Maydell s->pdcm_pd_sys_sense = value; 33404836414SPeter Maydell break; 33504836414SPeter Maydell case A_PDCM_PD_SRAM0_SENSE: 33604836414SPeter Maydell if (!s->is_sse200) { 33704836414SPeter Maydell goto bad_offset; 33804836414SPeter Maydell } 33904836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 34004836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n"); 34104836414SPeter Maydell s->pdcm_pd_sram0_sense = value; 34204836414SPeter Maydell break; 34304836414SPeter Maydell case A_PDCM_PD_SRAM1_SENSE: 34404836414SPeter Maydell if (!s->is_sse200) { 34504836414SPeter Maydell goto bad_offset; 34604836414SPeter Maydell } 34704836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 34804836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n"); 34904836414SPeter Maydell s->pdcm_pd_sram1_sense = value; 35004836414SPeter Maydell break; 35104836414SPeter Maydell case A_PDCM_PD_SRAM2_SENSE: 35204836414SPeter Maydell if (!s->is_sse200) { 35304836414SPeter Maydell goto bad_offset; 35404836414SPeter Maydell } 35504836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 35604836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n"); 35704836414SPeter Maydell s->pdcm_pd_sram2_sense = value; 35804836414SPeter Maydell break; 35904836414SPeter Maydell case A_PDCM_PD_SRAM3_SENSE: 36004836414SPeter Maydell if (!s->is_sse200) { 36104836414SPeter Maydell goto bad_offset; 36204836414SPeter Maydell } 36304836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 36404836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n"); 36504836414SPeter Maydell s->pdcm_pd_sram3_sense = value; 36604836414SPeter Maydell break; 36704836414SPeter Maydell case A_NMI_ENABLE: 36804836414SPeter Maydell /* In IoTKit this is BUSWAIT: reserved, R/O, zero */ 36904836414SPeter Maydell if (!s->is_sse200) { 37004836414SPeter Maydell goto ro_offset; 37104836414SPeter Maydell } 37204836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n"); 37304836414SPeter Maydell s->nmi_enable = value; 37404836414SPeter Maydell break; 37575750e4dSPeter Maydell case A_SECDBGSTAT: 37675750e4dSPeter Maydell case A_PID4 ... A_CID3: 37704836414SPeter Maydell ro_offset: 37875750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 37975750e4dSPeter Maydell "IoTKit SysCtl write: write of RO offset %x\n", 38075750e4dSPeter Maydell (int)offset); 38175750e4dSPeter Maydell break; 38275750e4dSPeter Maydell default: 38304836414SPeter Maydell bad_offset: 38475750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 38575750e4dSPeter Maydell "IoTKit SysCtl write: bad offset %x\n", (int)offset); 38675750e4dSPeter Maydell break; 38775750e4dSPeter Maydell } 38875750e4dSPeter Maydell } 38975750e4dSPeter Maydell 39075750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = { 39175750e4dSPeter Maydell .read = iotkit_sysctl_read, 39275750e4dSPeter Maydell .write = iotkit_sysctl_write, 39375750e4dSPeter Maydell .endianness = DEVICE_LITTLE_ENDIAN, 39475750e4dSPeter Maydell /* byte/halfword accesses are just zero-padded on reads and writes */ 39575750e4dSPeter Maydell .impl.min_access_size = 4, 39675750e4dSPeter Maydell .impl.max_access_size = 4, 39775750e4dSPeter Maydell .valid.min_access_size = 1, 39875750e4dSPeter Maydell .valid.max_access_size = 4, 39975750e4dSPeter Maydell }; 40075750e4dSPeter Maydell 40175750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev) 40275750e4dSPeter Maydell { 40375750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(dev); 40475750e4dSPeter Maydell 40575750e4dSPeter Maydell trace_iotkit_sysctl_reset(); 40675750e4dSPeter Maydell s->secure_debug = 0; 40775750e4dSPeter Maydell s->reset_syndrome = 1; 40875750e4dSPeter Maydell s->reset_mask = 0; 40975750e4dSPeter Maydell s->gretreg = 0; 410aab7a378SPeter Maydell s->initsvtor0 = s->initsvtor0_rst; 411aab7a378SPeter Maydell s->initsvtor1 = s->initsvtor1_rst; 412aab7a378SPeter Maydell s->cpuwait = s->cpuwait_rst; 41375750e4dSPeter Maydell s->wicctrl = 0; 41404836414SPeter Maydell s->scsecctrl = 0; 41504836414SPeter Maydell s->fclk_div = 0; 41604836414SPeter Maydell s->sysclk_div = 0; 41704836414SPeter Maydell s->clock_force = 0; 41804836414SPeter Maydell s->nmi_enable = 0; 41904836414SPeter Maydell s->ewctrl = 0; 42004836414SPeter Maydell s->pdcm_pd_sys_sense = 0x7f; 42104836414SPeter Maydell s->pdcm_pd_sram0_sense = 0; 42204836414SPeter Maydell s->pdcm_pd_sram1_sense = 0; 42304836414SPeter Maydell s->pdcm_pd_sram2_sense = 0; 42404836414SPeter Maydell s->pdcm_pd_sram3_sense = 0; 42575750e4dSPeter Maydell } 42675750e4dSPeter Maydell 42775750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj) 42875750e4dSPeter Maydell { 42975750e4dSPeter Maydell SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 43075750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(obj); 43175750e4dSPeter Maydell 43275750e4dSPeter Maydell memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops, 43375750e4dSPeter Maydell s, "iotkit-sysctl", 0x1000); 43475750e4dSPeter Maydell sysbus_init_mmio(sbd, &s->iomem); 43575750e4dSPeter Maydell } 43675750e4dSPeter Maydell 43704836414SPeter Maydell static void iotkit_sysctl_realize(DeviceState *dev, Error **errp) 43804836414SPeter Maydell { 43904836414SPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(dev); 44004836414SPeter Maydell 44104836414SPeter Maydell /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */ 44204836414SPeter Maydell if (extract32(s->sys_version, 28, 4) == 2) { 44304836414SPeter Maydell s->is_sse200 = true; 44404836414SPeter Maydell } 44504836414SPeter Maydell } 44604836414SPeter Maydell 44704836414SPeter Maydell static bool sse200_needed(void *opaque) 44804836414SPeter Maydell { 44904836414SPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 45004836414SPeter Maydell 45104836414SPeter Maydell return s->is_sse200; 45204836414SPeter Maydell } 45304836414SPeter Maydell 45404836414SPeter Maydell static const VMStateDescription iotkit_sysctl_sse200_vmstate = { 45504836414SPeter Maydell .name = "iotkit-sysctl/sse-200", 45604836414SPeter Maydell .version_id = 1, 45704836414SPeter Maydell .minimum_version_id = 1, 45804836414SPeter Maydell .needed = sse200_needed, 45904836414SPeter Maydell .fields = (VMStateField[]) { 46004836414SPeter Maydell VMSTATE_UINT32(scsecctrl, IoTKitSysCtl), 46104836414SPeter Maydell VMSTATE_UINT32(fclk_div, IoTKitSysCtl), 46204836414SPeter Maydell VMSTATE_UINT32(sysclk_div, IoTKitSysCtl), 46304836414SPeter Maydell VMSTATE_UINT32(clock_force, IoTKitSysCtl), 46404836414SPeter Maydell VMSTATE_UINT32(initsvtor1, IoTKitSysCtl), 46504836414SPeter Maydell VMSTATE_UINT32(nmi_enable, IoTKitSysCtl), 46604836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl), 46704836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl), 46804836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl), 46904836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl), 47004836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl), 47104836414SPeter Maydell VMSTATE_END_OF_LIST() 47204836414SPeter Maydell } 47304836414SPeter Maydell }; 47404836414SPeter Maydell 47575750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = { 47675750e4dSPeter Maydell .name = "iotkit-sysctl", 47775750e4dSPeter Maydell .version_id = 1, 47875750e4dSPeter Maydell .minimum_version_id = 1, 47975750e4dSPeter Maydell .fields = (VMStateField[]) { 48075750e4dSPeter Maydell VMSTATE_UINT32(secure_debug, IoTKitSysCtl), 48175750e4dSPeter Maydell VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl), 48275750e4dSPeter Maydell VMSTATE_UINT32(reset_mask, IoTKitSysCtl), 48375750e4dSPeter Maydell VMSTATE_UINT32(gretreg, IoTKitSysCtl), 484394e10d2SPeter Maydell VMSTATE_UINT32(initsvtor0, IoTKitSysCtl), 48575750e4dSPeter Maydell VMSTATE_UINT32(cpuwait, IoTKitSysCtl), 48675750e4dSPeter Maydell VMSTATE_UINT32(wicctrl, IoTKitSysCtl), 48775750e4dSPeter Maydell VMSTATE_END_OF_LIST() 48804836414SPeter Maydell }, 48904836414SPeter Maydell .subsections = (const VMStateDescription*[]) { 49004836414SPeter Maydell &iotkit_sysctl_sse200_vmstate, 49104836414SPeter Maydell NULL 49275750e4dSPeter Maydell } 49375750e4dSPeter Maydell }; 49475750e4dSPeter Maydell 49504836414SPeter Maydell static Property iotkit_sysctl_props[] = { 49604836414SPeter Maydell DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0), 497aab7a378SPeter Maydell DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0), 498aab7a378SPeter Maydell DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst, 499aab7a378SPeter Maydell 0x10000000), 500aab7a378SPeter Maydell DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst, 501aab7a378SPeter Maydell 0x10000000), 50204836414SPeter Maydell DEFINE_PROP_END_OF_LIST() 50304836414SPeter Maydell }; 50404836414SPeter Maydell 50575750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data) 50675750e4dSPeter Maydell { 50775750e4dSPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 50875750e4dSPeter Maydell 50975750e4dSPeter Maydell dc->vmsd = &iotkit_sysctl_vmstate; 51075750e4dSPeter Maydell dc->reset = iotkit_sysctl_reset; 511*4f67d30bSMarc-André Lureau device_class_set_props(dc, iotkit_sysctl_props); 51204836414SPeter Maydell dc->realize = iotkit_sysctl_realize; 51375750e4dSPeter Maydell } 51475750e4dSPeter Maydell 51575750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = { 51675750e4dSPeter Maydell .name = TYPE_IOTKIT_SYSCTL, 51775750e4dSPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 51875750e4dSPeter Maydell .instance_size = sizeof(IoTKitSysCtl), 51975750e4dSPeter Maydell .instance_init = iotkit_sysctl_init, 52075750e4dSPeter Maydell .class_init = iotkit_sysctl_class_init, 52175750e4dSPeter Maydell }; 52275750e4dSPeter Maydell 52375750e4dSPeter Maydell static void iotkit_sysctl_register_types(void) 52475750e4dSPeter Maydell { 52575750e4dSPeter Maydell type_register_static(&iotkit_sysctl_info); 52675750e4dSPeter Maydell } 52775750e4dSPeter Maydell 52875750e4dSPeter Maydell type_init(iotkit_sysctl_register_types); 529