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