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