xref: /qemu/hw/misc/armsse-cpu-pwrctrl.c (revision e4ea952fb0180e85655e9a93d39a1ad9442f76f2)
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