aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-10-24 19:37:33 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-10-24 19:37:34 +0100
commitfe4c04071f702e008da7db06d0a220b27e1ab3ac (patch)
tree97c3699d2cd15ec48436d53218178b903389f6e3 /tests
parent45b567d645c22fb79f4698a13396718084f7cf72 (diff)
parentcc083d8a25e0a886c3cd4bea0bf57ac4e896fa3f (diff)
downloadqemu-fe4c04071f702e008da7db06d0a220b27e1ab3ac.zip
qemu-fe4c04071f702e008da7db06d0a220b27e1ab3ac.tar.gz
qemu-fe4c04071f702e008da7db06d0a220b27e1ab3ac.tar.bz2
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20161024' into staging
target-arm queue: * support variable (runtime-determined) page sizes, for a nearly-20% speedup of TCG for ARMv7 and v8 CPUs with 4K pages * ptimer: add tests, support more flexible behaviour around what happens on the "zero" tick, use ptimer for a9gtimer * virt: ACPI: Add IORT Structure definition * i2c: Fix SMBus read transactions to avoid double events * timer: stm32f2xx_timer: add check for prescaler value * QOMify musicpal, pxa2xx_gpio, strongarm, pl110 * target-arm: Implement new HLT trap for semihosting * i2c: Add asserts for second smbus i2c_start_transfer() # gpg: Signature made Mon 24 Oct 2016 18:24:17 BST # gpg: using RSA key 0x3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20161024: (32 commits) i2c: Add asserts for second smbus i2c_start_transfer() target-arm: Implement new HLT trap for semihosting hw/display: QOM'ify pl110.c hw/arm: QOM'ify strongarm.c hw/arm: QOM'ify pxa2xx_gpio.c hw/arm: QOM'ify musicpal.c timer: stm32f2xx_timer: add check for prescaler value i2c: Fix SMBus read transactions to avoid double events timer: a9gtimer: remove loop to auto-increment comparator ARM: Virt: ACPI: Build an IORT table with RC and ITS nodes ACPI: Add IORT Structure definition tests: Add tests for the ARM MPTimer arm_mptimer: Convert to use ptimer tests: ptimer: Replace 10000 with 1 tests: ptimer: Change the copyright comment tests: ptimer: Add tests for "no counter round down" policy hw/ptimer: Add "no counter round down" policy tests: ptimer: Add tests for "no immediate reload" policy hw/ptimer: Add "no immediate reload" policy tests: ptimer: Add tests for "no immediate trigger" policy ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile.include3
-rw-r--r--tests/ptimer-test-stubs.c2
-rw-r--r--tests/ptimer-test.c362
-rw-r--r--tests/ptimer-test.h2
-rw-r--r--tests/test-arm-mptimer.c1105
5 files changed, 1401 insertions, 73 deletions
diff --git a/tests/Makefile.include b/tests/Makefile.include
index e65e9f7..91cc308 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -303,6 +303,8 @@ check-qtest-arm-y += tests/m25p80-test$(EXESUF)
gcov-files-arm-y += hw/misc/tmp105.c
check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
+check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
+gcov-files-arm-y += hw/timer/arm_mptimer.c
check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
@@ -684,6 +686,7 @@ tests/test-x86-cpuid-compat$(EXESUF): tests/test-x86-cpuid-compat.o $(qtest-obj-
tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
+tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
tests/migration/stress$(EXESUF): tests/migration/stress.o
$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")
diff --git a/tests/ptimer-test-stubs.c b/tests/ptimer-test-stubs.c
index e028a81..21d4ebb 100644
--- a/tests/ptimer-test-stubs.c
+++ b/tests/ptimer-test-stubs.c
@@ -1,7 +1,7 @@
/*
* Stubs for the ptimer-test
*
- * Author: Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c
index 7b0ddf6..b36a476 100644
--- a/tests/ptimer-test.c
+++ b/tests/ptimer-test.c
@@ -1,7 +1,7 @@
/*
* QTest testcase for the ptimer
*
- * Author: Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
@@ -99,6 +99,7 @@ static void check_oneshot(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
triggered = false;
@@ -106,34 +107,46 @@ static void check_oneshot(gconstpointer arg)
ptimer_set_count(ptimer, 10);
ptimer_run(ptimer, 1);
- qemu_clock_step(2000000 * 2 + 100000);
+ qemu_clock_step(2000000 * 2 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
g_assert_false(triggered);
ptimer_stop(ptimer);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
g_assert_false(triggered);
qemu_clock_step(2000000 * 11);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
g_assert_false(triggered);
ptimer_run(ptimer, 1);
- qemu_clock_step(2000000 * 7 + 100000);
+ qemu_clock_step(2000000 * 7 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
- g_assert_true(triggered);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0);
- triggered = false;
+ if (no_round_down) {
+ g_assert_false(triggered);
+ } else {
+ g_assert_true(triggered);
+
+ triggered = false;
+ }
qemu_clock_step(2000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
- g_assert_false(triggered);
+
+ if (no_round_down) {
+ g_assert_true(triggered);
+
+ triggered = false;
+ } else {
+ g_assert_false(triggered);
+ }
qemu_clock_step(4000000);
@@ -142,30 +155,30 @@ static void check_oneshot(gconstpointer arg)
ptimer_set_count(ptimer, 10);
- qemu_clock_step(20000000 + 100000);
+ qemu_clock_step(20000000 + 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
g_assert_false(triggered);
ptimer_set_limit(ptimer, 9, 1);
- qemu_clock_step(20000000 + 100000);
+ qemu_clock_step(20000000 + 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
g_assert_false(triggered);
ptimer_run(ptimer, 1);
- qemu_clock_step(2000000 + 100000);
+ qemu_clock_step(2000000 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
g_assert_false(triggered);
ptimer_set_count(ptimer, 20);
- qemu_clock_step(2000000 * 19 + 100000);
+ qemu_clock_step(2000000 * 19 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0);
g_assert_false(triggered);
qemu_clock_step(2000000);
@@ -177,7 +190,7 @@ static void check_oneshot(gconstpointer arg)
triggered = false;
- qemu_clock_step(2000000 * 12 + 100000);
+ qemu_clock_step(2000000 * 12 + 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
@@ -188,6 +201,10 @@ static void check_periodic(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
+ bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
+ bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
+ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
triggered = false;
@@ -195,28 +212,70 @@ static void check_periodic(gconstpointer arg)
ptimer_set_limit(ptimer, 10, 1);
ptimer_run(ptimer, 0);
- qemu_clock_step(2000000 * 10 + 100000);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
+ g_assert_false(triggered);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+ qemu_clock_step(1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 10 : 9);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 10 - 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, wrap_policy ? 0 : 10);
+ g_assert_true(triggered);
+
+ qemu_clock_step(1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ wrap_policy ? 0 : (no_round_down ? 10 : 9));
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
g_assert_false(triggered);
ptimer_set_count(ptimer, 20);
- qemu_clock_step(2000000 * 11 + 100000);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 20);
+ g_assert_false(triggered);
+
+ qemu_clock_step(1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 20 : 19);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 11 + 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 9 : 8);
g_assert_false(triggered);
qemu_clock_step(2000000 * 10);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
+ g_assert_true(triggered);
+
+ triggered = false;
+
+ ptimer_set_count(ptimer, 3);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+ g_assert_false(triggered);
+
+ qemu_clock_step(1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 3 : 2);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 4);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
g_assert_true(triggered);
ptimer_stop(ptimer);
@@ -224,50 +283,82 @@ static void check_periodic(gconstpointer arg)
qemu_clock_step(2000000);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
g_assert_false(triggered);
ptimer_set_count(ptimer, 3);
ptimer_run(ptimer, 0);
- qemu_clock_step(2000000 * 3 + 100000);
+ qemu_clock_step(2000000 * 3 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ wrap_policy ? 0 : (no_round_down ? 10 : 9));
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
g_assert_false(triggered);
ptimer_set_count(ptimer, 0);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
- g_assert_true(triggered);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ no_immediate_reload ? 0 : 10);
+
+ if (no_immediate_trigger) {
+ g_assert_false(triggered);
+ } else {
+ g_assert_true(triggered);
+ }
triggered = false;
- qemu_clock_step(2000000 * 12 + 100000);
+ qemu_clock_step(1);
+
+ if (no_immediate_reload) {
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000);
+
+ if (no_immediate_trigger) {
+ g_assert_true(triggered);
+ } else {
+ g_assert_false(triggered);
+ }
+
+ triggered = false;
+ }
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 10 : 9);
+ g_assert_false(triggered);
+
+ qemu_clock_step(2000000 * 12);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0));
g_assert_true(triggered);
ptimer_stop(ptimer);
triggered = false;
- qemu_clock_step(2000000 * 12 + 100000);
+ qemu_clock_step(2000000 * 10);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0));
g_assert_false(triggered);
ptimer_run(ptimer, 0);
ptimer_set_period(ptimer, 0);
- qemu_clock_step(2000000 + 100000);
+ qemu_clock_step(2000000 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0));
g_assert_false(triggered);
}
@@ -276,6 +367,8 @@ static void check_on_the_fly_mode_change(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
+ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
triggered = false;
@@ -283,16 +376,20 @@ static void check_on_the_fly_mode_change(gconstpointer arg)
ptimer_set_limit(ptimer, 10, 1);
ptimer_run(ptimer, 1);
- qemu_clock_step(2000000 * 9 + 100000);
+ qemu_clock_step(2000000 * 9 + 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0);
+ g_assert_false(triggered);
ptimer_run(ptimer, 0);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0);
g_assert_false(triggered);
qemu_clock_step(2000000);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ wrap_policy ? 0 : (no_round_down ? 10 : 9));
g_assert_true(triggered);
triggered = false;
@@ -301,7 +398,8 @@ static void check_on_the_fly_mode_change(gconstpointer arg)
ptimer_run(ptimer, 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ (no_round_down ? 1 : 0) + (wrap_policy ? 1 : 0));
g_assert_false(triggered);
qemu_clock_step(2000000 * 3);
@@ -315,6 +413,7 @@ static void check_on_the_fly_period_change(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
triggered = false;
@@ -322,17 +421,17 @@ static void check_on_the_fly_period_change(gconstpointer arg)
ptimer_set_limit(ptimer, 8, 1);
ptimer_run(ptimer, 1);
- qemu_clock_step(2000000 * 4 + 100000);
+ qemu_clock_step(2000000 * 4 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
g_assert_false(triggered);
ptimer_set_period(ptimer, 4000000);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
- qemu_clock_step(4000000 * 2 + 100000);
+ qemu_clock_step(4000000 * 2 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 2 : 0);
g_assert_false(triggered);
qemu_clock_step(4000000 * 2);
@@ -346,6 +445,7 @@ static void check_on_the_fly_freq_change(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
triggered = false;
@@ -353,17 +453,17 @@ static void check_on_the_fly_freq_change(gconstpointer arg)
ptimer_set_limit(ptimer, 8, 1);
ptimer_run(ptimer, 1);
- qemu_clock_step(2000000 * 4 + 100000);
+ qemu_clock_step(2000000 * 4 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
g_assert_false(triggered);
ptimer_set_freq(ptimer, 250);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
- qemu_clock_step(2000000 * 4 + 100000);
+ qemu_clock_step(2000000 * 4 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 2 : 0);
g_assert_false(triggered);
qemu_clock_step(2000000 * 4);
@@ -394,25 +494,53 @@ static void check_run_with_delta_0(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
+ bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
+ bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
+ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_set_limit(ptimer, 99, 0);
ptimer_run(ptimer, 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
- g_assert_true(triggered);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ no_immediate_reload ? 0 : 99);
+
+ if (no_immediate_trigger) {
+ g_assert_false(triggered);
+ } else {
+ g_assert_true(triggered);
+ }
triggered = false;
- qemu_clock_step(2000000 + 100000);
+ if (no_immediate_trigger || no_immediate_reload) {
+ qemu_clock_step(2000000 + 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ no_immediate_reload ? 0 : (no_round_down ? 98 : 97));
+
+ if (no_immediate_trigger && no_immediate_reload) {
+ g_assert_true(triggered);
+
+ triggered = false;
+ } else {
+ g_assert_false(triggered);
+ }
+
+ ptimer_set_count(ptimer, 99);
+ ptimer_run(ptimer, 1);
+ }
+
+ qemu_clock_step(2000000 + 1);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 98 : 97);
g_assert_false(triggered);
qemu_clock_step(2000000 * 97);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0);
g_assert_false(triggered);
qemu_clock_step(2000000 * 2);
@@ -424,19 +552,42 @@ static void check_run_with_delta_0(gconstpointer arg)
ptimer_set_count(ptimer, 0);
ptimer_run(ptimer, 0);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
- g_assert_true(triggered);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ no_immediate_reload ? 0 : 99);
+
+ if (no_immediate_trigger) {
+ g_assert_false(triggered);
+ } else {
+ g_assert_true(triggered);
+ }
+
+ triggered = false;
+
+ qemu_clock_step(1);
+
+ if (no_immediate_reload) {
+ qemu_clock_step(2000000);
+ }
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 99 : 98);
+
+ if (no_immediate_reload && no_immediate_trigger) {
+ g_assert_true(triggered);
+ } else {
+ g_assert_false(triggered);
+ }
triggered = false;
- qemu_clock_step(2000000 + 100000);
+ qemu_clock_step(2000000);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 98 : 97);
g_assert_false(triggered);
qemu_clock_step(2000000 * 98);
- g_assert_cmpuint(ptimer_get_count(ptimer), ==, 98);
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==,
+ wrap_policy ? 0 : (no_round_down ? 99 : 98));
g_assert_true(triggered);
ptimer_stop(ptimer);
@@ -447,6 +598,8 @@ static void check_periodic_with_load_0(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool continuous_trigger = (*policy & PTIMER_POLICY_CONTINUOUS_TRIGGER);
+ bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
triggered = false;
@@ -454,14 +607,46 @@ static void check_periodic_with_load_0(gconstpointer arg)
ptimer_run(ptimer, 0);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+
+ if (no_immediate_trigger) {
+ g_assert_false(triggered);
+ } else {
+ g_assert_true(triggered);
+ }
+
+ triggered = false;
+
+ qemu_clock_step(2000000 + 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
+
+ if (continuous_trigger || no_immediate_trigger) {
+ g_assert_true(triggered);
+ } else {
+ g_assert_false(triggered);
+ }
+
+ triggered = false;
+
+ ptimer_set_count(ptimer, 10);
+ ptimer_run(ptimer, 0);
+
+ qemu_clock_step(2000000 * 10 + 1);
+
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
triggered = false;
- qemu_clock_step(2000000 + 100000);
+ qemu_clock_step(2000000 + 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
- g_assert_false(triggered);
+
+ if (continuous_trigger) {
+ g_assert_true(triggered);
+ } else {
+ g_assert_false(triggered);
+ }
ptimer_stop(ptimer);
}
@@ -471,6 +656,7 @@ static void check_oneshot_with_load_0(gconstpointer arg)
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
+ bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
triggered = false;
@@ -478,26 +664,30 @@ static void check_oneshot_with_load_0(gconstpointer arg)
ptimer_run(ptimer, 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
- g_assert_true(triggered);
+
+ if (no_immediate_trigger) {
+ g_assert_false(triggered);
+ } else {
+ g_assert_true(triggered);
+ }
triggered = false;
- qemu_clock_step(2000000 + 100000);
+ qemu_clock_step(2000000 + 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
- g_assert_false(triggered);
- triggered = false;
-
- qemu_clock_step(2000000 + 100000);
-
- g_assert_false(triggered);
+ if (no_immediate_trigger) {
+ g_assert_true(triggered);
+ } else {
+ g_assert_false(triggered);
+ }
}
static void add_ptimer_tests(uint8_t policy)
{
uint8_t *ppolicy = g_malloc(1);
- char *policy_name = g_malloc(64);
+ char *policy_name = g_malloc0(256);
*ppolicy = policy;
@@ -505,6 +695,26 @@ static void add_ptimer_tests(uint8_t policy)
g_sprintf(policy_name, "default");
}
+ if (policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) {
+ g_strlcat(policy_name, "wrap_after_one_period,", 256);
+ }
+
+ if (policy & PTIMER_POLICY_CONTINUOUS_TRIGGER) {
+ g_strlcat(policy_name, "continuous_trigger,", 256);
+ }
+
+ if (policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER) {
+ g_strlcat(policy_name, "no_immediate_trigger,", 256);
+ }
+
+ if (policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD) {
+ g_strlcat(policy_name, "no_immediate_reload,", 256);
+ }
+
+ if (policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN) {
+ g_strlcat(policy_name, "no_counter_rounddown,", 256);
+ }
+
g_test_add_data_func(
g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
ppolicy, check_set_count);
@@ -550,6 +760,16 @@ static void add_ptimer_tests(uint8_t policy)
ppolicy, check_oneshot_with_load_0);
}
+static void add_all_ptimer_policies_comb_tests(void)
+{
+ int last_policy = PTIMER_POLICY_NO_COUNTER_ROUND_DOWN;
+ int policy = PTIMER_POLICY_DEFAULT;
+
+ for (; policy < (last_policy << 1); policy++) {
+ add_ptimer_tests(policy);
+ }
+}
+
int main(int argc, char **argv)
{
int i;
@@ -560,7 +780,7 @@ int main(int argc, char **argv)
main_loop_tlg.tl[i] = g_new0(QEMUTimerList, 1);
}
- add_ptimer_tests(PTIMER_POLICY_DEFAULT);
+ add_all_ptimer_policies_comb_tests();
qtest_allowed = true;
diff --git a/tests/ptimer-test.h b/tests/ptimer-test.h
index 98d9b8f..09ac56d 100644
--- a/tests/ptimer-test.h
+++ b/tests/ptimer-test.h
@@ -1,7 +1,7 @@
/*
* QTest testcase for the ptimer
*
- * Author: Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
diff --git a/tests/test-arm-mptimer.c b/tests/test-arm-mptimer.c
new file mode 100644
index 0000000..cb8f2df
--- /dev/null
+++ b/tests/test-arm-mptimer.c
@@ -0,0 +1,1105 @@
+/*
+ * QTest testcase for the ARM MPTimer
+ *
+ * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "libqtest.h"
+
+#define TIMER_BLOCK_SCALE(s) ((((s) & 0xff) + 1) * 10)
+
+#define TIMER_BLOCK_STEP(scaler, steps_nb) \
+ clock_step(TIMER_BLOCK_SCALE(scaler) * (int64_t)(steps_nb) + 1)
+
+#define TIMER_BASE_PHYS 0x1e000600
+
+#define TIMER_LOAD 0x00
+#define TIMER_COUNTER 0x04
+#define TIMER_CONTROL 0x08
+#define TIMER_INTSTAT 0x0C
+
+#define TIMER_CONTROL_ENABLE (1 << 0)
+#define TIMER_CONTROL_PERIODIC (1 << 1)
+#define TIMER_CONTROL_IT_ENABLE (1 << 2)
+#define TIMER_CONTROL_PRESCALER(p) (((p) & 0xff) << 8)
+
+#define PERIODIC 1
+#define ONESHOT 0
+#define NOSCALE 0
+
+static int nonscaled = NOSCALE;
+static int scaled = 122;
+
+static void timer_load(uint32_t load)
+{
+ writel(TIMER_BASE_PHYS + TIMER_LOAD, load);
+}
+
+static void timer_start(int periodic, uint32_t scale)
+{
+ uint32_t ctl = TIMER_CONTROL_ENABLE | TIMER_CONTROL_PRESCALER(scale);
+
+ if (periodic) {
+ ctl |= TIMER_CONTROL_PERIODIC;
+ }
+
+ writel(TIMER_BASE_PHYS + TIMER_CONTROL, ctl);
+}
+
+static void timer_stop(void)
+{
+ writel(TIMER_BASE_PHYS + TIMER_CONTROL, 0);
+}
+
+static void timer_int_clr(void)
+{
+ writel(TIMER_BASE_PHYS + TIMER_INTSTAT, 1);
+}
+
+static void timer_reset(void)
+{
+ timer_stop();
+ timer_load(0);
+ timer_int_clr();
+}
+
+static uint32_t timer_get_and_clr_int_sts(void)
+{
+ uint32_t int_sts = readl(TIMER_BASE_PHYS + TIMER_INTSTAT);
+
+ if (int_sts) {
+ timer_int_clr();
+ }
+
+ return int_sts;
+}
+
+static uint32_t timer_counter(void)
+{
+ return readl(TIMER_BASE_PHYS + TIMER_COUNTER);
+}
+
+static void timer_set_counter(uint32_t value)
+{
+ writel(TIMER_BASE_PHYS + TIMER_COUNTER, value);
+}
+
+static void test_timer_oneshot(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(9999999);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 9999);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+ g_assert_cmpuint(timer_counter(), ==, 9990000);
+
+ TIMER_BLOCK_STEP(scaler, 9990000);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ TIMER_BLOCK_STEP(scaler, 9990000);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_pause(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(999999999);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 999);
+
+ g_assert_cmpuint(timer_counter(), ==, 999999000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(scaler, 9000);
+
+ g_assert_cmpuint(timer_counter(), ==, 999990000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_stop();
+
+ g_assert_cmpuint(timer_counter(), ==, 999990000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(scaler, 90000);
+
+ g_assert_cmpuint(timer_counter(), ==, 999990000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 999990000);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ TIMER_BLOCK_STEP(scaler, 999990000);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+}
+
+static void test_timer_reload(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 90000);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 90000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_load(UINT32_MAX);
+
+ TIMER_BLOCK_STEP(scaler, 90000);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 90000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_periodic(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+ int repeat = 10;
+
+ timer_reset();
+ timer_load(100);
+ timer_start(PERIODIC, scaler);
+
+ while (repeat--) {
+ clock_step(TIMER_BLOCK_SCALE(scaler) * (101 + repeat) + 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 100 - repeat);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ clock_step(TIMER_BLOCK_SCALE(scaler) * (101 - repeat) - 1);
+ }
+}
+
+static void test_timer_oneshot_to_periodic(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(10000);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1000);
+
+ g_assert_cmpuint(timer_counter(), ==, 9000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 14001);
+
+ g_assert_cmpuint(timer_counter(), ==, 5000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+}
+
+static void test_timer_periodic_to_oneshot(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(99999999);
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 999);
+
+ g_assert_cmpuint(timer_counter(), ==, 99999000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 99999009);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+}
+
+static void test_timer_prescaler(void)
+{
+ timer_reset();
+ timer_load(9999999);
+ timer_start(ONESHOT, NOSCALE);
+
+ TIMER_BLOCK_STEP(NOSCALE, 9999998);
+
+ g_assert_cmpuint(timer_counter(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(NOSCALE, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ timer_reset();
+ timer_load(9999999);
+ timer_start(ONESHOT, 0xAB);
+
+ TIMER_BLOCK_STEP(0xAB, 9999998);
+
+ g_assert_cmpuint(timer_counter(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(0xAB, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+}
+
+static void test_timer_prescaler_on_the_fly(void)
+{
+ timer_reset();
+ timer_load(9999999);
+ timer_start(ONESHOT, NOSCALE);
+
+ TIMER_BLOCK_STEP(NOSCALE, 999);
+
+ g_assert_cmpuint(timer_counter(), ==, 9999000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(ONESHOT, 0xAB);
+
+ TIMER_BLOCK_STEP(0xAB, 9000);
+
+ g_assert_cmpuint(timer_counter(), ==, 9990000);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_set_oneshot_counter_to_0(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_set_counter(0);
+
+ TIMER_BLOCK_STEP(scaler, 10);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_set_periodic_counter_to_0(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_set_counter(0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - (scaler ? 0 : 1));
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ timer_reset();
+ timer_set_counter(UINT32_MAX);
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_set_counter(0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_noload_oneshot(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_noload_periodic(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_zero_load_oneshot(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_zero_load_periodic(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_zero_load_oneshot_to_nonzero(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ timer_load(999);
+
+ TIMER_BLOCK_STEP(scaler, 1001);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+}
+
+static void test_timer_zero_load_periodic_to_nonzero(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+ int i;
+
+ timer_reset();
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ timer_load(1999999);
+
+ for (i = 1; i < 10; i++) {
+ TIMER_BLOCK_STEP(scaler, 2000001);
+
+ g_assert_cmpuint(timer_counter(), ==, 1999999 - i);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+ }
+}
+
+static void test_timer_nonzero_load_oneshot_to_zero(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ timer_load(UINT32_MAX);
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_nonzero_load_periodic_to_zero(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ timer_load(UINT32_MAX);
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_set_periodic_counter_on_the_fly(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(UINT32_MAX / 2);
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX / 2 - 100);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_set_counter(UINT32_MAX);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 100);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_enable_and_set_counter(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ timer_set_counter(UINT32_MAX);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 100);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_set_counter_and_enable(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_set_counter(UINT32_MAX);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 100);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_set_counter_disabled(void)
+{
+ timer_reset();
+ timer_set_counter(999999999);
+
+ TIMER_BLOCK_STEP(NOSCALE, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 999999999);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_load_disabled(void)
+{
+ timer_reset();
+ timer_load(999999999);
+
+ TIMER_BLOCK_STEP(NOSCALE, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 999999999);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_oneshot_with_counter_0_on_start(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(999);
+ timer_set_counter(0);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_periodic_with_counter_0_on_start(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+ int i;
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_set_counter(0);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX + (scaler ? 1 : 0) - 100);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX + (scaler ? 1 : 0) - 200);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_reset();
+ timer_load(1999999);
+ timer_set_counter(0);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ for (i = 2 - (!!scaler ? 1 : 0); i < 10; i++) {
+ TIMER_BLOCK_STEP(scaler, 2000001);
+
+ g_assert_cmpuint(timer_counter(), ==, 1999999 - i);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+ }
+}
+
+static void test_periodic_counter(gconstpointer arg)
+{
+ const int test_load = 10;
+ int scaler = *((int *) arg);
+ int test_val;
+
+ timer_reset();
+ timer_load(test_load);
+ timer_start(PERIODIC, scaler);
+
+ clock_step(1);
+
+ for (test_val = 0; test_val <= test_load; test_val++) {
+ clock_step(TIMER_BLOCK_SCALE(scaler) * test_load);
+ g_assert_cmpint(timer_counter(), ==, test_val);
+ }
+}
+
+static void test_timer_set_counter_periodic_with_zero_load(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_start(PERIODIC, scaler);
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ timer_set_counter(999);
+
+ TIMER_BLOCK_STEP(scaler, 999);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_set_oneshot_load_to_0(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 100);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_set_periodic_load_to_0(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, UINT32_MAX - 100);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_load(0);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 100);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+ g_assert_cmpuint(timer_counter(), ==, 0);
+}
+
+static void test_deferred_trigger(void)
+{
+ int mode = ONESHOT;
+
+again:
+ timer_reset();
+ timer_start(mode, 255);
+
+ clock_step(100);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ timer_reset();
+ timer_load(2);
+ timer_start(mode, 255);
+
+ clock_step(100);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_start(mode, 255);
+
+ clock_step(100);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_set_counter(0);
+
+ clock_step(100);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ timer_reset();
+ timer_load(UINT32_MAX);
+ timer_start(mode, 255);
+
+ clock_step(100);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_load(0);
+
+ clock_step(100);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+
+ if (mode == ONESHOT) {
+ mode = PERIODIC;
+ goto again;
+ }
+}
+
+static void test_timer_zero_load_mode_switch(gconstpointer arg)
+{
+ int scaler = *((int *) arg);
+
+ timer_reset();
+ timer_load(0);
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ timer_start(ONESHOT, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ timer_start(PERIODIC, scaler);
+
+ TIMER_BLOCK_STEP(scaler, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, !!scaler);
+}
+
+static void test_timer_zero_load_prescaled_periodic_to_nonscaled_oneshot(void)
+{
+ timer_reset();
+ timer_load(0);
+ timer_start(PERIODIC, 255);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ timer_start(ONESHOT, NOSCALE);
+
+ TIMER_BLOCK_STEP(NOSCALE, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(NOSCALE, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_zero_load_prescaled_oneshot_to_nonscaled_periodic(void)
+{
+ timer_reset();
+ timer_load(0);
+ timer_start(ONESHOT, 255);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(PERIODIC, NOSCALE);
+
+ TIMER_BLOCK_STEP(NOSCALE, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_zero_load_nonscaled_oneshot_to_prescaled_periodic(void)
+{
+ timer_reset();
+ timer_load(0);
+ timer_start(ONESHOT, NOSCALE);
+
+ TIMER_BLOCK_STEP(NOSCALE, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(PERIODIC, 255);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+static void test_timer_zero_load_nonscaled_periodic_to_prescaled_oneshot(void)
+{
+ timer_reset();
+ timer_load(0);
+ timer_start(PERIODIC, NOSCALE);
+
+ TIMER_BLOCK_STEP(NOSCALE, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ timer_start(ONESHOT, 255);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 1);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+
+ TIMER_BLOCK_STEP(255, 1);
+
+ g_assert_cmpuint(timer_counter(), ==, 0);
+ g_assert_cmpuint(timer_get_and_clr_int_sts(), ==, 0);
+}
+
+int main(int argc, char **argv)
+{
+ int *scaler = &nonscaled;
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_func("mptimer/deferred_trigger", test_deferred_trigger);
+ qtest_add_func("mptimer/load_disabled", test_timer_load_disabled);
+ qtest_add_func("mptimer/set_counter_disabled", test_timer_set_counter_disabled);
+ qtest_add_func("mptimer/zero_load_prescaled_periodic_to_nonscaled_oneshot",
+ test_timer_zero_load_prescaled_periodic_to_nonscaled_oneshot);
+ qtest_add_func("mptimer/zero_load_prescaled_oneshot_to_nonscaled_periodic",
+ test_timer_zero_load_prescaled_oneshot_to_nonscaled_periodic);
+ qtest_add_func("mptimer/zero_load_nonscaled_oneshot_to_prescaled_periodic",
+ test_timer_zero_load_nonscaled_oneshot_to_prescaled_periodic);
+ qtest_add_func("mptimer/zero_load_nonscaled_periodic_to_prescaled_oneshot",
+ test_timer_zero_load_nonscaled_periodic_to_prescaled_oneshot);
+ qtest_add_func("mptimer/prescaler", test_timer_prescaler);
+ qtest_add_func("mptimer/prescaler_on_the_fly", test_timer_prescaler_on_the_fly);
+
+tests_with_prescaler_arg:
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/oneshot scaler=%d", *scaler),
+ scaler, test_timer_oneshot);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/pause scaler=%d", *scaler),
+ scaler, test_timer_pause);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/reload scaler=%d", *scaler),
+ scaler, test_timer_reload);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/periodic scaler=%d", *scaler),
+ scaler, test_timer_periodic);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/oneshot_to_periodic scaler=%d", *scaler),
+ scaler, test_timer_oneshot_to_periodic);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/periodic_to_oneshot scaler=%d", *scaler),
+ scaler, test_timer_periodic_to_oneshot);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/set_oneshot_counter_to_0 scaler=%d", *scaler),
+ scaler, test_timer_set_oneshot_counter_to_0);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/set_periodic_counter_to_0 scaler=%d", *scaler),
+ scaler, test_timer_set_periodic_counter_to_0);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/noload_oneshot scaler=%d", *scaler),
+ scaler, test_timer_noload_oneshot);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/noload_periodic scaler=%d", *scaler),
+ scaler, test_timer_noload_periodic);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/zero_load_oneshot scaler=%d", *scaler),
+ scaler, test_timer_zero_load_oneshot);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/zero_load_periodic scaler=%d", *scaler),
+ scaler, test_timer_zero_load_periodic);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/zero_load_oneshot_to_nonzero scaler=%d", *scaler),
+ scaler, test_timer_zero_load_oneshot_to_nonzero);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/zero_load_periodic_to_nonzero scaler=%d", *scaler),
+ scaler, test_timer_zero_load_periodic_to_nonzero);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/nonzero_load_oneshot_to_zero scaler=%d", *scaler),
+ scaler, test_timer_nonzero_load_oneshot_to_zero);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/nonzero_load_periodic_to_zero scaler=%d", *scaler),
+ scaler, test_timer_nonzero_load_periodic_to_zero);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/set_periodic_counter_on_the_fly scaler=%d", *scaler),
+ scaler, test_timer_set_periodic_counter_on_the_fly);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/enable_and_set_counter scaler=%d", *scaler),
+ scaler, test_timer_enable_and_set_counter);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/set_counter_and_enable scaler=%d", *scaler),
+ scaler, test_timer_set_counter_and_enable);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/oneshot_with_counter_0_on_start scaler=%d", *scaler),
+ scaler, test_timer_oneshot_with_counter_0_on_start);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/periodic_with_counter_0_on_start scaler=%d", *scaler),
+ scaler, test_timer_periodic_with_counter_0_on_start);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/periodic_counter scaler=%d", *scaler),
+ scaler, test_periodic_counter);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/set_counter_periodic_with_zero_load scaler=%d", *scaler),
+ scaler, test_timer_set_counter_periodic_with_zero_load);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/set_oneshot_load_to_0 scaler=%d", *scaler),
+ scaler, test_timer_set_oneshot_load_to_0);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/set_periodic_load_to_0 scaler=%d", *scaler),
+ scaler, test_timer_set_periodic_load_to_0);
+ qtest_add_data_func(
+ g_strdup_printf("mptimer/zero_load_mode_switch scaler=%d", *scaler),
+ scaler, test_timer_zero_load_mode_switch);
+
+ if (scaler == &nonscaled) {
+ scaler = &scaled;
+ goto tests_with_prescaler_arg;
+ }
+
+ qtest_start("-machine vexpress-a9");
+ ret = g_test_run();
+ qtest_end();
+
+ return ret;
+}