xref: /openbmc/qemu/tests/qtest/npcm7xx_timer-test.c (revision 2a6299fb137e8f0fcee205f584c52481cb8461f7)
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. */
tim_index(const TimerBlock * tim)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. */
timer_index(const Timer * t)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. */
tim_timer_irq(const TestData * td)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  
tim_write(const TestData * td,unsigned int offset,uint32_t value)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  
tim_read(const TestData * td,unsigned int offset)132  static uint32_t tim_read(const TestData *td, unsigned int offset)
133  {
134      return readl(td->tim->base_addr + offset);
135  }
136  
tim_write_tcsr(const TestData * td,uint32_t value)137  static void tim_write_tcsr(const TestData *td, uint32_t value)
138  {
139      tim_write(td, td->timer->tcsr_offset, value);
140  }
141  
tim_read_tcsr(const TestData * td)142  static uint32_t tim_read_tcsr(const TestData *td)
143  {
144      return tim_read(td, td->timer->tcsr_offset);
145  }
146  
tim_write_ticr(const TestData * td,uint32_t value)147  static void tim_write_ticr(const TestData *td, uint32_t value)
148  {
149      tim_write(td, td->timer->ticr_offset, value);
150  }
151  
tim_read_ticr(const TestData * td)152  static uint32_t tim_read_ticr(const TestData *td)
153  {
154      return tim_read(td, td->timer->ticr_offset);
155  }
156  
tim_read_tdr(const TestData * td)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. */
tim_calculate_step(uint32_t count,uint32_t prescale)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. */
tim_timer_bit(const TestData * td)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. */
tim_reset(const TestData * td)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. */
test_reset(gconstpointer test_data)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. */
test_reset_overrides_enable(gconstpointer test_data)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. */
test_oneshot_enable_then_disable(gconstpointer test_data)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. */
test_oneshot_ps5(gconstpointer test_data)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. */
test_oneshot_ps0(gconstpointer test_data)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. */
test_oneshot_ps255(gconstpointer test_data)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. */
test_oneshot_interrupt(gconstpointer test_data)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   */
test_pause_resume(gconstpointer test_data)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. */
test_prescaler_change(gconstpointer test_data)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. */
test_periodic_no_interrupt(gconstpointer test_data)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. */
test_periodic_interrupt(gconstpointer test_data)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      clock_step_next();
469  
470      tim_write_ticr(td, count);
471      tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
472  
473      for (i = 0; i < 4; i++) {
474          clock_step_next();
475  
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)));
478  
479          tim_write(td, TISR, tim_timer_bit(td));
480  
481          g_assert_cmphex(tim_read(td, TISR), ==, 0);
482          g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
483      }
484  }
485  
486  /*
487   * Verifies that the timer behaves correctly when disabled right before and
488   * exactly when it's supposed to expire.
489   */
test_disable_on_expiration(gconstpointer test_data)490  static void test_disable_on_expiration(gconstpointer test_data)
491  {
492      const TestData *td = test_data;
493      unsigned int count = 8;
494      unsigned int ps = 255;
495  
496      tim_reset(td);
497  
498      tim_write_ticr(td, count);
499      tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
500  
501      clock_step(tim_calculate_step(count, ps) - 1);
502  
503      tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
504      tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
505      clock_step(1);
506      tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
507      g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
508  }
509  
510  /*
511   * Constructs a name that includes the timer block, timer and testcase name,
512   * and adds the test to the test suite.
513   */
tim_add_test(const char * name,const TestData * td,GTestDataFunc fn)514  static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
515  {
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);
520  }
521  
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)
524  
main(int argc,char ** argv)525  int main(int argc, char **argv)
526  {
527      TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
528      int ret;
529      int i, j;
530  
531      g_test_init(&argc, &argv, NULL);
532      g_test_set_nonfatal_assertions();
533  
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];
539  
540              add_test(reset, td);
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);
552          }
553      }
554  
555      qtest_start("-machine npcm750-evb");
556      qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
557      ret = g_test_run();
558      qtest_end();
559  
560      return ret;
561  }
562