[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 20/44] hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL
From: |
Peter Maydell |
Subject: |
[PATCH 20/44] hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block |
Date: |
Fri, 19 Feb 2021 14:45:53 +0000 |
The SSE-300 has a new register block CPU<N>_PWRCTRL. There is one
instance of this per CPU in the system (so just one for the SSE-300),
and as well as the usual CIDR/PIDR ID registers it has just one
register, CPUPWRCFG. This register allows the guest to configure
behaviour of the system in power-down and deep-sleep states. Since
QEMU does not model those, we make the register a dummy
reads-as-written implementation.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/hw/misc/armsse-cpu-pwrctrl.h | 40 +++++++
hw/misc/armsse-cpu-pwrctrl.c | 149 +++++++++++++++++++++++++++
MAINTAINERS | 2 +
hw/arm/Kconfig | 1 +
hw/misc/Kconfig | 3 +
hw/misc/meson.build | 1 +
hw/misc/trace-events | 4 +
7 files changed, 200 insertions(+)
create mode 100644 include/hw/misc/armsse-cpu-pwrctrl.h
create mode 100644 hw/misc/armsse-cpu-pwrctrl.c
diff --git a/include/hw/misc/armsse-cpu-pwrctrl.h
b/include/hw/misc/armsse-cpu-pwrctrl.h
new file mode 100644
index 00000000000..51d45ede7db
--- /dev/null
+++ b/include/hw/misc/armsse-cpu-pwrctrl.h
@@ -0,0 +1,40 @@
+/*
+ * ARM SSE CPU PWRCTRL register block
+ *
+ * Copyright (c) 2021 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "CPU<N>_PWRCTRL block" which is part of the
+ * Arm Corstone SSE-300 Example Subsystem and documented in
+ * https://developer.arm.com/documentation/101773/0000
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the register bank
+ */
+
+#ifndef HW_MISC_ARMSSE_CPU_PWRCTRL_H
+#define HW_MISC_ARMSSE_CPU_PWRCTRL_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ARMSSE_CPU_PWRCTRL "armsse-cpu-pwrctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUPwrCtrl, ARMSSE_CPU_PWRCTRL)
+
+struct ARMSSECPUPwrCtrl {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t cpupwrcfg;
+};
+
+#endif
diff --git a/hw/misc/armsse-cpu-pwrctrl.c b/hw/misc/armsse-cpu-pwrctrl.c
new file mode 100644
index 00000000000..42fc38879f2
--- /dev/null
+++ b/hw/misc/armsse-cpu-pwrctrl.c
@@ -0,0 +1,149 @@
+/*
+ * Arm SSE CPU PWRCTRL register block
+ *
+ * Copyright (c) 2021 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "CPU<N>_PWRCTRL block" which is part of the
+ * Arm Corstone SSE-300 Example Subsystem and documented in
+ * https://developer.arm.com/documentation/101773/0000
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/misc/armsse-cpu-pwrctrl.h"
+
+REG32(CPUPWRCFG, 0x0)
+REG32(PID4, 0xfd0)
+REG32(PID5, 0xfd4)
+REG32(PID6, 0xfd8)
+REG32(PID7, 0xfdc)
+REG32(PID0, 0xfe0)
+REG32(PID1, 0xfe4)
+REG32(PID2, 0xfe8)
+REG32(PID3, 0xfec)
+REG32(CID0, 0xff0)
+REG32(CID1, 0xff4)
+REG32(CID2, 0xff8)
+REG32(CID3, 0xffc)
+
+/* PID/CID values */
+static const int cpu_pwrctrl_id[] = {
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+ 0x5a, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static uint64_t pwrctrl_read(void *opaque, hwaddr offset, unsigned size)
+{
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
+ uint64_t r;
+
+ switch (offset) {
+ case A_CPUPWRCFG:
+ r = s->cpupwrcfg;
+ break;
+ case A_PID4 ... A_CID3:
+ r = cpu_pwrctrl_id[(offset - A_PID4) / 4];
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE CPU_PWRCTRL read: bad offset %x\n", (int)offset);
+ r = 0;
+ break;
+ }
+ trace_armsse_cpu_pwrctrl_read(offset, r, size);
+ return r;
+}
+
+static void pwrctrl_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
+
+ trace_armsse_cpu_pwrctrl_write(offset, value, size);
+
+ switch (offset) {
+ case A_CPUPWRCFG:
+ qemu_log_mask(LOG_UNIMP,
+ "SSE CPU_PWRCTRL: CPUPWRCFG unimplemented\n");
+ s->cpupwrcfg = value;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "SSE CPU_PWRCTRL write: bad offset 0x%x\n", (int)offset);
+ break;
+ }
+}
+
+static const MemoryRegionOps pwrctrl_ops = {
+ .read = pwrctrl_read,
+ .write = pwrctrl_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static void pwrctrl_reset(DeviceState *dev)
+{
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(dev);
+
+ s->cpupwrcfg = 0;
+}
+
+static const VMStateDescription pwrctrl_vmstate = {
+ .name = "armsse-cpu-pwrctrl",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cpupwrcfg, ARMSSECPUPwrCtrl),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void pwrctrl_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(obj);
+
+ memory_region_init_io(&s->iomem, obj, &pwrctrl_ops,
+ s, "armsse-cpu-pwrctrl", 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void pwrctrl_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = pwrctrl_reset;
+ dc->vmsd = &pwrctrl_vmstate;
+}
+
+static const TypeInfo pwrctrl_info = {
+ .name = TYPE_ARMSSE_CPU_PWRCTRL,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ARMSSECPUPwrCtrl),
+ .instance_init = pwrctrl_init,
+ .class_init = pwrctrl_class_init,
+};
+
+static void pwrctrl_register_types(void)
+{
+ type_register_static(&pwrctrl_info);
+}
+
+type_init(pwrctrl_register_types);
diff --git a/MAINTAINERS b/MAINTAINERS
index df0eddc7170..c2103b40b9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -738,6 +738,8 @@ F: hw/misc/iotkit-sysctl.c
F: include/hw/misc/iotkit-sysctl.h
F: hw/misc/iotkit-sysinfo.c
F: include/hw/misc/iotkit-sysinfo.h
+F: hw/misc/armsse-cpu-pwrctrl.c
+F: include/hw/misc/armsse-cpu-pwrctrl.h
F: hw/misc/armsse-cpuid.c
F: include/hw/misc/armsse-cpuid.h
F: hw/misc/armsse-mhu.c
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 0492b212840..be9adf18594 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -504,6 +504,7 @@ config ARM11MPCORE
config ARMSSE
bool
select ARM_V7M
+ select ARMSSE_CPU_PWRCTRL
select ARMSSE_CPUID
select ARMSSE_MHU
select CMSDK_APB_TIMER
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 16b96e4dafb..5426b9b1a1a 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -8,6 +8,9 @@ config ARMSSE_CPUID
config ARMSSE_MHU
bool
+config ARMSSE_CPU_PWRCTRL
+ bool
+
config MAX111X
bool
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 629283957fc..e30a555db5c 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -96,6 +96,7 @@ softmmu_ss.add(when: 'CONFIG_TZ_MSC', if_true:
files('tz-msc.c'))
softmmu_ss.add(when: 'CONFIG_TZ_PPC', if_true: files('tz-ppc.c'))
softmmu_ss.add(when: 'CONFIG_IOTKIT_SECCTL', if_true: files('iotkit-secctl.c'))
softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true:
files('iotkit-sysinfo.c'))
+softmmu_ss.add(when: 'CONFIG_ARMSSE_CPU_PWRCTRL', if_true:
files('armsse-cpu-pwrctrl.c'))
softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index d626b9d7a7c..4b15db8ca48 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -186,6 +186,10 @@ iotkit_sysctl_read(uint64_t offset, uint64_t data,
unsigned size) "IoTKit SysCtl
iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit
SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
+# armsse-cpu-pwrctrl.c
+armsse_cpu_pwrctrl_read(uint64_t offset, uint64_t data, unsigned size)
"SSE-300 CPU_PWRCTRL read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+armsse_cpu_pwrctrl_write(uint64_t offset, uint64_t data, unsigned size)
"SSE-300 CPU_PWRCTRL write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+
# armsse-cpuid.c
armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200
CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200
CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
--
2.20.1
- [PATCH 07/44] hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values, (continued)
- [PATCH 07/44] hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values, Peter Maydell, 2021/02/19
- [PATCH 11/44] hw/timer/sse-counter: Model the SSE Subsystem System Counter, Peter Maydell, 2021/02/19
- [PATCH 10/44] hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR, Peter Maydell, 2021/02/19
- [PATCH 05/44] hw/arm/armsse: Introduce SSE subsystem version property, Peter Maydell, 2021/02/19
- [PATCH 08/44] hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values, Peter Maydell, 2021/02/19
- [PATCH 09/44] hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300, Peter Maydell, 2021/02/19
- [PATCH 12/44] hw/timer/sse-timer: Model the SSE Subsystem System Timer, Peter Maydell, 2021/02/19
- [PATCH 15/44] hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300, Peter Maydell, 2021/02/19
- [PATCH 17/44] hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers, Peter Maydell, 2021/02/19
- [PATCH 16/44] hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register, Peter Maydell, 2021/02/19
- [PATCH 20/44] hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block,
Peter Maydell <=
- [PATCH 23/44] hw/arm/armsse: Add framework for data-driven device placement, Peter Maydell, 2021/02/19
- [PATCH 18/44] hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values, Peter Maydell, 2021/02/19
- [PATCH 13/44] hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour, Peter Maydell, 2021/02/19
- [PATCH 14/44] hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300, Peter Maydell, 2021/02/19
- [PATCH 26/44] hw/arm/armsse: Move s32ktimer into data-driven framework, Peter Maydell, 2021/02/19
- [PATCH 31/44] hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo, Peter Maydell, 2021/02/19
- [PATCH 22/44] hw/arm/armsse: Add a define for number of IRQs used by the SSE itself, Peter Maydell, 2021/02/19
- [PATCH 21/44] hw/arm/armsse: Use an array for apb_ppc fields in the state structure, Peter Maydell, 2021/02/19