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