14cb44571SInès Varhol /*
24cb44571SInès Varhol * QTest testcase for STM32L4x5_EXTI
34cb44571SInès Varhol *
44cb44571SInès Varhol * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
54cb44571SInès Varhol * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
64cb44571SInès Varhol *
74cb44571SInès Varhol * This work is licensed under the terms of the GNU GPL, version 2 or later.
84cb44571SInès Varhol * See the COPYING file in the top-level directory.
94cb44571SInès Varhol */
104cb44571SInès Varhol
114cb44571SInès Varhol #include "qemu/osdep.h"
124cb44571SInès Varhol #include "libqtest-single.h"
134cb44571SInès Varhol
144cb44571SInès Varhol #define EXTI_BASE_ADDR 0x40010400
154cb44571SInès Varhol #define EXTI_IMR1 0x00
164cb44571SInès Varhol #define EXTI_EMR1 0x04
174cb44571SInès Varhol #define EXTI_RTSR1 0x08
184cb44571SInès Varhol #define EXTI_FTSR1 0x0C
194cb44571SInès Varhol #define EXTI_SWIER1 0x10
204cb44571SInès Varhol #define EXTI_PR1 0x14
214cb44571SInès Varhol #define EXTI_IMR2 0x20
224cb44571SInès Varhol #define EXTI_EMR2 0x24
234cb44571SInès Varhol #define EXTI_RTSR2 0x28
244cb44571SInès Varhol #define EXTI_FTSR2 0x2C
254cb44571SInès Varhol #define EXTI_SWIER2 0x30
264cb44571SInès Varhol #define EXTI_PR2 0x34
274cb44571SInès Varhol
284cb44571SInès Varhol #define NVIC_ISER 0xE000E100
294cb44571SInès Varhol #define NVIC_ISPR 0xE000E200
304cb44571SInès Varhol #define NVIC_ICPR 0xE000E280
314cb44571SInès Varhol
324cb44571SInès Varhol #define EXTI0_IRQ 6
334cb44571SInès Varhol #define EXTI1_IRQ 7
34397424f8SInès Varhol #define EXTI5_9_IRQ 23
354cb44571SInès Varhol #define EXTI35_IRQ 1
364cb44571SInès Varhol
enable_nvic_irq(unsigned int n)374cb44571SInès Varhol static void enable_nvic_irq(unsigned int n)
384cb44571SInès Varhol {
394cb44571SInès Varhol writel(NVIC_ISER, 1 << n);
404cb44571SInès Varhol }
414cb44571SInès Varhol
unpend_nvic_irq(unsigned int n)424cb44571SInès Varhol static void unpend_nvic_irq(unsigned int n)
434cb44571SInès Varhol {
444cb44571SInès Varhol writel(NVIC_ICPR, 1 << n);
454cb44571SInès Varhol }
464cb44571SInès Varhol
check_nvic_pending(unsigned int n)474cb44571SInès Varhol static bool check_nvic_pending(unsigned int n)
484cb44571SInès Varhol {
494cb44571SInès Varhol return readl(NVIC_ISPR) & (1 << n);
504cb44571SInès Varhol }
514cb44571SInès Varhol
exti_writel(unsigned int offset,uint32_t value)524cb44571SInès Varhol static void exti_writel(unsigned int offset, uint32_t value)
534cb44571SInès Varhol {
544cb44571SInès Varhol writel(EXTI_BASE_ADDR + offset, value);
554cb44571SInès Varhol }
564cb44571SInès Varhol
exti_readl(unsigned int offset)574cb44571SInès Varhol static uint32_t exti_readl(unsigned int offset)
584cb44571SInès Varhol {
594cb44571SInès Varhol return readl(EXTI_BASE_ADDR + offset);
604cb44571SInès Varhol }
614cb44571SInès Varhol
exti_set_irq(int num,int level)624cb44571SInès Varhol static void exti_set_irq(int num, int level)
634cb44571SInès Varhol {
644cb44571SInès Varhol qtest_set_irq_in(global_qtest, "/machine/soc/exti", NULL,
654cb44571SInès Varhol num, level);
664cb44571SInès Varhol }
674cb44571SInès Varhol
test_reg_write_read(void)684cb44571SInès Varhol static void test_reg_write_read(void)
694cb44571SInès Varhol {
704cb44571SInès Varhol /* Test that non-reserved bits in xMR and xTSR can be set and cleared */
714cb44571SInès Varhol
724cb44571SInès Varhol exti_writel(EXTI_IMR1, 0xFFFFFFFF);
7358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_IMR1), ==, 0xFFFFFFFF);
744cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000000);
7558045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_IMR1), ==, 0x00000000);
764cb44571SInès Varhol
774cb44571SInès Varhol exti_writel(EXTI_EMR1, 0xFFFFFFFF);
7858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_EMR1), ==, 0xFFFFFFFF);
794cb44571SInès Varhol exti_writel(EXTI_EMR1, 0x00000000);
8058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_EMR1), ==, 0x00000000);
814cb44571SInès Varhol
824cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0xFFFFFFFF);
8358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x007DFFFF);
844cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0x00000000);
8558045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x00000000);
864cb44571SInès Varhol
874cb44571SInès Varhol exti_writel(EXTI_FTSR1, 0xFFFFFFFF);
8858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x007DFFFF);
894cb44571SInès Varhol exti_writel(EXTI_FTSR1, 0x00000000);
9058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x00000000);
914cb44571SInès Varhol
924cb44571SInès Varhol exti_writel(EXTI_IMR2, 0xFFFFFFFF);
9358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x000000FF);
944cb44571SInès Varhol exti_writel(EXTI_IMR2, 0x00000000);
9558045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x00000000);
964cb44571SInès Varhol
974cb44571SInès Varhol exti_writel(EXTI_EMR2, 0xFFFFFFFF);
9858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x000000FF);
994cb44571SInès Varhol exti_writel(EXTI_EMR2, 0x00000000);
10058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x00000000);
1014cb44571SInès Varhol
1024cb44571SInès Varhol exti_writel(EXTI_RTSR2, 0xFFFFFFFF);
10358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000078);
1044cb44571SInès Varhol exti_writel(EXTI_RTSR2, 0x00000000);
10558045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
1064cb44571SInès Varhol
1074cb44571SInès Varhol exti_writel(EXTI_FTSR2, 0xFFFFFFFF);
10858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000078);
1094cb44571SInès Varhol exti_writel(EXTI_FTSR2, 0x00000000);
11058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
1114cb44571SInès Varhol }
1124cb44571SInès Varhol
test_direct_lines_write(void)1134cb44571SInès Varhol static void test_direct_lines_write(void)
1144cb44571SInès Varhol {
1154cb44571SInès Varhol /* Test that direct lines reserved bits are not written to */
1164cb44571SInès Varhol
1174cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0xFF820000);
11858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x00000000);
1194cb44571SInès Varhol
1204cb44571SInès Varhol exti_writel(EXTI_FTSR1, 0xFF820000);
12158045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x00000000);
1224cb44571SInès Varhol
1234cb44571SInès Varhol exti_writel(EXTI_SWIER1, 0xFF820000);
12458045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000000);
1254cb44571SInès Varhol
1264cb44571SInès Varhol exti_writel(EXTI_PR1, 0xFF820000);
12758045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
1284cb44571SInès Varhol
1294cb44571SInès Varhol exti_writel(EXTI_RTSR2, 0x00000087);
13058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
1314cb44571SInès Varhol
1324cb44571SInès Varhol exti_writel(EXTI_FTSR2, 0x00000087);
13358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
1344cb44571SInès Varhol
1354cb44571SInès Varhol exti_writel(EXTI_SWIER2, 0x00000087);
13658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
1374cb44571SInès Varhol
1384cb44571SInès Varhol exti_writel(EXTI_PR2, 0x00000087);
13958045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
1404cb44571SInès Varhol }
1414cb44571SInès Varhol
test_reserved_bits_write(void)1424cb44571SInès Varhol static void test_reserved_bits_write(void)
1434cb44571SInès Varhol {
1444cb44571SInès Varhol /* Test that reserved bits stay are not written to */
1454cb44571SInès Varhol
1464cb44571SInès Varhol exti_writel(EXTI_IMR2, 0xFFFFFF00);
14758045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x00000000);
1484cb44571SInès Varhol
1494cb44571SInès Varhol exti_writel(EXTI_EMR2, 0xFFFFFF00);
15058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x00000000);
1514cb44571SInès Varhol
1524cb44571SInès Varhol exti_writel(EXTI_RTSR2, 0xFFFFFF00);
15358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
1544cb44571SInès Varhol
1554cb44571SInès Varhol exti_writel(EXTI_FTSR2, 0xFFFFFF00);
15658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
1574cb44571SInès Varhol
1584cb44571SInès Varhol exti_writel(EXTI_SWIER2, 0xFFFFFF00);
15958045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
1604cb44571SInès Varhol
1614cb44571SInès Varhol exti_writel(EXTI_PR2, 0xFFFFFF00);
16258045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
1634cb44571SInès Varhol }
1644cb44571SInès Varhol
test_software_interrupt(void)1654cb44571SInès Varhol static void test_software_interrupt(void)
1664cb44571SInès Varhol {
1674cb44571SInès Varhol /*
1684cb44571SInès Varhol * Test that we can launch a software irq by :
1694cb44571SInès Varhol * - enabling its line in IMR
1704cb44571SInès Varhol * - and then setting a bit from '0' to '1' in SWIER
1714cb44571SInès Varhol *
1724cb44571SInès Varhol * And that the interruption stays pending in NVIC
1734cb44571SInès Varhol * even after clearing the pending bit in PR.
1744cb44571SInès Varhol */
1754cb44571SInès Varhol
1764cb44571SInès Varhol /*
1774cb44571SInès Varhol * Testing interrupt line EXTI0
1784cb44571SInès Varhol * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
1794cb44571SInès Varhol */
1804cb44571SInès Varhol
1814cb44571SInès Varhol enable_nvic_irq(EXTI0_IRQ);
1824cb44571SInès Varhol /* Check that there are no interrupts already pending in PR */
18358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
1844cb44571SInès Varhol /* Check that this specific interrupt isn't pending in NVIC */
1854cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
1864cb44571SInès Varhol
1874cb44571SInès Varhol /* Enable interrupt line EXTI0 */
1884cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000001);
1894cb44571SInès Varhol /* Set the right SWIER bit from '0' to '1' */
1904cb44571SInès Varhol exti_writel(EXTI_SWIER1, 0x00000000);
1914cb44571SInès Varhol exti_writel(EXTI_SWIER1, 0x00000001);
1924cb44571SInès Varhol
1934cb44571SInès Varhol /* Check that the write in SWIER was effective */
19458045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000001);
1954cb44571SInès Varhol /* Check that the corresponding pending bit in PR is set */
19658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
1974cb44571SInès Varhol /* Check that the corresponding interrupt is pending in the NVIC */
1984cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI0_IRQ));
1994cb44571SInès Varhol
2004cb44571SInès Varhol /* Clear the pending bit in PR */
2014cb44571SInès Varhol exti_writel(EXTI_PR1, 0x00000001);
2024cb44571SInès Varhol
2034cb44571SInès Varhol /* Check that the write in PR was effective */
20458045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
2054cb44571SInès Varhol /* Check that the corresponding bit in SWIER was cleared */
20658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000000);
2074cb44571SInès Varhol /* Check that the interrupt is still pending in the NVIC */
2084cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI0_IRQ));
2094cb44571SInès Varhol
2104cb44571SInès Varhol /*
2114cb44571SInès Varhol * Testing interrupt line EXTI35
2124cb44571SInès Varhol * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
2134cb44571SInès Varhol */
2144cb44571SInès Varhol
2154cb44571SInès Varhol enable_nvic_irq(EXTI35_IRQ);
2164cb44571SInès Varhol /* Check that there are no interrupts already pending */
21758045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
2184cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI35_IRQ));
2194cb44571SInès Varhol
2204cb44571SInès Varhol /* Enable interrupt line EXTI0 */
2214cb44571SInès Varhol exti_writel(EXTI_IMR2, 0x00000008);
2224cb44571SInès Varhol /* Set the right SWIER bit from '0' to '1' */
2234cb44571SInès Varhol exti_writel(EXTI_SWIER2, 0x00000000);
2244cb44571SInès Varhol exti_writel(EXTI_SWIER2, 0x00000008);
2254cb44571SInès Varhol
2264cb44571SInès Varhol /* Check that the write in SWIER was effective */
22758045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000008);
2284cb44571SInès Varhol /* Check that the corresponding pending bit in PR is set */
22958045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000008);
2304cb44571SInès Varhol /* Check that the corresponding interrupt is pending in the NVIC */
2314cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI35_IRQ));
2324cb44571SInès Varhol
2334cb44571SInès Varhol /* Clear the pending bit in PR */
2344cb44571SInès Varhol exti_writel(EXTI_PR2, 0x00000008);
2354cb44571SInès Varhol
2364cb44571SInès Varhol /* Check that the write in PR was effective */
23758045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
2384cb44571SInès Varhol /* Check that the corresponding bit in SWIER was cleared */
23958045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
2404cb44571SInès Varhol /* Check that the interrupt is still pending in the NVIC */
2414cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI35_IRQ));
2424cb44571SInès Varhol
2434cb44571SInès Varhol /* Clean NVIC */
2444cb44571SInès Varhol unpend_nvic_irq(EXTI0_IRQ);
2454cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
2464cb44571SInès Varhol unpend_nvic_irq(EXTI35_IRQ);
2474cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI35_IRQ));
2484cb44571SInès Varhol }
2494cb44571SInès Varhol
test_edge_selector(void)2504cb44571SInès Varhol static void test_edge_selector(void)
2514cb44571SInès Varhol {
2524cb44571SInès Varhol enable_nvic_irq(EXTI0_IRQ);
2534cb44571SInès Varhol
2544cb44571SInès Varhol /* Configure EXTI line 0 irq on rising edge */
2554cb44571SInès Varhol exti_set_irq(0, 1);
2564cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000001);
2574cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0x00000001);
2584cb44571SInès Varhol exti_writel(EXTI_FTSR1, 0x00000000);
2594cb44571SInès Varhol
2604cb44571SInès Varhol /* Test that an irq is raised on rising edge only */
2614cb44571SInès Varhol exti_set_irq(0, 0);
26258045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
2634cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
2644cb44571SInès Varhol
2654cb44571SInès Varhol exti_set_irq(0, 1);
26658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
2674cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI0_IRQ));
2684cb44571SInès Varhol
2694cb44571SInès Varhol /* Clean the test */
2704cb44571SInès Varhol exti_writel(EXTI_PR1, 0x00000001);
27158045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
2724cb44571SInès Varhol unpend_nvic_irq(EXTI0_IRQ);
2734cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
2744cb44571SInès Varhol
2754cb44571SInès Varhol /* Configure EXTI line 0 irq on falling edge */
2764cb44571SInès Varhol exti_set_irq(0, 0);
2774cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000001);
2784cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0x00000000);
2794cb44571SInès Varhol exti_writel(EXTI_FTSR1, 0x00000001);
2804cb44571SInès Varhol
2814cb44571SInès Varhol /* Test that an irq is raised on falling edge only */
2824cb44571SInès Varhol exti_set_irq(0, 1);
28358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
2844cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
2854cb44571SInès Varhol
2864cb44571SInès Varhol exti_set_irq(0, 0);
28758045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
2884cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI0_IRQ));
2894cb44571SInès Varhol
2904cb44571SInès Varhol /* Clean the test */
2914cb44571SInès Varhol exti_writel(EXTI_PR1, 0x00000001);
29258045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
2934cb44571SInès Varhol unpend_nvic_irq(EXTI0_IRQ);
2944cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
2954cb44571SInès Varhol
2964cb44571SInès Varhol /* Configure EXTI line 0 irq on falling and rising edge */
2974cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000001);
2984cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0x00000001);
2994cb44571SInès Varhol exti_writel(EXTI_FTSR1, 0x00000001);
3004cb44571SInès Varhol
3014cb44571SInès Varhol /* Test that an irq is raised on rising edge */
3024cb44571SInès Varhol exti_set_irq(0, 1);
30358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
3044cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI0_IRQ));
3054cb44571SInès Varhol
3064cb44571SInès Varhol /* Clean the test */
3074cb44571SInès Varhol exti_writel(EXTI_PR1, 0x00000001);
30858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
3094cb44571SInès Varhol unpend_nvic_irq(EXTI0_IRQ);
3104cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
3114cb44571SInès Varhol
3124cb44571SInès Varhol /* Test that an irq is raised on falling edge */
3134cb44571SInès Varhol exti_set_irq(0, 0);
31458045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
3154cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI0_IRQ));
3164cb44571SInès Varhol
3174cb44571SInès Varhol /* Clean the test */
3184cb44571SInès Varhol exti_writel(EXTI_PR1, 0x00000001);
31958045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
3204cb44571SInès Varhol unpend_nvic_irq(EXTI0_IRQ);
3214cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
3224cb44571SInès Varhol
3234cb44571SInès Varhol /* Configure EXTI line 0 irq without selecting an edge trigger */
3244cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000001);
3254cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0x00000000);
3264cb44571SInès Varhol exti_writel(EXTI_FTSR1, 0x00000000);
3274cb44571SInès Varhol
3284cb44571SInès Varhol /* Test that no irq is raised */
3294cb44571SInès Varhol exti_set_irq(0, 1);
33058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
3314cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
3324cb44571SInès Varhol
3334cb44571SInès Varhol exti_set_irq(0, 0);
33458045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
3354cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
3364cb44571SInès Varhol }
3374cb44571SInès Varhol
test_no_software_interrupt(void)3384cb44571SInès Varhol static void test_no_software_interrupt(void)
3394cb44571SInès Varhol {
3404cb44571SInès Varhol /*
3414cb44571SInès Varhol * Test that software irq doesn't happen when :
3424cb44571SInès Varhol * - corresponding bit in IMR isn't set
3434cb44571SInès Varhol * - SWIER is set to 1 before IMR is set to 1
3444cb44571SInès Varhol */
3454cb44571SInès Varhol
3464cb44571SInès Varhol /*
3474cb44571SInès Varhol * Testing interrupt line EXTI0
3484cb44571SInès Varhol * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
3494cb44571SInès Varhol */
3504cb44571SInès Varhol
3514cb44571SInès Varhol enable_nvic_irq(EXTI0_IRQ);
3524cb44571SInès Varhol /* Check that there are no interrupts already pending in PR */
35358045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
3544cb44571SInès Varhol /* Check that this specific interrupt isn't pending in NVIC */
3554cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
3564cb44571SInès Varhol
3574cb44571SInès Varhol /* Mask interrupt line EXTI0 */
3584cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000000);
3594cb44571SInès Varhol /* Set the corresponding SWIER bit from '0' to '1' */
3604cb44571SInès Varhol exti_writel(EXTI_SWIER1, 0x00000000);
3614cb44571SInès Varhol exti_writel(EXTI_SWIER1, 0x00000001);
3624cb44571SInès Varhol
3634cb44571SInès Varhol /* Check that the write in SWIER was effective */
36458045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000001);
3654cb44571SInès Varhol /* Check that the pending bit in PR wasn't set */
36658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
3674cb44571SInès Varhol /* Check that the interrupt isn't pending in NVIC */
3684cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
3694cb44571SInès Varhol
3704cb44571SInès Varhol /* Enable interrupt line EXTI0 */
3714cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000001);
3724cb44571SInès Varhol
3734cb44571SInès Varhol /* Check that the pending bit in PR wasn't set */
37458045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
3754cb44571SInès Varhol /* Check that the interrupt isn't pending in NVIC */
3764cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI0_IRQ));
3774cb44571SInès Varhol
3784cb44571SInès Varhol /*
3794cb44571SInès Varhol * Testing interrupt line EXTI35
3804cb44571SInès Varhol * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
3814cb44571SInès Varhol */
3824cb44571SInès Varhol
3834cb44571SInès Varhol enable_nvic_irq(EXTI35_IRQ);
3844cb44571SInès Varhol /* Check that there are no interrupts already pending in PR */
38558045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
3864cb44571SInès Varhol /* Check that this specific interrupt isn't pending in NVIC */
3874cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI35_IRQ));
3884cb44571SInès Varhol
3894cb44571SInès Varhol /* Mask interrupt line EXTI35 */
3904cb44571SInès Varhol exti_writel(EXTI_IMR2, 0x00000000);
3914cb44571SInès Varhol /* Set the corresponding SWIER bit from '0' to '1' */
3924cb44571SInès Varhol exti_writel(EXTI_SWIER2, 0x00000000);
3934cb44571SInès Varhol exti_writel(EXTI_SWIER2, 0x00000008);
3944cb44571SInès Varhol
3954cb44571SInès Varhol /* Check that the write in SWIER was effective */
39658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000008);
3974cb44571SInès Varhol /* Check that the pending bit in PR wasn't set */
39858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
3994cb44571SInès Varhol /* Check that the interrupt isn't pending in NVIC */
4004cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI35_IRQ));
4014cb44571SInès Varhol
4024cb44571SInès Varhol /* Enable interrupt line EXTI35 */
4034cb44571SInès Varhol exti_writel(EXTI_IMR2, 0x00000008);
4044cb44571SInès Varhol
4054cb44571SInès Varhol /* Check that the pending bit in PR wasn't set */
40658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
4074cb44571SInès Varhol /* Check that the interrupt isn't pending in NVIC */
4084cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI35_IRQ));
4094cb44571SInès Varhol }
4104cb44571SInès Varhol
test_masked_interrupt(void)4114cb44571SInès Varhol static void test_masked_interrupt(void)
4124cb44571SInès Varhol {
4134cb44571SInès Varhol /*
4144cb44571SInès Varhol * Test that irq doesn't happen when :
4154cb44571SInès Varhol * - corresponding bit in IMR isn't set
4164cb44571SInès Varhol * - SWIER is set to 1 before IMR is set to 1
4174cb44571SInès Varhol */
4184cb44571SInès Varhol
4194cb44571SInès Varhol /*
4204cb44571SInès Varhol * Testing interrupt line EXTI1
4214cb44571SInès Varhol * with rising edge from GPIOx pin 1
4224cb44571SInès Varhol */
4234cb44571SInès Varhol
4244cb44571SInès Varhol enable_nvic_irq(EXTI1_IRQ);
4254cb44571SInès Varhol /* Check that there are no interrupts already pending in PR */
42658045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
4274cb44571SInès Varhol /* Check that this specific interrupt isn't pending in NVIC */
4284cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI1_IRQ));
4294cb44571SInès Varhol
4304cb44571SInès Varhol /* Mask interrupt line EXTI1 */
4314cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000000);
4324cb44571SInès Varhol
4334cb44571SInès Varhol /* Configure interrupt on rising edge */
4344cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0x00000002);
4354cb44571SInès Varhol
4364cb44571SInès Varhol /* Simulate rising edge from GPIO line 1 */
4374cb44571SInès Varhol exti_set_irq(1, 1);
4384cb44571SInès Varhol
4394cb44571SInès Varhol /* Check that the pending bit in PR wasn't set */
44058045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
4414cb44571SInès Varhol /* Check that the interrupt isn't pending in NVIC */
4424cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI1_IRQ));
4434cb44571SInès Varhol
4444cb44571SInès Varhol /* Enable interrupt line EXTI1 */
4454cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000002);
4464cb44571SInès Varhol
4474cb44571SInès Varhol /* Check that the pending bit in PR wasn't set */
44858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
4494cb44571SInès Varhol /* Check that the interrupt isn't pending in NVIC */
4504cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI1_IRQ));
451*58c782deSInès Varhol
452*58c782deSInès Varhol /* Clean EXTI */
453*58c782deSInès Varhol exti_set_irq(1, 0);
4544cb44571SInès Varhol }
4554cb44571SInès Varhol
test_interrupt(void)4564cb44571SInès Varhol static void test_interrupt(void)
4574cb44571SInès Varhol {
4584cb44571SInès Varhol /*
4594cb44571SInès Varhol * Test that we can launch an irq by :
4604cb44571SInès Varhol * - enabling its line in IMR
4614cb44571SInès Varhol * - configuring interrupt on rising edge
4624cb44571SInès Varhol * - and then setting the input line from '0' to '1'
4634cb44571SInès Varhol *
4644cb44571SInès Varhol * And that the interruption stays pending in NVIC
4654cb44571SInès Varhol * even after clearing the pending bit in PR.
4664cb44571SInès Varhol */
4674cb44571SInès Varhol
4684cb44571SInès Varhol /*
4694cb44571SInès Varhol * Testing interrupt line EXTI1
4704cb44571SInès Varhol * with rising edge from GPIOx pin 1
4714cb44571SInès Varhol */
4724cb44571SInès Varhol
4734cb44571SInès Varhol enable_nvic_irq(EXTI1_IRQ);
4744cb44571SInès Varhol /* Check that there are no interrupts already pending in PR */
47558045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
4764cb44571SInès Varhol /* Check that this specific interrupt isn't pending in NVIC */
4774cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI1_IRQ));
4784cb44571SInès Varhol
4794cb44571SInès Varhol /* Enable interrupt line EXTI1 */
4804cb44571SInès Varhol exti_writel(EXTI_IMR1, 0x00000002);
4814cb44571SInès Varhol
4824cb44571SInès Varhol /* Configure interrupt on rising edge */
4834cb44571SInès Varhol exti_writel(EXTI_RTSR1, 0x00000002);
4844cb44571SInès Varhol
4854cb44571SInès Varhol /* Simulate rising edge from GPIO line 1 */
4864cb44571SInès Varhol exti_set_irq(1, 1);
4874cb44571SInès Varhol
4884cb44571SInès Varhol /* Check that the pending bit in PR was set */
48958045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000002);
4904cb44571SInès Varhol /* Check that the interrupt is pending in NVIC */
4914cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI1_IRQ));
4924cb44571SInès Varhol
4934cb44571SInès Varhol /* Clear the pending bit in PR */
4944cb44571SInès Varhol exti_writel(EXTI_PR1, 0x00000002);
4954cb44571SInès Varhol
4964cb44571SInès Varhol /* Check that the write in PR was effective */
49758045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
4984cb44571SInès Varhol /* Check that the interrupt is still pending in the NVIC */
4994cb44571SInès Varhol g_assert_true(check_nvic_pending(EXTI1_IRQ));
5004cb44571SInès Varhol
5014cb44571SInès Varhol /* Clean NVIC */
5024cb44571SInès Varhol unpend_nvic_irq(EXTI1_IRQ);
5034cb44571SInès Varhol g_assert_false(check_nvic_pending(EXTI1_IRQ));
504*58c782deSInès Varhol
505*58c782deSInès Varhol /* Clean EXTI */
506*58c782deSInès Varhol exti_set_irq(1, 0);
5074cb44571SInès Varhol }
5084cb44571SInès Varhol
test_orred_interrupts(void)509397424f8SInès Varhol static void test_orred_interrupts(void)
510397424f8SInès Varhol {
511397424f8SInès Varhol /*
512397424f8SInès Varhol * For lines EXTI5..9 (fanned-in to NVIC irq 23),
513397424f8SInès Varhol * test that raising the line pends interrupt
514397424f8SInès Varhol * 23 in NVIC.
515397424f8SInès Varhol */
516397424f8SInès Varhol enable_nvic_irq(EXTI5_9_IRQ);
517397424f8SInès Varhol /* Check that there are no interrupts already pending in PR */
51858045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
519397424f8SInès Varhol /* Check that this specific interrupt isn't pending in NVIC */
520397424f8SInès Varhol g_assert_false(check_nvic_pending(EXTI5_9_IRQ));
521397424f8SInès Varhol
522397424f8SInès Varhol /* Enable interrupt lines EXTI[5..9] */
523397424f8SInès Varhol exti_writel(EXTI_IMR1, (0x1F << 5));
524397424f8SInès Varhol
525397424f8SInès Varhol /* Configure interrupt on rising edge */
526397424f8SInès Varhol exti_writel(EXTI_RTSR1, (0x1F << 5));
527397424f8SInès Varhol
528397424f8SInès Varhol /* Raise GPIO line i, check that the interrupt is pending */
529397424f8SInès Varhol for (unsigned i = 5; i < 10; i++) {
530397424f8SInès Varhol exti_set_irq(i, 1);
53158045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 1 << i);
532397424f8SInès Varhol g_assert_true(check_nvic_pending(EXTI5_9_IRQ));
533397424f8SInès Varhol
534397424f8SInès Varhol exti_writel(EXTI_PR1, 1 << i);
53558045186SInès Varhol g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
536397424f8SInès Varhol g_assert_true(check_nvic_pending(EXTI5_9_IRQ));
537397424f8SInès Varhol
538397424f8SInès Varhol unpend_nvic_irq(EXTI5_9_IRQ);
539397424f8SInès Varhol g_assert_false(check_nvic_pending(EXTI5_9_IRQ));
540*58c782deSInès Varhol
541*58c782deSInès Varhol exti_set_irq(i, 0);
542397424f8SInès Varhol }
543397424f8SInès Varhol }
544397424f8SInès Varhol
main(int argc,char ** argv)5454cb44571SInès Varhol int main(int argc, char **argv)
5464cb44571SInès Varhol {
5474cb44571SInès Varhol int ret;
5484cb44571SInès Varhol
5494cb44571SInès Varhol g_test_init(&argc, &argv, NULL);
5504cb44571SInès Varhol g_test_set_nonfatal_assertions();
5514cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/direct_lines", test_direct_lines_write);
5524cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/reserved_bits", test_reserved_bits_write);
5534cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/reg_write_read", test_reg_write_read);
5544cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/no_software_interrupt",
5554cb44571SInès Varhol test_no_software_interrupt);
5564cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/software_interrupt",
5574cb44571SInès Varhol test_software_interrupt);
5584cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/masked_interrupt", test_masked_interrupt);
5594cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/interrupt", test_interrupt);
5604cb44571SInès Varhol qtest_add_func("stm32l4x5/exti/test_edge_selector", test_edge_selector);
561397424f8SInès Varhol qtest_add_func("stm32l4x5/exti/test_orred_interrupts",
562397424f8SInès Varhol test_orred_interrupts);
5634cb44571SInès Varhol
5644cb44571SInès Varhol qtest_start("-machine b-l475e-iot01a");
5654cb44571SInès Varhol ret = g_test_run();
5664cb44571SInès Varhol qtest_end();
5674cb44571SInès Varhol
5684cb44571SInès Varhol return ret;
5694cb44571SInès Varhol }
570