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" 18*7bbb12f3SPeter 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 35*7bbb12f3SPeter Maydell #define SSYS_BASE 0x400fe000 36*7bbb12f3SPeter Maydell #define RCC 0x60 37*7bbb12f3SPeter Maydell #define SYSDIV_SHIFT 23 38*7bbb12f3SPeter Maydell #define SYSDIV_LENGTH 4 39*7bbb12f3SPeter 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 70*7bbb12f3SPeter Maydell static void test_clock_change(void) 71*7bbb12f3SPeter Maydell { 72*7bbb12f3SPeter Maydell uint32_t rcc; 73*7bbb12f3SPeter Maydell 74*7bbb12f3SPeter Maydell /* 75*7bbb12f3SPeter Maydell * Test that writing to the stellaris board's RCC register to 76*7bbb12f3SPeter Maydell * change the system clock frequency causes the watchdog 77*7bbb12f3SPeter Maydell * to change the speed it counts at. 78*7bbb12f3SPeter Maydell */ 79*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 80*7bbb12f3SPeter Maydell 81*7bbb12f3SPeter Maydell writel(WDOG_BASE + WDOGCONTROL, 1); 82*7bbb12f3SPeter Maydell writel(WDOG_BASE + WDOGLOAD, 1000); 83*7bbb12f3SPeter Maydell 84*7bbb12f3SPeter Maydell /* Step to just past the 500th tick */ 85*7bbb12f3SPeter Maydell clock_step(80 * 500 + 1); 86*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 87*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500); 88*7bbb12f3SPeter Maydell 89*7bbb12f3SPeter Maydell /* Rewrite RCC.SYSDIV from 16 to 8, so the clock is now 40ns per tick */ 90*7bbb12f3SPeter Maydell rcc = readl(SSYS_BASE + RCC); 91*7bbb12f3SPeter Maydell g_assert_cmpuint(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf); 92*7bbb12f3SPeter Maydell rcc = deposit32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH, 7); 93*7bbb12f3SPeter Maydell writel(SSYS_BASE + RCC, rcc); 94*7bbb12f3SPeter Maydell 95*7bbb12f3SPeter Maydell /* Just past the 1000th tick: timer should have fired */ 96*7bbb12f3SPeter Maydell clock_step(40 * 500); 97*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1); 98*7bbb12f3SPeter Maydell 99*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0); 100*7bbb12f3SPeter Maydell 101*7bbb12f3SPeter Maydell /* VALUE reloads at following tick */ 102*7bbb12f3SPeter Maydell clock_step(41); 103*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000); 104*7bbb12f3SPeter Maydell 105*7bbb12f3SPeter Maydell /* Writing any value to WDOGINTCLR clears the interrupt and reloads */ 106*7bbb12f3SPeter Maydell clock_step(40 * 500); 107*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500); 108*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1); 109*7bbb12f3SPeter Maydell writel(WDOG_BASE + WDOGINTCLR, 0); 110*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000); 111*7bbb12f3SPeter Maydell g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0); 112*7bbb12f3SPeter Maydell } 113*7bbb12f3SPeter 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); 123*7bbb12f3SPeter Maydell qtest_add_func("/cmsdk-apb-watchdog/watchdog_clock_change", 124*7bbb12f3SPeter 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