Lines Matching +full:gpio +full:- +full:open +full:- +full:drain
4 * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5 * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
8 * See the COPYING file in the top-level directory.
12 #include "libqtest-single.h"
84 #define GPIO_ADDR_MASK (~(GPIO_SIZE - 1))
94 static uint32_t gpio_readl(unsigned int gpio, unsigned int offset) in gpio_readl() argument
96 return readl(gpio + offset); in gpio_readl()
99 static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value) in gpio_writel() argument
101 writel(gpio + offset, value); in gpio_writel()
104 static void gpio_set_bit(unsigned int gpio, unsigned int reg, in gpio_set_bit() argument
108 gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin); in gpio_set_bit()
111 static void gpio_set_2bits(unsigned int gpio, unsigned int reg, in gpio_set_2bits() argument
116 gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset); in gpio_set_2bits()
121 return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE; in get_gpio_id()
124 static void gpio_set_irq(unsigned int gpio, int num, int level) in gpio_set_irq() argument
126 g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c", in gpio_set_irq()
127 get_gpio_id(gpio) + 'a'); in gpio_set_irq()
131 static void disconnect_all_pins(unsigned int gpio) in disconnect_all_pins() argument
133 g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c", in disconnect_all_pins()
134 get_gpio_id(gpio) + 'a'); in disconnect_all_pins()
137 r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': " in disconnect_all_pins()
138 "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }", in disconnect_all_pins()
144 static uint32_t get_disconnected_pins(unsigned int gpio) in get_disconnected_pins() argument
146 g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c", in get_disconnected_pins()
147 get_gpio_id(gpio) + 'a'); in get_disconnected_pins()
151 r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':" in get_disconnected_pins()
152 " { 'path': %s, 'property': 'disconnected-pins'} }", path); in get_disconnected_pins()
159 static uint32_t reset(uint32_t gpio, unsigned int offset) in reset() argument
163 return moder_reset[get_gpio_id(gpio)]; in reset()
165 return pupdr_reset[get_gpio_id(gpio)]; in reset()
167 return idr_reset[get_gpio_id(gpio)]; in reset()
189 * Register IDR contains the actual values of all GPIO pins. in test_idr_reset_value()
191 * (intput/output/analog : register MODER, push-pull/open-drain : in test_idr_reset_value()
192 * register OTYPER, pull-up/pull-down/none : register PUPDR) in test_idr_reset_value()
229 /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */ in test_idr_reset_value()
244 /* ... 5: neither, 4: pull-up, 3: neither ... */ in test_idr_reset_value()
258 /* no pull-up or pull-down */ in test_idr_reset_value()
272 /* no pull-up or pull-down */ in test_idr_reset_value()
282 * GPIO line high : it should set the right bit in IDR in test_gpio_output_mode()
288 uint32_t gpio = test_gpio_addr(data); in test_gpio_output_mode() local
289 unsigned int gpio_id = get_gpio_id(gpio); in test_gpio_output_mode()
294 gpio_set_bit(gpio, ODR, pin, 1); in test_gpio_output_mode()
295 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR)); in test_gpio_output_mode()
299 gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT); in test_gpio_output_mode()
300 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin)); in test_gpio_output_mode()
304 gpio_set_bit(gpio, ODR, pin, 0); in test_gpio_output_mode()
305 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin)); in test_gpio_output_mode()
309 gpio_writel(gpio, ODR, reset(gpio, ODR)); in test_gpio_output_mode()
310 gpio_writel(gpio, MODER, reset(gpio, MODER)); in test_gpio_output_mode()
311 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR)); in test_gpio_output_mode()
319 * corresponding GPIO line high/low : it should set the in test_gpio_input_mode()
323 uint32_t gpio = test_gpio_addr(data); in test_gpio_input_mode() local
324 unsigned int gpio_id = get_gpio_id(gpio); in test_gpio_input_mode()
329 gpio_set_2bits(gpio, MODER, pin, MODER_INPUT); in test_gpio_input_mode()
330 gpio_set_irq(gpio, pin, 1); in test_gpio_input_mode()
331 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin)); in test_gpio_input_mode()
335 gpio_set_irq(gpio, pin, 0); in test_gpio_input_mode()
336 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin)); in test_gpio_input_mode()
340 gpio_writel(gpio, MODER, reset(gpio, MODER)); in test_gpio_input_mode()
341 disconnect_all_pins(gpio); in test_gpio_input_mode()
342 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR)); in test_gpio_input_mode()
348 * Test that a floating pin with pull-up sets the pin in test_pull_up_pull_down()
349 * high and vice-versa. in test_pull_up_pull_down()
352 uint32_t gpio = test_gpio_addr(data); in test_pull_up_pull_down() local
353 unsigned int gpio_id = get_gpio_id(gpio); in test_pull_up_pull_down()
357 /* Configure a line as input with pull-up, check the line is set high */ in test_pull_up_pull_down()
358 gpio_set_2bits(gpio, MODER, pin, MODER_INPUT); in test_pull_up_pull_down()
359 gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP); in test_pull_up_pull_down()
360 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin)); in test_pull_up_pull_down()
363 /* Configure the line with pull-down, check the line is low */ in test_pull_up_pull_down()
364 gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN); in test_pull_up_pull_down()
365 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin)); in test_pull_up_pull_down()
369 gpio_writel(gpio, MODER, reset(gpio, MODER)); in test_pull_up_pull_down()
370 gpio_writel(gpio, PUPDR, reset(gpio, PUPDR)); in test_pull_up_pull_down()
371 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR)); in test_pull_up_pull_down()
377 * Test that configuring a line in push-pull output mode in test_push_pull()
382 uint32_t gpio = test_gpio_addr(data); in test_push_pull() local
383 uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio); in test_push_pull()
387 /* Setting a line high externally, configuring it in push-pull output */ in test_push_pull()
389 gpio_set_irq(gpio, pin, 1); in test_push_pull()
390 gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT); in test_push_pull()
391 g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF); in test_push_pull()
392 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin)); in test_push_pull()
394 /* Setting a line low externally, configuring it in push-pull output */ in test_push_pull()
402 /* Trying to set a push-pull output pin, checking it doesn't work */ in test_push_pull()
403 gpio_set_irq(gpio, pin, 1); in test_push_pull()
404 g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF); in test_push_pull()
405 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin)); in test_push_pull()
407 /* Trying to reset a push-pull output pin, checking it doesn't work */ in test_push_pull()
413 gpio_writel(gpio, MODER, reset(gpio, MODER)); in test_push_pull()
421 * Test that configuring a line in open-drain output mode in test_open_drain()
423 * can't be set high externally while configured in open-drain. in test_open_drain()
426 * and it can be set low externally when in open-drain mode. in test_open_drain()
429 uint32_t gpio = test_gpio_addr(data); in test_open_drain() local
430 uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio); in test_open_drain()
434 /* Setting a line high externally, configuring it in open-drain output */ in test_open_drain()
436 gpio_set_irq(gpio, pin, 1); in test_open_drain()
437 gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN); in test_open_drain()
438 gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT); in test_open_drain()
439 g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF); in test_open_drain()
440 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin)); in test_open_drain()
442 /* Setting a line low externally, configuring it in open-drain output */ in test_open_drain()
452 /* Trying to set a open-drain output pin, checking it doesn't work */ in test_open_drain()
453 gpio_set_irq(gpio, pin, 1); in test_open_drain()
454 g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF); in test_open_drain()
455 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin)); in test_open_drain()
457 /* Trying to reset a open-drain output pin, checking it works */ in test_open_drain()
458 gpio_set_bit(gpio, ODR, pin, 1); in test_open_drain()
459 gpio_set_irq(gpio, pin, 0); in test_open_drain()
470 disconnect_all_pins(gpio); in test_open_drain()
471 gpio_writel(gpio, OTYPER, reset(gpio, OTYPER)); in test_open_drain()
472 gpio_writel(gpio, ODR, reset(gpio, ODR)); in test_open_drain()
473 gpio_writel(gpio, MODER, reset(gpio, MODER)); in test_open_drain()
474 g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR)); in test_open_drain()
485 uint32_t gpio = test_gpio_addr(data); in test_bsrr_brr() local
487 gpio_writel(gpio, BSRR, (1 << pin)); in test_bsrr_brr()
488 g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin)); in test_bsrr_brr()
490 gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS))); in test_bsrr_brr()
491 g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR)); in test_bsrr_brr()
493 gpio_writel(gpio, BSRR, (1 << pin)); in test_bsrr_brr()
494 g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin)); in test_bsrr_brr()
496 gpio_writel(gpio, BRR, (1 << pin)); in test_bsrr_brr()
497 g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR)); in test_bsrr_brr()
500 gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS))); in test_bsrr_brr()
501 g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin)); in test_bsrr_brr()
503 gpio_writel(gpio, BRR, (1 << pin)); in test_bsrr_brr()
504 g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR)); in test_bsrr_brr()
506 gpio_writel(gpio, ODR, reset(gpio, ODR)); in test_bsrr_brr()
512 * For each GPIO, enable its clock in RCC in test_clock_enable()
517 for (uint32_t gpio = GPIO_A; gpio <= GPIO_H; gpio += GPIO_B - GPIO_A) { in test_clock_enable() local
518 gpio_id = get_gpio_id(gpio); in test_clock_enable()
519 g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c/clk", in test_clock_enable()
522 /* Enable the gpio clock */ in test_clock_enable()
535 qtest_add_func("stm32l4x5/gpio/test_idr_reset_value", in main()
538 * The inputs for the tests (gpio and pin) can be changed, in main()
544 qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode", in main()
547 qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode", in main()
550 qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1", in main()
553 qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2", in main()
556 qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1", in main()
559 qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2", in main()
562 qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1", in main()
565 qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2", in main()
568 qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1", in main()
571 qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2", in main()
574 qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1", in main()
577 qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2", in main()
580 qtest_add_func("stm32l4x5/gpio/test_clock_enable", in main()
583 qtest_start("-machine b-l475e-iot01a"); in main()