xref: /qemu/tests/qtest/npcm7xx_timer-test.c (revision 5e6f3db2)
1 /*
2  * QTest testcase for the Nuvoton NPCM7xx Timer
3  *
4  * Copyright 2020 Google LLC
5  *
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.
10  *
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.
15  */
16 
17 #include "qemu/osdep.h"
18 #include "qemu/timer.h"
19 #include "libqtest-single.h"
20 
21 #define TIM_REF_HZ      (25000000)
22 
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)
31 
32 /* Registers shared between all timers in a module. */
33 #define TISR    0x18
34 #define WTCR    0x1c
35 # define WTCLK(x)       ((x) << 10)
36 
37 /* Power-on default; used to re-initialize timers before each test. */
38 #define TCSR_DEFAULT    PRESCALE(5)
39 
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;
46 
47 /* A timer block containing 5 timers. */
48 typedef struct TimerBlock {
49     int irq_base;
50     uint64_t base_addr;
51 } TimerBlock;
52 
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;
58 
59 const TimerBlock timer_block[] = {
60     {
61         .irq_base   = 32,
62         .base_addr  = 0xf0008000,
63     },
64     {
65         .irq_base   = 37,
66         .base_addr  = 0xf0009000,
67     },
68     {
69         .irq_base   = 42,
70         .base_addr  = 0xf000a000,
71     },
72 };
73 
74 const Timer timer[] = {
75     {
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,
95     },
96 };
97 
98 /* Returns the index of the timer block. */
99 static int tim_index(const TimerBlock *tim)
100 {
101     ptrdiff_t diff = tim - timer_block;
102 
103     g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
104 
105     return diff;
106 }
107 
108 /* Returns the index of a timer within a timer block. */
109 static int timer_index(const Timer *t)
110 {
111     ptrdiff_t diff = t - timer;
112 
113     g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
114 
115     return diff;
116 }
117 
118 /* Returns the irq line for a given timer. */
119 static int tim_timer_irq(const TestData *td)
120 {
121     return td->tim->irq_base + timer_index(td->timer);
122 }
123 
124 /* Register read/write accessors. */
125 
126 static void tim_write(const TestData *td,
127                       unsigned int offset, uint32_t value)
128 {
129     writel(td->tim->base_addr + offset, value);
130 }
131 
132 static uint32_t tim_read(const TestData *td, unsigned int offset)
133 {
134     return readl(td->tim->base_addr + offset);
135 }
136 
137 static void tim_write_tcsr(const TestData *td, uint32_t value)
138 {
139     tim_write(td, td->timer->tcsr_offset, value);
140 }
141 
142 static uint32_t tim_read_tcsr(const TestData *td)
143 {
144     return tim_read(td, td->timer->tcsr_offset);
145 }
146 
147 static void tim_write_ticr(const TestData *td, uint32_t value)
148 {
149     tim_write(td, td->timer->ticr_offset, value);
150 }
151 
152 static uint32_t tim_read_ticr(const TestData *td)
153 {
154     return tim_read(td, td->timer->ticr_offset);
155 }
156 
157 static uint32_t tim_read_tdr(const TestData *td)
158 {
159     return tim_read(td, td->timer->tdr_offset);
160 }
161 
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)
164 {
165     return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
166 }
167 
168 /* Returns a bitmask corresponding to the timer under test. */
169 static uint32_t tim_timer_bit(const TestData *td)
170 {
171     return BIT(timer_index(td->timer));
172 }
173 
174 /* Resets all timers to power-on defaults. */
175 static void tim_reset(const TestData *td)
176 {
177     int i, j;
178 
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);
184         }
185         writel(timer_block[i].base_addr + TISR, -1);
186     }
187 }
188 
189 /* Verifies the reset state of a timer. */
190 static void test_reset(gconstpointer test_data)
191 {
192     const TestData *td = test_data;
193 
194     tim_reset(td);
195 
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));
201 }
202 
203 /* Verifies that CRST wins if both CEN and CRST are set. */
204 static void test_reset_overrides_enable(gconstpointer test_data)
205 {
206     const TestData *td = test_data;
207 
208     tim_reset(td);
209 
210     /* CRST should force CEN to 0 */
211     tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
212 
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);
216 }
217 
218 /* Verifies the behavior when CEN is set and then cleared. */
219 static void test_oneshot_enable_then_disable(gconstpointer test_data)
220 {
221     const TestData *td = test_data;
222 
223     tim_reset(td);
224 
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);
228 
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)));
234 }
235 
236 /* Verifies that a one-shot timer fires when expected with prescaler 5. */
237 static void test_oneshot_ps5(gconstpointer test_data)
238 {
239     const TestData *td = test_data;
240     unsigned int count = 256;
241     unsigned int ps = 5;
242 
243     tim_reset(td);
244 
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);
249 
250     clock_step(tim_calculate_step(count, ps) - 1);
251 
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);
255 
256     clock_step(1);
257 
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)));
262 
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)));
267 
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)));
272 }
273 
274 /* Verifies that a one-shot timer fires when expected with prescaler 0. */
275 static void test_oneshot_ps0(gconstpointer test_data)
276 {
277     const TestData *td = test_data;
278     unsigned int count = 1;
279     unsigned int ps = 0;
280 
281     tim_reset(td);
282 
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);
287 
288     clock_step(tim_calculate_step(count, ps) - 1);
289 
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);
293 
294     clock_step(1);
295 
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)));
300 }
301 
302 /* Verifies that a one-shot timer fires when expected with highest prescaler. */
303 static void test_oneshot_ps255(gconstpointer test_data)
304 {
305     const TestData *td = test_data;
306     unsigned int count = (1U << 24) - 1;
307     unsigned int ps = 255;
308 
309     tim_reset(td);
310 
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);
315 
316     clock_step(tim_calculate_step(count, ps) - 1);
317 
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);
321 
322     clock_step(1);
323 
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)));
328 }
329 
330 /* Verifies that a oneshot timer fires an interrupt when expected. */
331 static void test_oneshot_interrupt(gconstpointer test_data)
332 {
333     const TestData *td = test_data;
334     unsigned int count = 256;
335     unsigned int ps = 7;
336 
337     tim_reset(td);
338 
339     tim_write_ticr(td, count);
340     tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
341 
342     clock_step_next();
343 
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)));
346 }
347 
348 /*
349  * Verifies that the timer can be paused and later resumed, and it still fires
350  * at the right moment.
351  */
352 static void test_pause_resume(gconstpointer test_data)
353 {
354     const TestData *td = test_data;
355     unsigned int count = 256;
356     unsigned int ps = 1;
357 
358     tim_reset(td);
359 
360     tim_write_ticr(td, count);
361     tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
362 
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);
367 
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)));
373 
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)));
380 
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)));
385 }
386 
387 /* Verifies that the prescaler can be changed while the timer is running. */
388 static void test_prescaler_change(gconstpointer test_data)
389 {
390     const TestData *td = test_data;
391     unsigned int count = 256;
392     unsigned int ps = 5;
393 
394     tim_reset(td);
395 
396     tim_write_ticr(td, count);
397     tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
398 
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);
406 
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);
414 
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);
422 
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);
427 
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));
431 }
432 
433 /* Verifies that a periodic timer automatically restarts after expiration. */
434 static void test_periodic_no_interrupt(gconstpointer test_data)
435 {
436     const TestData *td = test_data;
437     unsigned int count = 2;
438     unsigned int ps = 3;
439     int i;
440 
441     tim_reset(td);
442 
443     tim_write_ticr(td, count);
444     tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
445 
446     for (i = 0; i < 4; i++) {
447         clock_step_next();
448 
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)));
451 
452         tim_write(td, TISR, tim_timer_bit(td));
453 
454         g_assert_cmphex(tim_read(td, TISR), ==, 0);
455         g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
456     }
457 }
458 
459 /* Verifies that a periodict timer fires an interrupt every time it expires. */
460 static void test_periodic_interrupt(gconstpointer test_data)
461 {
462     const TestData *td = test_data;
463     unsigned int count = 65535;
464     unsigned int ps = 2;
465     int i;
466 
467     tim_reset(td);
468 
469     tim_write_ticr(td, count);
470     tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
471 
472     for (i = 0; i < 4; i++) {
473         clock_step_next();
474 
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)));
477 
478         tim_write(td, TISR, tim_timer_bit(td));
479 
480         g_assert_cmphex(tim_read(td, TISR), ==, 0);
481         g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
482     }
483 }
484 
485 /*
486  * Verifies that the timer behaves correctly when disabled right before and
487  * exactly when it's supposed to expire.
488  */
489 static void test_disable_on_expiration(gconstpointer test_data)
490 {
491     const TestData *td = test_data;
492     unsigned int count = 8;
493     unsigned int ps = 255;
494 
495     tim_reset(td);
496 
497     tim_write_ticr(td, count);
498     tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
499 
500     clock_step(tim_calculate_step(count, ps) - 1);
501 
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));
507 }
508 
509 /*
510  * Constructs a name that includes the timer block, timer and testcase name,
511  * and adds the test to the test suite.
512  */
513 static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
514 {
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);
519 }
520 
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)
523 
524 int main(int argc, char **argv)
525 {
526     TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
527     int ret;
528     int i, j;
529 
530     g_test_init(&argc, &argv, NULL);
531     g_test_set_nonfatal_assertions();
532 
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];
538 
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);
551         }
552     }
553 
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();
558 
559     return ret;
560 }
561