19cf5eb29SPeter Maydell /* 29cf5eb29SPeter Maydell * QTest testcase for the CMSDK APB watchdog device 39cf5eb29SPeter Maydell * 49cf5eb29SPeter Maydell * Copyright (c) 2021 Linaro Limited 59cf5eb29SPeter Maydell * 69cf5eb29SPeter Maydell * This program is free software; you can redistribute it and/or modify it 79cf5eb29SPeter Maydell * under the terms of the GNU General Public License as published by the 89cf5eb29SPeter Maydell * Free Software Foundation; either version 2 of the License, or 99cf5eb29SPeter Maydell * (at your option) any later version. 109cf5eb29SPeter Maydell * 119cf5eb29SPeter Maydell * This program is distributed in the hope that it will be useful, but WITHOUT 129cf5eb29SPeter Maydell * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 139cf5eb29SPeter Maydell * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 149cf5eb29SPeter Maydell * for more details. 159cf5eb29SPeter Maydell */ 169cf5eb29SPeter Maydell 179cf5eb29SPeter Maydell #include "qemu/osdep.h" 187bbb12f3SPeter Maydell #include "qemu/bitops.h" 199cf5eb29SPeter Maydell #include "libqtest-single.h" 209cf5eb29SPeter Maydell 219cf5eb29SPeter Maydell /* 229cf5eb29SPeter Maydell * lm3s811evb watchdog; at board startup this runs at 200MHz / 16 == 12.5MHz, 239cf5eb29SPeter Maydell * which is 80ns per tick. 249cf5eb29SPeter Maydell */ 259cf5eb29SPeter Maydell #define WDOG_BASE 0x40000000 269cf5eb29SPeter Maydell 279cf5eb29SPeter Maydell #define WDOGLOAD 0 289cf5eb29SPeter Maydell #define WDOGVALUE 4 299cf5eb29SPeter Maydell #define WDOGCONTROL 8 309cf5eb29SPeter Maydell #define WDOGINTCLR 0xc 319cf5eb29SPeter Maydell #define WDOGRIS 0x10 329cf5eb29SPeter Maydell #define WDOGMIS 0x14 339cf5eb29SPeter Maydell #define WDOGLOCK 0xc00 349cf5eb29SPeter Maydell 357bbb12f3SPeter Maydell #define SSYS_BASE 0x400fe000 367bbb12f3SPeter Maydell #define RCC 0x60 377bbb12f3SPeter Maydell #define SYSDIV_SHIFT 23 387bbb12f3SPeter Maydell #define SYSDIV_LENGTH 4 397bbb12f3SPeter Maydell 409cf5eb29SPeter Maydell static void test_watchdog(void) 419cf5eb29SPeter Maydell { 429cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 439cf5eb29SPeter Maydell 449cf5eb29SPeter Maydell writel(WDOG_BASE + WDOGCONTROL, 1); 459cf5eb29SPeter Maydell writel(WDOG_BASE + WDOGLOAD, 1000); 469cf5eb29SPeter Maydell 479cf5eb29SPeter Maydell /* Step to just past the 500th tick */ 489cf5eb29SPeter Maydell clock_step(500 * 80 + 1); 499cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 509cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500); 519cf5eb29SPeter Maydell 529cf5eb29SPeter Maydell /* Just past the 1000th tick: timer should have fired */ 539cf5eb29SPeter Maydell clock_step(500 * 80); 549cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1); 559cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0); 569cf5eb29SPeter Maydell 579cf5eb29SPeter Maydell /* VALUE reloads at following tick */ 589cf5eb29SPeter Maydell clock_step(80); 599cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000); 609cf5eb29SPeter Maydell 619cf5eb29SPeter Maydell /* Writing any value to WDOGINTCLR clears the interrupt and reloads */ 629cf5eb29SPeter Maydell clock_step(500 * 80); 639cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500); 649cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1); 659cf5eb29SPeter Maydell writel(WDOG_BASE + WDOGINTCLR, 0); 669cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000); 679cf5eb29SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 689cf5eb29SPeter Maydell } 699cf5eb29SPeter Maydell 707bbb12f3SPeter Maydell static void test_clock_change(void) 717bbb12f3SPeter Maydell { 727bbb12f3SPeter Maydell uint32_t rcc; 737bbb12f3SPeter Maydell 747bbb12f3SPeter Maydell /* 757bbb12f3SPeter Maydell * Test that writing to the stellaris board's RCC register to 767bbb12f3SPeter Maydell * change the system clock frequency causes the watchdog 777bbb12f3SPeter Maydell * to change the speed it counts at. 787bbb12f3SPeter Maydell */ 797bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 807bbb12f3SPeter Maydell 817bbb12f3SPeter Maydell writel(WDOG_BASE + WDOGCONTROL, 1); 827bbb12f3SPeter Maydell writel(WDOG_BASE + WDOGLOAD, 1000); 837bbb12f3SPeter Maydell 847bbb12f3SPeter Maydell /* Step to just past the 500th tick */ 857bbb12f3SPeter Maydell clock_step(80 * 500 + 1); 867bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 877bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500); 887bbb12f3SPeter Maydell 897bbb12f3SPeter Maydell /* Rewrite RCC.SYSDIV from 16 to 8, so the clock is now 40ns per tick */ 907bbb12f3SPeter Maydell rcc = readl(SSYS_BASE + RCC); 91*58045186SInès Varhol g_assert_cmphex(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf); 927bbb12f3SPeter Maydell rcc = deposit32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH, 7); 937bbb12f3SPeter Maydell writel(SSYS_BASE + RCC, rcc); 947bbb12f3SPeter Maydell 957bbb12f3SPeter Maydell /* Just past the 1000th tick: timer should have fired */ 967bbb12f3SPeter Maydell clock_step(40 * 500); 977bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1); 987bbb12f3SPeter Maydell 997bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0); 1007bbb12f3SPeter Maydell 1017bbb12f3SPeter Maydell /* VALUE reloads at following tick */ 1027bbb12f3SPeter Maydell clock_step(41); 1037bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000); 1047bbb12f3SPeter Maydell 1057bbb12f3SPeter Maydell /* Writing any value to WDOGINTCLR clears the interrupt and reloads */ 1067bbb12f3SPeter Maydell clock_step(40 * 500); 1077bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500); 1087bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1); 1097bbb12f3SPeter Maydell writel(WDOG_BASE + WDOGINTCLR, 0); 1107bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000); 1117bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 1127bbb12f3SPeter Maydell } 1137bbb12f3SPeter Maydell 1149cf5eb29SPeter Maydell int main(int argc, char **argv) 1159cf5eb29SPeter Maydell { 1169cf5eb29SPeter Maydell int r; 1179cf5eb29SPeter Maydell 1189cf5eb29SPeter Maydell g_test_init(&argc, &argv, NULL); 1199cf5eb29SPeter Maydell 1209cf5eb29SPeter Maydell qtest_start("-machine lm3s811evb"); 1219cf5eb29SPeter Maydell 1229cf5eb29SPeter Maydell qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog); 1237bbb12f3SPeter Maydell qtest_add_func("/cmsdk-apb-watchdog/watchdog_clock_change", 1247bbb12f3SPeter Maydell test_clock_change); 1259cf5eb29SPeter Maydell 1269cf5eb29SPeter Maydell r = g_test_run(); 1279cf5eb29SPeter Maydell 1289cf5eb29SPeter Maydell qtest_end(); 1299cf5eb29SPeter Maydell 1309cf5eb29SPeter Maydell return r; 1319cf5eb29SPeter Maydell } 132