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