Last active
July 20, 2016 17:00
-
-
Save digetx/dbd46109503b1a91941a to your computer and use it in GitHub Desktop.
ARM MPtimer tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef __KERNEL__ | |
#include <linux/delay.h> | |
#include <linux/io.h> | |
#include <linux/module.h> | |
#define abort() {pr_err("%s: %d\n", __func__, __LINE__); errored = 1; return;} | |
#define assert(a) if (!(a)) abort() | |
#define msleep(d) mdelay(d) | |
#define sleep(d) mdelay((d) * 1000) | |
#define UINT32_MAX U32_MAX | |
#else | |
#define _GNU_SOURCE | |
#include <assert.h> | |
#include <fcntl.h> | |
#include <sched.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#define pr_info(...) printf(__VA_ARGS__) | |
#define pr_err(...) fprintf(stderr, __VA_ARGS__) | |
#define msleep(d) usleep((d) * 1000) | |
#endif | |
#define RUN_TEST(t) if (!errored) t; | |
// #define TIMER_BASE_PHYS 0x1e000620 /* VExpress WDT */ | |
#define TIMER_BASE_PHYS 0x50040600 | |
#define TIMER_LOAD 0x00 | |
#define TIMER_COUNTER 0x04 | |
#define TIMER_CONTROL 0x08 | |
#define TIMER_INTSTAT 0x0C | |
#define TIMER_CONTROL_ENABLE (1 << 0) | |
#define TIMER_CONTROL_PERIODIC (1 << 1) | |
#define TIMER_CONTROL_IT_ENABLE (1 << 2) | |
#define TIMER_CONTROL_PRESCALER(v) (((v) & 0xff) << 8) | |
#define PERIODIC 1 | |
#define ONESHOT 0 | |
#define NOSCALE 0 | |
static int errored; | |
static int log_enb = 1; | |
static int scaler_test = 0; | |
#ifdef __KERNEL__ | |
static void __iomem *timer_base; | |
static uint32_t read_mem(u32 offset) | |
{ | |
return readl(timer_base + offset); | |
} | |
static void write_mem(u32 offset, uint32_t value) | |
{ | |
writel(value, timer_base + offset); | |
} | |
static void map_mem(u32 phys_address, u32 size) | |
{ | |
timer_base = ioremap_nocache(phys_address, size); | |
} | |
#else | |
static uint32_t * volatile timer_base_virt; | |
static uint32_t read_mem(off_t offset) | |
{ | |
return timer_base_virt[offset >> 2]; | |
} | |
static void write_mem(off_t offset, uint32_t value) | |
{ | |
timer_base_virt[offset >> 2] = value; | |
} | |
static void map_mem(off_t phys_address, off_t size) | |
{ | |
off_t PageOffset, PageAddress; | |
size_t PagesSize; | |
int mem_dev; | |
mem_dev = open("/dev/mem", O_RDWR | O_SYNC); | |
assert(mem_dev != -1); | |
PageOffset = phys_address % getpagesize(); | |
PageAddress = phys_address - PageOffset; | |
PagesSize = ((size / getpagesize()) + 1) * getpagesize(); | |
timer_base_virt = mmap(NULL, PagesSize, PROT_READ | PROT_WRITE, | |
MAP_SHARED, mem_dev, PageAddress); | |
assert(timer_base_virt != MAP_FAILED); | |
timer_base_virt += PageOffset >> 2; | |
} | |
#endif | |
static void timer_load(uint32_t load) | |
{ | |
if (log_enb) { | |
pr_info("%s: %u\n", __func__, load); | |
} | |
write_mem(TIMER_LOAD, load); | |
} | |
static void timer_start(int periodic, uint32_t scale) | |
{ | |
uint32_t ctl = TIMER_CONTROL_ENABLE; | |
scale += scaler_test; | |
if (log_enb) { | |
pr_info("%s: periodic=%d, scale=%d\n", | |
__func__, periodic, scale); | |
} | |
if (periodic) | |
ctl |= TIMER_CONTROL_PERIODIC; | |
if (0) | |
ctl |= TIMER_CONTROL_IT_ENABLE; | |
ctl |= TIMER_CONTROL_PRESCALER(scale); | |
write_mem(TIMER_CONTROL, ctl); | |
} | |
static void timer_stop(void) | |
{ | |
if (log_enb) { | |
pr_info("%s\n", __func__); | |
} | |
write_mem(TIMER_CONTROL, 0); | |
} | |
static void timer_int_clr(void) | |
{ | |
if (log_enb) { | |
pr_info("%s\n", __func__); | |
} | |
write_mem(TIMER_INTSTAT, 1); | |
} | |
static void timer_reset(void) | |
{ | |
if (log_enb) { | |
pr_info("%s: +\n", __func__); | |
} | |
timer_stop(); | |
timer_load(0); | |
timer_int_clr(); | |
if (log_enb) { | |
pr_info("%s: -\n", __func__); | |
} | |
} | |
static uint32_t timer_get_and_clr_int_sts(void) | |
{ | |
uint32_t int_sts = read_mem(TIMER_INTSTAT); | |
if (log_enb) { | |
pr_info("%s: %u\n", __func__, int_sts); | |
} | |
if (int_sts) { | |
timer_int_clr(); | |
} | |
return int_sts; | |
} | |
static uint32_t timer_counter(void) | |
{ | |
uint32_t counter = read_mem(TIMER_COUNTER); | |
if (log_enb) { | |
pr_info("%s: %u\n", __func__, counter); | |
} | |
return counter; | |
} | |
static void timer_set_counter(uint32_t value) | |
{ | |
if (log_enb) { | |
pr_info("%s: %u\n", __func__, value); | |
} | |
write_mem(TIMER_COUNTER, value); | |
} | |
static void test_timer_oneshot(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(scaler_test ? 999999 : 9999999); | |
timer_start(ONESHOT, NOSCALE); | |
assert(timer_get_and_clr_int_sts() == 0); | |
while (timer_counter()) { | |
sleep(1); | |
} | |
assert(timer_get_and_clr_int_sts() == 1); | |
} | |
static void test_timer_pause(void) | |
{ | |
uint32_t prev; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(scaler_test ? 9999999 : 999999999); | |
timer_start(ONESHOT, NOSCALE); | |
sleep(1); | |
prev = timer_counter(); | |
sleep(1); | |
timer_stop(); | |
assert(prev < scaler_test ? 9999999 : 999999999); | |
assert(timer_counter() != 0); | |
assert(timer_counter() < prev); | |
assert(timer_counter() < scaler_test ? 9999999 : 999999999); | |
assert(timer_get_and_clr_int_sts() == 0); | |
prev = timer_counter(); | |
sleep(1); | |
assert(timer_counter() == prev); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_start(ONESHOT, NOSCALE); | |
do { | |
prev = timer_counter(); | |
sleep(1); | |
assert(prev == 0 || prev > timer_counter() ); | |
} while (timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
assert(timer_counter() == 0); | |
sleep(1); | |
assert(timer_get_and_clr_int_sts() == 0); | |
assert(timer_counter() == 0); | |
} | |
static void test_timer_reload(void) | |
{ | |
uint32_t prev; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(ONESHOT, NOSCALE); | |
sleep(2); | |
prev = timer_counter(); | |
timer_load(UINT32_MAX); | |
sleep(1); | |
timer_stop(); | |
assert(timer_counter() > prev); | |
assert(timer_counter() < UINT32_MAX); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_periodic(void) | |
{ | |
int repeat = 10; | |
int it_set = 0; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(scaler_test ? 9999 : 999999); | |
timer_start(PERIODIC, NOSCALE); | |
do { | |
msleep(3); | |
timer_counter(); | |
if (timer_get_and_clr_int_sts()) { | |
it_set++; | |
} | |
} while (repeat--); | |
timer_stop(); | |
assert(it_set > 1); | |
} | |
static void test_timer_oneshot_to_periodic(void) | |
{ | |
uint32_t prev; | |
int repeat = 10; | |
int passed = 0; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(scaler_test ? 9999 : 999999); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(100); | |
prev = timer_counter(); | |
timer_start(PERIODIC, NOSCALE); | |
do { | |
msleep(3); | |
if (timer_counter() > prev) { | |
passed = 1; | |
break; | |
} | |
} while (repeat--); | |
timer_stop(); | |
assert(passed == 1); | |
assert(timer_get_and_clr_int_sts() == 1); | |
} | |
static void test_timer_periodic_to_oneshot(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(scaler_test ? 999999 : 99999999); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
timer_start(ONESHOT, NOSCALE); | |
sleep(5); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
} | |
static void test_timer_prescaler(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(9999999); | |
timer_start(ONESHOT, NOSCALE); | |
sleep(5); | |
timer_stop(); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
timer_reset(); | |
timer_load(9999999); | |
timer_start(ONESHOT, 0xAB); | |
sleep(5); | |
timer_stop(); | |
assert(timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_prescaler_on_the_fly(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(9999999); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(1); | |
timer_start(ONESHOT, 0xAB); | |
sleep(5); | |
timer_stop(); | |
assert(timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_set_oneshot_count_to_0(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(1); | |
assert(timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_set_counter(0); | |
msleep(3); | |
timer_stop(); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_set_periodic_count_to_0(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(1); | |
assert(timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_set_counter(0); | |
msleep(3); | |
timer_stop(); | |
assert(timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_reset(); | |
timer_set_counter(UINT32_MAX); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(1); | |
assert(timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_set_counter(0); | |
msleep(3); | |
timer_stop(); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_clean_start_oneshot(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_clean_start_periodic(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_zero_load_oneshot(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(0); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_zero_load_periodic(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(0); | |
sleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
sleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_zero_load_oneshot_to_nonzero(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(999); | |
sleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
} | |
static void test_timer_zero_load_periodic_to_nonzero(void) | |
{ | |
int repeat = 10; | |
int it_set = 0; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(scaler_test ? 1999 : 199999); | |
do { | |
msleep(3); | |
timer_counter(); | |
if (timer_get_and_clr_int_sts()) { | |
it_set++; | |
} | |
} while (repeat--); | |
timer_stop(); | |
assert(it_set > 1); | |
} | |
static void test_timer_nonzero_load_oneshot_to_zero(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(UINT32_MAX); | |
timer_load(0); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_nonzero_load_periodic_to_zero(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_load(UINT32_MAX); | |
timer_load(0); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_set_periodic_count_on_the_fly(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX / 2); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_counter() < UINT32_MAX / 2); | |
timer_set_counter(UINT32_MAX); | |
msleep(3); | |
timer_stop(); | |
assert(timer_counter() > UINT32_MAX / 2); | |
assert(timer_counter() < UINT32_MAX); | |
} | |
static void test_timer_enable_and_set_count(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_set_counter(UINT32_MAX); | |
msleep(3); | |
timer_stop(); | |
assert(timer_counter() > 0); | |
assert(timer_counter() < UINT32_MAX); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_set_count_and_enable(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_set_counter(UINT32_MAX); | |
timer_start(ONESHOT, NOSCALE); | |
sleep(1); | |
timer_stop(); | |
assert(timer_counter() > 0); | |
assert(timer_counter() < UINT32_MAX); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_set_count_disabled(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_set_counter(999999999); | |
sleep(1); | |
assert(timer_counter() == 999999999); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_set_load_disabled(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(999999999); | |
sleep(1); | |
assert(timer_counter() == 999999999); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_oneshot_with_count_0_on_start(void) | |
{ | |
timer_reset(); | |
timer_load(999); | |
timer_set_counter(0); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_periodic_with_count_0_on_start(void) | |
{ | |
int repeat = 10; | |
int it_set = 0; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_set_counter(0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
timer_stop(); | |
assert(timer_counter() != 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_reset(); | |
timer_load(scaler_test ? 1999 : 199999); | |
timer_set_counter(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_start(PERIODIC, NOSCALE); | |
assert(timer_get_and_clr_int_sts() == 0); | |
do { | |
msleep(3); | |
timer_counter(); | |
if (timer_get_and_clr_int_sts()) { | |
it_set++; | |
} | |
} while (repeat--); | |
timer_stop(); | |
assert(it_set > 1); | |
} | |
static void test_ptimer_limit_bug(void) | |
{ | |
#define TEST_LOAD 10 | |
int test_val; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(TEST_LOAD); | |
timer_start(PERIODIC, NOSCALE); | |
for (test_val = 0; test_val <= TEST_LOAD; test_val++) { | |
int retries = 999; | |
uint32_t counter; | |
pr_info("checking %d ...\n", test_val); | |
do { | |
counter = timer_counter(); | |
assert(counter <= TEST_LOAD); | |
msleep(3); | |
} while (counter != test_val && --retries); | |
assert(retries > 0); | |
} | |
timer_stop(); | |
} | |
static void test_ptimer_freq_period_bug(void) | |
{ | |
uint32_t counter; | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
counter = timer_counter(); | |
timer_start(ONESHOT, 1); | |
msleep(1); | |
assert(timer_counter() < counter); | |
timer_stop(); | |
} | |
static void test_timer_set_count_periodic_with_zero_load(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(PERIODIC, NOSCALE); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
timer_set_counter(999); | |
sleep(1); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
sleep(1); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_it_bit(void) | |
{ | |
int mode = PERIODIC; | |
pr_info("### %s ###\n", __func__); | |
scaler_test = 0; | |
timer_reset(); | |
timer_start(ONESHOT, 0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_set_counter(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_set_counter(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_start(ONESHOT, 1); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
msleep(3); | |
timer_set_counter(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
msleep(3); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
timer_reset(); | |
timer_set_counter(UINT32_MAX); | |
timer_start(ONESHOT, 0); | |
timer_set_counter(0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
msleep(3); | |
timer_set_counter(0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_reset(); | |
timer_set_counter(UINT32_MAX); | |
timer_start(ONESHOT, 255); | |
timer_set_counter(0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_set_counter(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(ONESHOT, 0); | |
timer_load(0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(ONESHOT, 255); | |
timer_load(0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_load(0); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
#define ASSERT(p) \ | |
msleep(5); \ | |
if (!(p)) { \ | |
pr_err("scaler = 0x%X %s\n", scaler_test, \ | |
mode == PERIODIC ? "periodic" : "oneshot"); \ | |
assert(0); \ | |
} \ | |
msleep(5); | |
again: | |
for (scaler_test = 0; scaler_test <= 0xFF; scaler_test++) { | |
int sts_expected = !!scaler_test; | |
int o = (mode == ONESHOT); | |
timer_reset(); | |
timer_start(mode, NOSCALE); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_load(0); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 1 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : (scaler_test != 0xFF))); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (scaler_test != 0xFF)); | |
timer_reset(); | |
timer_start(mode, NOSCALE); | |
timer_set_counter(0); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 1 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : (scaler_test != 0xFF))); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (scaler_test != 0xFF)); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(mode, NOSCALE); | |
ASSERT(timer_counter() > 0); | |
ASSERT(timer_get_and_clr_int_sts() == 0); | |
timer_set_counter(0); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == 0); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 0 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == 0); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 0 : (scaler_test != 0xFF))); | |
timer_reset(); | |
timer_set_counter(UINT32_MAX); | |
timer_start(mode, NOSCALE); | |
ASSERT(timer_get_and_clr_int_sts() == 0); | |
timer_load(0); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 1 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : (scaler_test != 0xFF))); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (scaler_test != 0xFF)); | |
timer_reset(); | |
timer_start(mode, NOSCALE); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_start(!mode, NOSCALE); | |
ASSERT(timer_get_and_clr_int_sts() == (sts_expected)); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 0 : sts_expected)); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 1 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : (scaler_test != 0xFF))); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (scaler_test != 0xFF)); | |
timer_reset(); | |
timer_start(mode, NOSCALE); | |
timer_load(0); | |
timer_set_counter(0); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 1 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : (scaler_test != 0xFF))); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (scaler_test != 0xFF)); | |
timer_reset(); | |
timer_set_counter(UINT32_MAX); | |
timer_start(mode, NOSCALE); | |
timer_set_counter(0); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 1 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : (scaler_test != 0xFF))); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (scaler_test != 0xFF)); | |
timer_reset(); | |
timer_set_counter(UINT32_MAX); | |
timer_start(mode, NOSCALE); | |
timer_load(0); | |
ASSERT(timer_get_and_clr_int_sts() == sts_expected); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : sts_expected)); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (!o ? 1 : (scaler_test != 0xFF))); | |
ASSERT(timer_get_and_clr_int_sts() == (o ? 0 : (scaler_test != 0xFF))); | |
timer_start(mode, 1); | |
ASSERT(timer_get_and_clr_int_sts() == (scaler_test != 0xFF)); | |
} | |
#undef ASSERT | |
if (mode == PERIODIC) { | |
mode = ONESHOT; | |
goto again; | |
} | |
} | |
static void test_timer_set_oneshot_load_to_0(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_load(0); | |
msleep(3); | |
timer_stop(); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_set_periodic_load_to_0(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
timer_load(0); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
assert(timer_counter() == 0); | |
} | |
static void test_delayed_it_set_icount_only(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_start(PERIODIC, 255); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
} | |
static void test_delayed_it_set(void) | |
{ | |
int mode = ONESHOT; | |
int tries, passed; | |
pr_info("### %s ###\n", __func__); | |
#define MAX_TRIES 5 | |
again: | |
tries = MAX_TRIES; | |
passed = 0; | |
while (tries--) { | |
timer_reset(); | |
timer_start(mode, 255); | |
if (timer_counter() == 0) { | |
passed = 1; | |
break; | |
} | |
} | |
msleep(3); | |
assert(passed == 1); | |
assert(timer_get_and_clr_int_sts() == 1); | |
tries = MAX_TRIES; | |
passed = 0; | |
while (tries--) { | |
timer_reset(); | |
timer_load(2); | |
timer_start(mode, 255); | |
if (timer_counter() == 2) { | |
passed = 1; | |
break; | |
} | |
} | |
msleep(3); | |
assert(passed == 1); | |
assert(timer_get_and_clr_int_sts() == 1); | |
tries = MAX_TRIES; | |
passed = 1; | |
while (tries--) { | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(mode, 255); | |
timer_set_counter(0); | |
if (timer_get_and_clr_int_sts() == 1) { | |
passed = 0; | |
break; | |
} | |
} | |
assert(passed == 1); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
tries = MAX_TRIES; | |
passed = 1; | |
while (tries--) { | |
timer_reset(); | |
timer_load(UINT32_MAX); | |
timer_start(mode, 255); | |
timer_load(0); | |
if (timer_get_and_clr_int_sts() == 1) { | |
passed = 0; | |
break; | |
} | |
} | |
assert(passed == 1); | |
msleep(3); | |
assert(timer_get_and_clr_int_sts() == 1); | |
if (mode == ONESHOT) { | |
mode = PERIODIC; | |
goto again; | |
} | |
} | |
static void test_timer_zero_load_mode_switch(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(0); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
msleep(3); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == !!scaler_test); | |
} | |
static void test_timer_zero_load_prescaled_periodic_to_nonscaled_oneshot(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(0); | |
timer_start(PERIODIC, 255); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_zero_load_prescaled_oneshot_to_nonscaled_periodic(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(0); | |
timer_start(ONESHOT, 255); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
static void test_timer_zero_load_nonscaled_oneshot_to_prescaled_periodic(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(0); | |
timer_start(ONESHOT, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_start(PERIODIC, 255); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
} | |
static void test_timer_zero_load_nonscaled_periodic_to_prescaled_oneshot(void) | |
{ | |
pr_info("### %s ###\n", __func__); | |
timer_reset(); | |
timer_load(0); | |
timer_start(PERIODIC, NOSCALE); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
timer_start(ONESHOT, 255); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 1); | |
msleep(3); | |
assert(timer_counter() == 0); | |
assert(timer_get_and_clr_int_sts() == 0); | |
} | |
#ifndef __KERNEL__ | |
static void set_cpu_affinity(void) | |
{ | |
cpu_set_t mask; | |
CPU_ZERO(&mask); | |
CPU_SET(0, &mask); | |
assert(sched_setaffinity(0, sizeof(mask), &mask) == 0); | |
} | |
int main(void) | |
{ | |
set_cpu_affinity(); | |
#else | |
static int mptimer_tests(void) | |
{ | |
#endif | |
map_mem(TIMER_BASE_PHYS, 0x10); | |
RUN_TEST( test_delayed_it_set_icount_only() ); | |
RUN_TEST( test_ptimer_limit_bug() ); | |
RUN_TEST( test_delayed_it_set() ); | |
RUN_TEST( test_timer_zero_load_prescaled_periodic_to_nonscaled_oneshot() ); | |
RUN_TEST( test_timer_zero_load_prescaled_oneshot_to_nonscaled_periodic() ); | |
RUN_TEST( test_timer_zero_load_nonscaled_oneshot_to_prescaled_periodic() ); | |
RUN_TEST( test_timer_zero_load_nonscaled_periodic_to_prescaled_oneshot() ); | |
RUN_TEST( test_timer_prescaler() ); | |
RUN_TEST( test_timer_prescaler_on_the_fly() ); | |
start: | |
RUN_TEST( test_timer_set_count_disabled() ); | |
RUN_TEST( test_timer_set_load_disabled() ); | |
RUN_TEST( test_timer_oneshot() ); | |
RUN_TEST( test_timer_pause() ); | |
RUN_TEST( test_timer_reload() ); | |
RUN_TEST( test_timer_periodic() ); | |
RUN_TEST( test_timer_oneshot_to_periodic() ); | |
RUN_TEST( test_timer_periodic_to_oneshot() ); | |
RUN_TEST( test_timer_set_oneshot_count_to_0() ); | |
RUN_TEST( test_timer_set_periodic_count_to_0() ); | |
RUN_TEST( test_timer_clean_start_oneshot() ); | |
RUN_TEST( test_timer_clean_start_periodic() ); | |
RUN_TEST( test_timer_zero_load_oneshot() ); | |
RUN_TEST( test_timer_zero_load_periodic() ); | |
RUN_TEST( test_timer_zero_load_oneshot_to_nonzero() ); | |
RUN_TEST( test_timer_zero_load_periodic_to_nonzero() ); | |
RUN_TEST( test_timer_nonzero_load_oneshot_to_zero() ); | |
RUN_TEST( test_timer_nonzero_load_periodic_to_zero() ); | |
RUN_TEST( test_timer_set_periodic_count_on_the_fly() ); | |
RUN_TEST( test_timer_enable_and_set_count() ); | |
RUN_TEST( test_timer_set_count_and_enable() ); | |
RUN_TEST( test_timer_oneshot_with_count_0_on_start() ); | |
RUN_TEST( test_timer_periodic_with_count_0_on_start() ); | |
RUN_TEST( test_ptimer_freq_period_bug() ); | |
RUN_TEST( test_timer_set_count_periodic_with_zero_load() ); | |
RUN_TEST( test_timer_set_oneshot_load_to_0() ); | |
RUN_TEST( test_timer_set_periodic_load_to_0() ); | |
RUN_TEST( test_timer_zero_load_mode_switch() ); | |
if (scaler_test == 0) { | |
scaler_test = 122; | |
goto start; | |
} | |
RUN_TEST( test_it_bit() ); | |
if (errored) { | |
pr_err("tests failed!!!\n"); | |
} else { | |
pr_info("tests passed\n"); | |
} | |
#ifdef __KERNEL__ | |
return -1; | |
} | |
module_init(mptimer_tests); | |
MODULE_LICENSE("GPL"); | |
#else | |
return 0; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment