mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210129-1' into staging
target-arm queue: * Implement ID_PFR2 * Conditionalize DBGDIDR * rename xlnx-zcu102.canbusN properties * provide powerdown/reset mechanism for secure firmware on 'virt' board * hw/misc: Fix arith overflow in NPCM7XX PWM module * target/arm: Replace magic value by MMU_DATA_LOAD definition * configure: fix preadv errors on Catalina macOS with new XCode * Various configure and other cleanups in preparation for iOS support * hvf: Add hypervisor entitlement to output binaries (needed for Big Sur) * Implement pvpanic-pci device * Convert the CMSDK timer devices to the Clock framework # gpg: Signature made Fri 29 Jan 2021 16:08:02 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-20210129-1: (46 commits) hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS arm: Remove frq properties on CMSDK timer, dualtimer, watchdog, ARMSSE arm: Don't set freq properties on CMSDK timer, dualtimer, watchdog, ARMSSE hw/arm/armsse: Use Clock to set system_clock_scale tests/qtest/cmsdk-apb-watchdog-test: Test clock changes hw/watchdog/cmsdk-apb-watchdog: Convert to use Clock input hw/timer/cmsdk-apb-dualtimer: Convert to use Clock input hw/timer/cmsdk-apb-timer: Convert to use Clock input hw/arm/stellaris: Create Clock input for watchdog hw/arm/stellaris: Convert SSYS to QOM device hw/arm/musca: Create and connect ARMSSE Clocks hw/arm/mps2-tz: Create and connect ARMSSE Clocks hw/arm/mps2: Create and connect SYSCLK Clock hw/arm/mps2: Inline CMSDK_APB_TIMER creation hw/arm/armsse: Wire up clocks hw/arm/armsse: Rename "MAINCLK" property to "MAINCLK_FRQ" hw/watchdog/cmsdk-apb-watchdog: Add Clock input hw/timer/cmsdk-apb-dualtimer: Add Clock input hw/timer/cmsdk-apb-timer: Add Clock input hw/timer/cmsdk-apb-timer: Rename CMSDKAPBTIMER struct to CMSDKAPBTimer ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -581,12 +581,15 @@ F: include/hw/rtc/pl031.h
|
||||
F: include/hw/arm/primecell.h
|
||||
F: hw/timer/cmsdk-apb-timer.c
|
||||
F: include/hw/timer/cmsdk-apb-timer.h
|
||||
F: tests/qtest/cmsdk-apb-timer-test.c
|
||||
F: hw/timer/cmsdk-apb-dualtimer.c
|
||||
F: include/hw/timer/cmsdk-apb-dualtimer.h
|
||||
F: tests/qtest/cmsdk-apb-dualtimer-test.c
|
||||
F: hw/char/cmsdk-apb-uart.c
|
||||
F: include/hw/char/cmsdk-apb-uart.h
|
||||
F: hw/watchdog/cmsdk-apb-watchdog.c
|
||||
F: include/hw/watchdog/cmsdk-apb-watchdog.h
|
||||
F: tests/qtest/cmsdk-apb-watchdog-test.c
|
||||
F: hw/misc/tz-ppc.c
|
||||
F: include/hw/misc/tz-ppc.h
|
||||
F: hw/misc/tz-mpc.c
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.hypervisor</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -238,6 +238,7 @@ cpu=""
|
||||
iasl="iasl"
|
||||
interp_prefix="/usr/gnemul/qemu-%M"
|
||||
static="no"
|
||||
cross_compile="no"
|
||||
cross_prefix=""
|
||||
audio_drv_list=""
|
||||
block_drv_rw_whitelist=""
|
||||
@@ -318,6 +319,7 @@ fdt="auto"
|
||||
netmap="no"
|
||||
sdl="auto"
|
||||
sdl_image="auto"
|
||||
coreaudio="auto"
|
||||
virtiofsd="auto"
|
||||
virtfs="auto"
|
||||
libudev="auto"
|
||||
@@ -469,6 +471,7 @@ for opt do
|
||||
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
|
||||
case "$opt" in
|
||||
--cross-prefix=*) cross_prefix="$optarg"
|
||||
cross_compile="yes"
|
||||
;;
|
||||
--cc=*) CC="$optarg"
|
||||
;;
|
||||
@@ -622,13 +625,6 @@ fi
|
||||
# the correct CPU with the --cpu option.
|
||||
case $targetos in
|
||||
Darwin)
|
||||
# on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
|
||||
# run 64-bit userspace code.
|
||||
# If the user didn't specify a CPU explicitly and the kernel says this is
|
||||
# 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
|
||||
if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
|
||||
cpu="x86_64"
|
||||
fi
|
||||
HOST_DSOSUF=".dylib"
|
||||
;;
|
||||
SunOS)
|
||||
@@ -772,13 +768,8 @@ OpenBSD)
|
||||
Darwin)
|
||||
bsd="yes"
|
||||
darwin="yes"
|
||||
if [ "$cpu" = "x86_64" ] ; then
|
||||
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
|
||||
QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
|
||||
fi
|
||||
audio_drv_list="coreaudio try-sdl"
|
||||
audio_drv_list="try-coreaudio try-sdl"
|
||||
audio_possible_drivers="coreaudio sdl"
|
||||
QEMU_LDFLAGS="-framework CoreFoundation -framework IOKit $QEMU_LDFLAGS"
|
||||
# Disable attempts to use ObjectiveC features in os/object.h since they
|
||||
# won't work when we're compiling with gcc as a C compiler.
|
||||
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
|
||||
@@ -1691,7 +1682,7 @@ $(echo Deprecated targets: $deprecated_targets_list | \
|
||||
--target-list-exclude=LIST exclude a set of targets from the default target-list
|
||||
|
||||
Advanced options (experts only):
|
||||
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
|
||||
--cross-prefix=PREFIX use PREFIX for compile tools, PREFIX can be blank [$cross_prefix]
|
||||
--cc=CC use C compiler CC [$cc]
|
||||
--iasl=IASL use ACPI compiler IASL [$iasl]
|
||||
--host-cc=CC use C compiler CC [$host_cc] for code run at
|
||||
@@ -3145,6 +3136,24 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# detect CoreAudio
|
||||
if test "$coreaudio" != "no" ; then
|
||||
coreaudio_libs="-framework CoreAudio"
|
||||
cat > $TMPC << EOF
|
||||
#include <CoreAudio/CoreAudio.h>
|
||||
int main(void)
|
||||
{
|
||||
return (int)AudioGetCurrentHostTime();
|
||||
}
|
||||
EOF
|
||||
if compile_prog "" "$coreaudio_libs" ; then
|
||||
coreaudio=yes
|
||||
else
|
||||
coreaudio=no
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# Sound support libraries probe
|
||||
|
||||
@@ -3201,8 +3210,20 @@ for drv in $audio_drv_list; do
|
||||
fi
|
||||
;;
|
||||
|
||||
coreaudio)
|
||||
coreaudio | try-coreaudio)
|
||||
if test "$coreaudio" = "no"; then
|
||||
if test "$drv" = "try-coreaudio"; then
|
||||
audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio//')
|
||||
else
|
||||
error_exit "$drv check failed" \
|
||||
"Make sure to have the $drv is available."
|
||||
fi
|
||||
else
|
||||
coreaudio_libs="-framework CoreAudio"
|
||||
if test "$drv" = "try-coreaudio"; then
|
||||
audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio/coreaudio/')
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
dsound)
|
||||
@@ -3531,19 +3552,6 @@ if compile_prog "" "" ; then
|
||||
iovec=yes
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# preadv probe
|
||||
cat > $TMPC <<EOF
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
int main(void) { return preadv(0, 0, 0, 0); }
|
||||
EOF
|
||||
preadv=no
|
||||
if compile_prog "" "" ; then
|
||||
preadv=yes
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# fdt probe
|
||||
|
||||
@@ -5748,9 +5756,6 @@ fi
|
||||
if test "$iovec" = "yes" ; then
|
||||
echo "CONFIG_IOVEC=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$preadv" = "yes" ; then
|
||||
echo "CONFIG_PREADV=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$membarrier" = "yes" ; then
|
||||
echo "CONFIG_MEMBARRIER=y" >> $config_host_mak
|
||||
fi
|
||||
@@ -6297,6 +6302,7 @@ echo "cpp_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross
|
||||
echo "[binaries]" >> $cross
|
||||
echo "c = [$(meson_quote $cc)]" >> $cross
|
||||
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx)]" >> $cross
|
||||
test -n "$objcc" && echo "objc = [$(meson_quote $objcc)]" >> $cross
|
||||
echo "ar = [$(meson_quote $ar)]" >> $cross
|
||||
echo "nm = [$(meson_quote $nm)]" >> $cross
|
||||
echo "pkgconfig = [$(meson_quote $pkg_config_exe)]" >> $cross
|
||||
@@ -6306,7 +6312,7 @@ if has $sdl2_config; then
|
||||
fi
|
||||
echo "strip = [$(meson_quote $strip)]" >> $cross
|
||||
echo "windres = [$(meson_quote $windres)]" >> $cross
|
||||
if test -n "$cross_prefix"; then
|
||||
if test "$cross_compile" = "yes"; then
|
||||
cross_arg="--cross-file config-meson.cross"
|
||||
echo "[host_machine]" >> $cross
|
||||
if test "$mingw32" = "yes" ; then
|
||||
@@ -6315,10 +6321,16 @@ if test -n "$cross_prefix"; then
|
||||
if test "$linux" = "yes" ; then
|
||||
echo "system = 'linux'" >> $cross
|
||||
fi
|
||||
if test "$darwin" = "yes" ; then
|
||||
echo "system = 'darwin'" >> $cross
|
||||
fi
|
||||
case "$ARCH" in
|
||||
i386|x86_64)
|
||||
i386)
|
||||
echo "cpu_family = 'x86'" >> $cross
|
||||
;;
|
||||
x86_64)
|
||||
echo "cpu_family = 'x86_64'" >> $cross
|
||||
;;
|
||||
ppc64le)
|
||||
echo "cpu_family = 'ppc64'" >> $cross
|
||||
;;
|
||||
|
||||
@@ -235,6 +235,22 @@ object during device instance init. For example:
|
||||
/* set initial value to 10ns / 100MHz */
|
||||
clock_set_ns(clk, 10);
|
||||
|
||||
To enforce that the clock is wired up by the board code, you can
|
||||
call ``clock_has_source()`` in your device's realize method:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
if (!clock_has_source(s->clk)) {
|
||||
error_setg(errp, "MyDevice: clk input must be connected");
|
||||
return;
|
||||
}
|
||||
|
||||
Note that this only checks that the clock has been wired up; it is
|
||||
still possible that the output clock connected to it is disabled
|
||||
or has not yet been configured, in which case the period will be
|
||||
zero. You should use the clock callback to find out when the clock
|
||||
period changes.
|
||||
|
||||
Fetching clock frequency/period
|
||||
-------------------------------
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ PCI devices (other than virtio):
|
||||
1b36:000d PCI xhci usb host adapter
|
||||
1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c
|
||||
1b36:0010 PCIe NVMe device (-device nvme)
|
||||
1b36:0011 PCI PVPanic device (-device pvpanic-pci)
|
||||
|
||||
All these devices are documented in docs/specs.
|
||||
|
||||
|
||||
+12
-1
@@ -1,7 +1,7 @@
|
||||
PVPANIC DEVICE
|
||||
==============
|
||||
|
||||
pvpanic device is a simulated ISA device, through which a guest panic
|
||||
pvpanic device is a simulated device, through which a guest panic
|
||||
event is sent to qemu, and a QMP event is generated. This allows
|
||||
management apps (e.g. libvirt) to be notified and respond to the event.
|
||||
|
||||
@@ -9,6 +9,9 @@ The management app has the option of waiting for GUEST_PANICKED events,
|
||||
and/or polling for guest-panicked RunState, to learn when the pvpanic
|
||||
device has fired a panic event.
|
||||
|
||||
The pvpanic device can be implemented as an ISA device (using IOPORT) or as a
|
||||
PCI device.
|
||||
|
||||
ISA Interface
|
||||
-------------
|
||||
|
||||
@@ -24,6 +27,14 @@ bit 1: a guest panic has happened and will be handled by the guest;
|
||||
the host should record it or report it, but should not affect
|
||||
the execution of the guest.
|
||||
|
||||
PCI Interface
|
||||
-------------
|
||||
|
||||
The PCI interface is similar to the ISA interface except that it uses an MMIO
|
||||
address space provided by its BAR0, 1 byte long. Any machine with a PCI bus
|
||||
can enable a pvpanic device by adding '-device pvpanic-pci' to the command
|
||||
line.
|
||||
|
||||
ACPI Interface
|
||||
--------------
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ The virt board supports:
|
||||
- Secure-World-only devices if the CPU has TrustZone:
|
||||
|
||||
- A second PL011 UART
|
||||
- A second PL061 GPIO controller, with GPIO lines for triggering
|
||||
a system reset or system poweroff
|
||||
- A secure flash memory
|
||||
- 16MB of secure RAM
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ config ARM_VIRT
|
||||
select PL011 # UART
|
||||
select PL031 # RTC
|
||||
select PL061 # GPIO
|
||||
select GPIO_PWR
|
||||
select PLATFORM_BUS
|
||||
select SMBIOS
|
||||
select VIRTIO_MMIO
|
||||
|
||||
+33
-15
@@ -21,6 +21,7 @@
|
||||
#include "hw/arm/armsse.h"
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
|
||||
/* Format of the System Information block SYS_CONFIG register */
|
||||
typedef enum SysConfigFormat {
|
||||
@@ -47,7 +48,6 @@ static Property iotkit_properties[] = {
|
||||
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
|
||||
MemoryRegion *),
|
||||
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
|
||||
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
|
||||
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
|
||||
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
|
||||
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
|
||||
@@ -59,7 +59,6 @@ static Property armsse_properties[] = {
|
||||
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
|
||||
MemoryRegion *),
|
||||
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
|
||||
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
|
||||
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
|
||||
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
|
||||
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
|
||||
@@ -231,6 +230,16 @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
|
||||
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
|
||||
}
|
||||
|
||||
static void armsse_mainclk_update(void *opaque)
|
||||
{
|
||||
ARMSSE *s = ARM_SSE(opaque);
|
||||
/*
|
||||
* Set system_clock_scale from our Clock input; this is what
|
||||
* controls the tick rate of the CPU SysTick timer.
|
||||
*/
|
||||
system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
|
||||
}
|
||||
|
||||
static void armsse_init(Object *obj)
|
||||
{
|
||||
ARMSSE *s = ARM_SSE(obj);
|
||||
@@ -241,6 +250,10 @@ static void armsse_init(Object *obj)
|
||||
assert(info->sram_banks <= MAX_SRAM_BANKS);
|
||||
assert(info->num_cpus <= SSE_MAX_CPUS);
|
||||
|
||||
s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
|
||||
armsse_mainclk_update, s);
|
||||
s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
|
||||
|
||||
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
|
||||
|
||||
for (i = 0; i < info->num_cpus; i++) {
|
||||
@@ -447,9 +460,11 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s->mainclk_frq) {
|
||||
error_setg(errp, "MAINCLK property was not set");
|
||||
return;
|
||||
if (!clock_has_source(s->mainclk)) {
|
||||
error_setg(errp, "MAINCLK clock was not connected");
|
||||
}
|
||||
if (!clock_has_source(s->s32kclk)) {
|
||||
error_setg(errp, "S32KCLK clock was not connected");
|
||||
}
|
||||
|
||||
assert(info->num_cpus <= SSE_MAX_CPUS);
|
||||
@@ -710,7 +725,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
* it to the appropriate PPC port; then we can realize the PPC and
|
||||
* map its upstream ends to the right place in the container.
|
||||
*/
|
||||
qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
|
||||
qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -720,7 +735,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr),
|
||||
&error_abort);
|
||||
|
||||
qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
|
||||
qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -730,7 +745,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr),
|
||||
&error_abort);
|
||||
|
||||
qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
|
||||
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -888,7 +903,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
/* Devices behind APB PPC1:
|
||||
* 0x4002f000: S32K timer
|
||||
*/
|
||||
qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
|
||||
qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -981,7 +996,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
|
||||
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
|
||||
|
||||
qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
|
||||
qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -991,7 +1006,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
|
||||
|
||||
qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
|
||||
qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -999,7 +1014,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
armsse_get_common_irq_in(s, 1));
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
|
||||
|
||||
qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
|
||||
qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
|
||||
return;
|
||||
}
|
||||
@@ -1104,7 +1119,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
*/
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
|
||||
|
||||
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
|
||||
/* Set initial system_clock_scale from MAINCLK */
|
||||
armsse_mainclk_update(s);
|
||||
}
|
||||
|
||||
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
|
||||
@@ -1127,9 +1143,11 @@ static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
|
||||
|
||||
static const VMStateDescription armsse_vmstate = {
|
||||
.name = "iotkit",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_CLOCK(mainclk, ARMSSE),
|
||||
VMSTATE_CLOCK(s32kclk, ARMSSE),
|
||||
VMSTATE_UINT32(nsccfg, ARMSSE),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
|
||||
+13
-1
@@ -62,6 +62,7 @@
|
||||
#include "hw/net/lan9118.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/core/split-irq.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define MPS2TZ_NUMIRQ 92
|
||||
@@ -100,6 +101,8 @@ struct MPS2TZMachineState {
|
||||
qemu_or_irq uart_irq_orgate;
|
||||
DeviceState *lan9118;
|
||||
SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
|
||||
Clock *sysclk;
|
||||
Clock *s32kclk;
|
||||
};
|
||||
|
||||
#define TYPE_MPS2TZ_MACHINE "mps2tz"
|
||||
@@ -110,6 +113,8 @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
|
||||
|
||||
/* Main SYSCLK frequency in Hz */
|
||||
#define SYSCLK_FRQ 20000000
|
||||
/* Slow 32Khz S32KCLK frequency in Hz */
|
||||
#define S32KCLK_FRQ (32 * 1000)
|
||||
|
||||
/* Create an alias of an entire original MemoryRegion @orig
|
||||
* located at @base in the memory map.
|
||||
@@ -396,13 +401,20 @@ static void mps2tz_common_init(MachineState *machine)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* These clocks don't need migration because they are fixed-frequency */
|
||||
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
|
||||
clock_set_hz(mms->sysclk, SYSCLK_FRQ);
|
||||
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
|
||||
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
|
||||
|
||||
object_initialize_child(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit,
|
||||
mmc->armsse_type);
|
||||
iotkitdev = DEVICE(&mms->iotkit);
|
||||
object_property_set_link(OBJECT(&mms->iotkit), "memory",
|
||||
OBJECT(system_memory), &error_abort);
|
||||
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
|
||||
qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
|
||||
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
|
||||
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
|
||||
|
||||
/*
|
||||
|
||||
+24
-4
@@ -46,6 +46,7 @@
|
||||
#include "hw/net/lan9118.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/watchdog/cmsdk-apb-watchdog.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
typedef enum MPS2FPGAType {
|
||||
@@ -83,6 +84,8 @@ struct MPS2MachineState {
|
||||
/* CMSDK APB subsystem */
|
||||
CMSDKAPBDualTimer dualtimer;
|
||||
CMSDKAPBWatchdog watchdog;
|
||||
CMSDKAPBTimer timer[2];
|
||||
Clock *sysclk;
|
||||
};
|
||||
|
||||
#define TYPE_MPS2_MACHINE "mps2"
|
||||
@@ -139,6 +142,10 @@ static void mps2_common_init(MachineState *machine)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* This clock doesn't need migration because it is fixed-frequency */
|
||||
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
|
||||
clock_set_hz(mms->sysclk, SYSCLK_FRQ);
|
||||
|
||||
/* The FPGA images have an odd combination of different RAMs,
|
||||
* because in hardware they are different implementations and
|
||||
* connected to different buses, giving varying performance/size
|
||||
@@ -330,18 +337,31 @@ static void mps2_common_init(MachineState *machine)
|
||||
}
|
||||
|
||||
/* CMSDK APB subsystem */
|
||||
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
|
||||
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
|
||||
for (i = 0; i < ARRAY_SIZE(mms->timer); i++) {
|
||||
g_autofree char *name = g_strdup_printf("timer%d", i);
|
||||
hwaddr base = 0x40000000 + i * 0x1000;
|
||||
int irqno = 8 + i;
|
||||
SysBusDevice *sbd;
|
||||
|
||||
object_initialize_child(OBJECT(mms), name, &mms->timer[i],
|
||||
TYPE_CMSDK_APB_TIMER);
|
||||
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
|
||||
qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
|
||||
sysbus_realize_and_unref(sbd, &error_fatal);
|
||||
sysbus_mmio_map(sbd, 0, base);
|
||||
sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
|
||||
}
|
||||
|
||||
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
|
||||
TYPE_CMSDK_APB_DUALTIMER);
|
||||
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
|
||||
qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
|
||||
qdev_get_gpio_in(armv7m, 10));
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
|
||||
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
|
||||
TYPE_CMSDK_APB_WATCHDOG);
|
||||
qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
|
||||
qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
|
||||
qdev_get_gpio_in_named(armv7m, "NMI", 0));
|
||||
|
||||
+12
-1
@@ -33,6 +33,7 @@
|
||||
#include "hw/misc/tz-ppc.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "hw/rtc/pl031.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define MUSCA_NUMIRQ_MAX 96
|
||||
@@ -82,6 +83,8 @@ struct MuscaMachineState {
|
||||
UnimplementedDeviceState sdio;
|
||||
UnimplementedDeviceState gpio;
|
||||
UnimplementedDeviceState cryptoisland;
|
||||
Clock *sysclk;
|
||||
Clock *s32kclk;
|
||||
};
|
||||
|
||||
#define TYPE_MUSCA_MACHINE "musca"
|
||||
@@ -96,6 +99,8 @@ OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE)
|
||||
* don't model that in our SSE-200 model yet.
|
||||
*/
|
||||
#define SYSCLK_FRQ 40000000
|
||||
/* Slow 32Khz S32KCLK frequency in Hz */
|
||||
#define S32KCLK_FRQ (32 * 1000)
|
||||
|
||||
static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
|
||||
{
|
||||
@@ -367,6 +372,11 @@ static void musca_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
|
||||
clock_set_hz(mms->sysclk, SYSCLK_FRQ);
|
||||
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
|
||||
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
|
||||
|
||||
object_initialize_child(OBJECT(machine), "sse-200", &mms->sse,
|
||||
TYPE_SSE200);
|
||||
ssedev = DEVICE(&mms->sse);
|
||||
@@ -375,7 +385,8 @@ static void musca_init(MachineState *machine)
|
||||
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
|
||||
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
|
||||
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
|
||||
qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
|
||||
qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
|
||||
qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
|
||||
/*
|
||||
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
|
||||
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
|
||||
|
||||
+129
-41
@@ -26,6 +26,7 @@
|
||||
#include "hw/watchdog/cmsdk-apb-watchdog.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "cpu.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
@@ -357,7 +358,12 @@ static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
/* System controller. */
|
||||
|
||||
typedef struct {
|
||||
#define TYPE_STELLARIS_SYS "stellaris-sys"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ssys_state, STELLARIS_SYS)
|
||||
|
||||
struct ssys_state {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
uint32_t pborctl;
|
||||
uint32_t ldopctl;
|
||||
@@ -371,11 +377,19 @@ typedef struct {
|
||||
uint32_t dcgc[3];
|
||||
uint32_t clkvclr;
|
||||
uint32_t ldoarst;
|
||||
qemu_irq irq;
|
||||
Clock *sysclk;
|
||||
/* Properties (all read-only registers) */
|
||||
uint32_t user0;
|
||||
uint32_t user1;
|
||||
qemu_irq irq;
|
||||
stellaris_board_info *board;
|
||||
} ssys_state;
|
||||
uint32_t did0;
|
||||
uint32_t did1;
|
||||
uint32_t dc0;
|
||||
uint32_t dc1;
|
||||
uint32_t dc2;
|
||||
uint32_t dc3;
|
||||
uint32_t dc4;
|
||||
};
|
||||
|
||||
static void ssys_update(ssys_state *s)
|
||||
{
|
||||
@@ -430,7 +444,7 @@ static uint32_t pllcfg_fury[16] = {
|
||||
|
||||
static int ssys_board_class(const ssys_state *s)
|
||||
{
|
||||
uint32_t did0 = s->board->did0;
|
||||
uint32_t did0 = s->did0;
|
||||
switch (did0 & DID0_VER_MASK) {
|
||||
case DID0_VER_0:
|
||||
return DID0_CLASS_SANDSTORM;
|
||||
@@ -456,19 +470,19 @@ static uint64_t ssys_read(void *opaque, hwaddr offset,
|
||||
|
||||
switch (offset) {
|
||||
case 0x000: /* DID0 */
|
||||
return s->board->did0;
|
||||
return s->did0;
|
||||
case 0x004: /* DID1 */
|
||||
return s->board->did1;
|
||||
return s->did1;
|
||||
case 0x008: /* DC0 */
|
||||
return s->board->dc0;
|
||||
return s->dc0;
|
||||
case 0x010: /* DC1 */
|
||||
return s->board->dc1;
|
||||
return s->dc1;
|
||||
case 0x014: /* DC2 */
|
||||
return s->board->dc2;
|
||||
return s->dc2;
|
||||
case 0x018: /* DC3 */
|
||||
return s->board->dc3;
|
||||
return s->dc3;
|
||||
case 0x01c: /* DC4 */
|
||||
return s->board->dc4;
|
||||
return s->dc4;
|
||||
case 0x030: /* PBORCTL */
|
||||
return s->pborctl;
|
||||
case 0x034: /* LDOPCTL */
|
||||
@@ -543,15 +557,26 @@ static bool ssys_use_rcc2(ssys_state *s)
|
||||
}
|
||||
|
||||
/*
|
||||
* Caculate the sys. clock period in ms.
|
||||
* Calculate the system clock period. We only want to propagate
|
||||
* this change to the rest of the system if we're not being called
|
||||
* from migration post-load.
|
||||
*/
|
||||
static void ssys_calculate_system_clock(ssys_state *s)
|
||||
static void ssys_calculate_system_clock(ssys_state *s, bool propagate_clock)
|
||||
{
|
||||
/*
|
||||
* SYSDIV field specifies divisor: 0 == /1, 1 == /2, etc. Input
|
||||
* clock is 200MHz, which is a period of 5 ns. Dividing the clock
|
||||
* frequency by X is the same as multiplying the period by X.
|
||||
*/
|
||||
if (ssys_use_rcc2(s)) {
|
||||
system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
|
||||
} else {
|
||||
system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
|
||||
}
|
||||
clock_set_ns(s->sysclk, system_clock_scale);
|
||||
if (propagate_clock) {
|
||||
clock_propagate(s->sysclk);
|
||||
}
|
||||
}
|
||||
|
||||
static void ssys_write(void *opaque, hwaddr offset,
|
||||
@@ -586,7 +611,7 @@ static void ssys_write(void *opaque, hwaddr offset,
|
||||
s->int_status |= (1 << 6);
|
||||
}
|
||||
s->rcc = value;
|
||||
ssys_calculate_system_clock(s);
|
||||
ssys_calculate_system_clock(s, true);
|
||||
break;
|
||||
case 0x070: /* RCC2 */
|
||||
if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
|
||||
@@ -598,7 +623,7 @@ static void ssys_write(void *opaque, hwaddr offset,
|
||||
s->int_status |= (1 << 6);
|
||||
}
|
||||
s->rcc2 = value;
|
||||
ssys_calculate_system_clock(s);
|
||||
ssys_calculate_system_clock(s, true);
|
||||
break;
|
||||
case 0x100: /* RCGC0 */
|
||||
s->rcgc[0] = value;
|
||||
@@ -646,9 +671,9 @@ static const MemoryRegionOps ssys_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void ssys_reset(void *opaque)
|
||||
static void stellaris_sys_reset_enter(Object *obj, ResetType type)
|
||||
{
|
||||
ssys_state *s = (ssys_state *)opaque;
|
||||
ssys_state *s = STELLARIS_SYS(obj);
|
||||
|
||||
s->pborctl = 0x7ffd;
|
||||
s->rcc = 0x078e3ac0;
|
||||
@@ -661,14 +686,25 @@ static void ssys_reset(void *opaque)
|
||||
s->rcgc[0] = 1;
|
||||
s->scgc[0] = 1;
|
||||
s->dcgc[0] = 1;
|
||||
ssys_calculate_system_clock(s);
|
||||
}
|
||||
|
||||
static void stellaris_sys_reset_hold(Object *obj)
|
||||
{
|
||||
ssys_state *s = STELLARIS_SYS(obj);
|
||||
|
||||
/* OK to propagate clocks from the hold phase */
|
||||
ssys_calculate_system_clock(s, true);
|
||||
}
|
||||
|
||||
static void stellaris_sys_reset_exit(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static int stellaris_sys_post_load(void *opaque, int version_id)
|
||||
{
|
||||
ssys_state *s = opaque;
|
||||
|
||||
ssys_calculate_system_clock(s);
|
||||
ssys_calculate_system_clock(s, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -691,30 +727,61 @@ static const VMStateDescription vmstate_stellaris_sys = {
|
||||
VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
|
||||
VMSTATE_UINT32(clkvclr, ssys_state),
|
||||
VMSTATE_UINT32(ldoarst, ssys_state),
|
||||
/* No field for sysclk -- handled in post-load instead */
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static int stellaris_sys_init(uint32_t base, qemu_irq irq,
|
||||
stellaris_board_info * board,
|
||||
uint8_t *macaddr)
|
||||
static Property stellaris_sys_properties[] = {
|
||||
DEFINE_PROP_UINT32("user0", ssys_state, user0, 0),
|
||||
DEFINE_PROP_UINT32("user1", ssys_state, user1, 0),
|
||||
DEFINE_PROP_UINT32("did0", ssys_state, did0, 0),
|
||||
DEFINE_PROP_UINT32("did1", ssys_state, did1, 0),
|
||||
DEFINE_PROP_UINT32("dc0", ssys_state, dc0, 0),
|
||||
DEFINE_PROP_UINT32("dc1", ssys_state, dc1, 0),
|
||||
DEFINE_PROP_UINT32("dc2", ssys_state, dc2, 0),
|
||||
DEFINE_PROP_UINT32("dc3", ssys_state, dc3, 0),
|
||||
DEFINE_PROP_UINT32("dc4", ssys_state, dc4, 0),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void stellaris_sys_instance_init(Object *obj)
|
||||
{
|
||||
ssys_state *s;
|
||||
ssys_state *s = STELLARIS_SYS(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
|
||||
|
||||
s = g_new0(ssys_state, 1);
|
||||
s->irq = irq;
|
||||
s->board = board;
|
||||
/* Most devices come preprogrammed with a MAC address in the user data. */
|
||||
s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
|
||||
s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
|
||||
|
||||
memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000);
|
||||
memory_region_add_subregion(get_system_memory(), base, &s->iomem);
|
||||
ssys_reset(s);
|
||||
vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_stellaris_sys, s);
|
||||
return 0;
|
||||
memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
|
||||
}
|
||||
|
||||
static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
|
||||
stellaris_board_info *board,
|
||||
uint8_t *macaddr)
|
||||
{
|
||||
DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
|
||||
/* Most devices come preprogrammed with a MAC address in the user data. */
|
||||
qdev_prop_set_uint32(dev, "user0",
|
||||
macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
|
||||
qdev_prop_set_uint32(dev, "user1",
|
||||
macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
|
||||
qdev_prop_set_uint32(dev, "did0", board->did0);
|
||||
qdev_prop_set_uint32(dev, "did1", board->did1);
|
||||
qdev_prop_set_uint32(dev, "dc0", board->dc0);
|
||||
qdev_prop_set_uint32(dev, "dc1", board->dc1);
|
||||
qdev_prop_set_uint32(dev, "dc2", board->dc2);
|
||||
qdev_prop_set_uint32(dev, "dc3", board->dc3);
|
||||
qdev_prop_set_uint32(dev, "dc4", board->dc4);
|
||||
|
||||
sysbus_realize_and_unref(sbd, &error_fatal);
|
||||
sysbus_mmio_map(sbd, 0, base);
|
||||
sysbus_connect_irq(sbd, 0, irq);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
/* I2C controller. */
|
||||
|
||||
@@ -1280,6 +1347,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
|
||||
int flash_size;
|
||||
I2CBus *i2c;
|
||||
DeviceState *dev;
|
||||
DeviceState *ssys_dev;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
@@ -1330,16 +1398,15 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
|
||||
}
|
||||
}
|
||||
|
||||
stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
|
||||
board, nd_table[0].macaddr.a);
|
||||
ssys_dev = stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
|
||||
board, nd_table[0].macaddr.a);
|
||||
|
||||
|
||||
if (board->dc1 & (1 << 3)) { /* watchdog present */
|
||||
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
|
||||
|
||||
/* system_clock_scale is valid now */
|
||||
uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
|
||||
qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
|
||||
qdev_connect_clock_in(dev, "WDOGCLK",
|
||||
qdev_get_clock_out(ssys_dev, "SYSCLK"));
|
||||
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev),
|
||||
@@ -1553,11 +1620,32 @@ static const TypeInfo stellaris_adc_info = {
|
||||
.class_init = stellaris_adc_class_init,
|
||||
};
|
||||
|
||||
static void stellaris_sys_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||
|
||||
dc->vmsd = &vmstate_stellaris_sys;
|
||||
rc->phases.enter = stellaris_sys_reset_enter;
|
||||
rc->phases.hold = stellaris_sys_reset_hold;
|
||||
rc->phases.exit = stellaris_sys_reset_exit;
|
||||
device_class_set_props(dc, stellaris_sys_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo stellaris_sys_info = {
|
||||
.name = TYPE_STELLARIS_SYS,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ssys_state),
|
||||
.instance_init = stellaris_sys_instance_init,
|
||||
.class_init = stellaris_sys_class_init,
|
||||
};
|
||||
|
||||
static void stellaris_register_types(void)
|
||||
{
|
||||
type_register_static(&stellaris_i2c_info);
|
||||
type_register_static(&stellaris_gptm_info);
|
||||
type_register_static(&stellaris_adc_info);
|
||||
type_register_static(&stellaris_sys_info);
|
||||
}
|
||||
|
||||
type_init(stellaris_register_types)
|
||||
|
||||
+90
-21
@@ -153,6 +153,7 @@ static const MemMapEntry base_memmap[] = {
|
||||
[VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN },
|
||||
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
|
||||
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
|
||||
[VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
|
||||
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
|
||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
|
||||
@@ -820,17 +821,80 @@ static void virt_powerdown_req(Notifier *n, void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static void create_gpio(const VirtMachineState *vms)
|
||||
static void create_gpio_keys(const VirtMachineState *vms,
|
||||
DeviceState *pl061_dev,
|
||||
uint32_t phandle)
|
||||
{
|
||||
gpio_key_dev = sysbus_create_simple("gpio-key", -1,
|
||||
qdev_get_gpio_in(pl061_dev, 3));
|
||||
|
||||
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
|
||||
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
|
||||
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
|
||||
|
||||
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
|
||||
"label", "GPIO Key Poweroff");
|
||||
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
|
||||
KEY_POWER);
|
||||
qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
|
||||
"gpios", phandle, 3, 0);
|
||||
}
|
||||
|
||||
#define SECURE_GPIO_POWEROFF 0
|
||||
#define SECURE_GPIO_RESET 1
|
||||
|
||||
static void create_secure_gpio_pwr(const VirtMachineState *vms,
|
||||
DeviceState *pl061_dev,
|
||||
uint32_t phandle)
|
||||
{
|
||||
DeviceState *gpio_pwr_dev;
|
||||
|
||||
/* gpio-pwr */
|
||||
gpio_pwr_dev = sysbus_create_simple("gpio-pwr", -1, NULL);
|
||||
|
||||
/* connect secure pl061 to gpio-pwr */
|
||||
qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_RESET,
|
||||
qdev_get_gpio_in_named(gpio_pwr_dev, "reset", 0));
|
||||
qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_POWEROFF,
|
||||
qdev_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0));
|
||||
|
||||
qemu_fdt_add_subnode(vms->fdt, "/gpio-poweroff");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "compatible",
|
||||
"gpio-poweroff");
|
||||
qemu_fdt_setprop_cells(vms->fdt, "/gpio-poweroff",
|
||||
"gpios", phandle, SECURE_GPIO_POWEROFF, 0);
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "status", "disabled");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "secure-status",
|
||||
"okay");
|
||||
|
||||
qemu_fdt_add_subnode(vms->fdt, "/gpio-restart");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "compatible",
|
||||
"gpio-restart");
|
||||
qemu_fdt_setprop_cells(vms->fdt, "/gpio-restart",
|
||||
"gpios", phandle, SECURE_GPIO_RESET, 0);
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "status", "disabled");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "secure-status",
|
||||
"okay");
|
||||
}
|
||||
|
||||
static void create_gpio_devices(const VirtMachineState *vms, int gpio,
|
||||
MemoryRegion *mem)
|
||||
{
|
||||
char *nodename;
|
||||
DeviceState *pl061_dev;
|
||||
hwaddr base = vms->memmap[VIRT_GPIO].base;
|
||||
hwaddr size = vms->memmap[VIRT_GPIO].size;
|
||||
int irq = vms->irqmap[VIRT_GPIO];
|
||||
hwaddr base = vms->memmap[gpio].base;
|
||||
hwaddr size = vms->memmap[gpio].size;
|
||||
int irq = vms->irqmap[gpio];
|
||||
const char compat[] = "arm,pl061\0arm,primecell";
|
||||
SysBusDevice *s;
|
||||
|
||||
pl061_dev = sysbus_create_simple("pl061", base,
|
||||
qdev_get_gpio_in(vms->gic, irq));
|
||||
pl061_dev = qdev_new("pl061");
|
||||
s = SYS_BUS_DEVICE(pl061_dev);
|
||||
sysbus_realize_and_unref(s, &error_fatal);
|
||||
memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
|
||||
sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
|
||||
|
||||
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
|
||||
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
|
||||
@@ -847,21 +911,19 @@ static void create_gpio(const VirtMachineState *vms)
|
||||
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
|
||||
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
|
||||
|
||||
gpio_key_dev = sysbus_create_simple("gpio-key", -1,
|
||||
qdev_get_gpio_in(pl061_dev, 3));
|
||||
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
|
||||
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
|
||||
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
|
||||
|
||||
qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
|
||||
qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
|
||||
"label", "GPIO Key Poweroff");
|
||||
qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
|
||||
KEY_POWER);
|
||||
qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
|
||||
"gpios", phandle, 3, 0);
|
||||
if (gpio != VIRT_GPIO) {
|
||||
/* Mark as not usable by the normal world */
|
||||
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
|
||||
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
|
||||
}
|
||||
g_free(nodename);
|
||||
|
||||
/* Child gpio devices */
|
||||
if (gpio == VIRT_GPIO) {
|
||||
create_gpio_keys(vms, pl061_dev, phandle);
|
||||
} else {
|
||||
create_secure_gpio_pwr(vms, pl061_dev, phandle);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_virtio_devices(const VirtMachineState *vms)
|
||||
@@ -1990,7 +2052,11 @@ static void machvirt_init(MachineState *machine)
|
||||
if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
|
||||
vms->acpi_dev = create_acpi_ged(vms);
|
||||
} else {
|
||||
create_gpio(vms);
|
||||
create_gpio_devices(vms, VIRT_GPIO, sysmem);
|
||||
}
|
||||
|
||||
if (vms->secure && !vmc->no_secure_gpio) {
|
||||
create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem);
|
||||
}
|
||||
|
||||
/* connect powerdown request */
|
||||
@@ -2608,8 +2674,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 0)
|
||||
|
||||
static void virt_machine_5_2_options(MachineClass *mc)
|
||||
{
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
|
||||
virt_machine_6_0_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
|
||||
vmc->no_secure_gpio = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(5, 2)
|
||||
|
||||
|
||||
@@ -219,12 +219,12 @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
|
||||
s->secure = false;
|
||||
/* Default to virt (EL2) being disabled */
|
||||
s->virt = false;
|
||||
object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
|
||||
object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
|
||||
(Object **)&s->canbus[0],
|
||||
object_property_allow_set_link,
|
||||
0);
|
||||
|
||||
object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
|
||||
object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
|
||||
(Object **)&s->canbus[1],
|
||||
object_property_allow_set_link,
|
||||
0);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "sysemu/qtest.h"
|
||||
#include "block/aio.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/clock.h"
|
||||
|
||||
#define DELTA_ADJUST 1
|
||||
#define DELTA_NO_ADJUST -1
|
||||
@@ -348,6 +349,39 @@ void ptimer_set_period(ptimer_state *s, int64_t period)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set counter increment interval from a Clock */
|
||||
void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clk,
|
||||
unsigned int divisor)
|
||||
{
|
||||
/*
|
||||
* The raw clock period is a 64-bit value in units of 2^-32 ns;
|
||||
* put another way it's a 32.32 fixed-point ns value. Our internal
|
||||
* representation of the period is 64.32 fixed point ns, so
|
||||
* the conversion is simple.
|
||||
*/
|
||||
uint64_t raw_period = clock_get(clk);
|
||||
uint64_t period_frac;
|
||||
|
||||
assert(s->in_transaction);
|
||||
s->delta = ptimer_get_count(s);
|
||||
s->period = extract64(raw_period, 32, 32);
|
||||
period_frac = extract64(raw_period, 0, 32);
|
||||
/*
|
||||
* divisor specifies a possible frequency divisor between the
|
||||
* clock and the timer, so it is a multiplier on the period.
|
||||
* We do the multiply after splitting the raw period out into
|
||||
* period and frac to avoid having to do a 32*64->96 multiply.
|
||||
*/
|
||||
s->period *= divisor;
|
||||
period_frac *= divisor;
|
||||
s->period += extract64(period_frac, 32, 32);
|
||||
s->period_frac = (uint32_t)period_frac;
|
||||
|
||||
if (s->enabled) {
|
||||
s->need_reload = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set counter frequency in Hz. */
|
||||
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
|
||||
{
|
||||
|
||||
@@ -8,5 +8,8 @@ config PL061
|
||||
config GPIO_KEY
|
||||
bool
|
||||
|
||||
config GPIO_PWR
|
||||
bool
|
||||
|
||||
config SIFIVE_GPIO
|
||||
bool
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* GPIO qemu power controller
|
||||
*
|
||||
* Copyright (c) 2020 Linaro Limited
|
||||
*
|
||||
* Author: Maxim Uvarov <maxim.uvarov@linaro.org>
|
||||
*
|
||||
* Virtual gpio driver which can be used on top of pl061
|
||||
* to reboot and shutdown qemu virtual machine. One of use
|
||||
* case is gpio driver for secure world application (ARM
|
||||
* Trusted Firmware.).
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* QEMU interface:
|
||||
* two named input GPIO lines:
|
||||
* 'reset' : when asserted, trigger system reset
|
||||
* 'shutdown' : when asserted, trigger system shutdown
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/runstate.h"
|
||||
|
||||
#define TYPE_GPIOPWR "gpio-pwr"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(GPIO_PWR_State, GPIOPWR)
|
||||
|
||||
struct GPIO_PWR_State {
|
||||
SysBusDevice parent_obj;
|
||||
};
|
||||
|
||||
static void gpio_pwr_reset(void *opaque, int n, int level)
|
||||
{
|
||||
if (level) {
|
||||
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_pwr_shutdown(void *opaque, int n, int level)
|
||||
{
|
||||
if (level) {
|
||||
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_pwr_init(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
|
||||
qdev_init_gpio_in_named(dev, gpio_pwr_reset, "reset", 1);
|
||||
qdev_init_gpio_in_named(dev, gpio_pwr_shutdown, "shutdown", 1);
|
||||
}
|
||||
|
||||
static const TypeInfo gpio_pwr_info = {
|
||||
.name = TYPE_GPIOPWR,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(GPIO_PWR_State),
|
||||
.instance_init = gpio_pwr_init,
|
||||
};
|
||||
|
||||
static void gpio_pwr_register_types(void)
|
||||
{
|
||||
type_register_static(&gpio_pwr_info);
|
||||
}
|
||||
|
||||
type_init(gpio_pwr_register_types)
|
||||
@@ -1,5 +1,6 @@
|
||||
softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c'))
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ config PC
|
||||
imply ISA_DEBUG
|
||||
imply PARALLEL
|
||||
imply PCI_DEVICES
|
||||
imply PVPANIC
|
||||
imply PVPANIC_ISA
|
||||
imply QXL
|
||||
imply SEV
|
||||
imply SGA
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user