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 if (ret == -ENOTSUP) {
34 TC_PRINT("NOTE: cannot configure pin as disconnected; trying as input\n");
35 ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_INPUT | GPIO_PULL_UP);
36 }
37 zassert_ok(ret, "config PIN_OUT failed");
38
39 /* 1. Configure PIN_IN callback */
40 ret = gpio_pin_configure(dev_in, PIN_IN, GPIO_INPUT);
41 zassert_ok(ret, "config PIN_IN failed");
42
43 gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN));
44 ret = gpio_add_callback(dev_in, &drv_data->gpio_cb);
45 zassert_ok(ret, "add callback failed");
46
47 /* 2. Enable PIN callback as both edges */
48 ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_BOTH);
49 if (ret == -ENOTSUP) {
50 TC_PRINT("Both edge GPIO interrupt not supported.\n");
51 gpio_remove_callback(dev_in, &drv_data->gpio_cb);
52 } else {
53 zassert_ok(ret, "enable callback failed");
54 }
55
56 /* 3. Configure PIN_OUT as open drain, internal pull-up (may trigger
57 * callback)
58 */
59 ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP);
60 if (ret == -ENOTSUP) {
61 TC_PRINT("Open drain not supported.\n");
62 gpio_remove_callback(dev_in, &drv_data->gpio_cb);
63 ztest_test_skip();
64 return;
65 }
66 zassert_ok(ret, "config PIN_OUT failed");
67
68 /* 4. Configure PIN_OUT again (should not trigger callback) */
69 ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP);
70 zassert_ok(ret, "config PIN_OUT twice failed");
71
72 /* 5. Wait a bit and ensure that interrupt happened at most once */
73 k_sleep(K_MSEC(10));
74 zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt);
75
76 ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE);
77 if (ret == -ENOTSUP) {
78 TC_PRINT("GPIO_INT_DISABLE not supported.\n");
79 } else {
80 zassert_ok(ret, "interrupt disabling failed");
81 }
82
83 gpio_remove_callback(dev_in, &drv_data->gpio_cb);
84 }
85
ZTEST(after_flash_gpio_config_trigger,test_gpio_config_trigger)86 ZTEST(after_flash_gpio_config_trigger, test_gpio_config_trigger)
87 {
88 const struct device *const dev_in = DEVICE_DT_GET(DEV_IN);
89 const struct device *const dev_out = DEVICE_DT_GET(DEV_OUT);
90 struct drv_data *drv_data = &data;
91 int ret;
92
93 cb_cnt = 0;
94
95 ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_DISCONNECTED);
96 if (ret == -ENOTSUP) {
97 TC_PRINT("NOTE: cannot configure pin as disconnected; trying as input\n");
98 ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_INPUT | GPIO_PULL_UP);
99 }
100 zassert_ok(ret, "config PIN_OUT failed");
101
102 /* 1. Configure PIN_IN callback */
103 ret = gpio_pin_configure(dev_in, PIN_IN, GPIO_INPUT);
104 zassert_ok(ret, "config PIN_IN failed");
105
106 gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN));
107 ret = gpio_add_callback(dev_in, &drv_data->gpio_cb);
108 zassert_ok(ret, "add callback failed");
109
110 /* 2. Enable PIN callback as both edges */
111 ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_BOTH);
112 if (ret == -ENOTSUP) {
113 TC_PRINT("Both edge GPIO interrupt not supported.\n");
114 gpio_remove_callback(dev_in, &drv_data->gpio_cb);
115 } else {
116 zassert_ok(ret, "enable callback failed");
117 }
118
119 /* 3. Configure PIN_OUT as open drain, internal pull-up (may trigger
120 * callback)
121 */
122 ret = gpio_pin_configure(dev_out, PIN_OUT, GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_PULL_UP);
123 if (ret == -ENOTSUP) {
124 TC_PRINT("Open drain not supported.\n");
125 gpio_remove_callback(dev_in, &drv_data->gpio_cb);
126 ztest_test_skip();
127 return;
128 }
129 zassert_ok(ret, "config PIN_OUT failed");
130
131 /* 4. Wait a bit and ensure that interrupt happened at most once */
132 k_sleep(K_MSEC(10));
133 zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt);
134
135 ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE);
136 if (ret == -ENOTSUP) {
137 TC_PRINT("GPIO_INT_DISABLE not supported.\n");
138 } else {
139 zassert_ok(ret, "interrupt disabling failed");
140 }
141
142 gpio_remove_callback(dev_in, &drv_data->gpio_cb);
143 }
144