xref: /qemu/tests/qtest/stm32l4x5_gpio-test.c (revision 029171b5)
1 /*
2  * QTest testcase for STM32L4x5_GPIO
3  *
4  * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5  * Copyright (c) 2024 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 GPIO_BASE_ADDR 0x48000000
15 #define GPIO_SIZE      0x400
16 #define NUM_GPIOS      8
17 #define NUM_GPIO_PINS  16
18 
19 #define GPIO_A 0x48000000
20 #define GPIO_B 0x48000400
21 #define GPIO_C 0x48000800
22 #define GPIO_D 0x48000C00
23 #define GPIO_E 0x48001000
24 #define GPIO_F 0x48001400
25 #define GPIO_G 0x48001800
26 #define GPIO_H 0x48001C00
27 
28 #define MODER 0x00
29 #define OTYPER 0x04
30 #define PUPDR 0x0C
31 #define IDR 0x10
32 #define ODR 0x14
33 #define BSRR 0x18
34 #define BRR 0x28
35 
36 #define MODER_INPUT 0
37 #define MODER_OUTPUT 1
38 
39 #define PUPDR_NONE 0
40 #define PUPDR_PULLUP 1
41 #define PUPDR_PULLDOWN 2
42 
43 #define OTYPER_PUSH_PULL 0
44 #define OTYPER_OPEN_DRAIN 1
45 
46 /* SoC forwards GPIOs to SysCfg */
47 #define SYSCFG "/machine/soc"
48 
49 const uint32_t moder_reset[NUM_GPIOS] = {
50     0xABFFFFFF,
51     0xFFFFFEBF,
52     0xFFFFFFFF,
53     0xFFFFFFFF,
54     0xFFFFFFFF,
55     0xFFFFFFFF,
56     0xFFFFFFFF,
57     0x0000000F
58 };
59 
60 const uint32_t pupdr_reset[NUM_GPIOS] = {
61     0x64000000,
62     0x00000100,
63     0x00000000,
64     0x00000000,
65     0x00000000,
66     0x00000000,
67     0x00000000,
68     0x00000000
69 };
70 
71 const uint32_t idr_reset[NUM_GPIOS] = {
72     0x0000A000,
73     0x00000010,
74     0x00000000,
75     0x00000000,
76     0x00000000,
77     0x00000000,
78     0x00000000,
79     0x00000000
80 };
81 
82 #define PIN_MASK        0xF
83 #define GPIO_ADDR_MASK  (~(GPIO_SIZE - 1))
84 
85 static inline void *test_data(uint32_t gpio_addr, uint8_t pin)
86 {
87     return (void *)(uintptr_t)((gpio_addr & GPIO_ADDR_MASK) | (pin & PIN_MASK));
88 }
89 
90 #define test_gpio_addr(data)      ((uintptr_t)(data) & GPIO_ADDR_MASK)
91 #define test_pin(data)            ((uintptr_t)(data) & PIN_MASK)
92 
93 static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
94 {
95     return readl(gpio + offset);
96 }
97 
98 static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
99 {
100     writel(gpio + offset, value);
101 }
102 
103 static void gpio_set_bit(unsigned int gpio, unsigned int reg,
104                          unsigned int pin, uint32_t value)
105 {
106     uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
107     gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
108 }
109 
110 static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
111                            unsigned int pin, uint32_t value)
112 {
113     uint32_t offset = 2 * pin;
114     uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
115     gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
116 }
117 
118 static unsigned int get_gpio_id(uint32_t gpio_addr)
119 {
120     return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
121 }
122 
123 static void gpio_set_irq(unsigned int gpio, int num, int level)
124 {
125     g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
126                                             get_gpio_id(gpio) + 'a');
127     qtest_set_irq_in(global_qtest, name, NULL, num, level);
128 }
129 
130 static void disconnect_all_pins(unsigned int gpio)
131 {
132     g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
133                                             get_gpio_id(gpio) + 'a');
134     QDict *r;
135 
136     r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
137         "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
138         path, 0xFFFF);
139     g_assert_false(qdict_haskey(r, "error"));
140     qobject_unref(r);
141 }
142 
143 static uint32_t get_disconnected_pins(unsigned int gpio)
144 {
145     g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
146                                             get_gpio_id(gpio) + 'a');
147     uint32_t disconnected_pins = 0;
148     QDict *r;
149 
150     r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
151         " { 'path': %s, 'property': 'disconnected-pins'} }", path);
152     g_assert_false(qdict_haskey(r, "error"));
153     disconnected_pins = qdict_get_int(r, "return");
154     qobject_unref(r);
155     return disconnected_pins;
156 }
157 
158 static uint32_t reset(uint32_t gpio, unsigned int offset)
159 {
160     switch (offset) {
161     case MODER:
162         return moder_reset[get_gpio_id(gpio)];
163     case PUPDR:
164         return pupdr_reset[get_gpio_id(gpio)];
165     case IDR:
166         return idr_reset[get_gpio_id(gpio)];
167     }
168     return 0x0;
169 }
170 
171 static void system_reset(void)
172 {
173     QDict *r;
174     r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
175     g_assert_false(qdict_haskey(r, "error"));
176     qobject_unref(r);
177 }
178 
179 static void test_idr_reset_value(void)
180 {
181     /*
182      * Checks that the values in MODER, OTYPER, PUPDR and ODR
183      * after reset are correct, and that the value in IDR is
184      * coherent.
185      * Since AF and analog modes aren't implemented, IDR reset
186      * values aren't the same as with a real board.
187      *
188      * Register IDR contains the actual values of all GPIO pins.
189      * Its value depends on the pins' configuration
190      * (intput/output/analog : register MODER, push-pull/open-drain :
191      * register OTYPER, pull-up/pull-down/none : register PUPDR)
192      * and on the values stored in register ODR
193      * (in case the pin is in output mode).
194      */
195 
196     gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
197     gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
198     gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
199     gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
200 
201     gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
202     gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
203     gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
204     gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
205 
206     gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
207     gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
208     gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
209     gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
210 
211     gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
212     gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
213     gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
214     gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
215 
216     system_reset();
217 
218     uint32_t moder = gpio_readl(GPIO_A, MODER);
219     uint32_t odr = gpio_readl(GPIO_A, ODR);
220     uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
221     uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
222     uint32_t idr = gpio_readl(GPIO_A, IDR);
223     /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
224     /* here AF is the same as Analog and Input mode */
225     g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
226     g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
227     g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
228     /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
229     g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
230     /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
231     g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
232 
233     moder = gpio_readl(GPIO_B, MODER);
234     odr = gpio_readl(GPIO_B, ODR);
235     otyper = gpio_readl(GPIO_B, OTYPER);
236     pupdr = gpio_readl(GPIO_B, PUPDR);
237     idr = gpio_readl(GPIO_B, IDR);
238     /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
239     /* here AF is the same as Analog and Input mode */
240     g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
241     g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
242     g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
243     /* ... 5: neither, 4: pull-up, 3: neither ... */
244     g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
245     /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
246     g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
247 
248     moder = gpio_readl(GPIO_C, MODER);
249     odr = gpio_readl(GPIO_C, ODR);
250     otyper = gpio_readl(GPIO_C, OTYPER);
251     pupdr = gpio_readl(GPIO_C, PUPDR);
252     idr = gpio_readl(GPIO_C, IDR);
253     /* Analog, same as Input mode*/
254     g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
255     g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
256     g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
257     /* no pull-up or pull-down */
258     g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
259     /* reset value */
260     g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
261 
262     moder = gpio_readl(GPIO_H, MODER);
263     odr = gpio_readl(GPIO_H, ODR);
264     otyper = gpio_readl(GPIO_H, OTYPER);
265     pupdr = gpio_readl(GPIO_H, PUPDR);
266     idr = gpio_readl(GPIO_H, IDR);
267     /* Analog, same as Input mode */
268     g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
269     g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
270     g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
271     /* no pull-up or pull-down */
272     g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
273     /* reset value */
274     g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
275 }
276 
277 static void test_gpio_output_mode(const void *data)
278 {
279     /*
280      * Checks that setting a bit in ODR sets the corresponding
281      * GPIO line high : it should set the right bit in IDR
282      * and send an irq to syscfg.
283      * Additionally, it checks that values written to ODR
284      * when not in output mode are stored and not discarded.
285      */
286     unsigned int pin = test_pin(data);
287     uint32_t gpio = test_gpio_addr(data);
288     unsigned int gpio_id = get_gpio_id(gpio);
289 
290     qtest_irq_intercept_in(global_qtest, SYSCFG);
291 
292     /* Set a bit in ODR and check nothing happens */
293     gpio_set_bit(gpio, ODR, pin, 1);
294     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
295     g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
296 
297     /* Configure the relevant line as output and check the pin is high */
298     gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
299     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
300     g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
301 
302     /* Reset the bit in ODR and check the pin is low */
303     gpio_set_bit(gpio, ODR, pin, 0);
304     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
305     g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
306 
307     /* Clean the test */
308     gpio_writel(gpio, ODR, reset(gpio, ODR));
309     gpio_writel(gpio, MODER, reset(gpio, MODER));
310     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
311     g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
312 }
313 
314 static void test_gpio_input_mode(const void *data)
315 {
316     /*
317      * Test that setting a line high/low externally sets the
318      * corresponding GPIO line high/low : it should set the
319      * right bit in IDR and send an irq to syscfg.
320      */
321     unsigned int pin = test_pin(data);
322     uint32_t gpio = test_gpio_addr(data);
323     unsigned int gpio_id = get_gpio_id(gpio);
324 
325     qtest_irq_intercept_in(global_qtest, SYSCFG);
326 
327     /* Configure a line as input, raise it, and check that the pin is high */
328     gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
329     gpio_set_irq(gpio, pin, 1);
330     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
331     g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
332 
333     /* Lower the line and check that the pin is low */
334     gpio_set_irq(gpio, pin, 0);
335     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
336     g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
337 
338     /* Clean the test */
339     gpio_writel(gpio, MODER, reset(gpio, MODER));
340     disconnect_all_pins(gpio);
341     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
342 }
343 
344 static void test_pull_up_pull_down(const void *data)
345 {
346     /*
347      * Test that a floating pin with pull-up sets the pin
348      * high and vice-versa.
349      */
350     unsigned int pin = test_pin(data);
351     uint32_t gpio = test_gpio_addr(data);
352     unsigned int gpio_id = get_gpio_id(gpio);
353 
354     qtest_irq_intercept_in(global_qtest, SYSCFG);
355 
356     /* Configure a line as input with pull-up, check the line is set high */
357     gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
358     gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
359     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
360     g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
361 
362     /* Configure the line with pull-down, check the line is low */
363     gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
364     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
365     g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
366 
367     /* Clean the test */
368     gpio_writel(gpio, MODER, reset(gpio, MODER));
369     gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
370     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
371 }
372 
373 static void test_push_pull(const void *data)
374 {
375     /*
376      * Test that configuring a line in push-pull output mode
377      * disconnects the pin, that the pin can't be set or reset
378      * externally afterwards.
379      */
380     unsigned int pin = test_pin(data);
381     uint32_t gpio = test_gpio_addr(data);
382     uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
383 
384     qtest_irq_intercept_in(global_qtest, SYSCFG);
385 
386     /* Setting a line high externally, configuring it in push-pull output */
387     /* And checking the pin was disconnected */
388     gpio_set_irq(gpio, pin, 1);
389     gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
390     g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
391     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
392 
393     /* Setting a line low externally, configuring it in push-pull output */
394     /* And checking the pin was disconnected */
395     gpio_set_irq(gpio2, pin, 0);
396     gpio_set_bit(gpio2, ODR, pin, 1);
397     gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
398     g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
399     g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
400 
401     /* Trying to set a push-pull output pin, checking it doesn't work */
402     gpio_set_irq(gpio, pin, 1);
403     g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
404     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
405 
406     /* Trying to reset a push-pull output pin, checking it doesn't work */
407     gpio_set_irq(gpio2, pin, 0);
408     g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
409     g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
410 
411     /* Clean the test */
412     gpio_writel(gpio, MODER, reset(gpio, MODER));
413     gpio_writel(gpio2, ODR, reset(gpio2, ODR));
414     gpio_writel(gpio2, MODER, reset(gpio2, MODER));
415 }
416 
417 static void test_open_drain(const void *data)
418 {
419     /*
420      * Test that configuring a line in open-drain output mode
421      * disconnects a pin set high externally and that the pin
422      * can't be set high externally while configured in open-drain.
423      *
424      * However a pin set low externally shouldn't be disconnected,
425      * and it can be set low externally when in open-drain mode.
426      */
427     unsigned int pin = test_pin(data);
428     uint32_t gpio = test_gpio_addr(data);
429     uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
430 
431     qtest_irq_intercept_in(global_qtest, SYSCFG);
432 
433     /* Setting a line high externally, configuring it in open-drain output */
434     /* And checking the pin was disconnected */
435     gpio_set_irq(gpio, pin, 1);
436     gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
437     gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
438     g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
439     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
440 
441     /* Setting a line low externally, configuring it in open-drain output */
442     /* And checking the pin wasn't disconnected */
443     gpio_set_irq(gpio2, pin, 0);
444     gpio_set_bit(gpio2, ODR, pin, 1);
445     gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
446     gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
447     g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
448     g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
449                                reset(gpio2, IDR) & ~(1 << pin));
450 
451     /* Trying to set a open-drain output pin, checking it doesn't work */
452     gpio_set_irq(gpio, pin, 1);
453     g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
454     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
455 
456     /* Trying to reset a open-drain output pin, checking it works */
457     gpio_set_bit(gpio, ODR, pin, 1);
458     gpio_set_irq(gpio, pin, 0);
459     g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
460     g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
461                                reset(gpio2, IDR) & ~(1 << pin));
462 
463     /* Clean the test */
464     disconnect_all_pins(gpio2);
465     gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
466     gpio_writel(gpio2, ODR, reset(gpio2, ODR));
467     gpio_writel(gpio2, MODER, reset(gpio2, MODER));
468     g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
469     disconnect_all_pins(gpio);
470     gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
471     gpio_writel(gpio, ODR, reset(gpio, ODR));
472     gpio_writel(gpio, MODER, reset(gpio, MODER));
473     g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
474 }
475 
476 static void test_bsrr_brr(const void *data)
477 {
478     /*
479      * Test that writing a '1' in BSS and BSRR
480      * has the desired effect on ODR.
481      * In BSRR, BSx has priority over BRx.
482      */
483     unsigned int pin = test_pin(data);
484     uint32_t gpio = test_gpio_addr(data);
485 
486     gpio_writel(gpio, BSRR, (1 << pin));
487     g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
488 
489     gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
490     g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
491 
492     gpio_writel(gpio, BSRR, (1 << pin));
493     g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
494 
495     gpio_writel(gpio, BRR, (1 << pin));
496     g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
497 
498     /* BSx should have priority over BRx */
499     gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
500     g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
501 
502     gpio_writel(gpio, BRR, (1 << pin));
503     g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
504 
505     gpio_writel(gpio, ODR, reset(gpio, ODR));
506 }
507 
508 int main(int argc, char **argv)
509 {
510     int ret;
511 
512     g_test_init(&argc, &argv, NULL);
513     g_test_set_nonfatal_assertions();
514     qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
515                    test_idr_reset_value);
516     /*
517      * The inputs for the tests (gpio and pin) can be changed,
518      * but the tests don't work for pins that are high at reset
519      * (GPIOA15, GPIO13 and GPIOB5).
520      * Specifically, rising the pin then checking `get_irq()`
521      * is problematic since the pin was already high.
522      */
523     qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
524                         test_data(GPIO_C, 5),
525                         test_gpio_output_mode);
526     qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
527                         test_data(GPIO_H, 3),
528                         test_gpio_output_mode);
529     qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
530                         test_data(GPIO_D, 6),
531                         test_gpio_input_mode);
532     qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
533                         test_data(GPIO_C, 10),
534                         test_gpio_input_mode);
535     qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
536                         test_data(GPIO_B, 5),
537                         test_pull_up_pull_down);
538     qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
539                         test_data(GPIO_F, 1),
540                         test_pull_up_pull_down);
541     qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
542                         test_data(GPIO_G, 6),
543                         test_push_pull);
544     qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
545                         test_data(GPIO_H, 3),
546                         test_push_pull);
547     qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
548                         test_data(GPIO_C, 4),
549                         test_open_drain);
550     qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
551                         test_data(GPIO_E, 11),
552                         test_open_drain);
553     qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
554                         test_data(GPIO_A, 12),
555                         test_bsrr_brr);
556     qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
557                         test_data(GPIO_D, 0),
558                         test_bsrr_brr);
559 
560     qtest_start("-machine b-l475e-iot01a");
561     ret = g_test_run();
562     qtest_end();
563 
564     return ret;
565 }
566