14239b311SPeter Maydell /* 24239b311SPeter Maydell * Arm SSE CPU PWRCTRL register block 34239b311SPeter Maydell * 44239b311SPeter Maydell * Copyright (c) 2021 Linaro Limited 54239b311SPeter Maydell * Written by Peter Maydell 64239b311SPeter Maydell * 74239b311SPeter Maydell * This program is free software; you can redistribute it and/or modify 84239b311SPeter Maydell * it under the terms of the GNU General Public License version 2 or 94239b311SPeter Maydell * (at your option) any later version. 104239b311SPeter Maydell */ 114239b311SPeter Maydell 124239b311SPeter Maydell /* 134239b311SPeter Maydell * This is a model of the "CPU<N>_PWRCTRL block" which is part of the 144239b311SPeter Maydell * Arm Corstone SSE-300 Example Subsystem and documented in 154239b311SPeter Maydell * https://developer.arm.com/documentation/101773/0000 164239b311SPeter Maydell */ 174239b311SPeter Maydell 184239b311SPeter Maydell #include "qemu/osdep.h" 194239b311SPeter Maydell #include "qemu/log.h" 204239b311SPeter Maydell #include "qemu/module.h" 214239b311SPeter Maydell #include "trace.h" 224239b311SPeter Maydell #include "qapi/error.h" 234239b311SPeter Maydell #include "migration/vmstate.h" 244239b311SPeter Maydell #include "hw/sysbus.h" 254239b311SPeter Maydell #include "hw/registerfields.h" 264239b311SPeter Maydell #include "hw/misc/armsse-cpu-pwrctrl.h" 274239b311SPeter Maydell 284239b311SPeter Maydell REG32(CPUPWRCFG, 0x0) 294239b311SPeter Maydell REG32(PID4, 0xfd0) 304239b311SPeter Maydell REG32(PID5, 0xfd4) 314239b311SPeter Maydell REG32(PID6, 0xfd8) 324239b311SPeter Maydell REG32(PID7, 0xfdc) 334239b311SPeter Maydell REG32(PID0, 0xfe0) 344239b311SPeter Maydell REG32(PID1, 0xfe4) 354239b311SPeter Maydell REG32(PID2, 0xfe8) 364239b311SPeter Maydell REG32(PID3, 0xfec) 374239b311SPeter Maydell REG32(CID0, 0xff0) 384239b311SPeter Maydell REG32(CID1, 0xff4) 394239b311SPeter Maydell REG32(CID2, 0xff8) 404239b311SPeter Maydell REG32(CID3, 0xffc) 414239b311SPeter Maydell 424239b311SPeter Maydell /* PID/CID values */ 434239b311SPeter Maydell static const int cpu_pwrctrl_id[] = { 444239b311SPeter Maydell 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ 454239b311SPeter Maydell 0x5a, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ 464239b311SPeter Maydell 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 474239b311SPeter Maydell }; 484239b311SPeter Maydell 494239b311SPeter Maydell static uint64_t pwrctrl_read(void *opaque, hwaddr offset, unsigned size) 504239b311SPeter Maydell { 514239b311SPeter Maydell ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque); 524239b311SPeter Maydell uint64_t r; 534239b311SPeter Maydell 544239b311SPeter Maydell switch (offset) { 554239b311SPeter Maydell case A_CPUPWRCFG: 564239b311SPeter Maydell r = s->cpupwrcfg; 574239b311SPeter Maydell break; 584239b311SPeter Maydell case A_PID4 ... A_CID3: 594239b311SPeter Maydell r = cpu_pwrctrl_id[(offset - A_PID4) / 4]; 604239b311SPeter Maydell break; 614239b311SPeter Maydell default: 624239b311SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 634239b311SPeter Maydell "SSE CPU_PWRCTRL read: bad offset %x\n", (int)offset); 644239b311SPeter Maydell r = 0; 654239b311SPeter Maydell break; 664239b311SPeter Maydell } 674239b311SPeter Maydell trace_armsse_cpu_pwrctrl_read(offset, r, size); 684239b311SPeter Maydell return r; 694239b311SPeter Maydell } 704239b311SPeter Maydell 714239b311SPeter Maydell static void pwrctrl_write(void *opaque, hwaddr offset, 724239b311SPeter Maydell uint64_t value, unsigned size) 734239b311SPeter Maydell { 744239b311SPeter Maydell ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque); 754239b311SPeter Maydell 764239b311SPeter Maydell trace_armsse_cpu_pwrctrl_write(offset, value, size); 774239b311SPeter Maydell 784239b311SPeter Maydell switch (offset) { 794239b311SPeter Maydell case A_CPUPWRCFG: 804239b311SPeter Maydell qemu_log_mask(LOG_UNIMP, 814239b311SPeter Maydell "SSE CPU_PWRCTRL: CPUPWRCFG unimplemented\n"); 824239b311SPeter Maydell s->cpupwrcfg = value; 834239b311SPeter Maydell break; 844239b311SPeter Maydell default: 854239b311SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 864239b311SPeter Maydell "SSE CPU_PWRCTRL write: bad offset 0x%x\n", (int)offset); 874239b311SPeter Maydell break; 884239b311SPeter Maydell } 894239b311SPeter Maydell } 904239b311SPeter Maydell 914239b311SPeter Maydell static const MemoryRegionOps pwrctrl_ops = { 924239b311SPeter Maydell .read = pwrctrl_read, 934239b311SPeter Maydell .write = pwrctrl_write, 944239b311SPeter Maydell .endianness = DEVICE_LITTLE_ENDIAN, 954239b311SPeter Maydell .impl.min_access_size = 4, 964239b311SPeter Maydell .impl.max_access_size = 4, 974239b311SPeter Maydell .valid.min_access_size = 4, 984239b311SPeter Maydell .valid.max_access_size = 4, 994239b311SPeter Maydell }; 1004239b311SPeter Maydell 1014239b311SPeter Maydell static void pwrctrl_reset(DeviceState *dev) 1024239b311SPeter Maydell { 1034239b311SPeter Maydell ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(dev); 1044239b311SPeter Maydell 1054239b311SPeter Maydell s->cpupwrcfg = 0; 1064239b311SPeter Maydell } 1074239b311SPeter Maydell 1084239b311SPeter Maydell static const VMStateDescription pwrctrl_vmstate = { 1094239b311SPeter Maydell .name = "armsse-cpu-pwrctrl", 1104239b311SPeter Maydell .version_id = 1, 1114239b311SPeter Maydell .minimum_version_id = 1, 112*e4ea952fSRichard Henderson .fields = (const VMStateField[]) { 1134239b311SPeter Maydell VMSTATE_UINT32(cpupwrcfg, ARMSSECPUPwrCtrl), 1144239b311SPeter Maydell VMSTATE_END_OF_LIST() 1154239b311SPeter Maydell }, 1164239b311SPeter Maydell }; 1174239b311SPeter Maydell 1184239b311SPeter Maydell static void pwrctrl_init(Object *obj) 1194239b311SPeter Maydell { 1204239b311SPeter Maydell SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 1214239b311SPeter Maydell ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(obj); 1224239b311SPeter Maydell 1234239b311SPeter Maydell memory_region_init_io(&s->iomem, obj, &pwrctrl_ops, 1244239b311SPeter Maydell s, "armsse-cpu-pwrctrl", 0x1000); 1254239b311SPeter Maydell sysbus_init_mmio(sbd, &s->iomem); 1264239b311SPeter Maydell } 1274239b311SPeter Maydell 1284239b311SPeter Maydell static void pwrctrl_class_init(ObjectClass *klass, void *data) 1294239b311SPeter Maydell { 1304239b311SPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 1314239b311SPeter Maydell 1324239b311SPeter Maydell dc->reset = pwrctrl_reset; 1334239b311SPeter Maydell dc->vmsd = &pwrctrl_vmstate; 1344239b311SPeter Maydell } 1354239b311SPeter Maydell 1364239b311SPeter Maydell static const TypeInfo pwrctrl_info = { 1374239b311SPeter Maydell .name = TYPE_ARMSSE_CPU_PWRCTRL, 1384239b311SPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 1394239b311SPeter Maydell .instance_size = sizeof(ARMSSECPUPwrCtrl), 1404239b311SPeter Maydell .instance_init = pwrctrl_init, 1414239b311SPeter Maydell .class_init = pwrctrl_class_init, 1424239b311SPeter Maydell }; 1434239b311SPeter Maydell 1444239b311SPeter Maydell static void pwrctrl_register_types(void) 1454239b311SPeter Maydell { 1464239b311SPeter Maydell type_register_static(&pwrctrl_info); 1474239b311SPeter Maydell } 1484239b311SPeter Maydell 1494239b311SPeter Maydell type_init(pwrctrl_register_types); 150