Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-migration-20210726a...
[qemu/armbru.git] / tests / qtest / npcm7xx_timer-test.c
blob83774a5b903b91fee03f116ca72297d92df34af7
1 /*
2 * QTest testcase for the Nuvoton NPCM7xx Timer
4 * Copyright 2020 Google LLC
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
17 #include "qemu/osdep.h"
18 #include "qemu/timer.h"
19 #include "libqtest-single.h"
21 #define TIM_REF_HZ (25000000)
23 /* Bits in TCSRx */
24 #define CEN BIT(30)
25 #define IE BIT(29)
26 #define MODE_ONESHOT (0 << 27)
27 #define MODE_PERIODIC (1 << 27)
28 #define CRST BIT(26)
29 #define CACT BIT(25)
30 #define PRESCALE(x) (x)
32 /* Registers shared between all timers in a module. */
33 #define TISR 0x18
34 #define WTCR 0x1c
35 # define WTCLK(x) ((x) << 10)
37 /* Power-on default; used to re-initialize timers before each test. */
38 #define TCSR_DEFAULT PRESCALE(5)
40 /* Register offsets for a timer within a timer block. */
41 typedef struct Timer {
42 unsigned int tcsr_offset;
43 unsigned int ticr_offset;
44 unsigned int tdr_offset;
45 } Timer;
47 /* A timer block containing 5 timers. */
48 typedef struct TimerBlock {
49 int irq_base;
50 uint64_t base_addr;
51 } TimerBlock;
53 /* Testdata for testing a particular timer within a timer block. */
54 typedef struct TestData {
55 const TimerBlock *tim;
56 const Timer *timer;
57 } TestData;
59 const TimerBlock timer_block[] = {
61 .irq_base = 32,
62 .base_addr = 0xf0008000,
65 .irq_base = 37,
66 .base_addr = 0xf0009000,
69 .irq_base = 42,
70 .base_addr = 0xf000a000,
74 const Timer timer[] = {
76 .tcsr_offset = 0x00,
77 .ticr_offset = 0x08,
78 .tdr_offset = 0x10,
79 }, {
80 .tcsr_offset = 0x04,
81 .ticr_offset = 0x0c,
82 .tdr_offset = 0x14,
83 }, {
84 .tcsr_offset = 0x20,
85 .ticr_offset = 0x28,
86 .tdr_offset = 0x30,
87 }, {
88 .tcsr_offset = 0x24,
89 .ticr_offset = 0x2c,
90 .tdr_offset = 0x34,
91 }, {
92 .tcsr_offset = 0x40,
93 .ticr_offset = 0x48,
94 .tdr_offset = 0x50,
98 /* Returns the index of the timer block. */
99 static int tim_index(const TimerBlock *tim)
101 ptrdiff_t diff = tim - timer_block;
103 g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
105 return diff;
108 /* Returns the index of a timer within a timer block. */
109 static int timer_index(const Timer *t)
111 ptrdiff_t diff = t - timer;
113 g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
115 return diff;
118 /* Returns the irq line for a given timer. */
119 static int tim_timer_irq(const TestData *td)
121 return td->tim->irq_base + timer_index(td->timer);
124 /* Register read/write accessors. */
126 static void tim_write(const TestData *td,
127 unsigned int offset, uint32_t value)
129 writel(td->tim->base_addr + offset, value);
132 static uint32_t tim_read(const TestData *td, unsigned int offset)
134 return readl(td->tim->base_addr + offset);
137 static void tim_write_tcsr(const TestData *td, uint32_t value)
139 tim_write(td, td->timer->tcsr_offset, value);
142 static uint32_t tim_read_tcsr(const TestData *td)
144 return tim_read(td, td->timer->tcsr_offset);
147 static void tim_write_ticr(const TestData *td, uint32_t value)
149 tim_write(td, td->timer->ticr_offset, value);
152 static uint32_t tim_read_ticr(const TestData *td)
154 return tim_read(td, td->timer->ticr_offset);
157 static uint32_t tim_read_tdr(const TestData *td)
159 return tim_read(td, td->timer->tdr_offset);
162 /* Returns the number of nanoseconds to count the given number of cycles. */
163 static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
165 return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
168 /* Returns a bitmask corresponding to the timer under test. */
169 static uint32_t tim_timer_bit(const TestData *td)
171 return BIT(timer_index(td->timer));
174 /* Resets all timers to power-on defaults. */
175 static void tim_reset(const TestData *td)
177 int i, j;
179 /* Reset all the timers, in case a previous test left a timer running. */
180 for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
181 for (j = 0; j < ARRAY_SIZE(timer); j++) {
182 writel(timer_block[i].base_addr + timer[j].tcsr_offset,
183 CRST | TCSR_DEFAULT);
185 writel(timer_block[i].base_addr + TISR, -1);
189 /* Verifies the reset state of a timer. */
190 static void test_reset(gconstpointer test_data)
192 const TestData *td = test_data;
194 tim_reset(td);
196 g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
197 g_assert_cmphex(tim_read_ticr(td), ==, 0);
198 g_assert_cmphex(tim_read_tdr(td), ==, 0);
199 g_assert_cmphex(tim_read(td, TISR), ==, 0);
200 g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
203 /* Verifies that CRST wins if both CEN and CRST are set. */
204 static void test_reset_overrides_enable(gconstpointer test_data)
206 const TestData *td = test_data;
208 tim_reset(td);
210 /* CRST should force CEN to 0 */
211 tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
213 g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
214 g_assert_cmphex(tim_read_tdr(td), ==, 0);
215 g_assert_cmphex(tim_read(td, TISR), ==, 0);
218 /* Verifies the behavior when CEN is set and then cleared. */
219 static void test_oneshot_enable_then_disable(gconstpointer test_data)
221 const TestData *td = test_data;
223 tim_reset(td);
225 /* Enable the timer with zero initial count, then disable it again. */
226 tim_write_tcsr(td, CEN | TCSR_DEFAULT);
227 tim_write_tcsr(td, TCSR_DEFAULT);
229 g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
230 g_assert_cmphex(tim_read_tdr(td), ==, 0);
231 /* Timer interrupt flag should be set, but interrupts are not enabled. */
232 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
233 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
236 /* Verifies that a one-shot timer fires when expected with prescaler 5. */
237 static void test_oneshot_ps5(gconstpointer test_data)
239 const TestData *td = test_data;
240 unsigned int count = 256;
241 unsigned int ps = 5;
243 tim_reset(td);
245 tim_write_ticr(td, count);
246 tim_write_tcsr(td, CEN | PRESCALE(ps));
247 g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
248 g_assert_cmpuint(tim_read_tdr(td), ==, count);
250 clock_step(tim_calculate_step(count, ps) - 1);
252 g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
253 g_assert_cmpuint(tim_read_tdr(td), <, count);
254 g_assert_cmphex(tim_read(td, TISR), ==, 0);
256 clock_step(1);
258 g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
259 g_assert_cmpuint(tim_read_tdr(td), ==, count);
260 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
261 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
263 /* Clear the interrupt flag. */
264 tim_write(td, TISR, tim_timer_bit(td));
265 g_assert_cmphex(tim_read(td, TISR), ==, 0);
266 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
268 /* Verify that this isn't a periodic timer. */
269 clock_step(2 * tim_calculate_step(count, ps));
270 g_assert_cmphex(tim_read(td, TISR), ==, 0);
271 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
274 /* Verifies that a one-shot timer fires when expected with prescaler 0. */
275 static void test_oneshot_ps0(gconstpointer test_data)
277 const TestData *td = test_data;
278 unsigned int count = 1;
279 unsigned int ps = 0;
281 tim_reset(td);
283 tim_write_ticr(td, count);
284 tim_write_tcsr(td, CEN | PRESCALE(ps));
285 g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
286 g_assert_cmpuint(tim_read_tdr(td), ==, count);
288 clock_step(tim_calculate_step(count, ps) - 1);
290 g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
291 g_assert_cmpuint(tim_read_tdr(td), <, count);
292 g_assert_cmphex(tim_read(td, TISR), ==, 0);
294 clock_step(1);
296 g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
297 g_assert_cmpuint(tim_read_tdr(td), ==, count);
298 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
299 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
302 /* Verifies that a one-shot timer fires when expected with highest prescaler. */
303 static void test_oneshot_ps255(gconstpointer test_data)
305 const TestData *td = test_data;
306 unsigned int count = (1U << 24) - 1;
307 unsigned int ps = 255;
309 tim_reset(td);
311 tim_write_ticr(td, count);
312 tim_write_tcsr(td, CEN | PRESCALE(ps));
313 g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
314 g_assert_cmpuint(tim_read_tdr(td), ==, count);
316 clock_step(tim_calculate_step(count, ps) - 1);
318 g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
319 g_assert_cmpuint(tim_read_tdr(td), <, count);
320 g_assert_cmphex(tim_read(td, TISR), ==, 0);
322 clock_step(1);
324 g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
325 g_assert_cmpuint(tim_read_tdr(td), ==, count);
326 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
327 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
330 /* Verifies that a oneshot timer fires an interrupt when expected. */
331 static void test_oneshot_interrupt(gconstpointer test_data)
333 const TestData *td = test_data;
334 unsigned int count = 256;
335 unsigned int ps = 7;
337 tim_reset(td);
339 tim_write_ticr(td, count);
340 tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
342 clock_step_next();
344 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
345 g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
349 * Verifies that the timer can be paused and later resumed, and it still fires
350 * at the right moment.
352 static void test_pause_resume(gconstpointer test_data)
354 const TestData *td = test_data;
355 unsigned int count = 256;
356 unsigned int ps = 1;
358 tim_reset(td);
360 tim_write_ticr(td, count);
361 tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
363 /* Pause the timer halfway to expiration. */
364 clock_step(tim_calculate_step(count / 2, ps));
365 tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
366 g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
368 /* Counter should not advance during the following step. */
369 clock_step(2 * tim_calculate_step(count, ps));
370 g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
371 g_assert_cmphex(tim_read(td, TISR), ==, 0);
372 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
374 /* Resume the timer and run _almost_ to expiration. */
375 tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
376 clock_step(tim_calculate_step(count / 2, ps) - 1);
377 g_assert_cmpuint(tim_read_tdr(td), <, count);
378 g_assert_cmphex(tim_read(td, TISR), ==, 0);
379 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
381 /* Now, run the rest of the way and verify that the interrupt fires. */
382 clock_step(1);
383 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
384 g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
387 /* Verifies that the prescaler can be changed while the timer is runnin. */
388 static void test_prescaler_change(gconstpointer test_data)
390 const TestData *td = test_data;
391 unsigned int count = 256;
392 unsigned int ps = 5;
394 tim_reset(td);
396 tim_write_ticr(td, count);
397 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
399 /* Run a quarter of the way, and change the prescaler. */
400 clock_step(tim_calculate_step(count / 4, ps));
401 g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
402 ps = 2;
403 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
404 /* The counter must not change. */
405 g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
407 /* Run another quarter of the way, and change the prescaler again. */
408 clock_step(tim_calculate_step(count / 4, ps));
409 g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
410 ps = 8;
411 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
412 /* The counter must not change. */
413 g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
415 /* Run another quarter of the way, and change the prescaler again. */
416 clock_step(tim_calculate_step(count / 4, ps));
417 g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
418 ps = 0;
419 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
420 /* The counter must not change. */
421 g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
423 /* Run almost to expiration, and verify the timer didn't fire yet. */
424 clock_step(tim_calculate_step(count / 4, ps) - 1);
425 g_assert_cmpuint(tim_read_tdr(td), <, count);
426 g_assert_cmphex(tim_read(td, TISR), ==, 0);
428 /* Now, run the rest of the way and verify that the timer fires. */
429 clock_step(1);
430 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
433 /* Verifies that a periodic timer automatically restarts after expiration. */
434 static void test_periodic_no_interrupt(gconstpointer test_data)
436 const TestData *td = test_data;
437 unsigned int count = 2;
438 unsigned int ps = 3;
439 int i;
441 tim_reset(td);
443 tim_write_ticr(td, count);
444 tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
446 for (i = 0; i < 4; i++) {
447 clock_step_next();
449 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
450 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
452 tim_write(td, TISR, tim_timer_bit(td));
454 g_assert_cmphex(tim_read(td, TISR), ==, 0);
455 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
459 /* Verifies that a periodict timer fires an interrupt every time it expires. */
460 static void test_periodic_interrupt(gconstpointer test_data)
462 const TestData *td = test_data;
463 unsigned int count = 65535;
464 unsigned int ps = 2;
465 int i;
467 tim_reset(td);
469 tim_write_ticr(td, count);
470 tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
472 for (i = 0; i < 4; i++) {
473 clock_step_next();
475 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
476 g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
478 tim_write(td, TISR, tim_timer_bit(td));
480 g_assert_cmphex(tim_read(td, TISR), ==, 0);
481 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
486 * Verifies that the timer behaves correctly when disabled right before and
487 * exactly when it's supposed to expire.
489 static void test_disable_on_expiration(gconstpointer test_data)
491 const TestData *td = test_data;
492 unsigned int count = 8;
493 unsigned int ps = 255;
495 tim_reset(td);
497 tim_write_ticr(td, count);
498 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
500 clock_step(tim_calculate_step(count, ps) - 1);
502 tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
503 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
504 clock_step(1);
505 tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
506 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
510 * Constructs a name that includes the timer block, timer and testcase name,
511 * and adds the test to the test suite.
513 static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
515 g_autofree char *full_name = g_strdup_printf(
516 "npcm7xx_timer/tim[%d]/timer[%d]/%s", tim_index(td->tim),
517 timer_index(td->timer), name);
518 qtest_add_data_func(full_name, td, fn);
521 /* Convenience macro for adding a test with a predictable function name. */
522 #define add_test(name, td) tim_add_test(#name, td, test_##name)
524 int main(int argc, char **argv)
526 TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
527 int ret;
528 int i, j;
530 g_test_init(&argc, &argv, NULL);
531 g_test_set_nonfatal_assertions();
533 for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
534 for (j = 0; j < ARRAY_SIZE(timer); j++) {
535 TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
536 td->tim = &timer_block[i];
537 td->timer = &timer[j];
539 add_test(reset, td);
540 add_test(reset_overrides_enable, td);
541 add_test(oneshot_enable_then_disable, td);
542 add_test(oneshot_ps5, td);
543 add_test(oneshot_ps0, td);
544 add_test(oneshot_ps255, td);
545 add_test(oneshot_interrupt, td);
546 add_test(pause_resume, td);
547 add_test(prescaler_change, td);
548 add_test(periodic_no_interrupt, td);
549 add_test(periodic_interrupt, td);
550 add_test(disable_on_expiration, td);
554 qtest_start("-machine npcm750-evb");
555 qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
556 ret = g_test_run();
557 qtest_end();
559 return ret;