1 /*
2  * Copyright (c) 2023 Intel Corporation
3  * Copyright 2024 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include "test_gpio.h"
9 
10 static struct drv_data data;
11 static int cb_cnt;
12 
callback(const struct device * dev,struct gpio_callback * gpio_cb,uint32_t pins)13 static void callback(const struct device *dev,
14 		     struct gpio_callback *gpio_cb, uint32_t pins)
15 {
16 	/*= checkpoint: pins should be marked with correct pin number bit =*/
17 	zassert_equal(pins, BIT(PIN_IN),
18 		      "unexpected pins %x", pins);
19 
20 	++cb_cnt;
21 }
22 
ZTEST(after_flash_gpio_config_trigger,test_gpio_config_twice_trigger)23 ZTEST(after_flash_gpio_config_trigger, test_gpio_config_twice_trigger)
24 {
25 	const struct device *const dev_in = DEVICE_DT_GET(DEV_IN);
26 	const struct device *const dev_out = DEVICE_DT_GET(DEV_OUT);
27 	struct drv_data *drv_data = &data;
28 	int ret;
29 
30 	cb_cnt = 0;
31 
32 	ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_DISCONNECTED);
33 
34 	/* 1. Configure PIN_IN callback */
35 	ret = gpio_pin_configure(dev_in, PIN_IN, GPIO_INPUT);
36 	zassert_ok(ret, "config PIN_IN failed");
37 
38 	gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN));
39 	ret = gpio_add_callback(dev_in, &drv_data->gpio_cb);
40 	zassert_ok(ret, "add callback failed");
41 
42 	/* 2. Enable PIN callback as both edges */
43 	ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_BOTH);
44 	if (ret == -ENOTSUP) {
45 		TC_PRINT("Both edge GPIO interrupt not supported.\n");
46 		gpio_remove_callback(dev_in, &drv_data->gpio_cb);
47 	} else {
48 		zassert_ok(ret, "enable callback failed");
49 	}
50 
51 	/* 3. Configure PIN_OUT as open drain, internal pull-up (may trigger
52 	 * callback)
53 	 */
54 	ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP);
55 	if (ret == -ENOTSUP) {
56 		TC_PRINT("Open drain not supported.\n");
57 		gpio_remove_callback(dev_in, &drv_data->gpio_cb);
58 		ztest_test_skip();
59 		return;
60 	}
61 	zassert_ok(ret, "config PIN_OUT failed");
62 
63 	/* 4. Configure PIN_OUT again (should not trigger callback)  */
64 	ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP);
65 	zassert_ok(ret, "config PIN_OUT twice failed");
66 
67 	/* 5. Wait a bit and ensure that interrupt happened at most once */
68 	k_sleep(K_MSEC(10));
69 	zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt);
70 
71 	gpio_remove_callback(dev_in, &drv_data->gpio_cb);
72 }
73 
ZTEST(after_flash_gpio_config_trigger,test_gpio_config_trigger)74 ZTEST(after_flash_gpio_config_trigger, test_gpio_config_trigger)
75 {
76 	const struct device *const dev_in = DEVICE_DT_GET(DEV_IN);
77 	const struct device *const dev_out = DEVICE_DT_GET(DEV_OUT);
78 	struct drv_data *drv_data = &data;
79 	int ret;
80 
81 	cb_cnt = 0;
82 
83 	ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_DISCONNECTED);
84 
85 	/* 1. Configure PIN_IN callback */
86 	ret = gpio_pin_configure(dev_in, PIN_IN, GPIO_INPUT);
87 	zassert_ok(ret, "config PIN_IN failed");
88 
89 	gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN));
90 	ret = gpio_add_callback(dev_in, &drv_data->gpio_cb);
91 	zassert_ok(ret, "add callback failed");
92 
93 	/* 2. Enable PIN callback as both edges */
94 	ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_BOTH);
95 	if (ret == -ENOTSUP) {
96 		TC_PRINT("Both edge GPIO interrupt not supported.\n");
97 		gpio_remove_callback(dev_in, &drv_data->gpio_cb);
98 	} else {
99 		zassert_ok(ret, "enable callback failed");
100 	}
101 
102 	/* 3. Configure PIN_OUT as open drain, internal pull-up (may trigger
103 	 * callback)
104 	 */
105 	ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP);
106 	if (ret == -ENOTSUP) {
107 		TC_PRINT("Open drain not supported.\n");
108 		gpio_remove_callback(dev_in, &drv_data->gpio_cb);
109 		ztest_test_skip();
110 		return;
111 	}
112 	zassert_ok(ret, "config PIN_OUT failed");
113 
114 	/* 4. Wait a bit and ensure that interrupt happened at most once */
115 	k_sleep(K_MSEC(10));
116 	zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt);
117 
118 	gpio_remove_callback(dev_in, &drv_data->gpio_cb);
119 }
120