summaryrefslogtreecommitdiffstats
path: root/hw/misc
diff options
context:
space:
mode:
authorPeter Maydell2021-03-10 14:57:31 +0100
committerPeter Maydell2021-03-10 14:57:31 +0100
commit5c6295a45b4fceac913c11abc62488c49c02b9fd (patch)
tree30e5cfdd69dd343a7a6e7dce459c6121fcedb55c /hw/misc
parentMerge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (diff)
parenthw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() (diff)
downloadqemu-5c6295a45b4fceac913c11abc62488c49c02b9fd.tar.gz
qemu-5c6295a45b4fceac913c11abc62488c49c02b9fd.tar.xz
qemu-5c6295a45b4fceac913c11abc62488c49c02b9fd.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210310' into staging
target-arm queue: * Add new mps3-an547 board * target/arm: Restrict v7A TCG cpus to TCG accel * Implement a Xilinx CSU DMA model * hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() # gpg: Signature made Wed 10 Mar 2021 13:56:20 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20210310: (54 commits) hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_ hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips hw/ssi: xilinx_spips: Clean up coding convention issues hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI hw/arm: xlnx-zynqmp: Clean up coding convention issues hw/dma: Implement a Xilinx CSU DMA model target/arm: Restrict v7A TCG cpus to TCG accel tests/qtest/sse-timer-test: Test counter scaling changes tests/qtest/sse-timer-test: Test the system timer tests/qtest/sse-timer-test: Add simple test of the SSE counter docs/system/arm/mps2.rst: Document the new mps3-an547 board hw/arm/mps2-tz: Add new mps3-an547 board hw/arm/mps2-tz: Make initsvtor0 setting board-specific hw/arm/mps2-tz: Support running APB peripherals on different clock hw/misc/mps2-scc: Implement changes for AN547 hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate hw/arm/mps2-tz: Make UART overflow IRQ board-specific hw/arm/armsse: Add SSE-300 support ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/misc')
-rw-r--r--hw/misc/Kconfig9
-rw-r--r--hw/misc/armsse-cpu-pwrctrl.c149
-rw-r--r--hw/misc/bcm2835_cprman.c23
-rw-r--r--hw/misc/iotkit-secctl.c50
-rw-r--r--hw/misc/iotkit-sysctl.c522
-rw-r--r--hw/misc/iotkit-sysinfo.c51
-rw-r--r--hw/misc/meson.build1
-rw-r--r--hw/misc/mps2-fpgaio.c52
-rw-r--r--hw/misc/mps2-scc.c15
-rw-r--r--hw/misc/npcm7xx_clk.c26
-rw-r--r--hw/misc/npcm7xx_pwm.c2
-rw-r--r--hw/misc/trace-events4
-rw-r--r--hw/misc/zynq_slcr.c5
13 files changed, 767 insertions, 142 deletions
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 19c216f3ef..5426b9b1a1 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -2,6 +2,15 @@ config APPLESMC
bool
depends on ISA_BUS
+config ARMSSE_CPUID
+ bool
+
+config ARMSSE_MHU
+ bool
+
+config ARMSSE_CPU_PWRCTRL
+ bool
+
config MAX111X
bool
diff --git a/hw/misc/armsse-cpu-pwrctrl.c b/hw/misc/armsse-cpu-pwrctrl.c
new file mode 100644
index 0000000000..42fc38879f
--- /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/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
index 7e415a017c..75e6c574d4 100644
--- a/hw/misc/bcm2835_cprman.c
+++ b/hw/misc/bcm2835_cprman.c
@@ -107,7 +107,7 @@ static void pll_update(CprmanPllState *pll)
clock_update_hz(pll->out, freq);
}
-static void pll_xosc_update(void *opaque)
+static void pll_xosc_update(void *opaque, ClockEvent event)
{
pll_update(CPRMAN_PLL(opaque));
}
@@ -116,7 +116,8 @@ static void pll_init(Object *obj)
{
CprmanPllState *s = CPRMAN_PLL(obj);
- s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s);
+ s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update,
+ s, ClockUpdate);
s->out = qdev_init_clock_out(DEVICE(s), "out");
}
@@ -209,7 +210,7 @@ static void pll_update_all_channels(BCM2835CprmanState *s,
}
}
-static void pll_channel_pll_in_update(void *opaque)
+static void pll_channel_pll_in_update(void *opaque, ClockEvent event)
{
pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
}
@@ -219,7 +220,8 @@ static void pll_channel_init(Object *obj)
CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
- pll_channel_pll_in_update, s);
+ pll_channel_pll_in_update, s,
+ ClockUpdate);
s->out = qdev_init_clock_out(DEVICE(s), "out");
}
@@ -303,7 +305,7 @@ static void clock_mux_update(CprmanClockMuxState *mux)
clock_update_hz(mux->out, freq);
}
-static void clock_mux_src_update(void *opaque)
+static void clock_mux_src_update(void *opaque, ClockEvent event)
{
CprmanClockMuxState **backref = opaque;
CprmanClockMuxState *s = *backref;
@@ -335,7 +337,8 @@ static void clock_mux_init(Object *obj)
s->backref[i] = s;
s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
clock_mux_src_update,
- &s->backref[i]);
+ &s->backref[i],
+ ClockUpdate);
g_free(name);
}
@@ -380,7 +383,7 @@ static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s)
clock_update(s->out, clock_get(src));
}
-static void dsi0hsck_mux_in_update(void *opaque)
+static void dsi0hsck_mux_in_update(void *opaque, ClockEvent event)
{
dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque));
}
@@ -390,8 +393,10 @@ static void dsi0hsck_mux_init(Object *obj)
CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj);
DeviceState *dev = DEVICE(obj);
- s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, s);
- s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, s);
+ s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update,
+ s, ClockUpdate);
+ s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update,
+ s, ClockUpdate);
s->out = qdev_init_clock_out(DEVICE(s), "out");
}
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
index 9fdb82056a..7b41cfa8fc 100644
--- a/hw/misc/iotkit-secctl.c
+++ b/hw/misc/iotkit-secctl.c
@@ -19,6 +19,8 @@
#include "hw/registerfields.h"
#include "hw/irq.h"
#include "hw/misc/iotkit-secctl.h"
+#include "hw/arm/armsse-version.h"
+#include "hw/qdev-properties.h"
/* Registers in the secure privilege control block */
REG32(SECRESPCFG, 0x10)
@@ -95,6 +97,19 @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
0x0d, 0xf0, 0x05, 0xb1,
};
+static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
+ 0x04, 0x00, 0x00, 0x00,
+ 0x52, 0xb8, 0x2b, 0x00,
+ 0x0d, 0xf0, 0x05, 0xb1,
+};
+
+static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
+ 0x04, 0x00, 0x00, 0x00,
+ 0x53, 0xb8, 0x2b, 0x00,
+ 0x0d, 0xf0, 0x05, 0xb1,
+};
+
+
/* The register sets for the various PPCs (AHB internal, APB internal,
* AHB expansion, APB expansion) are all set up so that they are
* in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
@@ -213,7 +228,14 @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
case A_CID1:
case A_CID2:
case A_CID3:
- r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
+ switch (s->sse_version) {
+ case ARMSSE_SSE300:
+ r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
+ break;
+ default:
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
+ break;
+ }
break;
case A_SECPPCINTCLR:
case A_SECMSCINTCLR:
@@ -473,7 +495,14 @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
case A_CID1:
case A_CID2:
case A_CID3:
- r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
+ switch (s->sse_version) {
+ case ARMSSE_SSE300:
+ r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
+ break;
+ default:
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
+ break;
+ }
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
@@ -710,6 +739,16 @@ static void iotkit_secctl_init(Object *obj)
sysbus_init_mmio(sbd, &s->ns_regs);
}
+static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
+{
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
+
+ if (!armsse_version_valid(s->sse_version)) {
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
+ return;
+ }
+}
+
static const VMStateDescription iotkit_secctl_ppc_vmstate = {
.name = "iotkit-secctl-ppc",
.version_id = 1,
@@ -775,12 +814,19 @@ static const VMStateDescription iotkit_secctl_vmstate = {
},
};
+static Property iotkit_secctl_props[] = {
+ DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &iotkit_secctl_vmstate;
dc->reset = iotkit_secctl_reset;
+ dc->realize = iotkit_secctl_realize;
+ device_class_set_props(dc, iotkit_secctl_props);
}
static const TypeInfo iotkit_secctl_info = {
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index 222511c4b0..9ee8fe8495 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -28,6 +28,7 @@
#include "hw/registerfields.h"
#include "hw/misc/iotkit-sysctl.h"
#include "hw/qdev-properties.h"
+#include "hw/arm/armsse-version.h"
#include "target/arm/arm-powerctl.h"
#include "target/arm/cpu.h"
@@ -44,16 +45,22 @@ REG32(SWRESET, 0x108)
FIELD(SWRESET, SWRESETREQ, 9, 1)
REG32(GRETREG, 0x10c)
REG32(INITSVTOR0, 0x110)
+ FIELD(INITSVTOR0, LOCK, 0, 1)
+ FIELD(INITSVTOR0, VTOR, 7, 25)
REG32(INITSVTOR1, 0x114)
REG32(CPUWAIT, 0x118)
REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
REG32(WICCTRL, 0x120)
REG32(EWCTRL, 0x124)
+REG32(PWRCTRL, 0x1fc)
+ FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
+ FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
REG32(PDCM_PD_SYS_SENSE, 0x200)
+REG32(PDCM_PD_CPU0_SENSE, 0x204)
REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
REG32(PDCM_PD_SRAM1_SENSE, 0x210)
-REG32(PDCM_PD_SRAM2_SENSE, 0x214)
-REG32(PDCM_PD_SRAM3_SENSE, 0x218)
+REG32(PDCM_PD_SRAM2_SENSE, 0x214) /* PDCM_PD_VMR0_SENSE on SSE300 */
+REG32(PDCM_PD_SRAM3_SENSE, 0x218) /* PDCM_PD_VMR1_SENSE on SSE300 */
REG32(PID4, 0xfd0)
REG32(PID5, 0xfd4)
REG32(PID6, 0xfd8)
@@ -68,12 +75,19 @@ REG32(CID2, 0xff8)
REG32(CID3, 0xffc)
/* PID/CID values */
-static const int sysctl_id[] = {
+static const int iotkit_sysctl_id[] = {
0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
+/* Also used by the SSE300 */
+static const int sse200_sysctl_id[] = {
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+ 0x54, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
/*
* Set the initial secure vector table offset address for the core.
* This will take effect when the CPU next resets.
@@ -100,28 +114,52 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->secure_debug;
break;
case A_SCSECCTRL:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ r = s->scsecctrl;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->scsecctrl;
break;
case A_FCLK_DIV:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ r = s->fclk_div;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->fclk_div;
break;
case A_SYSCLK_DIV:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ r = s->sysclk_div;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->sysclk_div;
break;
case A_CLOCK_FORCE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ r = s->clock_force;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->clock_force;
break;
case A_RESET_SYNDROME:
r = s->reset_syndrome;
@@ -136,63 +174,178 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
r = s->initsvtor0;
break;
case A_INITSVTOR1:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ goto bad_offset;
+ case ARMSSE_SSE200:
+ r = s->initsvtor1;
+ break;
+ case ARMSSE_SSE300:
goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- r = s->initsvtor1;
break;
case A_CPUWAIT:
- r = s->cpuwait;
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ r = s->cpuwait;
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this is reserved (for INITSVTOR2) */
+ goto bad_offset;
+ default:
+ g_assert_not_reached();
+ }
break;
case A_NMI_ENABLE:
- /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ /* In IoTKit this is named BUSWAIT but marked reserved, R/O, zero */
r = 0;
break;
+ case ARMSSE_SSE200:
+ r = s->nmi_enable;
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this is reserved (for INITSVTOR3) */
+ goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- r = s->nmi_enable;
break;
case A_WICCTRL:
- r = s->wicctrl;
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ r = s->wicctrl;
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this offset is CPUWAIT */
+ r = s->cpuwait;
+ break;
+ default:
+ g_assert_not_reached();
+ }
break;
case A_EWCTRL:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ r = s->ewctrl;
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this offset is is NMI_ENABLE */
+ r = s->nmi_enable;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
+ case A_PWRCTRL:
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ goto bad_offset;
+ case ARMSSE_SSE300:
+ r = s->pwrctrl;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->ewctrl;
break;
case A_PDCM_PD_SYS_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ r = s->pdcm_pd_sys_sense;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
+ case A_PDCM_PD_CPU0_SENSE:
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ goto bad_offset;
+ case ARMSSE_SSE300:
+ r = s->pdcm_pd_cpu0_sense;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->pdcm_pd_sys_sense;
break;
case A_PDCM_PD_SRAM0_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ r = s->pdcm_pd_sram0_sense;
+ break;
+ case ARMSSE_SSE300:
+ goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- r = s->pdcm_pd_sram0_sense;
break;
case A_PDCM_PD_SRAM1_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ goto bad_offset;
+ case ARMSSE_SSE200:
+ r = s->pdcm_pd_sram1_sense;
+ break;
+ case ARMSSE_SSE300:
goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- r = s->pdcm_pd_sram1_sense;
break;
case A_PDCM_PD_SRAM2_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ r = s->pdcm_pd_sram2_sense;
+ break;
+ case ARMSSE_SSE300:
+ r = s->pdcm_pd_vmr0_sense;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->pdcm_pd_sram2_sense;
break;
case A_PDCM_PD_SRAM3_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ r = s->pdcm_pd_sram3_sense;
+ break;
+ case ARMSSE_SSE300:
+ r = s->pdcm_pd_vmr1_sense;
+ break;
+ default:
+ g_assert_not_reached();
}
- r = s->pdcm_pd_sram3_sense;
break;
case A_PID4 ... A_CID3:
- r = sysctl_id[(offset - A_PID4) / 4];
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ r = iotkit_sysctl_id[(offset - A_PID4) / 4];
+ break;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ r = sse200_sysctl_id[(offset - A_PID4) / 4];
+ break;
+ default:
+ g_assert_not_reached();
+ }
break;
case A_SECDBGSET:
case A_SECDBGCLR:
@@ -213,6 +366,21 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
return r;
}
+static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
+{
+ int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
+ int i;
+
+ for (i = 0; i < num_cpus; i++) {
+ uint32_t mask = 1 << i;
+ if ((s->cpuwait & mask) && !(value & mask)) {
+ /* Powering up CPU 0 */
+ arm_set_cpu_on_and_reset(i);
+ }
+ }
+ s->cpuwait = value;
+}
+
static void iotkit_sysctl_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
@@ -249,23 +417,53 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
s->gretreg = value;
break;
case A_INITSVTOR0:
- s->initsvtor0 = value;
- set_init_vtor(0, s->initsvtor0);
+ switch (s->sse_version) {
+ case ARMSSE_SSE300:
+ /* SSE300 has a LOCK bit which prevents further writes when set */
+ if (s->initsvtor0 & R_INITSVTOR0_LOCK_MASK) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "IoTKit INITSVTOR0 write when register locked\n");
+ break;
+ }
+ s->initsvtor0 = value;
+ set_init_vtor(0, s->initsvtor0 & R_INITSVTOR0_VTOR_MASK);
+ break;
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ s->initsvtor0 = value;
+ set_init_vtor(0, s->initsvtor0);
+ break;
+ default:
+ g_assert_not_reached();
+ }
break;
case A_CPUWAIT:
- if ((s->cpuwait & 1) && !(value & 1)) {
- /* Powering up CPU 0 */
- arm_set_cpu_on_and_reset(0);
- }
- if ((s->cpuwait & 2) && !(value & 2)) {
- /* Powering up CPU 1 */
- arm_set_cpu_on_and_reset(1);
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ cpuwait_write(s, value);
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this is reserved (for INITSVTOR2) */
+ goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- s->cpuwait = value;
break;
case A_WICCTRL:
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
- s->wicctrl = value;
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
+ s->wicctrl = value;
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this offset is CPUWAIT */
+ cpuwait_write(s, value);
+ break;
+ default:
+ g_assert_not_reached();
+ }
break;
case A_SECDBGSET:
/* write-1-to-set */
@@ -283,94 +481,214 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
}
break;
case A_SCSECCTRL:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
+ s->scsecctrl = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
- s->scsecctrl = value;
break;
case A_FCLK_DIV:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
+ s->fclk_div = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
- s->fclk_div = value;
break;
case A_SYSCLK_DIV:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
+ s->sysclk_div = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
- s->sysclk_div = value;
break;
case A_CLOCK_FORCE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
+ s->clock_force = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
- s->clock_force = value;
break;
case A_INITSVTOR1:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ s->initsvtor1 = value;
+ set_init_vtor(1, s->initsvtor1);
+ break;
+ case ARMSSE_SSE300:
+ goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- s->initsvtor1 = value;
- set_init_vtor(1, s->initsvtor1);
break;
case A_EWCTRL:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
+ s->ewctrl = value;
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this offset is is NMI_ENABLE */
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
+ s->nmi_enable = value;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
+ case A_PWRCTRL:
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
+ goto bad_offset;
+ case ARMSSE_SSE300:
+ if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "IoTKit PWRCTRL write when register locked\n");
+ break;
+ }
+ s->pwrctrl = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
- s->ewctrl = value;
break;
case A_PDCM_PD_SYS_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ goto bad_offset;
+ case ARMSSE_SSE200:
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
+ s->pdcm_pd_sys_sense = value;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
+ case A_PDCM_PD_CPU0_SENSE:
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ case ARMSSE_SSE200:
goto bad_offset;
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_CPU0_SENSE unimplemented\n");
+ s->pdcm_pd_cpu0_sense = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP,
- "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
- s->pdcm_pd_sys_sense = value;
break;
case A_PDCM_PD_SRAM0_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ goto bad_offset;
+ case ARMSSE_SSE200:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
+ s->pdcm_pd_sram0_sense = value;
+ break;
+ case ARMSSE_SSE300:
goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP,
- "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
- s->pdcm_pd_sram0_sense = value;
break;
case A_PDCM_PD_SRAM1_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
+ goto bad_offset;
+ case ARMSSE_SSE200:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
+ s->pdcm_pd_sram1_sense = value;
+ break;
+ case ARMSSE_SSE300:
goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP,
- "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
- s->pdcm_pd_sram1_sense = value;
break;
case A_PDCM_PD_SRAM2_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
+ s->pdcm_pd_sram2_sense = value;
+ break;
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_VMR0_SENSE unimplemented\n");
+ s->pdcm_pd_vmr0_sense = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP,
- "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
- s->pdcm_pd_sram2_sense = value;
break;
case A_PDCM_PD_SRAM3_SENSE:
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto bad_offset;
+ case ARMSSE_SSE200:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
+ s->pdcm_pd_sram3_sense = value;
+ break;
+ case ARMSSE_SSE300:
+ qemu_log_mask(LOG_UNIMP,
+ "IoTKit SysCtl PDCM_PD_VMR1_SENSE unimplemented\n");
+ s->pdcm_pd_vmr1_sense = value;
+ break;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP,
- "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
- s->pdcm_pd_sram3_sense = value;
break;
case A_NMI_ENABLE:
/* In IoTKit this is BUSWAIT: reserved, R/O, zero */
- if (!s->is_sse200) {
+ switch (s->sse_version) {
+ case ARMSSE_IOTKIT:
goto ro_offset;
+ case ARMSSE_SSE200:
+ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
+ s->nmi_enable = value;
+ break;
+ case ARMSSE_SSE300:
+ /* In SSE300 this is reserved (for INITSVTOR3) */
+ goto bad_offset;
+ default:
+ g_assert_not_reached();
}
- qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
- s->nmi_enable = value;
break;
case A_SECDBGSTAT:
case A_PID4 ... A_CID3:
@@ -417,11 +735,15 @@ static void iotkit_sysctl_reset(DeviceState *dev)
s->clock_force = 0;
s->nmi_enable = 0;
s->ewctrl = 0;
+ s->pwrctrl = 0x3;
s->pdcm_pd_sys_sense = 0x7f;
s->pdcm_pd_sram0_sense = 0;
s->pdcm_pd_sram1_sense = 0;
s->pdcm_pd_sram2_sense = 0;
s->pdcm_pd_sram3_sense = 0;
+ s->pdcm_pd_cpu0_sense = 0;
+ s->pdcm_pd_vmr0_sense = 0;
+ s->pdcm_pd_vmr1_sense = 0;
}
static void iotkit_sysctl_init(Object *obj)
@@ -438,17 +760,38 @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
{
IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
- /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
- if (extract32(s->sys_version, 28, 4) == 2) {
- s->is_sse200 = true;
+ if (!armsse_version_valid(s->sse_version)) {
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
+ return;
}
}
+static bool sse300_needed(void *opaque)
+{
+ IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
+
+ return s->sse_version == ARMSSE_SSE300;
+}
+
+static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
+ .name = "iotkit-sysctl/sse-300",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = sse300_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_cpu0_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_vmr0_sense, IoTKitSysCtl),
+ VMSTATE_UINT32(pdcm_pd_vmr1_sense, IoTKitSysCtl),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool sse200_needed(void *opaque)
{
IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
- return s->is_sse200;
+ return s->sse_version != ARMSSE_IOTKIT;
}
static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
@@ -488,12 +831,13 @@ static const VMStateDescription iotkit_sysctl_vmstate = {
},
.subsections = (const VMStateDescription*[]) {
&iotkit_sysctl_sse200_vmstate,
+ &iotkit_sysctl_sse300_vmstate,
NULL
}
};
static Property iotkit_sysctl_props[] = {
- DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
+ DEFINE_PROP_UINT32("sse-version", IoTKitSysCtl, sse_version, 0),
DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
0x10000000),
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
index 52e70053df..aaa9305b2e 100644
--- a/hw/misc/iotkit-sysinfo.c
+++ b/hw/misc/iotkit-sysinfo.c
@@ -26,9 +26,12 @@
#include "hw/registerfields.h"
#include "hw/misc/iotkit-sysinfo.h"
#include "hw/qdev-properties.h"
+#include "hw/arm/armsse-version.h"
REG32(SYS_VERSION, 0x0)
REG32(SYS_CONFIG, 0x4)
+REG32(SYS_CONFIG1, 0x8)
+REG32(IIDR, 0xfc8)
REG32(PID4, 0xfd0)
REG32(PID5, 0xfd4)
REG32(PID6, 0xfd8)
@@ -49,6 +52,12 @@ static const int sysinfo_id[] = {
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
};
+static const int sysinfo_sse300_id[] = {
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+ 0x58, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
unsigned size)
{
@@ -63,10 +72,36 @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
case A_SYS_CONFIG:
r = s->sys_config;
break;
+ case A_SYS_CONFIG1:
+ switch (s->sse_version) {
+ case ARMSSE_SSE300:
+ return 0;
+ break;
+ default:
+ goto bad_read;
+ }
+ break;
+ case A_IIDR:
+ switch (s->sse_version) {
+ case ARMSSE_SSE300:
+ return s->iidr;
+ break;
+ default:
+ goto bad_read;
+ }
+ break;
case A_PID4 ... A_CID3:
- r = sysinfo_id[(offset - A_PID4) / 4];
+ switch (s->sse_version) {
+ case ARMSSE_SSE300:
+ r = sysinfo_sse300_id[(offset - A_PID4) / 4];
+ break;
+ default:
+ r = sysinfo_id[(offset - A_PID4) / 4];
+ break;
+ }
break;
default:
+ bad_read:
qemu_log_mask(LOG_GUEST_ERROR,
"IoTKit SysInfo read: bad offset %x\n", (int)offset);
r = 0;
@@ -99,6 +134,8 @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
static Property iotkit_sysinfo_props[] = {
DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
+ DEFINE_PROP_UINT32("sse-version", IoTKitSysInfo, sse_version, 0),
+ DEFINE_PROP_UINT32("IIDR", IoTKitSysInfo, iidr, 0),
DEFINE_PROP_END_OF_LIST()
};
@@ -112,6 +149,16 @@ static void iotkit_sysinfo_init(Object *obj)
sysbus_init_mmio(sbd, &s->iomem);
}
+static void iotkit_sysinfo_realize(DeviceState *dev, Error **errp)
+{
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(dev);
+
+ if (!armsse_version_valid(s->sse_version)) {
+ error_setg(errp, "invalid sse-version value %d", s->sse_version);
+ return;
+ }
+}
+
static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -120,7 +167,7 @@ static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
* This device has no guest-modifiable state and so it
* does not need a reset function or VMState.
*/
-
+ dc->realize = iotkit_sysinfo_realize;
device_class_set_props(dc, iotkit_sysinfo_props);
}
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 629283957f..e30a555db5 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/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
index f3db88ddcc..07b8cbdad2 100644
--- a/hw/misc/mps2-fpgaio.c
+++ b/hw/misc/mps2-fpgaio.c
@@ -29,6 +29,7 @@
#include "qemu/timer.h"
REG32(LED0, 0)
+REG32(DBGCTRL, 4)
REG32(BUTTON, 8)
REG32(CLK1HZ, 0x10)
REG32(CLK100HZ, 0x14)
@@ -129,6 +130,12 @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
case A_LED0:
r = s->led0;
break;
+ case A_DBGCTRL:
+ if (!s->has_dbgctrl) {
+ goto bad_offset;
+ }
+ r = s->dbgctrl;
+ break;
case A_BUTTON:
/* User-pressable board buttons. We don't model that, so just return
* zeroes.
@@ -195,6 +202,14 @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
}
}
break;
+ case A_DBGCTRL:
+ if (!s->has_dbgctrl) {
+ goto bad_offset;
+ }
+ qemu_log_mask(LOG_UNIMP,
+ "MPS2 FPGAIO: DBGCTRL unimplemented\n");
+ s->dbgctrl = value;
+ break;
case A_PRESCALE:
resync_counter(s);
s->prescale = value;
@@ -225,6 +240,7 @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
s->pscntr = value;
break;
default:
+ bad_offset:
qemu_log_mask(LOG_GUEST_ERROR,
"MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
break;
@@ -285,41 +301,22 @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
}
}
-static bool mps2_fpgaio_counters_needed(void *opaque)
-{
- /* Currently vmstate.c insists all subsections have a 'needed' function */
- return true;
-}
-
-static const VMStateDescription mps2_fpgaio_counters_vmstate = {
- .name = "mps2-fpgaio/counters",
- .version_id = 2,
- .minimum_version_id = 2,
- .needed = mps2_fpgaio_counters_needed,
- .fields = (VMStateField[]) {
- VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
- VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
- VMSTATE_UINT32(counter, MPS2FPGAIO),
- VMSTATE_UINT32(pscntr, MPS2FPGAIO),
- VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
- VMSTATE_END_OF_LIST()
- }
-};
-
static const VMStateDescription mps2_fpgaio_vmstate = {
.name = "mps2-fpgaio",
- .version_id = 1,
- .minimum_version_id = 1,
+ .version_id = 3,
+ .minimum_version_id = 3,
.fields = (VMStateField[]) {
VMSTATE_UINT32(led0, MPS2FPGAIO),
VMSTATE_UINT32(prescale, MPS2FPGAIO),
VMSTATE_UINT32(misc, MPS2FPGAIO),
+ VMSTATE_UINT32(dbgctrl, MPS2FPGAIO),
+ VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
+ VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
+ VMSTATE_UINT32(counter, MPS2FPGAIO),
+ VMSTATE_UINT32(pscntr, MPS2FPGAIO),
+ VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
VMSTATE_END_OF_LIST()
},
- .subsections = (const VMStateDescription*[]) {
- &mps2_fpgaio_counters_vmstate,
- NULL
- }
};
static Property mps2_fpgaio_properties[] = {
@@ -328,6 +325,7 @@ static Property mps2_fpgaio_properties[] = {
/* Number of LEDs controlled by LED0 register */
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
+ DEFINE_PROP_BOOL("has-dbgctrl", MPS2FPGAIO, has_dbgctrl, false),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
index 140a4b9ceb..c56aca86ad 100644
--- a/hw/misc/mps2-scc.c
+++ b/hw/misc/mps2-scc.c
@@ -110,14 +110,14 @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
r = s->cfg1;
break;
case A_CFG2:
- if (scc_partno(s) != 0x524) {
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
/* CFG2 reserved on other boards */
goto bad_offset;
}
r = s->cfg2;
break;
case A_CFG3:
- if (scc_partno(s) == 0x524) {
+ if (scc_partno(s) == 0x524 && scc_partno(s) == 0x547) {
/* CFG3 reserved on AN524 */
goto bad_offset;
}
@@ -130,7 +130,7 @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
r = s->cfg4;
break;
case A_CFG5:
- if (scc_partno(s) != 0x524) {
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
/* CFG5 reserved on other boards */
goto bad_offset;
}
@@ -185,7 +185,10 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
switch (offset) {
case A_CFG0:
- /* TODO on some boards bit 0 controls RAM remapping */
+ /*
+ * TODO on some boards bit 0 controls RAM remapping;
+ * on others bit 1 is CPU_WAIT.
+ */
s->cfg0 = value;
break;
case A_CFG1:
@@ -195,7 +198,7 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
}
break;
case A_CFG2:
- if (scc_partno(s) != 0x524) {
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
/* CFG2 reserved on other boards */
goto bad_offset;
}
@@ -203,7 +206,7 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
s->cfg2 = value;
break;
case A_CFG5:
- if (scc_partno(s) != 0x524) {
+ if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
/* CFG5 reserved on other boards */
goto bad_offset;
}
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
index 0bcae9ce95..a1ee67dc9a 100644
--- a/hw/misc/npcm7xx_clk.c
+++ b/hw/misc/npcm7xx_clk.c
@@ -586,15 +586,26 @@ static const DividerInitInfo divider_init_info_list[] = {
},
};
+static void npcm7xx_clk_update_pll_cb(void *opaque, ClockEvent event)
+{
+ npcm7xx_clk_update_pll(opaque);
+}
+
static void npcm7xx_clk_pll_init(Object *obj)
{
NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
- npcm7xx_clk_update_pll, pll);
+ npcm7xx_clk_update_pll_cb, pll,
+ ClockUpdate);
pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
}
+static void npcm7xx_clk_update_sel_cb(void *opaque, ClockEvent event)
+{
+ npcm7xx_clk_update_sel(opaque);
+}
+
static void npcm7xx_clk_sel_init(Object *obj)
{
int i;
@@ -603,16 +614,23 @@ static void npcm7xx_clk_sel_init(Object *obj)
for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
g_strdup_printf("clock-in[%d]", i),
- npcm7xx_clk_update_sel, sel);
+ npcm7xx_clk_update_sel_cb, sel, ClockUpdate);
}
sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
}
+
+static void npcm7xx_clk_update_divider_cb(void *opaque, ClockEvent event)
+{
+ npcm7xx_clk_update_divider(opaque);
+}
+
static void npcm7xx_clk_divider_init(Object *obj)
{
NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
- npcm7xx_clk_update_divider, div);
+ npcm7xx_clk_update_divider_cb,
+ div, ClockUpdate);
div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
}
@@ -875,7 +893,7 @@ static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
{
int i;
- s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL, 0);
/* First pass: init all converter modules */
QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
index dabcb6c0f9..ce192bb274 100644
--- a/hw/misc/npcm7xx_pwm.c
+++ b/hw/misc/npcm7xx_pwm.c
@@ -493,7 +493,7 @@ static void npcm7xx_pwm_init(Object *obj)
memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
TYPE_NPCM7XX_PWM, 4 * KiB);
sysbus_init_mmio(sbd, &s->iomem);
- s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL, 0);
for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
object_property_add_uint32_ptr(obj, "freq[*]",
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index d626b9d7a7..4b15db8ca4 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"
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 66504a9d3a..c66d7db177 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -307,9 +307,10 @@ static void zynq_slcr_propagate_clocks(ZynqSLCRState *s)
clock_propagate(s->uart1_ref_clk);
}
-static void zynq_slcr_ps_clk_callback(void *opaque)
+static void zynq_slcr_ps_clk_callback(void *opaque, ClockEvent event)
{
ZynqSLCRState *s = (ZynqSLCRState *) opaque;
+
zynq_slcr_compute_clocks(s);
zynq_slcr_propagate_clocks(s);
}
@@ -576,7 +577,7 @@ static const MemoryRegionOps slcr_ops = {
};
static const ClockPortInitArray zynq_slcr_clocks = {
- QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback),
+ QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback, ClockUpdate),
QDEV_CLOCK_OUT(ZynqSLCRState, uart0_ref_clk),
QDEV_CLOCK_OUT(ZynqSLCRState, uart1_ref_clk),
QDEV_CLOCK_END