1 /*
2  * QTest testcase for STM32L4x5_SYSCFG
3  *
4  * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5  * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
6  *
7  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8  * See the COPYING file in the top-level directory.
9  */
10 
11 #include "qemu/osdep.h"
12 #include "libqtest-single.h"
13 
14 #define SYSCFG_BASE_ADDR 0x40010000
15 #define SYSCFG_MEMRMP 0x00
16 #define SYSCFG_CFGR1 0x04
17 #define SYSCFG_EXTICR1 0x08
18 #define SYSCFG_EXTICR2 0x0C
19 #define SYSCFG_EXTICR3 0x10
20 #define SYSCFG_EXTICR4 0x14
21 #define SYSCFG_SCSR 0x18
22 #define SYSCFG_CFGR2 0x1C
23 #define SYSCFG_SWPR 0x20
24 #define SYSCFG_SKR 0x24
25 #define SYSCFG_SWPR2 0x28
26 #define INVALID_ADDR 0x2C
27 
28 static void syscfg_writel(unsigned int offset, uint32_t value)
29 {
30     writel(SYSCFG_BASE_ADDR + offset, value);
31 }
32 
33 static uint32_t syscfg_readl(unsigned int offset)
34 {
35     return readl(SYSCFG_BASE_ADDR + offset);
36 }
37 
38 static void syscfg_set_irq(int num, int level)
39 {
40    qtest_set_irq_in(global_qtest, "/machine/soc/syscfg",
41                     NULL, num, level);
42 }
43 
44 static void system_reset(void)
45 {
46     QDict *response;
47     response = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
48     g_assert(qdict_haskey(response, "return"));
49     qobject_unref(response);
50 }
51 
52 static void test_reset(void)
53 {
54     /*
55      * Test that registers are initialized at the correct values
56      */
57     g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
58 
59     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
60 
61     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
62 
63     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
64 
65     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
66 
67     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
68 
69     g_assert_cmpuint(syscfg_readl(SYSCFG_SCSR), ==, 0x00000000);
70 
71     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
72 
73     g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0x00000000);
74 
75     g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
76 
77     g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0x00000000);
78 }
79 
80 static void test_reserved_bits(void)
81 {
82     /*
83      * Test that reserved bits stay at reset value
84      * (which is 0 for all of them) by writing '1'
85      * in all reserved bits (keeping reset value for
86      * other bits) and checking that the
87      * register is still at reset value
88      */
89     syscfg_writel(SYSCFG_MEMRMP, 0xFFFFFEF8);
90     g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
91 
92     syscfg_writel(SYSCFG_CFGR1, 0x7F00FEFF);
93     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
94 
95     syscfg_writel(SYSCFG_EXTICR1, 0xFFFF0000);
96     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
97 
98     syscfg_writel(SYSCFG_EXTICR2, 0xFFFF0000);
99     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
100 
101     syscfg_writel(SYSCFG_EXTICR3, 0xFFFF0000);
102     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
103 
104     syscfg_writel(SYSCFG_EXTICR4, 0xFFFF0000);
105     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
106 
107     syscfg_writel(SYSCFG_SKR, 0xFFFFFF00);
108     g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
109 }
110 
111 static void test_set_and_clear(void)
112 {
113     /*
114      * Test that regular bits can be set and cleared
115      */
116     syscfg_writel(SYSCFG_MEMRMP, 0x00000107);
117     g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000107);
118     syscfg_writel(SYSCFG_MEMRMP, 0x00000000);
119     g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
120 
121     /* cfgr1 bit 0 is clear only so we keep it set */
122     syscfg_writel(SYSCFG_CFGR1, 0xFCFF0101);
123     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0xFCFF0101);
124     syscfg_writel(SYSCFG_CFGR1, 0x00000001);
125     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000001);
126 
127     syscfg_writel(SYSCFG_EXTICR1, 0x0000FFFF);
128     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x0000FFFF);
129     syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
130     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
131 
132     syscfg_writel(SYSCFG_EXTICR2, 0x0000FFFF);
133     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x0000FFFF);
134     syscfg_writel(SYSCFG_EXTICR2, 0x00000000);
135     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
136 
137     syscfg_writel(SYSCFG_EXTICR3, 0x0000FFFF);
138     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x0000FFFF);
139     syscfg_writel(SYSCFG_EXTICR3, 0x00000000);
140     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
141 
142     syscfg_writel(SYSCFG_EXTICR4, 0x0000FFFF);
143     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x0000FFFF);
144     syscfg_writel(SYSCFG_EXTICR4, 0x00000000);
145     g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
146 
147     syscfg_writel(SYSCFG_SKR, 0x000000FF);
148     g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x000000FF);
149     syscfg_writel(SYSCFG_SKR, 0x00000000);
150     g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
151 }
152 
153 static void test_clear_by_writing_1(void)
154 {
155     /*
156      * Test that writing '1' doesn't set the bit
157      */
158     syscfg_writel(SYSCFG_CFGR2, 0x00000100);
159     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
160 }
161 
162 static void test_set_only_bits(void)
163 {
164     /*
165      * Test that set only bits stay can't be cleared
166      */
167     syscfg_writel(SYSCFG_CFGR2, 0x0000000F);
168     syscfg_writel(SYSCFG_CFGR2, 0x00000000);
169     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x0000000F);
170 
171     syscfg_writel(SYSCFG_SWPR, 0xFFFFFFFF);
172     syscfg_writel(SYSCFG_SWPR, 0x00000000);
173     g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0xFFFFFFFF);
174 
175     syscfg_writel(SYSCFG_SWPR2, 0xFFFFFFFF);
176     syscfg_writel(SYSCFG_SWPR2, 0x00000000);
177     g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0xFFFFFFFF);
178 
179     system_reset();
180 }
181 
182 static void test_clear_only_bits(void)
183 {
184     /*
185      * Test that clear only bits stay can't be set
186      */
187     syscfg_writel(SYSCFG_CFGR1, 0x00000000);
188     syscfg_writel(SYSCFG_CFGR1, 0x00000001);
189     g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000000);
190 
191     system_reset();
192 }
193 
194 static void test_interrupt(void)
195 {
196     /*
197      * Test that GPIO rising lines result in an irq
198      * with the right configuration
199      */
200     qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
201 
202     /* GPIOA is the default source for EXTI lines 0 to 15 */
203 
204     syscfg_set_irq(0, 1);
205 
206     g_assert_true(get_irq(0));
207 
208 
209     syscfg_set_irq(15, 1);
210 
211     g_assert_true(get_irq(15));
212 
213     /* Configure GPIOB[1] as the source input for EXTI1 */
214     syscfg_writel(SYSCFG_EXTICR1, 0x00000010);
215 
216     syscfg_set_irq(17, 1);
217 
218     g_assert_true(get_irq(1));
219 
220     /* Clean the test */
221     syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
222     syscfg_set_irq(0, 0);
223     syscfg_set_irq(15, 0);
224     syscfg_set_irq(17, 0);
225 }
226 
227 static void test_irq_pin_multiplexer(void)
228 {
229     /*
230      * Test that syscfg irq sets the right exti irq
231      */
232 
233     qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
234 
235     syscfg_set_irq(0, 1);
236 
237     /* Check that irq 0 was set and irq 15 wasn't */
238     g_assert_true(get_irq(0));
239     g_assert_false(get_irq(15));
240 
241     /* Clean the test */
242     syscfg_set_irq(0, 0);
243 
244     syscfg_set_irq(15, 1);
245 
246     /* Check that irq 15 was set and irq 0 wasn't */
247     g_assert_true(get_irq(15));
248     g_assert_false(get_irq(0));
249 
250     /* Clean the test */
251     syscfg_set_irq(15, 0);
252 }
253 
254 static void test_irq_gpio_multiplexer(void)
255 {
256     /*
257      * Test that an irq is generated only by the right GPIO
258      */
259 
260     qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
261 
262     /* GPIOA is the default source for EXTI lines 0 to 15 */
263 
264     /* Check that setting rising pin GPIOA[0] generates an irq */
265     syscfg_set_irq(0, 1);
266 
267     g_assert_true(get_irq(0));
268 
269     /* Clean the test */
270     syscfg_set_irq(0, 0);
271 
272     /* Check that setting rising pin GPIOB[0] doesn't generate an irq */
273     syscfg_set_irq(16, 1);
274 
275     g_assert_false(get_irq(0));
276 
277     /* Clean the test */
278     syscfg_set_irq(16, 0);
279 
280     /* Configure GPIOB[0] as the source input for EXTI0 */
281     syscfg_writel(SYSCFG_EXTICR1, 0x00000001);
282 
283     /* Check that setting rising pin GPIOA[0] doesn't generate an irq */
284     syscfg_set_irq(0, 1);
285 
286     g_assert_false(get_irq(0));
287 
288     /* Clean the test */
289     syscfg_set_irq(0, 0);
290 
291     /* Check that setting rising pin GPIOB[0] generates an irq */
292     syscfg_set_irq(16, 1);
293 
294     g_assert_true(get_irq(0));
295 
296     /* Clean the test */
297     syscfg_set_irq(16, 0);
298     syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
299 }
300 
301 int main(int argc, char **argv)
302 {
303     int ret;
304 
305     g_test_init(&argc, &argv, NULL);
306     g_test_set_nonfatal_assertions();
307 
308     qtest_add_func("stm32l4x5/syscfg/test_reset", test_reset);
309     qtest_add_func("stm32l4x5/syscfg/test_reserved_bits",
310                    test_reserved_bits);
311     qtest_add_func("stm32l4x5/syscfg/test_set_and_clear",
312                    test_set_and_clear);
313     qtest_add_func("stm32l4x5/syscfg/test_clear_by_writing_1",
314                    test_clear_by_writing_1);
315     qtest_add_func("stm32l4x5/syscfg/test_set_only_bits",
316                    test_set_only_bits);
317     qtest_add_func("stm32l4x5/syscfg/test_clear_only_bits",
318                    test_clear_only_bits);
319     qtest_add_func("stm32l4x5/syscfg/test_interrupt",
320                    test_interrupt);
321     qtest_add_func("stm32l4x5/syscfg/test_irq_pin_multiplexer",
322                    test_irq_pin_multiplexer);
323     qtest_add_func("stm32l4x5/syscfg/test_irq_gpio_multiplexer",
324                    test_irq_gpio_multiplexer);
325 
326     qtest_start("-machine b-l475e-iot01a");
327     ret = g_test_run();
328     qtest_end();
329 
330     return ret;
331 }
332