diff options
author | Peter Maydell | 2021-03-10 14:57:31 +0100 |
---|---|---|
committer | Peter Maydell | 2021-03-10 14:57:31 +0100 |
commit | 5c6295a45b4fceac913c11abc62488c49c02b9fd (patch) | |
tree | 30e5cfdd69dd343a7a6e7dce459c6121fcedb55c /hw/misc | |
parent | Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (diff) | |
parent | hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() (diff) | |
download | qemu-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/Kconfig | 9 | ||||
-rw-r--r-- | hw/misc/armsse-cpu-pwrctrl.c | 149 | ||||
-rw-r--r-- | hw/misc/bcm2835_cprman.c | 23 | ||||
-rw-r--r-- | hw/misc/iotkit-secctl.c | 50 | ||||
-rw-r--r-- | hw/misc/iotkit-sysctl.c | 522 | ||||
-rw-r--r-- | hw/misc/iotkit-sysinfo.c | 51 | ||||
-rw-r--r-- | hw/misc/meson.build | 1 | ||||
-rw-r--r-- | hw/misc/mps2-fpgaio.c | 52 | ||||
-rw-r--r-- | hw/misc/mps2-scc.c | 15 | ||||
-rw-r--r-- | hw/misc/npcm7xx_clk.c | 26 | ||||
-rw-r--r-- | hw/misc/npcm7xx_pwm.c | 2 | ||||
-rw-r--r-- | hw/misc/trace-events | 4 | ||||
-rw-r--r-- | hw/misc/zynq_slcr.c | 5 |
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 |