1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
10 #include <rte_cycles.h>
11 #include <rte_rawdev.h>
12 #include <rte_rawdev_pmd.h>
13 #include <rte_service.h>
15 #include "cnxk_gpio.h"
16 #include "rte_pmd_cnxk_gpio.h"
18 #define CNXK_GPIO_BUFSZ 128
20 #define OTX_IOC_MAGIC 0xF2
21 #define OTX_IOC_TRIGGER_GPIO_HANDLER \
27 cnxk_gpio_attr_exists(const char *attr)
31 return !stat(attr, &st);
35 cnxk_gpio_read_attr(char *attr, char *val)
40 fp = fopen(attr, "r");
44 ret = fscanf(fp, "%s", val);
57 #define CNXK_GPIO_ERR_STR(err, str, ...) do { \
59 RTE_LOG(ERR, PMD, "%s:%d: " str " (%d)\n", __func__, __LINE__, \
60 ##__VA_ARGS__, err); \
66 cnxk_gpio_validate_attr(char *attr, const char *expected)
68 char buf[CNXK_GPIO_BUFSZ];
71 ret = cnxk_gpio_read_attr(attr, buf);
75 if (strncmp(buf, expected, sizeof(buf)))
81 #define CNXK_GPIO_PATH_FMT "/sys/class/gpio/gpio%d"
84 cnxk_gpio_test_input(uint16_t dev_id, int base, int gpio)
86 char buf[CNXK_GPIO_BUFSZ];
89 n = snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, base + gpio);
90 snprintf(buf + n, sizeof(buf) - n, "/direction");
92 ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
93 CNXK_GPIO_ERR_STR(ret, "failed to set dir to input");
94 ret = cnxk_gpio_validate_attr(buf, "in");
95 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
97 ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1) |
98 rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
101 CNXK_GPIO_ERR_STR(ret, "input pin overwritten");
104 snprintf(buf + n, sizeof(buf) - n, "/edge");
106 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
107 CNXK_GPIO_PIN_EDGE_FALLING);
108 CNXK_GPIO_ERR_STR(ret, "failed to set edge to falling");
109 ret = cnxk_gpio_validate_attr(buf, "falling");
110 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
112 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
113 CNXK_GPIO_PIN_EDGE_RISING);
114 CNXK_GPIO_ERR_STR(ret, "failed to change edge to rising");
115 ret = cnxk_gpio_validate_attr(buf, "rising");
116 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
118 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_BOTH);
119 CNXK_GPIO_ERR_STR(ret, "failed to change edge to both");
120 ret = cnxk_gpio_validate_attr(buf, "both");
121 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
123 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
124 CNXK_GPIO_ERR_STR(ret, "failed to set edge to none");
125 ret = cnxk_gpio_validate_attr(buf, "none");
126 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
129 * calling this makes sure kernel driver switches off inverted
132 rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
139 cnxk_gpio_trigger_irq(int gpio)
143 ret = ioctl(fd, OTX_IOC_TRIGGER_GPIO_HANDLER, gpio);
145 return ret == -1 ? -errno : 0;
149 cnxk_gpio_irq_handler(int gpio, void *data)
155 cnxk_gpio_test_irq(uint16_t dev_id, int gpio)
159 ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
160 CNXK_GPIO_ERR_STR(ret, "failed to set dir to input");
163 ret = rte_pmd_gpio_register_irq(dev_id, gpio, rte_lcore_id(),
164 cnxk_gpio_irq_handler, &irq_data);
165 CNXK_GPIO_ERR_STR(ret, "failed to register irq handler");
167 ret = rte_pmd_gpio_enable_interrupt(dev_id, gpio,
168 CNXK_GPIO_PIN_EDGE_RISING);
169 CNXK_GPIO_ERR_STR(ret, "failed to enable interrupt");
171 ret = cnxk_gpio_trigger_irq(gpio);
172 CNXK_GPIO_ERR_STR(ret, "failed to trigger irq");
174 ret = *(volatile int *)&irq_data == gpio ? 0 : -EIO;
175 CNXK_GPIO_ERR_STR(ret, "failed to test irq");
177 ret = rte_pmd_gpio_disable_interrupt(dev_id, gpio);
178 CNXK_GPIO_ERR_STR(ret, "failed to disable interrupt");
180 ret = rte_pmd_gpio_unregister_irq(dev_id, gpio);
181 CNXK_GPIO_ERR_STR(ret, "failed to unregister irq handler");
183 rte_pmd_gpio_disable_interrupt(dev_id, gpio);
184 rte_pmd_gpio_unregister_irq(dev_id, gpio);
190 cnxk_gpio_test_output(uint16_t dev_id, int base, int gpio)
192 char buf[CNXK_GPIO_BUFSZ];
195 n = snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, base + gpio);
197 snprintf(buf + n, sizeof(buf) - n, "/direction");
198 ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_OUT);
199 CNXK_GPIO_ERR_STR(ret, "failed to set dir to out");
200 ret = cnxk_gpio_validate_attr(buf, "out");
201 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
203 snprintf(buf + n, sizeof(buf) - n, "/value");
204 ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
205 CNXK_GPIO_ERR_STR(ret, "failed to set value to 0");
206 ret = cnxk_gpio_validate_attr(buf, "0");
207 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
208 ret = rte_pmd_gpio_get_pin_value(dev_id, gpio, &val);
209 CNXK_GPIO_ERR_STR(ret, "failed to read value");
212 CNXK_GPIO_ERR_STR(ret, "read %d instead of 0", val);
214 ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1);
215 CNXK_GPIO_ERR_STR(ret, "failed to set value to 1");
216 ret = cnxk_gpio_validate_attr(buf, "1");
217 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
218 ret = rte_pmd_gpio_get_pin_value(dev_id, gpio, &val);
219 CNXK_GPIO_ERR_STR(ret, "failed to read value");
222 CNXK_GPIO_ERR_STR(ret, "read %d instead of 1", val);
224 snprintf(buf + n, sizeof(buf) - n, "/direction");
225 ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_LOW);
226 CNXK_GPIO_ERR_STR(ret, "failed to set dir to low");
227 ret = cnxk_gpio_validate_attr(buf, "out");
228 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
229 snprintf(buf + n, sizeof(buf) - n, "/value");
230 ret = cnxk_gpio_validate_attr(buf, "0");
231 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
233 snprintf(buf + n, sizeof(buf) - n, "/direction");
234 ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_HIGH);
235 CNXK_GPIO_ERR_STR(ret, "failed to set dir to high");
236 ret = cnxk_gpio_validate_attr(buf, "out");
237 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
238 snprintf(buf + n, sizeof(buf) - n, "/value");
239 ret = cnxk_gpio_validate_attr(buf, "1");
240 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
242 snprintf(buf + n, sizeof(buf) - n, "/edge");
243 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
244 CNXK_GPIO_PIN_EDGE_FALLING);
245 ret = ret == 0 ? -EIO : 0;
246 CNXK_GPIO_ERR_STR(ret, "changed edge to falling");
247 ret = cnxk_gpio_validate_attr(buf, "none");
248 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
250 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
251 CNXK_GPIO_PIN_EDGE_RISING);
252 ret = ret == 0 ? -EIO : 0;
253 CNXK_GPIO_ERR_STR(ret, "changed edge to rising");
254 ret = cnxk_gpio_validate_attr(buf, "none");
255 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
257 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_BOTH);
258 ret = ret == 0 ? -EIO : 0;
259 CNXK_GPIO_ERR_STR(ret, "changed edge to both");
260 ret = cnxk_gpio_validate_attr(buf, "none");
261 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
263 /* this one should succeed */
264 ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
265 CNXK_GPIO_ERR_STR(ret, "failed to change edge to none");
266 ret = cnxk_gpio_validate_attr(buf, "none");
267 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
269 snprintf(buf + n, sizeof(buf) - n, "/active_low");
270 ret = rte_pmd_gpio_set_pin_active_low(dev_id, gpio, 1);
271 CNXK_GPIO_ERR_STR(ret, "failed to set active_low to 1");
272 ret = cnxk_gpio_validate_attr(buf, "1");
273 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
275 ret = rte_pmd_gpio_get_pin_active_low(dev_id, gpio, &val);
276 CNXK_GPIO_ERR_STR(ret, "failed to read active_low");
279 CNXK_GPIO_ERR_STR(ret, "read %d instead of 1", val);
281 snprintf(buf + n, sizeof(buf) - n, "/value");
282 ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1);
283 CNXK_GPIO_ERR_STR(ret, "failed to set value to 1");
284 ret = cnxk_gpio_validate_attr(buf, "1");
285 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
287 ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
288 CNXK_GPIO_ERR_STR(ret, "failed to set value to 0");
289 ret = cnxk_gpio_validate_attr(buf, "0");
290 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
292 snprintf(buf + n, sizeof(buf) - n, "/active_low");
293 ret = rte_pmd_gpio_set_pin_active_low(dev_id, gpio, 0);
294 CNXK_GPIO_ERR_STR(ret, "failed to set active_low to 0");
295 ret = cnxk_gpio_validate_attr(buf, "0");
296 CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
303 cnxk_gpio_selftest(uint16_t dev_id)
305 struct cnxk_gpio_queue_conf conf;
306 struct cnxk_gpiochip *gpiochip;
307 char buf[CNXK_GPIO_BUFSZ];
308 struct rte_rawdev *rawdev;
309 unsigned int queues, i;
310 struct cnxk_gpio *gpio;
313 rawdev = rte_rawdev_pmd_get_named_dev("cnxk_gpio");
316 gpiochip = rawdev->dev_private;
318 queues = rte_rawdev_queue_count(dev_id);
322 ret = rte_rawdev_start(dev_id);
326 fd = open("/dev/otx-gpio-ctr", O_RDWR | O_SYNC);
330 for (i = 0; i < queues; i++) {
331 ret = rte_rawdev_queue_conf_get(dev_id, i, &conf, sizeof(conf));
334 "failed to read queue configuration (%d)\n",
339 RTE_LOG(INFO, PMD, "testing queue%d (gpio%d)\n", i, conf.gpio);
341 if (conf.size != 1) {
342 RTE_LOG(ERR, PMD, "wrong queue size received\n");
347 ret = rte_rawdev_queue_setup(dev_id, i, NULL, 0);
349 RTE_LOG(ERR, PMD, "failed to setup queue (%d)\n", ret);
353 gpio = gpiochip->gpios[conf.gpio];
354 snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, gpio->num);
355 if (!cnxk_gpio_attr_exists(buf)) {
356 RTE_LOG(ERR, PMD, "%s does not exist\n", buf);
361 ret = cnxk_gpio_test_input(dev_id, gpiochip->base, conf.gpio);
365 ret = cnxk_gpio_test_irq(dev_id, conf.gpio);
369 ret = cnxk_gpio_test_output(dev_id, gpiochip->base, conf.gpio);
372 ret = rte_rawdev_queue_release(dev_id, i);
374 RTE_LOG(ERR, PMD, "failed to release queue (%d)\n",
379 if (cnxk_gpio_attr_exists(buf)) {
380 RTE_LOG(ERR, PMD, "%s still exists\n", buf);