/* Copyright 2021 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Test USB PD timer module. */ #include "atomic.h" #include "test_util.h" #include "timer.h" #include "usb_pd_timer.h" /* * Verify the bit operations and make sure another port is not affected */ int verify_pd_timers_bit_ops(int prim_port, int sec_port) { for (int bit = 0; bit < PD_TIMER_COUNT; ++bit) { /* Check the initial state */ TEST_EQ(PD_CHK_ACTIVE(prim_port, bit), 0, "%d"); TEST_EQ(PD_CHK_ACTIVE(sec_port, bit), 0, "%d"); PD_SET_ACTIVE(prim_port, bit); for (int i = 0; i < PD_TIMER_COUNT; ++i) { if (i != bit) TEST_EQ(PD_CHK_ACTIVE(prim_port, i), 0, "%d"); else TEST_NE(PD_CHK_ACTIVE(prim_port, i), 0, "%d"); /* Make sure the second port is not affected. */ TEST_EQ(PD_CHK_ACTIVE(sec_port, i), 0, "%d"); } PD_CLR_ACTIVE(prim_port, bit); } /* * Clear one disabled bit at a time and verify it is the only * bit clear. Reset the bit on each iteration of the bit loop. */ for (int bit = 0; bit < PD_TIMER_COUNT; ++bit) { /* Check the initial state */ TEST_NE(PD_CHK_DISABLED(prim_port, bit), 0, "%d"); TEST_NE(PD_CHK_DISABLED(sec_port, bit), 0, "%d"); PD_CLR_DISABLED(prim_port, bit); for (int i = 0; i < PD_TIMER_COUNT; ++i) { if (i != bit) TEST_NE(PD_CHK_DISABLED(prim_port, i), 0, "%d"); else TEST_EQ(PD_CHK_DISABLED(prim_port, i), 0, "%d"); /* Make sure the second port is not affected. */ TEST_NE(PD_CHK_DISABLED(sec_port, i), 0, "%d"); } PD_SET_DISABLED(prim_port, bit); } return EC_SUCCESS; } /* * Verify the init operation of PD timers. */ int test_pd_timers_init(void) { int bit; int prim_port, sec_port; /* * Initialization calling pd_timer_init will initialize the port's * active timer to be clear and disabled timer to be set for all mask * bits */ for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) { prim_port = port; sec_port = (port + 1) % CONFIG_USB_PD_PORT_MAX_COUNT; pd_timer_init(prim_port); for (bit = 0; bit < PD_TIMER_COUNT; ++bit) TEST_EQ(PD_CHK_ACTIVE(prim_port, bit), 0, "%d"); for (bit = 0; bit < PD_TIMER_COUNT; ++bit) TEST_NE(PD_CHK_DISABLED(prim_port, bit), 0, "%d"); /* * Make sure pd_timer_init(sec_port) doesn't affect other ports */ for (bit = 0; bit < PD_TIMER_COUNT; ++bit) { PD_SET_ACTIVE(prim_port, bit); PD_CLR_DISABLED(prim_port, bit); } pd_timer_init(sec_port); for (bit = 0; bit < PD_TIMER_COUNT; ++bit) { TEST_NE(PD_CHK_ACTIVE(prim_port, bit), 0, "%d"); TEST_EQ(PD_CHK_DISABLED(prim_port, bit), 0, "%d"); } } return EC_SUCCESS; } /* * Verify the operation of the underlying bit operations underlying the timer * module. This is technically redundant with the higher level test below, but * it is useful for catching bugs during timer changes. */ int test_pd_timers_bit_ops(void) { int prim_port, sec_port; for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) { prim_port = port; sec_port = (port + 1) % CONFIG_USB_PD_PORT_MAX_COUNT; pd_timer_init(prim_port); pd_timer_init(sec_port); verify_pd_timers_bit_ops(prim_port, sec_port); } return EC_SUCCESS; } int test_pd_timers(void) { int bit; int ms_to_expire; const int port = 0; /* * Initialization calling pd_timer_init will initialize the port's * active timer to be clear and disabled timer to be set for all mask * bits. */ pd_timer_init(port); /* Verify all timers are disabled. */ for (bit = 0; bit < PD_TIMER_COUNT; ++bit) TEST_ASSERT(pd_timer_is_disabled(port, bit)); /* Enable some timers. */ for (bit = 0; bit < 5; ++bit) pd_timer_enable(0, bit, (bit + 1) * 50); /* Verify all timers for enabled/disabled. */ for (bit = 0; bit < PD_TIMER_COUNT; ++bit) { if (bit < 5) TEST_ASSERT(!pd_timer_is_disabled(port, bit)); else TEST_ASSERT(pd_timer_is_disabled(port, bit)); } /* Disable the first timer; verify all timers for enabled/disabled. */ pd_timer_disable(port, 0); TEST_ASSERT(pd_timer_is_disabled(port, 0)); for (bit = 1; bit < 5; ++bit) TEST_ASSERT(!pd_timer_is_disabled(port, bit)); for (; bit < PD_TIMER_COUNT; ++bit) TEST_ASSERT(pd_timer_is_disabled(port, bit)); /* * Verify finding the next timer to expire. * * Timer at BIT(1) is the next to expire and originally had an expire * time of 100ms. So allow for the test's simulated time lapse and * verify in the 90-100 range. */ ms_to_expire = pd_timer_next_expiration(port); TEST_GE(ms_to_expire, 90, "%d"); TEST_LE(ms_to_expire, 100, "%d"); /* Enable the timers in the PRL range. */ for (bit = PR_TIMER_START; bit <= PR_TIMER_END; ++bit) pd_timer_enable(port, bit, 20); /* Verify all timers for enabled/disabled. */ for (bit = 0; bit < PD_TIMER_COUNT; ++bit) { if ((bit > 0 && bit < 5) || (bit >= PR_TIMER_START && bit <= PR_TIMER_END)) TEST_ASSERT(!pd_timer_is_disabled(port, bit)); else TEST_ASSERT(pd_timer_is_disabled(port, bit)); } /* Verify that the PRL timers haven't expired yet. */ for (bit = PR_TIMER_START; bit <= PR_TIMER_END; ++bit) TEST_ASSERT(!pd_timer_is_expired(port, bit)); /* Allow the PRL timers to expire and verify that they have expired. */ msleep(21); for (bit = PR_TIMER_START; bit <= PR_TIMER_END; ++bit) TEST_ASSERT(pd_timer_is_expired(port, bit)); /* Disable the PRL range. */ pd_timer_disable_range(port, PR_TIMER_RANGE); /* Verify all timers for enabled/disabled. */ TEST_ASSERT(pd_timer_is_disabled(port, 0)); for (bit = 1; bit < 5; ++bit) TEST_ASSERT(!pd_timer_is_disabled(port, bit)); for (; bit < PD_TIMER_COUNT; ++bit) TEST_ASSERT(pd_timer_is_disabled(port, bit)); /* * Disable the PE and DPM timer ranges, which contain the previously * enabled timers 1-5. */ pd_timer_disable_range(port, DPM_TIMER_RANGE); pd_timer_disable_range(port, PE_TIMER_RANGE); /* Verify all timers are disabled. */ for (bit = 0; bit < PD_TIMER_COUNT; ++bit) TEST_ASSERT(pd_timer_is_disabled(port, bit)); return EC_SUCCESS; } void run_test(int argc, const char **argv) { RUN_TEST(test_pd_timers_init); RUN_TEST(test_pd_timers_bit_ops); RUN_TEST(test_pd_timers); test_print_result(); }