xref: /qemu/tests/qtest/stm32l4x5_exti-test.c (revision 58045186fccaf400d3938fad220a99b1b5f3da6d)
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 
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 
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 
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 
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 
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 
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 
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);
73*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_IMR1), ==, 0xFFFFFFFF);
744cb44571SInès Varhol     exti_writel(EXTI_IMR1, 0x00000000);
75*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_IMR1), ==, 0x00000000);
764cb44571SInès Varhol 
774cb44571SInès Varhol     exti_writel(EXTI_EMR1, 0xFFFFFFFF);
78*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_EMR1), ==, 0xFFFFFFFF);
794cb44571SInès Varhol     exti_writel(EXTI_EMR1, 0x00000000);
80*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_EMR1), ==, 0x00000000);
814cb44571SInès Varhol 
824cb44571SInès Varhol     exti_writel(EXTI_RTSR1, 0xFFFFFFFF);
83*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x007DFFFF);
844cb44571SInès Varhol     exti_writel(EXTI_RTSR1, 0x00000000);
85*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x00000000);
864cb44571SInès Varhol 
874cb44571SInès Varhol     exti_writel(EXTI_FTSR1, 0xFFFFFFFF);
88*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x007DFFFF);
894cb44571SInès Varhol     exti_writel(EXTI_FTSR1, 0x00000000);
90*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x00000000);
914cb44571SInès Varhol 
924cb44571SInès Varhol     exti_writel(EXTI_IMR2, 0xFFFFFFFF);
93*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x000000FF);
944cb44571SInès Varhol     exti_writel(EXTI_IMR2, 0x00000000);
95*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x00000000);
964cb44571SInès Varhol 
974cb44571SInès Varhol     exti_writel(EXTI_EMR2, 0xFFFFFFFF);
98*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x000000FF);
994cb44571SInès Varhol     exti_writel(EXTI_EMR2, 0x00000000);
100*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x00000000);
1014cb44571SInès Varhol 
1024cb44571SInès Varhol     exti_writel(EXTI_RTSR2, 0xFFFFFFFF);
103*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000078);
1044cb44571SInès Varhol     exti_writel(EXTI_RTSR2, 0x00000000);
105*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
1064cb44571SInès Varhol 
1074cb44571SInès Varhol     exti_writel(EXTI_FTSR2, 0xFFFFFFFF);
108*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000078);
1094cb44571SInès Varhol     exti_writel(EXTI_FTSR2, 0x00000000);
110*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
1114cb44571SInès Varhol }
1124cb44571SInès Varhol 
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);
118*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x00000000);
1194cb44571SInès Varhol 
1204cb44571SInès Varhol     exti_writel(EXTI_FTSR1, 0xFF820000);
121*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x00000000);
1224cb44571SInès Varhol 
1234cb44571SInès Varhol     exti_writel(EXTI_SWIER1, 0xFF820000);
124*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000000);
1254cb44571SInès Varhol 
1264cb44571SInès Varhol     exti_writel(EXTI_PR1, 0xFF820000);
127*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
1284cb44571SInès Varhol 
1294cb44571SInès Varhol     exti_writel(EXTI_RTSR2, 0x00000087);
130*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
1314cb44571SInès Varhol 
1324cb44571SInès Varhol     exti_writel(EXTI_FTSR2, 0x00000087);
133*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
1344cb44571SInès Varhol 
1354cb44571SInès Varhol     exti_writel(EXTI_SWIER2, 0x00000087);
136*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
1374cb44571SInès Varhol 
1384cb44571SInès Varhol     exti_writel(EXTI_PR2, 0x00000087);
139*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
1404cb44571SInès Varhol }
1414cb44571SInès Varhol 
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);
147*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x00000000);
1484cb44571SInès Varhol 
1494cb44571SInès Varhol     exti_writel(EXTI_EMR2, 0xFFFFFF00);
150*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x00000000);
1514cb44571SInès Varhol 
1524cb44571SInès Varhol     exti_writel(EXTI_RTSR2, 0xFFFFFF00);
153*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
1544cb44571SInès Varhol 
1554cb44571SInès Varhol     exti_writel(EXTI_FTSR2, 0xFFFFFF00);
156*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
1574cb44571SInès Varhol 
1584cb44571SInès Varhol     exti_writel(EXTI_SWIER2, 0xFFFFFF00);
159*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
1604cb44571SInès Varhol 
1614cb44571SInès Varhol     exti_writel(EXTI_PR2, 0xFFFFFF00);
162*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
1634cb44571SInès Varhol }
1644cb44571SInès Varhol 
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 */
183*58045186SInè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 */
194*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000001);
1954cb44571SInès Varhol     /* Check that the corresponding pending bit in PR is set */
196*58045186SInè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 */
204*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
2054cb44571SInès Varhol     /* Check that the corresponding bit in SWIER was cleared */
206*58045186SInè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 */
217*58045186SInè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 */
227*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000008);
2284cb44571SInès Varhol     /* Check that the corresponding pending bit in PR is set */
229*58045186SInè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 */
237*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
2384cb44571SInès Varhol     /* Check that the corresponding bit in SWIER was cleared */
239*58045186SInè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 
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);
262*58045186SInè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);
266*58045186SInè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);
271*58045186SInè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);
283*58045186SInè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);
287*58045186SInè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);
292*58045186SInè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);
303*58045186SInè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);
308*58045186SInè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);
314*58045186SInè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);
319*58045186SInè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);
330*58045186SInè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);
334*58045186SInè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 
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 */
353*58045186SInè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 */
364*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000001);
3654cb44571SInès Varhol     /* Check that the pending bit in PR wasn't set */
366*58045186SInè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 */
374*58045186SInè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 */
385*58045186SInè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 */
396*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000008);
3974cb44571SInès Varhol     /* Check that the pending bit in PR wasn't set */
398*58045186SInè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 */
406*58045186SInè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 
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 */
426*58045186SInè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 */
440*58045186SInè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 */
448*58045186SInè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));
4514cb44571SInès Varhol }
4524cb44571SInès Varhol 
4534cb44571SInès Varhol static void test_interrupt(void)
4544cb44571SInès Varhol {
4554cb44571SInès Varhol     /*
4564cb44571SInès Varhol      * Test that we can launch an irq by :
4574cb44571SInès Varhol      * - enabling its line in IMR
4584cb44571SInès Varhol      * - configuring interrupt on rising edge
4594cb44571SInès Varhol      * - and then setting the input line from '0' to '1'
4604cb44571SInès Varhol      *
4614cb44571SInès Varhol      * And that the interruption stays pending in NVIC
4624cb44571SInès Varhol      * even after clearing the pending bit in PR.
4634cb44571SInès Varhol      */
4644cb44571SInès Varhol 
4654cb44571SInès Varhol     /*
4664cb44571SInès Varhol      * Testing interrupt line EXTI1
4674cb44571SInès Varhol      * with rising edge from GPIOx pin 1
4684cb44571SInès Varhol      */
4694cb44571SInès Varhol 
4704cb44571SInès Varhol     enable_nvic_irq(EXTI1_IRQ);
4714cb44571SInès Varhol     /* Check that there are no interrupts already pending in PR */
472*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
4734cb44571SInès Varhol     /* Check that this specific interrupt isn't pending in NVIC */
4744cb44571SInès Varhol     g_assert_false(check_nvic_pending(EXTI1_IRQ));
4754cb44571SInès Varhol 
4764cb44571SInès Varhol     /* Enable interrupt line EXTI1 */
4774cb44571SInès Varhol     exti_writel(EXTI_IMR1, 0x00000002);
4784cb44571SInès Varhol 
4794cb44571SInès Varhol     /* Configure interrupt on rising edge */
4804cb44571SInès Varhol     exti_writel(EXTI_RTSR1, 0x00000002);
4814cb44571SInès Varhol 
4824cb44571SInès Varhol     /* Simulate rising edge from GPIO line 1 */
4834cb44571SInès Varhol     exti_set_irq(1, 1);
4844cb44571SInès Varhol 
4854cb44571SInès Varhol     /* Check that the pending bit in PR was set */
486*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000002);
4874cb44571SInès Varhol     /* Check that the interrupt is pending in NVIC */
4884cb44571SInès Varhol     g_assert_true(check_nvic_pending(EXTI1_IRQ));
4894cb44571SInès Varhol 
4904cb44571SInès Varhol     /* Clear the pending bit in PR */
4914cb44571SInès Varhol     exti_writel(EXTI_PR1, 0x00000002);
4924cb44571SInès Varhol 
4934cb44571SInès Varhol     /* Check that the write in PR was effective */
494*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
4954cb44571SInès Varhol     /* Check that the interrupt is still pending in the NVIC */
4964cb44571SInès Varhol     g_assert_true(check_nvic_pending(EXTI1_IRQ));
4974cb44571SInès Varhol 
4984cb44571SInès Varhol     /* Clean NVIC */
4994cb44571SInès Varhol     unpend_nvic_irq(EXTI1_IRQ);
5004cb44571SInès Varhol     g_assert_false(check_nvic_pending(EXTI1_IRQ));
5014cb44571SInès Varhol }
5024cb44571SInès Varhol 
503397424f8SInès Varhol static void test_orred_interrupts(void)
504397424f8SInès Varhol {
505397424f8SInès Varhol     /*
506397424f8SInès Varhol      * For lines EXTI5..9 (fanned-in to NVIC irq 23),
507397424f8SInès Varhol      * test that raising the line pends interrupt
508397424f8SInès Varhol      * 23 in NVIC.
509397424f8SInès Varhol      */
510397424f8SInès Varhol     enable_nvic_irq(EXTI5_9_IRQ);
511397424f8SInès Varhol     /* Check that there are no interrupts already pending in PR */
512*58045186SInès Varhol     g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
513397424f8SInès Varhol     /* Check that this specific interrupt isn't pending in NVIC */
514397424f8SInès Varhol     g_assert_false(check_nvic_pending(EXTI5_9_IRQ));
515397424f8SInès Varhol 
516397424f8SInès Varhol     /* Enable interrupt lines EXTI[5..9] */
517397424f8SInès Varhol     exti_writel(EXTI_IMR1, (0x1F << 5));
518397424f8SInès Varhol 
519397424f8SInès Varhol     /* Configure interrupt on rising edge */
520397424f8SInès Varhol     exti_writel(EXTI_RTSR1, (0x1F << 5));
521397424f8SInès Varhol 
522397424f8SInès Varhol     /* Raise GPIO line i, check that the interrupt is pending */
523397424f8SInès Varhol     for (unsigned i = 5; i < 10; i++) {
524397424f8SInès Varhol         exti_set_irq(i, 1);
525*58045186SInès Varhol         g_assert_cmphex(exti_readl(EXTI_PR1), ==, 1 << i);
526397424f8SInès Varhol         g_assert_true(check_nvic_pending(EXTI5_9_IRQ));
527397424f8SInès Varhol 
528397424f8SInès Varhol         exti_writel(EXTI_PR1, 1 << i);
529*58045186SInès Varhol         g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
530397424f8SInès Varhol         g_assert_true(check_nvic_pending(EXTI5_9_IRQ));
531397424f8SInès Varhol 
532397424f8SInès Varhol         unpend_nvic_irq(EXTI5_9_IRQ);
533397424f8SInès Varhol         g_assert_false(check_nvic_pending(EXTI5_9_IRQ));
534397424f8SInès Varhol     }
535397424f8SInès Varhol }
536397424f8SInès Varhol 
5374cb44571SInès Varhol int main(int argc, char **argv)
5384cb44571SInès Varhol {
5394cb44571SInès Varhol     int ret;
5404cb44571SInès Varhol 
5414cb44571SInès Varhol     g_test_init(&argc, &argv, NULL);
5424cb44571SInès Varhol     g_test_set_nonfatal_assertions();
5434cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/direct_lines", test_direct_lines_write);
5444cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/reserved_bits", test_reserved_bits_write);
5454cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/reg_write_read", test_reg_write_read);
5464cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/no_software_interrupt",
5474cb44571SInès Varhol                    test_no_software_interrupt);
5484cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/software_interrupt",
5494cb44571SInès Varhol                    test_software_interrupt);
5504cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/masked_interrupt", test_masked_interrupt);
5514cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/interrupt", test_interrupt);
5524cb44571SInès Varhol     qtest_add_func("stm32l4x5/exti/test_edge_selector", test_edge_selector);
553397424f8SInès Varhol     qtest_add_func("stm32l4x5/exti/test_orred_interrupts",
554397424f8SInès Varhol                    test_orred_interrupts);
5554cb44571SInès Varhol 
5564cb44571SInès Varhol     qtest_start("-machine b-l475e-iot01a");
5574cb44571SInès Varhol     ret = g_test_run();
5584cb44571SInès Varhol     qtest_end();
5594cb44571SInès Varhol 
5604cb44571SInès Varhol     return ret;
5614cb44571SInès Varhol }
562