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
17 #include "qemu/osdep.h"
18 #include "qemu/timer.h"
19 #include "libqtest-single.h"
21 #define TIM_REF_HZ (25000000)
26 #define MODE_ONESHOT (0 << 27)
27 #define MODE_PERIODIC (1 << 27)
30 #define PRESCALE(x) (x)
32 /* Registers shared between all timers in a module. */
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;
47 /* A timer block containing 5 timers. */
48 typedef struct TimerBlock {
53 /* Testdata for testing a particular timer within a timer block. */
54 typedef struct TestData {
55 const TimerBlock *tim;
59 const TimerBlock timer_block[] = {
62 .base_addr = 0xf0008000,
66 .base_addr = 0xf0009000,
70 .base_addr = 0xf000a000,
74 const Timer timer[] = {
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));
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));
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)
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;
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;
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;
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;
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);
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;
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);
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;
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);
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;
339 tim_write_ticr(td, count);
340 tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
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;
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. */
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 running. */
388 static void test_prescaler_change(gconstpointer test_data)
390 const TestData *td = test_data;
391 unsigned int count = 256;
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);
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);
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);
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. */
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;
443 tim_write_ticr(td, count);
444 tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
446 for (i = 0; i < 4; i++) {
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;
470 tim_write_ticr(td, count);
471 tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
473 for (i = 0; i < 4; i++) {
476 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
477 g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
479 tim_write(td, TISR, tim_timer_bit(td));
481 g_assert_cmphex(tim_read(td, TISR), ==, 0);
482 g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
487 * Verifies that the timer behaves correctly when disabled right before and
488 * exactly when it's supposed to expire.
490 static void test_disable_on_expiration(gconstpointer test_data)
492 const TestData *td = test_data;
493 unsigned int count = 8;
494 unsigned int ps = 255;
498 tim_write_ticr(td, count);
499 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
501 clock_step(tim_calculate_step(count, ps) - 1);
503 tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
504 tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
506 tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
507 g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
511 * Constructs a name that includes the timer block, timer and testcase name,
512 * and adds the test to the test suite.
514 static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
516 g_autofree char *full_name = g_strdup_printf(
517 "npcm7xx_timer/tim[%d]/timer[%d]/%s", tim_index(td->tim),
518 timer_index(td->timer), name);
519 qtest_add_data_func(full_name, td, fn);
522 /* Convenience macro for adding a test with a predictable function name. */
523 #define add_test(name, td) tim_add_test(#name, td, test_##name)
525 int main(int argc, char **argv)
527 TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
531 g_test_init(&argc, &argv, NULL);
532 g_test_set_nonfatal_assertions();
534 for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
535 for (j = 0; j < ARRAY_SIZE(timer); j++) {
536 TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
537 td->tim = &timer_block[i];
538 td->timer = &timer[j];
541 add_test(reset_overrides_enable, td);
542 add_test(oneshot_enable_then_disable, td);
543 add_test(oneshot_ps5, td);
544 add_test(oneshot_ps0, td);
545 add_test(oneshot_ps255, td);
546 add_test(oneshot_interrupt, td);
547 add_test(pause_resume, td);
548 add_test(prescaler_change, td);
549 add_test(periodic_no_interrupt, td);
550 add_test(periodic_interrupt, td);
551 add_test(disable_on_expiration, td);
555 qtest_start("-machine npcm750-evb");
556 qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");