1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
8 #include <rte_bus_vdev.h>
10 #include <rte_kvargs.h>
11 #include <rte_lcore.h>
12 #include <rte_rawdev_pmd.h>
16 #include "cnxk_gpio.h"
17 #include "rte_pmd_cnxk_gpio.h"
19 #define CNXK_GPIO_BUFSZ 128
20 #define CNXK_GPIO_CLASS_PATH "/sys/class/gpio"
22 static const char *const cnxk_gpio_args[] = {
23 #define CNXK_GPIO_ARG_GPIOCHIP "gpiochip"
24 CNXK_GPIO_ARG_GPIOCHIP,
25 #define CNXK_GPIO_ARG_ALLOWLIST "allowlist"
26 CNXK_GPIO_ARG_ALLOWLIST,
30 static char *allowlist;
33 cnxk_gpio_format_name(char *name, size_t len)
35 snprintf(name, len, "cnxk_gpio");
39 cnxk_gpio_filter_gpiochip(const struct dirent *dirent)
41 const char *pattern = "gpiochip";
43 return !strncmp(dirent->d_name, pattern, strlen(pattern));
47 cnxk_gpio_set_defaults(struct cnxk_gpiochip *gpiochip)
49 struct dirent **namelist;
52 n = scandir(CNXK_GPIO_CLASS_PATH, &namelist, cnxk_gpio_filter_gpiochip,
57 sscanf(namelist[0]->d_name, "gpiochip%d", &gpiochip->num);
64 cnxk_gpio_parse_arg_gpiochip(const char *key __rte_unused, const char *value,
70 val = strtol(value, NULL, 10);
74 *(int *)extra_args = (int)val;
80 cnxk_gpio_parse_arg_allowlist(const char *key __rte_unused, const char *value,
81 void *extra_args __rte_unused)
83 allowlist = strdup(value);
91 cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip, const char *args)
93 struct rte_kvargs *kvlist;
96 kvlist = rte_kvargs_parse(args, cnxk_gpio_args);
100 ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_GPIOCHIP);
102 ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_GPIOCHIP,
103 cnxk_gpio_parse_arg_gpiochip,
109 ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_ALLOWLIST);
111 ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_ALLOWLIST,
112 cnxk_gpio_parse_arg_allowlist, NULL);
119 rte_kvargs_free(kvlist);
125 cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip)
127 int i, ret, val, queue = 0;
131 list = rte_calloc(NULL, gpiochip->num_gpios, sizeof(*list), 0);
135 /* replace brackets with something meaningless for strtol() */
137 allowlist[strlen(allowlist) - 1] = ' ';
139 /* quiesce -Wcast-qual */
140 token = strtok((char *)(uintptr_t)allowlist, ",");
143 val = strtol(token, NULL, 10);
145 RTE_LOG(ERR, PMD, "failed to parse %s\n", token);
150 if (val < 0 || val >= gpiochip->num_gpios) {
151 RTE_LOG(ERR, PMD, "gpio%d out of 0-%d range\n", val,
152 gpiochip->num_gpios - 1);
157 for (i = 0; i < queue; i++) {
161 RTE_LOG(WARNING, PMD, "gpio%d already allowed\n", val);
166 } while ((token = strtok(NULL, ",")));
168 gpiochip->allowlist = list;
169 gpiochip->num_queues = queue;
179 cnxk_gpio_read_attr(char *attr, char *val)
184 fp = fopen(attr, "r");
188 ret = fscanf(fp, "%s", val);
202 cnxk_gpio_read_attr_int(char *attr, int *val)
204 char buf[CNXK_GPIO_BUFSZ];
207 ret = cnxk_gpio_read_attr(attr, buf);
211 ret = sscanf(buf, "%d", val);
219 cnxk_gpio_write_attr(const char *attr, const char *val)
227 fp = fopen(attr, "w");
231 ret = fprintf(fp, "%s", val);
245 cnxk_gpio_write_attr_int(const char *attr, int val)
247 char buf[CNXK_GPIO_BUFSZ];
249 snprintf(buf, sizeof(buf), "%d", val);
251 return cnxk_gpio_write_attr(attr, buf);
255 cnxk_gpio_queue_valid(struct cnxk_gpiochip *gpiochip, uint16_t queue)
257 return queue < gpiochip->num_queues;
261 cnxk_queue_to_gpio(struct cnxk_gpiochip *gpiochip, uint16_t queue)
263 return gpiochip->allowlist ? gpiochip->allowlist[queue] : queue;
266 static struct cnxk_gpio *
267 cnxk_gpio_lookup(struct cnxk_gpiochip *gpiochip, uint16_t queue)
269 int gpio = cnxk_queue_to_gpio(gpiochip, queue);
271 return gpiochip->gpios[gpio];
275 cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
276 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
278 struct cnxk_gpiochip *gpiochip = dev->dev_private;
279 char buf[CNXK_GPIO_BUFSZ];
280 struct cnxk_gpio *gpio;
283 RTE_SET_USED(queue_conf);
284 RTE_SET_USED(queue_conf_size);
286 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
289 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
293 gpio = rte_zmalloc(NULL, sizeof(*gpio), 0);
297 num = cnxk_queue_to_gpio(gpiochip, queue_id);
298 gpio->num = num + gpiochip->base;
299 gpio->gpiochip = gpiochip;
301 snprintf(buf, sizeof(buf), "%s/export", CNXK_GPIO_CLASS_PATH);
302 ret = cnxk_gpio_write_attr_int(buf, gpio->num);
308 gpiochip->gpios[num] = gpio;
314 cnxk_gpio_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
316 struct cnxk_gpiochip *gpiochip = dev->dev_private;
317 char buf[CNXK_GPIO_BUFSZ];
318 struct cnxk_gpio *gpio;
321 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
324 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
328 snprintf(buf, sizeof(buf), "%s/unexport", CNXK_GPIO_CLASS_PATH);
329 ret = cnxk_gpio_write_attr_int(buf, gpio->num);
333 num = cnxk_queue_to_gpio(gpiochip, queue_id);
334 gpiochip->gpios[num] = NULL;
341 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
342 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
344 struct cnxk_gpiochip *gpiochip = dev->dev_private;
345 struct cnxk_gpio_queue_conf *conf = queue_conf;
347 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
350 if (queue_conf_size != sizeof(*conf))
354 conf->gpio = cnxk_queue_to_gpio(gpiochip, queue_id);
360 cnxk_gpio_queue_count(struct rte_rawdev *dev)
362 struct cnxk_gpiochip *gpiochip = dev->dev_private;
364 return gpiochip->num_queues;
367 static const struct {
368 enum cnxk_gpio_pin_edge edge;
370 } cnxk_gpio_edge_name[] = {
371 { CNXK_GPIO_PIN_EDGE_NONE, "none" },
372 { CNXK_GPIO_PIN_EDGE_FALLING, "falling" },
373 { CNXK_GPIO_PIN_EDGE_RISING, "rising" },
374 { CNXK_GPIO_PIN_EDGE_BOTH, "both" },
378 cnxk_gpio_edge_to_name(enum cnxk_gpio_pin_edge edge)
382 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
383 if (cnxk_gpio_edge_name[i].edge == edge)
384 return cnxk_gpio_edge_name[i].name;
390 static enum cnxk_gpio_pin_edge
391 cnxk_gpio_name_to_edge(const char *name)
395 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
396 if (!strcmp(cnxk_gpio_edge_name[i].name, name))
400 return cnxk_gpio_edge_name[i].edge;
403 static const struct {
404 enum cnxk_gpio_pin_dir dir;
406 } cnxk_gpio_dir_name[] = {
407 { CNXK_GPIO_PIN_DIR_IN, "in" },
408 { CNXK_GPIO_PIN_DIR_OUT, "out" },
409 { CNXK_GPIO_PIN_DIR_HIGH, "high" },
410 { CNXK_GPIO_PIN_DIR_LOW, "low" },
414 cnxk_gpio_dir_to_name(enum cnxk_gpio_pin_dir dir)
418 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
419 if (cnxk_gpio_dir_name[i].dir == dir)
420 return cnxk_gpio_dir_name[i].name;
426 static enum cnxk_gpio_pin_dir
427 cnxk_gpio_name_to_dir(const char *name)
431 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
432 if (!strcmp(cnxk_gpio_dir_name[i].name, name))
436 return cnxk_gpio_dir_name[i].dir;
440 cnxk_gpio_register_irq(struct cnxk_gpio *gpio, struct cnxk_gpio_irq *irq)
444 ret = cnxk_gpio_irq_request(gpio->num - gpio->gpiochip->base, irq->cpu);
448 gpio->handler = irq->handler;
449 gpio->data = irq->data;
450 gpio->cpu = irq->cpu;
456 cnxk_gpio_unregister_irq(struct cnxk_gpio *gpio)
458 return cnxk_gpio_irq_free(gpio->num - gpio->gpiochip->base);
462 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
464 struct cnxk_gpio_msg *msg = rbuf->buf_addr;
465 enum cnxk_gpio_pin_edge edge;
466 enum cnxk_gpio_pin_dir dir;
467 char buf[CNXK_GPIO_BUFSZ];
471 n = snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH,
475 case CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE:
476 snprintf(buf + n, sizeof(buf) - n, "/value");
477 ret = cnxk_gpio_write_attr_int(buf, !!*(int *)msg->data);
479 case CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE:
480 snprintf(buf + n, sizeof(buf) - n, "/edge");
481 edge = *(enum cnxk_gpio_pin_edge *)msg->data;
482 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_edge_to_name(edge));
484 case CNXK_GPIO_MSG_TYPE_SET_PIN_DIR:
485 snprintf(buf + n, sizeof(buf) - n, "/direction");
486 dir = *(enum cnxk_gpio_pin_dir *)msg->data;
487 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_dir_to_name(dir));
489 case CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW:
490 snprintf(buf + n, sizeof(buf) - n, "/active_low");
491 val = *(int *)msg->data;
492 ret = cnxk_gpio_write_attr_int(buf, val);
494 case CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE:
495 snprintf(buf + n, sizeof(buf) - n, "/value");
496 ret = cnxk_gpio_read_attr_int(buf, &val);
500 rsp = rte_zmalloc(NULL, sizeof(int), 0);
506 case CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE:
507 snprintf(buf + n, sizeof(buf) - n, "/edge");
508 ret = cnxk_gpio_read_attr(buf, buf);
512 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_edge), 0);
516 *(enum cnxk_gpio_pin_edge *)rsp = cnxk_gpio_name_to_edge(buf);
518 case CNXK_GPIO_MSG_TYPE_GET_PIN_DIR:
519 snprintf(buf + n, sizeof(buf) - n, "/direction");
520 ret = cnxk_gpio_read_attr(buf, buf);
524 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_dir), 0);
528 *(enum cnxk_gpio_pin_dir *)rsp = cnxk_gpio_name_to_dir(buf);
530 case CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW:
531 snprintf(buf + n, sizeof(buf) - n, "/active_low");
532 ret = cnxk_gpio_read_attr_int(buf, &val);
536 rsp = rte_zmalloc(NULL, sizeof(int), 0);
542 case CNXK_GPIO_MSG_TYPE_REGISTER_IRQ:
543 ret = cnxk_gpio_register_irq(gpio,
544 (struct cnxk_gpio_irq *)msg->data);
546 case CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ:
547 ret = cnxk_gpio_unregister_irq(gpio);
553 /* get rid of last response if any */
555 RTE_LOG(WARNING, PMD, "previous response got overwritten\n");
564 cnxk_gpio_valid(struct cnxk_gpiochip *gpiochip, int gpio)
566 return gpio < gpiochip->num_gpios && gpiochip->gpios[gpio];
570 cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
571 unsigned int count, rte_rawdev_obj_t context)
573 struct cnxk_gpiochip *gpiochip = dev->dev_private;
574 unsigned int gpio_num = (size_t)context;
575 struct cnxk_gpio *gpio;
581 if (!cnxk_gpio_valid(gpiochip, gpio_num))
583 gpio = gpiochip->gpios[gpio_num];
585 ret = cnxk_gpio_process_buf(gpio, buffers[0]);
593 cnxk_gpio_dequeue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
594 unsigned int count, rte_rawdev_obj_t context)
596 struct cnxk_gpiochip *gpiochip = dev->dev_private;
597 unsigned int gpio_num = (size_t)context;
598 struct cnxk_gpio *gpio;
603 if (!cnxk_gpio_valid(gpiochip, gpio_num))
605 gpio = gpiochip->gpios[gpio_num];
608 buffers[0]->buf_addr = gpio->rsp;
618 cnxk_gpio_dev_close(struct rte_rawdev *dev)
625 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
626 .dev_close = cnxk_gpio_dev_close,
627 .enqueue_bufs = cnxk_gpio_enqueue_bufs,
628 .dequeue_bufs = cnxk_gpio_dequeue_bufs,
629 .queue_def_conf = cnxk_gpio_queue_def_conf,
630 .queue_count = cnxk_gpio_queue_count,
631 .queue_setup = cnxk_gpio_queue_setup,
632 .queue_release = cnxk_gpio_queue_release,
633 .dev_selftest = cnxk_gpio_selftest,
637 cnxk_gpio_probe(struct rte_vdev_device *dev)
639 char name[RTE_RAWDEV_NAME_MAX_LEN];
640 struct cnxk_gpiochip *gpiochip;
641 struct rte_rawdev *rawdev;
642 char buf[CNXK_GPIO_BUFSZ];
645 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
648 cnxk_gpio_format_name(name, sizeof(name));
649 rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip),
652 RTE_LOG(ERR, PMD, "failed to allocate %s rawdev", name);
656 rawdev->dev_ops = &cnxk_gpio_rawdev_ops;
657 rawdev->device = &dev->device;
658 rawdev->driver_name = dev->device.name;
660 gpiochip = rawdev->dev_private;
661 cnxk_gpio_set_defaults(gpiochip);
663 /* defaults may be overwritten by this call */
664 ret = cnxk_gpio_parse_args(gpiochip, rte_vdev_device_args(dev));
668 ret = cnxk_gpio_irq_init(gpiochip);
673 snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH,
675 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->base);
677 RTE_LOG(ERR, PMD, "failed to read %s", buf);
681 /* read number of available gpios */
682 snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH,
684 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->num_gpios);
686 RTE_LOG(ERR, PMD, "failed to read %s", buf);
689 gpiochip->num_queues = gpiochip->num_gpios;
692 ret = cnxk_gpio_parse_allowlist(gpiochip);
699 gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios,
700 sizeof(struct cnxk_gpio *), 0);
701 if (!gpiochip->gpios) {
702 RTE_LOG(ERR, PMD, "failed to allocate gpios memory");
710 rte_free(gpiochip->allowlist);
711 rte_rawdev_pmd_release(rawdev);
717 cnxk_gpio_remove(struct rte_vdev_device *dev)
719 char name[RTE_RAWDEV_NAME_MAX_LEN];
720 struct cnxk_gpiochip *gpiochip;
721 struct rte_rawdev *rawdev;
722 struct cnxk_gpio *gpio;
727 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
730 cnxk_gpio_format_name(name, sizeof(name));
731 rawdev = rte_rawdev_pmd_get_named_dev(name);
735 gpiochip = rawdev->dev_private;
736 for (i = 0; i < gpiochip->num_gpios; i++) {
737 gpio = gpiochip->gpios[i];
742 cnxk_gpio_unregister_irq(gpio);
744 cnxk_gpio_queue_release(rawdev, gpio->num);
747 rte_free(gpiochip->allowlist);
748 rte_free(gpiochip->gpios);
749 cnxk_gpio_irq_fini();
750 rte_rawdev_pmd_release(rawdev);
755 static struct rte_vdev_driver cnxk_gpio_drv = {
756 .probe = cnxk_gpio_probe,
757 .remove = cnxk_gpio_remove,
760 RTE_PMD_REGISTER_VDEV(cnxk_gpio, cnxk_gpio_drv);
761 RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio,