1 /*
2  * Copyright (c) 2022 Meta
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/gpio.h>
9 #include <zephyr/ztest.h>
10 
11 #define TEST_NODE            DT_GPIO_CTLR(DT_ALIAS(led0), gpios)
12 #define TEST_PIN             DT_GPIO_PIN(DT_ALIAS(led0), gpios)
13 #define TEST_PIN_DTS_FLAGS   DT_GPIO_FLAGS(DT_ALIAS(led0), gpios)
14 
15 struct gpio_get_direction_fixture {
16 	const struct device *port;
17 	gpio_pin_t pin;
18 	gpio_flags_t flags;
19 };
20 
gpio_get_direction_setup(void)21 static void *gpio_get_direction_setup(void)
22 {
23 	static struct gpio_get_direction_fixture fixture;
24 
25 	fixture.pin = TEST_PIN;
26 	fixture.port = DEVICE_DT_GET(TEST_NODE);
27 
28 	return &fixture;
29 }
30 
gpio_get_direction_before(void * arg)31 static void gpio_get_direction_before(void *arg)
32 {
33 	struct gpio_get_direction_fixture *fixture = (struct gpio_get_direction_fixture *)arg;
34 
35 	zassert_true(device_is_ready(fixture->port), "GPIO device is not ready");
36 }
37 
common(struct gpio_get_direction_fixture * fixture)38 static void common(struct gpio_get_direction_fixture *fixture)
39 {
40 	int rv;
41 
42 	rv = gpio_pin_configure(fixture->port, fixture->pin, fixture->flags);
43 	if (rv == -ENOTSUP) {
44 		/* some drivers / hw might not support e.g. input-output or disconnect */
45 		ztest_test_skip();
46 	}
47 
48 	zassert_ok(rv, "gpio_pin_configure() failed: %d", rv);
49 }
50 
ZTEST_F(gpio_get_direction,test_disconnect)51 ZTEST_F(gpio_get_direction, test_disconnect)
52 {
53 	int rv;
54 
55 	fixture->flags = GPIO_DISCONNECTED;
56 	common(fixture);
57 
58 	rv = gpio_pin_is_input(fixture->port, fixture->pin);
59 	if (rv == -ENOSYS) {
60 		/* gpio_pin_direction() is not supported in the driver */
61 		ztest_test_skip();
62 	}
63 
64 	zassert_equal(false, rv, "gpio_pin_is_input() failed: %d", rv);
65 
66 	rv = gpio_pin_is_output(fixture->port, fixture->pin);
67 	zassert_equal(false, rv, "gpio_pin_is_output() failed: %d", rv);
68 }
69 
ZTEST_F(gpio_get_direction,test_input)70 ZTEST_F(gpio_get_direction, test_input)
71 {
72 	int rv;
73 	fixture->flags = GPIO_INPUT;
74 
75 	common(fixture);
76 
77 	rv = gpio_pin_is_input(fixture->port, fixture->pin);
78 	if (rv == -ENOSYS) {
79 		/* gpio_pin_direction() is not supported in the driver */
80 		ztest_test_skip();
81 	}
82 
83 	zassert_equal(true, rv, "gpio_pin_is_input() failed: %d", rv);
84 
85 	rv = gpio_pin_is_output(fixture->port, fixture->pin);
86 	zassert_equal(false, rv, "gpio_pin_is_output() failed: %d", rv);
87 }
88 
ZTEST_F(gpio_get_direction,test_output)89 ZTEST_F(gpio_get_direction, test_output)
90 {
91 	int rv;
92 	fixture->flags = GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW;
93 
94 	common(fixture);
95 
96 	rv = gpio_pin_is_input(fixture->port, fixture->pin);
97 	if (rv == -ENOSYS) {
98 		/* gpio_pin_direction() is not supported in the driver */
99 		ztest_test_skip();
100 	}
101 
102 	zassert_equal(false, rv, "gpio_pin_is_input() failed: %d", rv);
103 
104 	rv = gpio_pin_is_output(fixture->port, fixture->pin);
105 	zassert_equal(true, rv, "gpio_pin_is_output() failed: %d", rv);
106 }
107 
ZTEST_F(gpio_get_direction,test_input_output)108 ZTEST_F(gpio_get_direction, test_input_output)
109 {
110 	int rv;
111 	fixture->flags = GPIO_INPUT | GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW;
112 
113 	common(fixture);
114 
115 	rv = gpio_pin_is_input(fixture->port, fixture->pin);
116 	if (rv == -ENOSYS) {
117 		/* some drivers / gpio hw do not support input-output mode */
118 		ztest_test_skip();
119 	}
120 
121 	zassert_equal(true, rv, "gpio_pin_is_input() failed: %d", rv);
122 
123 	rv = gpio_pin_is_output(fixture->port, fixture->pin);
124 	zassert_equal(true, rv, "gpio_pin_is_output() failed: %d", rv);
125 }
126 
127 ZTEST_SUITE(gpio_get_direction, NULL, gpio_get_direction_setup, gpio_get_direction_before, NULL,
128 	    NULL);
129