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" 2075750e4dSPeter Maydell #include "qemu/log.h" 2175750e4dSPeter Maydell #include "trace.h" 2275750e4dSPeter Maydell #include "qapi/error.h" 2375750e4dSPeter Maydell #include "sysemu/sysemu.h" 2475750e4dSPeter Maydell #include "hw/sysbus.h" 2575750e4dSPeter Maydell #include "hw/registerfields.h" 2675750e4dSPeter Maydell #include "hw/misc/iotkit-sysctl.h" 2775750e4dSPeter Maydell 2875750e4dSPeter Maydell REG32(SECDBGSTAT, 0x0) 2975750e4dSPeter Maydell REG32(SECDBGSET, 0x4) 3075750e4dSPeter Maydell REG32(SECDBGCLR, 0x8) 3175750e4dSPeter Maydell REG32(RESET_SYNDROME, 0x100) 3275750e4dSPeter Maydell REG32(RESET_MASK, 0x104) 3375750e4dSPeter Maydell REG32(SWRESET, 0x108) 3475750e4dSPeter Maydell FIELD(SWRESET, SWRESETREQ, 9, 1) 3575750e4dSPeter Maydell REG32(GRETREG, 0x10c) 36*394e10d2SPeter Maydell REG32(INITSVTOR0, 0x110) 3775750e4dSPeter Maydell REG32(CPUWAIT, 0x118) 3875750e4dSPeter Maydell REG32(BUSWAIT, 0x11c) 3975750e4dSPeter Maydell REG32(WICCTRL, 0x120) 4075750e4dSPeter Maydell REG32(PID4, 0xfd0) 4175750e4dSPeter Maydell REG32(PID5, 0xfd4) 4275750e4dSPeter Maydell REG32(PID6, 0xfd8) 4375750e4dSPeter Maydell REG32(PID7, 0xfdc) 4475750e4dSPeter Maydell REG32(PID0, 0xfe0) 4575750e4dSPeter Maydell REG32(PID1, 0xfe4) 4675750e4dSPeter Maydell REG32(PID2, 0xfe8) 4775750e4dSPeter Maydell REG32(PID3, 0xfec) 4875750e4dSPeter Maydell REG32(CID0, 0xff0) 4975750e4dSPeter Maydell REG32(CID1, 0xff4) 5075750e4dSPeter Maydell REG32(CID2, 0xff8) 5175750e4dSPeter Maydell REG32(CID3, 0xffc) 5275750e4dSPeter Maydell 5375750e4dSPeter Maydell /* PID/CID values */ 5475750e4dSPeter Maydell static const int sysctl_id[] = { 5575750e4dSPeter Maydell 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ 5675750e4dSPeter Maydell 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ 5775750e4dSPeter Maydell 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 5875750e4dSPeter Maydell }; 5975750e4dSPeter Maydell 6075750e4dSPeter Maydell static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset, 6175750e4dSPeter Maydell unsigned size) 6275750e4dSPeter Maydell { 6375750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 6475750e4dSPeter Maydell uint64_t r; 6575750e4dSPeter Maydell 6675750e4dSPeter Maydell switch (offset) { 6775750e4dSPeter Maydell case A_SECDBGSTAT: 6875750e4dSPeter Maydell r = s->secure_debug; 6975750e4dSPeter Maydell break; 7075750e4dSPeter Maydell case A_RESET_SYNDROME: 7175750e4dSPeter Maydell r = s->reset_syndrome; 7275750e4dSPeter Maydell break; 7375750e4dSPeter Maydell case A_RESET_MASK: 7475750e4dSPeter Maydell r = s->reset_mask; 7575750e4dSPeter Maydell break; 7675750e4dSPeter Maydell case A_GRETREG: 7775750e4dSPeter Maydell r = s->gretreg; 7875750e4dSPeter Maydell break; 79*394e10d2SPeter Maydell case A_INITSVTOR0: 80*394e10d2SPeter Maydell r = s->initsvtor0; 8175750e4dSPeter Maydell break; 8275750e4dSPeter Maydell case A_CPUWAIT: 8375750e4dSPeter Maydell r = s->cpuwait; 8475750e4dSPeter Maydell break; 8575750e4dSPeter Maydell case A_BUSWAIT: 8675750e4dSPeter Maydell /* In IoTKit BUSWAIT is reserved, R/O, zero */ 8775750e4dSPeter Maydell r = 0; 8875750e4dSPeter Maydell break; 8975750e4dSPeter Maydell case A_WICCTRL: 9075750e4dSPeter Maydell r = s->wicctrl; 9175750e4dSPeter Maydell break; 9275750e4dSPeter Maydell case A_PID4 ... A_CID3: 9375750e4dSPeter Maydell r = sysctl_id[(offset - A_PID4) / 4]; 9475750e4dSPeter Maydell break; 9575750e4dSPeter Maydell case A_SECDBGSET: 9675750e4dSPeter Maydell case A_SECDBGCLR: 9775750e4dSPeter Maydell case A_SWRESET: 9875750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 9975750e4dSPeter Maydell "IoTKit SysCtl read: read of WO offset %x\n", 10075750e4dSPeter Maydell (int)offset); 10175750e4dSPeter Maydell r = 0; 10275750e4dSPeter Maydell break; 10375750e4dSPeter Maydell default: 10475750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 10575750e4dSPeter Maydell "IoTKit SysCtl read: bad offset %x\n", (int)offset); 10675750e4dSPeter Maydell r = 0; 10775750e4dSPeter Maydell break; 10875750e4dSPeter Maydell } 10975750e4dSPeter Maydell trace_iotkit_sysctl_read(offset, r, size); 11075750e4dSPeter Maydell return r; 11175750e4dSPeter Maydell } 11275750e4dSPeter Maydell 11375750e4dSPeter Maydell static void iotkit_sysctl_write(void *opaque, hwaddr offset, 11475750e4dSPeter Maydell uint64_t value, unsigned size) 11575750e4dSPeter Maydell { 11675750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque); 11775750e4dSPeter Maydell 11875750e4dSPeter Maydell trace_iotkit_sysctl_write(offset, value, size); 11975750e4dSPeter Maydell 12075750e4dSPeter Maydell /* 12175750e4dSPeter Maydell * Most of the state here has to do with control of reset and 12275750e4dSPeter Maydell * similar kinds of power up -- for instance the guest can ask 12375750e4dSPeter Maydell * what the reason for the last reset was, or forbid reset for 12475750e4dSPeter Maydell * some causes (like the non-secure watchdog). Most of this is 12575750e4dSPeter Maydell * not relevant to QEMU, which doesn't really model anything other 12675750e4dSPeter Maydell * than a full power-on reset. 12775750e4dSPeter Maydell * We just model the registers as reads-as-written. 12875750e4dSPeter Maydell */ 12975750e4dSPeter Maydell 13075750e4dSPeter Maydell switch (offset) { 13175750e4dSPeter Maydell case A_RESET_SYNDROME: 13275750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, 13375750e4dSPeter Maydell "IoTKit SysCtl RESET_SYNDROME unimplemented\n"); 13475750e4dSPeter Maydell s->reset_syndrome = value; 13575750e4dSPeter Maydell break; 13675750e4dSPeter Maydell case A_RESET_MASK: 13775750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n"); 13875750e4dSPeter Maydell s->reset_mask = value; 13975750e4dSPeter Maydell break; 14075750e4dSPeter Maydell case A_GRETREG: 14175750e4dSPeter Maydell /* 14275750e4dSPeter Maydell * General retention register, which is only reset by a power-on 14375750e4dSPeter Maydell * reset. Technically this implementation is complete, since 14475750e4dSPeter Maydell * QEMU only supports power-on resets... 14575750e4dSPeter Maydell */ 14675750e4dSPeter Maydell s->gretreg = value; 14775750e4dSPeter Maydell break; 148*394e10d2SPeter Maydell case A_INITSVTOR0: 149*394e10d2SPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVTOR0 unimplemented\n"); 150*394e10d2SPeter Maydell s->initsvtor0 = value; 15175750e4dSPeter Maydell break; 15275750e4dSPeter Maydell case A_CPUWAIT: 15375750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n"); 15475750e4dSPeter Maydell s->cpuwait = value; 15575750e4dSPeter Maydell break; 15675750e4dSPeter Maydell case A_WICCTRL: 15775750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n"); 15875750e4dSPeter Maydell s->wicctrl = value; 15975750e4dSPeter Maydell break; 16075750e4dSPeter Maydell case A_SECDBGSET: 16175750e4dSPeter Maydell /* write-1-to-set */ 16275750e4dSPeter Maydell qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n"); 16375750e4dSPeter Maydell s->secure_debug |= value; 16475750e4dSPeter Maydell break; 16575750e4dSPeter Maydell case A_SECDBGCLR: 16675750e4dSPeter Maydell /* write-1-to-clear */ 16775750e4dSPeter Maydell s->secure_debug &= ~value; 16875750e4dSPeter Maydell break; 16975750e4dSPeter Maydell case A_SWRESET: 17075750e4dSPeter Maydell /* One w/o bit to request a reset; all other bits reserved */ 17175750e4dSPeter Maydell if (value & R_SWRESET_SWRESETREQ_MASK) { 17275750e4dSPeter Maydell qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 17375750e4dSPeter Maydell } 17475750e4dSPeter Maydell break; 17575750e4dSPeter Maydell case A_BUSWAIT: /* In IoTKit BUSWAIT is reserved, R/O, zero */ 17675750e4dSPeter Maydell case A_SECDBGSTAT: 17775750e4dSPeter Maydell case A_PID4 ... A_CID3: 17875750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 17975750e4dSPeter Maydell "IoTKit SysCtl write: write of RO offset %x\n", 18075750e4dSPeter Maydell (int)offset); 18175750e4dSPeter Maydell break; 18275750e4dSPeter Maydell default: 18375750e4dSPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 18475750e4dSPeter Maydell "IoTKit SysCtl write: bad offset %x\n", (int)offset); 18575750e4dSPeter Maydell break; 18675750e4dSPeter Maydell } 18775750e4dSPeter Maydell } 18875750e4dSPeter Maydell 18975750e4dSPeter Maydell static const MemoryRegionOps iotkit_sysctl_ops = { 19075750e4dSPeter Maydell .read = iotkit_sysctl_read, 19175750e4dSPeter Maydell .write = iotkit_sysctl_write, 19275750e4dSPeter Maydell .endianness = DEVICE_LITTLE_ENDIAN, 19375750e4dSPeter Maydell /* byte/halfword accesses are just zero-padded on reads and writes */ 19475750e4dSPeter Maydell .impl.min_access_size = 4, 19575750e4dSPeter Maydell .impl.max_access_size = 4, 19675750e4dSPeter Maydell .valid.min_access_size = 1, 19775750e4dSPeter Maydell .valid.max_access_size = 4, 19875750e4dSPeter Maydell }; 19975750e4dSPeter Maydell 20075750e4dSPeter Maydell static void iotkit_sysctl_reset(DeviceState *dev) 20175750e4dSPeter Maydell { 20275750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(dev); 20375750e4dSPeter Maydell 20475750e4dSPeter Maydell trace_iotkit_sysctl_reset(); 20575750e4dSPeter Maydell s->secure_debug = 0; 20675750e4dSPeter Maydell s->reset_syndrome = 1; 20775750e4dSPeter Maydell s->reset_mask = 0; 20875750e4dSPeter Maydell s->gretreg = 0; 209*394e10d2SPeter Maydell s->initsvtor0 = 0x10000000; 21075750e4dSPeter Maydell s->cpuwait = 0; 21175750e4dSPeter Maydell s->wicctrl = 0; 21275750e4dSPeter Maydell } 21375750e4dSPeter Maydell 21475750e4dSPeter Maydell static void iotkit_sysctl_init(Object *obj) 21575750e4dSPeter Maydell { 21675750e4dSPeter Maydell SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 21775750e4dSPeter Maydell IoTKitSysCtl *s = IOTKIT_SYSCTL(obj); 21875750e4dSPeter Maydell 21975750e4dSPeter Maydell memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops, 22075750e4dSPeter Maydell s, "iotkit-sysctl", 0x1000); 22175750e4dSPeter Maydell sysbus_init_mmio(sbd, &s->iomem); 22275750e4dSPeter Maydell } 22375750e4dSPeter Maydell 22475750e4dSPeter Maydell static const VMStateDescription iotkit_sysctl_vmstate = { 22575750e4dSPeter Maydell .name = "iotkit-sysctl", 22675750e4dSPeter Maydell .version_id = 1, 22775750e4dSPeter Maydell .minimum_version_id = 1, 22875750e4dSPeter Maydell .fields = (VMStateField[]) { 22975750e4dSPeter Maydell VMSTATE_UINT32(secure_debug, IoTKitSysCtl), 23075750e4dSPeter Maydell VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl), 23175750e4dSPeter Maydell VMSTATE_UINT32(reset_mask, IoTKitSysCtl), 23275750e4dSPeter Maydell VMSTATE_UINT32(gretreg, IoTKitSysCtl), 233*394e10d2SPeter Maydell VMSTATE_UINT32(initsvtor0, IoTKitSysCtl), 23475750e4dSPeter Maydell VMSTATE_UINT32(cpuwait, IoTKitSysCtl), 23575750e4dSPeter Maydell VMSTATE_UINT32(wicctrl, IoTKitSysCtl), 23675750e4dSPeter Maydell VMSTATE_END_OF_LIST() 23775750e4dSPeter Maydell } 23875750e4dSPeter Maydell }; 23975750e4dSPeter Maydell 24075750e4dSPeter Maydell static void iotkit_sysctl_class_init(ObjectClass *klass, void *data) 24175750e4dSPeter Maydell { 24275750e4dSPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 24375750e4dSPeter Maydell 24475750e4dSPeter Maydell dc->vmsd = &iotkit_sysctl_vmstate; 24575750e4dSPeter Maydell dc->reset = iotkit_sysctl_reset; 24675750e4dSPeter Maydell } 24775750e4dSPeter Maydell 24875750e4dSPeter Maydell static const TypeInfo iotkit_sysctl_info = { 24975750e4dSPeter Maydell .name = TYPE_IOTKIT_SYSCTL, 25075750e4dSPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 25175750e4dSPeter Maydell .instance_size = sizeof(IoTKitSysCtl), 25275750e4dSPeter Maydell .instance_init = iotkit_sysctl_init, 25375750e4dSPeter Maydell .class_init = iotkit_sysctl_class_init, 25475750e4dSPeter Maydell }; 25575750e4dSPeter Maydell 25675750e4dSPeter Maydell static void iotkit_sysctl_register_types(void) 25775750e4dSPeter Maydell { 25875750e4dSPeter Maydell type_register_static(&iotkit_sysctl_info); 25975750e4dSPeter Maydell } 26075750e4dSPeter Maydell 26175750e4dSPeter Maydell type_init(iotkit_sysctl_register_types); 262