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" 22*0b8fa32fSMarkus Armbruster #include "qemu/module.h" 2375750e4dSPeter Maydell #include "trace.h" 2475750e4dSPeter Maydell #include "qapi/error.h" 2575750e4dSPeter Maydell #include "sysemu/sysemu.h" 2675750e4dSPeter Maydell #include "hw/sysbus.h" 2775750e4dSPeter Maydell #include "hw/registerfields.h" 2875750e4dSPeter Maydell #include "hw/misc/iotkit-sysctl.h" 290f862986SPeter Maydell #include "target/arm/arm-powerctl.h" 300f862986SPeter Maydell #include "target/arm/cpu.h" 3175750e4dSPeter Maydell 3275750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0) 3375750e4dSPeter Maydell REG32(SECDBGSET, 0x4) 3475750e4dSPeter Maydell REG32(SECDBGCLR, 0x8) 3504836414SPeter Maydell REG32(SCSECCTRL, 0xc) 3604836414SPeter Maydell REG32(FCLK_DIV, 0x10) 3704836414SPeter Maydell REG32(SYSCLK_DIV, 0x14) 3804836414SPeter Maydell REG32(CLOCK_FORCE, 0x18) 3975750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100) 4075750e4dSPeter Maydell REG32(RESET_MASK, 0x104) 4175750e4dSPeter Maydell REG32(SWRESET, 0x108) 4275750e4dSPeter Maydell FIELD(SWRESET, SWRESETREQ, 9, 1) 4375750e4dSPeter Maydell REG32(GRETREG, 0x10c) 44394e10d2SPeter Maydell REG32(INITSVTOR0, 0x110) 4504836414SPeter Maydell REG32(INITSVTOR1, 0x114) 4675750e4dSPeter Maydell REG32(CPUWAIT, 0x118) 4704836414SPeter Maydell REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */ 4875750e4dSPeter Maydell REG32(WICCTRL, 0x120) 4904836414SPeter Maydell REG32(EWCTRL, 0x124) 5004836414SPeter Maydell REG32(PDCM_PD_SYS_SENSE, 0x200) 5104836414SPeter Maydell REG32(PDCM_PD_SRAM0_SENSE, 0x20c) 5204836414SPeter Maydell REG32(PDCM_PD_SRAM1_SENSE, 0x210) 5304836414SPeter Maydell REG32(PDCM_PD_SRAM2_SENSE, 0x214) 5404836414SPeter Maydell REG32(PDCM_PD_SRAM3_SENSE, 0x218) 5575750e4dSPeter Maydell REG32(PID4, 0xfd0) 5675750e4dSPeter Maydell REG32(PID5, 0xfd4) 5775750e4dSPeter Maydell REG32(PID6, 0xfd8) 5875750e4dSPeter Maydell REG32(PID7, 0xfdc) 5975750e4dSPeter Maydell REG32(PID0, 0xfe0) 6075750e4dSPeter Maydell REG32(PID1, 0xfe4) 6175750e4dSPeter Maydell REG32(PID2, 0xfe8) 6275750e4dSPeter Maydell REG32(PID3, 0xfec) 6375750e4dSPeter Maydell REG32(CID0, 0xff0) 6475750e4dSPeter Maydell REG32(CID1, 0xff4) 6575750e4dSPeter Maydell REG32(CID2, 0xff8) 6675750e4dSPeter Maydell REG32(CID3, 0xffc) 6775750e4dSPeter Maydell 6875750e4dSPeter Maydell /* PID/CID values */ 6975750e4dSPeter Maydell static const int sysctl_id[] = { 7075750e4dSPeter Maydell 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ 7175750e4dSPeter Maydell 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ 7275750e4dSPeter Maydell 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 7375750e4dSPeter Maydell }; 7475750e4dSPeter Maydell 750f862986SPeter Maydell /* 760f862986SPeter Maydell * Set the initial secure vector table offset address for the core. 770f862986SPeter Maydell * This will take effect when the CPU next resets. 780f862986SPeter Maydell */ 790f862986SPeter Maydell static void set_init_vtor(uint64_t cpuid, uint32_t vtor) 800f862986SPeter Maydell { 810f862986SPeter Maydell Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid)); 820f862986SPeter Maydell 830f862986SPeter Maydell if (cpuobj) { 840f862986SPeter Maydell if (object_property_find(cpuobj, "init-svtor", NULL)) { 850f862986SPeter Maydell object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort); 860f862986SPeter Maydell } 870f862986SPeter Maydell } 880f862986SPeter Maydell } 890f862986SPeter Maydell 9075750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset, 9175750e4dSPeter Maydell unsigned size) 9275750e4dSPeter Maydell { 9375750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 9475750e4dSPeter Maydell uint64_t r; 9575750e4dSPeter Maydell 9675750e4dSPeter Maydell switch (offset) { 9775750e4dSPeter Maydell case A_SECDBGSTAT: 9875750e4dSPeter Maydell r = s->secure_debug; 9975750e4dSPeter Maydell break; 10004836414SPeter Maydell case A_SCSECCTRL: 10104836414SPeter Maydell if (!s->is_sse200) { 10204836414SPeter Maydell goto bad_offset; 10304836414SPeter Maydell } 10404836414SPeter Maydell r = s->scsecctrl; 10504836414SPeter Maydell break; 10604836414SPeter Maydell case A_FCLK_DIV: 10704836414SPeter Maydell if (!s->is_sse200) { 10804836414SPeter Maydell goto bad_offset; 10904836414SPeter Maydell } 11004836414SPeter Maydell r = s->fclk_div; 11104836414SPeter Maydell break; 11204836414SPeter Maydell case A_SYSCLK_DIV: 11304836414SPeter Maydell if (!s->is_sse200) { 11404836414SPeter Maydell goto bad_offset; 11504836414SPeter Maydell } 11604836414SPeter Maydell r = s->sysclk_div; 11704836414SPeter Maydell break; 11804836414SPeter Maydell case A_CLOCK_FORCE: 11904836414SPeter Maydell if (!s->is_sse200) { 12004836414SPeter Maydell goto bad_offset; 12104836414SPeter Maydell } 12204836414SPeter Maydell r = s->clock_force; 12304836414SPeter Maydell break; 12475750e4dSPeter Maydell case A_RESET_SYNDROME: 12575750e4dSPeter Maydell r = s->reset_syndrome; 12675750e4dSPeter Maydell break; 12775750e4dSPeter Maydell case A_RESET_MASK: 12875750e4dSPeter Maydell r = s->reset_mask; 12975750e4dSPeter Maydell break; 13075750e4dSPeter Maydell case A_GRETREG: 13175750e4dSPeter Maydell r = s->gretreg; 13275750e4dSPeter Maydell break; 133394e10d2SPeter Maydell case A_INITSVTOR0: 134394e10d2SPeter Maydell r = s->initsvtor0; 13575750e4dSPeter Maydell break; 13604836414SPeter Maydell case A_INITSVTOR1: 13704836414SPeter Maydell if (!s->is_sse200) { 13804836414SPeter Maydell goto bad_offset; 13904836414SPeter Maydell } 14004836414SPeter Maydell r = s->initsvtor1; 14104836414SPeter Maydell break; 14275750e4dSPeter Maydell case A_CPUWAIT: 14375750e4dSPeter Maydell r = s->cpuwait; 14475750e4dSPeter Maydell break; 14504836414SPeter Maydell case A_NMI_ENABLE: 14604836414SPeter Maydell /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */ 14704836414SPeter Maydell if (!s->is_sse200) { 14875750e4dSPeter Maydell r = 0; 14975750e4dSPeter Maydell break; 15004836414SPeter Maydell } 15104836414SPeter Maydell r = s->nmi_enable; 15204836414SPeter Maydell break; 15375750e4dSPeter Maydell case A_WICCTRL: 15475750e4dSPeter Maydell r = s->wicctrl; 15575750e4dSPeter Maydell break; 15604836414SPeter Maydell case A_EWCTRL: 15704836414SPeter Maydell if (!s->is_sse200) { 15804836414SPeter Maydell goto bad_offset; 15904836414SPeter Maydell } 16004836414SPeter Maydell r = s->ewctrl; 16104836414SPeter Maydell break; 16204836414SPeter Maydell case A_PDCM_PD_SYS_SENSE: 16304836414SPeter Maydell if (!s->is_sse200) { 16404836414SPeter Maydell goto bad_offset; 16504836414SPeter Maydell } 16604836414SPeter Maydell r = s->pdcm_pd_sys_sense; 16704836414SPeter Maydell break; 16804836414SPeter Maydell case A_PDCM_PD_SRAM0_SENSE: 16904836414SPeter Maydell if (!s->is_sse200) { 17004836414SPeter Maydell goto bad_offset; 17104836414SPeter Maydell } 17204836414SPeter Maydell r = s->pdcm_pd_sram0_sense; 17304836414SPeter Maydell break; 17404836414SPeter Maydell case A_PDCM_PD_SRAM1_SENSE: 17504836414SPeter Maydell if (!s->is_sse200) { 17604836414SPeter Maydell goto bad_offset; 17704836414SPeter Maydell } 17804836414SPeter Maydell r = s->pdcm_pd_sram1_sense; 17904836414SPeter Maydell break; 18004836414SPeter Maydell case A_PDCM_PD_SRAM2_SENSE: 18104836414SPeter Maydell if (!s->is_sse200) { 18204836414SPeter Maydell goto bad_offset; 18304836414SPeter Maydell } 18404836414SPeter Maydell r = s->pdcm_pd_sram2_sense; 18504836414SPeter Maydell break; 18604836414SPeter Maydell case A_PDCM_PD_SRAM3_SENSE: 18704836414SPeter Maydell if (!s->is_sse200) { 18804836414SPeter Maydell goto bad_offset; 18904836414SPeter Maydell } 19004836414SPeter Maydell r = s->pdcm_pd_sram3_sense; 19104836414SPeter Maydell break; 19275750e4dSPeter Maydell case A_PID4 ... A_CID3: 19375750e4dSPeter Maydell r = sysctl_id[(offset - A_PID4) / 4]; 19475750e4dSPeter Maydell break; 19575750e4dSPeter Maydell case A_SECDBGSET: 19675750e4dSPeter Maydell case A_SECDBGCLR: 19775750e4dSPeter Maydell case A_SWRESET: 19875750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 19975750e4dSPeter Maydell "IoTKit SysCtl read: read of WO offset %x\n", 20075750e4dSPeter Maydell (int)offset); 20175750e4dSPeter Maydell r = 0; 20275750e4dSPeter Maydell break; 20375750e4dSPeter Maydell default: 20404836414SPeter Maydell bad_offset: 20575750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 20675750e4dSPeter Maydell "IoTKit SysCtl read: bad offset %x\n", (int)offset); 20775750e4dSPeter Maydell r = 0; 20875750e4dSPeter Maydell break; 20975750e4dSPeter Maydell } 21075750e4dSPeter Maydell trace_iotkit_sysctl_read(offset, r, size); 21175750e4dSPeter Maydell return r; 21275750e4dSPeter Maydell } 21375750e4dSPeter Maydell 21475750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset, 21575750e4dSPeter Maydell uint64_t value, unsigned size) 21675750e4dSPeter Maydell { 21775750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 21875750e4dSPeter Maydell 21975750e4dSPeter Maydell trace_iotkit_sysctl_write(offset, value, size); 22075750e4dSPeter Maydell 22175750e4dSPeter Maydell /* 22275750e4dSPeter Maydell * Most of the state here has to do with control of reset and 22375750e4dSPeter Maydell * similar kinds of power up -- for instance the guest can ask 22475750e4dSPeter Maydell * what the reason for the last reset was, or forbid reset for 22575750e4dSPeter Maydell * some causes (like the non-secure watchdog). Most of this is 22675750e4dSPeter Maydell * not relevant to QEMU, which doesn't really model anything other 22775750e4dSPeter Maydell * than a full power-on reset. 22875750e4dSPeter Maydell * We just model the registers as reads-as-written. 22975750e4dSPeter Maydell */ 23075750e4dSPeter Maydell 23175750e4dSPeter Maydell switch (offset) { 23275750e4dSPeter Maydell case A_RESET_SYNDROME: 23375750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, 23475750e4dSPeter Maydell "IoTKit SysCtl RESET_SYNDROME unimplemented\n"); 23575750e4dSPeter Maydell s->reset_syndrome = value; 23675750e4dSPeter Maydell break; 23775750e4dSPeter Maydell case A_RESET_MASK: 23875750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n"); 23975750e4dSPeter Maydell s->reset_mask = value; 24075750e4dSPeter Maydell break; 24175750e4dSPeter Maydell case A_GRETREG: 24275750e4dSPeter Maydell /* 24375750e4dSPeter Maydell * General retention register, which is only reset by a power-on 24475750e4dSPeter Maydell * reset. Technically this implementation is complete, since 24575750e4dSPeter Maydell * QEMU only supports power-on resets... 24675750e4dSPeter Maydell */ 24775750e4dSPeter Maydell s->gretreg = value; 24875750e4dSPeter Maydell break; 249394e10d2SPeter Maydell case A_INITSVTOR0: 250394e10d2SPeter Maydell s->initsvtor0 = value; 2510f862986SPeter Maydell set_init_vtor(0, s->initsvtor0); 25275750e4dSPeter Maydell break; 25375750e4dSPeter Maydell case A_CPUWAIT: 2540f862986SPeter Maydell if ((s->cpuwait & 1) && !(value & 1)) { 2550f862986SPeter Maydell /* Powering up CPU 0 */ 2560f862986SPeter Maydell arm_set_cpu_on_and_reset(0); 2570f862986SPeter Maydell } 2580f862986SPeter Maydell if ((s->cpuwait & 2) && !(value & 2)) { 2590f862986SPeter Maydell /* Powering up CPU 1 */ 2600f862986SPeter Maydell arm_set_cpu_on_and_reset(1); 2610f862986SPeter Maydell } 26275750e4dSPeter Maydell s->cpuwait = value; 26375750e4dSPeter Maydell break; 26475750e4dSPeter Maydell case A_WICCTRL: 26575750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n"); 26675750e4dSPeter Maydell s->wicctrl = value; 26775750e4dSPeter Maydell break; 26875750e4dSPeter Maydell case A_SECDBGSET: 26975750e4dSPeter Maydell /* write-1-to-set */ 27075750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n"); 27175750e4dSPeter Maydell s->secure_debug |= value; 27275750e4dSPeter Maydell break; 27375750e4dSPeter Maydell case A_SECDBGCLR: 27475750e4dSPeter Maydell /* write-1-to-clear */ 27575750e4dSPeter Maydell s->secure_debug &= ~value; 27675750e4dSPeter Maydell break; 27775750e4dSPeter Maydell case A_SWRESET: 27875750e4dSPeter Maydell /* One w/o bit to request a reset; all other bits reserved */ 27975750e4dSPeter Maydell if (value & R_SWRESET_SWRESETREQ_MASK) { 28075750e4dSPeter Maydell qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 28175750e4dSPeter Maydell } 28275750e4dSPeter Maydell break; 28304836414SPeter Maydell case A_SCSECCTRL: 28404836414SPeter Maydell if (!s->is_sse200) { 28504836414SPeter Maydell goto bad_offset; 28604836414SPeter Maydell } 28704836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n"); 28804836414SPeter Maydell s->scsecctrl = value; 28904836414SPeter Maydell break; 29004836414SPeter Maydell case A_FCLK_DIV: 29104836414SPeter Maydell if (!s->is_sse200) { 29204836414SPeter Maydell goto bad_offset; 29304836414SPeter Maydell } 29404836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n"); 29504836414SPeter Maydell s->fclk_div = value; 29604836414SPeter Maydell break; 29704836414SPeter Maydell case A_SYSCLK_DIV: 29804836414SPeter Maydell if (!s->is_sse200) { 29904836414SPeter Maydell goto bad_offset; 30004836414SPeter Maydell } 30104836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n"); 30204836414SPeter Maydell s->sysclk_div = value; 30304836414SPeter Maydell break; 30404836414SPeter Maydell case A_CLOCK_FORCE: 30504836414SPeter Maydell if (!s->is_sse200) { 30604836414SPeter Maydell goto bad_offset; 30704836414SPeter Maydell } 30804836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n"); 30904836414SPeter Maydell s->clock_force = value; 31004836414SPeter Maydell break; 31104836414SPeter Maydell case A_INITSVTOR1: 31204836414SPeter Maydell if (!s->is_sse200) { 31304836414SPeter Maydell goto bad_offset; 31404836414SPeter Maydell } 31504836414SPeter Maydell s->initsvtor1 = value; 3160f862986SPeter Maydell set_init_vtor(1, s->initsvtor1); 31704836414SPeter Maydell break; 31804836414SPeter Maydell case A_EWCTRL: 31904836414SPeter Maydell if (!s->is_sse200) { 32004836414SPeter Maydell goto bad_offset; 32104836414SPeter Maydell } 32204836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n"); 32304836414SPeter Maydell s->ewctrl = value; 32404836414SPeter Maydell break; 32504836414SPeter Maydell case A_PDCM_PD_SYS_SENSE: 32604836414SPeter Maydell if (!s->is_sse200) { 32704836414SPeter Maydell goto bad_offset; 32804836414SPeter Maydell } 32904836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 33004836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n"); 33104836414SPeter Maydell s->pdcm_pd_sys_sense = value; 33204836414SPeter Maydell break; 33304836414SPeter Maydell case A_PDCM_PD_SRAM0_SENSE: 33404836414SPeter Maydell if (!s->is_sse200) { 33504836414SPeter Maydell goto bad_offset; 33604836414SPeter Maydell } 33704836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 33804836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n"); 33904836414SPeter Maydell s->pdcm_pd_sram0_sense = value; 34004836414SPeter Maydell break; 34104836414SPeter Maydell case A_PDCM_PD_SRAM1_SENSE: 34204836414SPeter Maydell if (!s->is_sse200) { 34304836414SPeter Maydell goto bad_offset; 34404836414SPeter Maydell } 34504836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 34604836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n"); 34704836414SPeter Maydell s->pdcm_pd_sram1_sense = value; 34804836414SPeter Maydell break; 34904836414SPeter Maydell case A_PDCM_PD_SRAM2_SENSE: 35004836414SPeter Maydell if (!s->is_sse200) { 35104836414SPeter Maydell goto bad_offset; 35204836414SPeter Maydell } 35304836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 35404836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n"); 35504836414SPeter Maydell s->pdcm_pd_sram2_sense = value; 35604836414SPeter Maydell break; 35704836414SPeter Maydell case A_PDCM_PD_SRAM3_SENSE: 35804836414SPeter Maydell if (!s->is_sse200) { 35904836414SPeter Maydell goto bad_offset; 36004836414SPeter Maydell } 36104836414SPeter Maydell qemu_log_mask(LOG_UNIMP, 36204836414SPeter Maydell "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n"); 36304836414SPeter Maydell s->pdcm_pd_sram3_sense = value; 36404836414SPeter Maydell break; 36504836414SPeter Maydell case A_NMI_ENABLE: 36604836414SPeter Maydell /* In IoTKit this is BUSWAIT: reserved, R/O, zero */ 36704836414SPeter Maydell if (!s->is_sse200) { 36804836414SPeter Maydell goto ro_offset; 36904836414SPeter Maydell } 37004836414SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n"); 37104836414SPeter Maydell s->nmi_enable = value; 37204836414SPeter Maydell break; 37375750e4dSPeter Maydell case A_SECDBGSTAT: 37475750e4dSPeter Maydell case A_PID4 ... A_CID3: 37504836414SPeter Maydell ro_offset: 37675750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 37775750e4dSPeter Maydell "IoTKit SysCtl write: write of RO offset %x\n", 37875750e4dSPeter Maydell (int)offset); 37975750e4dSPeter Maydell break; 38075750e4dSPeter Maydell default: 38104836414SPeter Maydell bad_offset: 38275750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 38375750e4dSPeter Maydell "IoTKit SysCtl write: bad offset %x\n", (int)offset); 38475750e4dSPeter Maydell break; 38575750e4dSPeter Maydell } 38675750e4dSPeter Maydell } 38775750e4dSPeter Maydell 38875750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = { 38975750e4dSPeter Maydell .read = iotkit_sysctl_read, 39075750e4dSPeter Maydell .write = iotkit_sysctl_write, 39175750e4dSPeter Maydell .endianness = DEVICE_LITTLE_ENDIAN, 39275750e4dSPeter Maydell /* byte/halfword accesses are just zero-padded on reads and writes */ 39375750e4dSPeter Maydell .impl.min_access_size = 4, 39475750e4dSPeter Maydell .impl.max_access_size = 4, 39575750e4dSPeter Maydell .valid.min_access_size = 1, 39675750e4dSPeter Maydell .valid.max_access_size = 4, 39775750e4dSPeter Maydell }; 39875750e4dSPeter Maydell 39975750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev) 40075750e4dSPeter Maydell { 40175750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(dev); 40275750e4dSPeter Maydell 40375750e4dSPeter Maydell trace_iotkit_sysctl_reset(); 40475750e4dSPeter Maydell s->secure_debug = 0; 40575750e4dSPeter Maydell s->reset_syndrome = 1; 40675750e4dSPeter Maydell s->reset_mask = 0; 40775750e4dSPeter Maydell s->gretreg = 0; 408aab7a378SPeter Maydell s->initsvtor0 = s->initsvtor0_rst; 409aab7a378SPeter Maydell s->initsvtor1 = s->initsvtor1_rst; 410aab7a378SPeter Maydell s->cpuwait = s->cpuwait_rst; 41175750e4dSPeter Maydell s->wicctrl = 0; 41204836414SPeter Maydell s->scsecctrl = 0; 41304836414SPeter Maydell s->fclk_div = 0; 41404836414SPeter Maydell s->sysclk_div = 0; 41504836414SPeter Maydell s->clock_force = 0; 41604836414SPeter Maydell s->nmi_enable = 0; 41704836414SPeter Maydell s->ewctrl = 0; 41804836414SPeter Maydell s->pdcm_pd_sys_sense = 0x7f; 41904836414SPeter Maydell s->pdcm_pd_sram0_sense = 0; 42004836414SPeter Maydell s->pdcm_pd_sram1_sense = 0; 42104836414SPeter Maydell s->pdcm_pd_sram2_sense = 0; 42204836414SPeter Maydell s->pdcm_pd_sram3_sense = 0; 42375750e4dSPeter Maydell } 42475750e4dSPeter Maydell 42575750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj) 42675750e4dSPeter Maydell { 42775750e4dSPeter Maydell SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 42875750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(obj); 42975750e4dSPeter Maydell 43075750e4dSPeter Maydell memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops, 43175750e4dSPeter Maydell s, "iotkit-sysctl", 0x1000); 43275750e4dSPeter Maydell sysbus_init_mmio(sbd, &s->iomem); 43375750e4dSPeter Maydell } 43475750e4dSPeter Maydell 43504836414SPeter Maydell static void iotkit_sysctl_realize(DeviceState *dev, Error **errp) 43604836414SPeter Maydell { 43704836414SPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(dev); 43804836414SPeter Maydell 43904836414SPeter Maydell /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */ 44004836414SPeter Maydell if (extract32(s->sys_version, 28, 4) == 2) { 44104836414SPeter Maydell s->is_sse200 = true; 44204836414SPeter Maydell } 44304836414SPeter Maydell } 44404836414SPeter Maydell 44504836414SPeter Maydell static bool sse200_needed(void *opaque) 44604836414SPeter Maydell { 44704836414SPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 44804836414SPeter Maydell 44904836414SPeter Maydell return s->is_sse200; 45004836414SPeter Maydell } 45104836414SPeter Maydell 45204836414SPeter Maydell static const VMStateDescription iotkit_sysctl_sse200_vmstate = { 45304836414SPeter Maydell .name = "iotkit-sysctl/sse-200", 45404836414SPeter Maydell .version_id = 1, 45504836414SPeter Maydell .minimum_version_id = 1, 45604836414SPeter Maydell .needed = sse200_needed, 45704836414SPeter Maydell .fields = (VMStateField[]) { 45804836414SPeter Maydell VMSTATE_UINT32(scsecctrl, IoTKitSysCtl), 45904836414SPeter Maydell VMSTATE_UINT32(fclk_div, IoTKitSysCtl), 46004836414SPeter Maydell VMSTATE_UINT32(sysclk_div, IoTKitSysCtl), 46104836414SPeter Maydell VMSTATE_UINT32(clock_force, IoTKitSysCtl), 46204836414SPeter Maydell VMSTATE_UINT32(initsvtor1, IoTKitSysCtl), 46304836414SPeter Maydell VMSTATE_UINT32(nmi_enable, IoTKitSysCtl), 46404836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl), 46504836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl), 46604836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl), 46704836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl), 46804836414SPeter Maydell VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl), 46904836414SPeter Maydell VMSTATE_END_OF_LIST() 47004836414SPeter Maydell } 47104836414SPeter Maydell }; 47204836414SPeter Maydell 47375750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = { 47475750e4dSPeter Maydell .name = "iotkit-sysctl", 47575750e4dSPeter Maydell .version_id = 1, 47675750e4dSPeter Maydell .minimum_version_id = 1, 47775750e4dSPeter Maydell .fields = (VMStateField[]) { 47875750e4dSPeter Maydell VMSTATE_UINT32(secure_debug, IoTKitSysCtl), 47975750e4dSPeter Maydell VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl), 48075750e4dSPeter Maydell VMSTATE_UINT32(reset_mask, IoTKitSysCtl), 48175750e4dSPeter Maydell VMSTATE_UINT32(gretreg, IoTKitSysCtl), 482394e10d2SPeter Maydell VMSTATE_UINT32(initsvtor0, IoTKitSysCtl), 48375750e4dSPeter Maydell VMSTATE_UINT32(cpuwait, IoTKitSysCtl), 48475750e4dSPeter Maydell VMSTATE_UINT32(wicctrl, IoTKitSysCtl), 48575750e4dSPeter Maydell VMSTATE_END_OF_LIST() 48604836414SPeter Maydell }, 48704836414SPeter Maydell .subsections = (const VMStateDescription*[]) { 48804836414SPeter Maydell &iotkit_sysctl_sse200_vmstate, 48904836414SPeter Maydell NULL 49075750e4dSPeter Maydell } 49175750e4dSPeter Maydell }; 49275750e4dSPeter Maydell 49304836414SPeter Maydell static Property iotkit_sysctl_props[] = { 49404836414SPeter Maydell DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0), 495aab7a378SPeter Maydell DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0), 496aab7a378SPeter Maydell DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst, 497aab7a378SPeter Maydell 0x10000000), 498aab7a378SPeter Maydell DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst, 499aab7a378SPeter Maydell 0x10000000), 50004836414SPeter Maydell DEFINE_PROP_END_OF_LIST() 50104836414SPeter Maydell }; 50204836414SPeter Maydell 50375750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data) 50475750e4dSPeter Maydell { 50575750e4dSPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 50675750e4dSPeter Maydell 50775750e4dSPeter Maydell dc->vmsd = &iotkit_sysctl_vmstate; 50875750e4dSPeter Maydell dc->reset = iotkit_sysctl_reset; 50904836414SPeter Maydell dc->props = iotkit_sysctl_props; 51004836414SPeter Maydell dc->realize = iotkit_sysctl_realize; 51175750e4dSPeter Maydell } 51275750e4dSPeter Maydell 51375750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = { 51475750e4dSPeter Maydell .name = TYPE_IOTKIT_SYSCTL, 51575750e4dSPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 51675750e4dSPeter Maydell .instance_size = sizeof(IoTKitSysCtl), 51775750e4dSPeter Maydell .instance_init = iotkit_sysctl_init, 51875750e4dSPeter Maydell .class_init = iotkit_sysctl_class_init, 51975750e4dSPeter Maydell }; 52075750e4dSPeter Maydell 52175750e4dSPeter Maydell static void iotkit_sysctl_register_types(void) 52275750e4dSPeter Maydell { 52375750e4dSPeter Maydell type_register_static(&iotkit_sysctl_info); 52475750e4dSPeter Maydell } 52575750e4dSPeter Maydell 52675750e4dSPeter Maydell type_init(iotkit_sysctl_register_types); 527