qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

npcm7xx_timer-test.c (17054B)


      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 runnin. */
    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 }