1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
9 #include <rte_bus_vdev.h>
11 #include <rte_kvargs.h>
12 #include <rte_lcore.h>
13 #include <rte_rawdev_pmd.h>
17 #include "cnxk_gpio.h"
18 #include "rte_pmd_cnxk_gpio.h"
20 #define CNXK_GPIO_BUFSZ 128
21 #define CNXK_GPIO_CLASS_PATH "/sys/class/gpio"
23 static const char *const cnxk_gpio_args[] = {
24 #define CNXK_GPIO_ARG_GPIOCHIP "gpiochip"
25 CNXK_GPIO_ARG_GPIOCHIP,
26 #define CNXK_GPIO_ARG_ALLOWLIST "allowlist"
27 CNXK_GPIO_ARG_ALLOWLIST,
31 static char *allowlist;
34 cnxk_gpio_format_name(char *name, size_t len)
36 snprintf(name, len, "cnxk_gpio");
40 cnxk_gpio_filter_gpiochip(const struct dirent *dirent)
42 const char *pattern = "gpiochip";
44 return !strncmp(dirent->d_name, pattern, strlen(pattern));
48 cnxk_gpio_set_defaults(struct cnxk_gpiochip *gpiochip)
50 struct dirent **namelist;
53 n = scandir(CNXK_GPIO_CLASS_PATH, &namelist, cnxk_gpio_filter_gpiochip,
58 sscanf(namelist[0]->d_name, "gpiochip%d", &gpiochip->num);
65 cnxk_gpio_parse_arg_gpiochip(const char *key __rte_unused, const char *value,
71 val = strtol(value, NULL, 10);
75 *(int *)extra_args = (int)val;
81 cnxk_gpio_parse_arg_allowlist(const char *key __rte_unused, const char *value,
82 void *extra_args __rte_unused)
84 allowlist = strdup(value);
92 cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip, const char *args)
94 struct rte_kvargs *kvlist;
97 kvlist = rte_kvargs_parse(args, cnxk_gpio_args);
101 ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_GPIOCHIP);
103 ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_GPIOCHIP,
104 cnxk_gpio_parse_arg_gpiochip,
110 ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_ALLOWLIST);
112 ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_ALLOWLIST,
113 cnxk_gpio_parse_arg_allowlist, NULL);
120 rte_kvargs_free(kvlist);
126 cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip)
128 int i, ret, val, queue = 0;
132 list = rte_calloc(NULL, gpiochip->num_gpios, sizeof(*list), 0);
136 /* replace brackets with something meaningless for strtol() */
138 allowlist[strlen(allowlist) - 1] = ' ';
140 /* quiesce -Wcast-qual */
141 token = strtok((char *)(uintptr_t)allowlist, ",");
144 val = strtol(token, NULL, 10);
146 RTE_LOG(ERR, PMD, "failed to parse %s\n", token);
151 if (val < 0 || val >= gpiochip->num_gpios) {
152 RTE_LOG(ERR, PMD, "gpio%d out of 0-%d range\n", val,
153 gpiochip->num_gpios - 1);
158 for (i = 0; i < queue; i++) {
162 RTE_LOG(WARNING, PMD, "gpio%d already allowed\n", val);
167 } while ((token = strtok(NULL, ",")));
169 gpiochip->allowlist = list;
170 gpiochip->num_queues = queue;
180 cnxk_gpio_read_attr(char *attr, char *val)
185 fp = fopen(attr, "r");
189 ret = fscanf(fp, "%s", val);
209 cnxk_gpio_read_attr_int(char *attr, int *val)
211 char buf[CNXK_GPIO_BUFSZ];
214 ret = cnxk_gpio_read_attr(attr, buf);
218 ret = sscanf(buf, "%d", val);
226 cnxk_gpio_write_attr(const char *attr, const char *val)
234 fp = fopen(attr, "w");
238 ret = fprintf(fp, "%s", val);
252 cnxk_gpio_write_attr_int(const char *attr, int val)
254 char buf[CNXK_GPIO_BUFSZ];
256 snprintf(buf, sizeof(buf), "%d", val);
258 return cnxk_gpio_write_attr(attr, buf);
262 cnxk_gpio_queue_valid(struct cnxk_gpiochip *gpiochip, uint16_t queue)
264 return queue < gpiochip->num_queues;
268 cnxk_queue_to_gpio(struct cnxk_gpiochip *gpiochip, uint16_t queue)
270 return gpiochip->allowlist ? gpiochip->allowlist[queue] : queue;
273 static struct cnxk_gpio *
274 cnxk_gpio_lookup(struct cnxk_gpiochip *gpiochip, uint16_t queue)
276 int gpio = cnxk_queue_to_gpio(gpiochip, queue);
278 return gpiochip->gpios[gpio];
282 cnxk_gpio_exists(int num)
284 char buf[CNXK_GPIO_BUFSZ];
287 snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH, num);
289 return !stat(buf, &st);
293 cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
294 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
296 struct cnxk_gpiochip *gpiochip = dev->dev_private;
297 char buf[CNXK_GPIO_BUFSZ];
298 struct cnxk_gpio *gpio;
301 RTE_SET_USED(queue_conf);
302 RTE_SET_USED(queue_conf_size);
304 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
307 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
311 gpio = rte_zmalloc(NULL, sizeof(*gpio), 0);
315 num = cnxk_queue_to_gpio(gpiochip, queue_id);
316 gpio->num = num + gpiochip->base;
317 gpio->gpiochip = gpiochip;
319 if (!cnxk_gpio_exists(gpio->num)) {
320 snprintf(buf, sizeof(buf), "%s/export", CNXK_GPIO_CLASS_PATH);
321 ret = cnxk_gpio_write_attr_int(buf, gpio->num);
327 RTE_LOG(WARNING, PMD, "using existing gpio%d\n", gpio->num);
330 gpiochip->gpios[num] = gpio;
336 cnxk_gpio_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
338 struct cnxk_gpiochip *gpiochip = dev->dev_private;
339 char buf[CNXK_GPIO_BUFSZ];
340 struct cnxk_gpio *gpio;
343 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
346 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
350 snprintf(buf, sizeof(buf), "%s/unexport", CNXK_GPIO_CLASS_PATH);
351 ret = cnxk_gpio_write_attr_int(buf, gpio->num);
355 num = cnxk_queue_to_gpio(gpiochip, queue_id);
356 gpiochip->gpios[num] = NULL;
363 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
364 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
366 struct cnxk_gpiochip *gpiochip = dev->dev_private;
367 struct cnxk_gpio_queue_conf *conf = queue_conf;
369 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
372 if (queue_conf_size != sizeof(*conf))
376 conf->gpio = cnxk_queue_to_gpio(gpiochip, queue_id);
382 cnxk_gpio_queue_count(struct rte_rawdev *dev)
384 struct cnxk_gpiochip *gpiochip = dev->dev_private;
386 return gpiochip->num_queues;
389 static const struct {
390 enum cnxk_gpio_pin_edge edge;
392 } cnxk_gpio_edge_name[] = {
393 { CNXK_GPIO_PIN_EDGE_NONE, "none" },
394 { CNXK_GPIO_PIN_EDGE_FALLING, "falling" },
395 { CNXK_GPIO_PIN_EDGE_RISING, "rising" },
396 { CNXK_GPIO_PIN_EDGE_BOTH, "both" },
400 cnxk_gpio_edge_to_name(enum cnxk_gpio_pin_edge edge)
404 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
405 if (cnxk_gpio_edge_name[i].edge == edge)
406 return cnxk_gpio_edge_name[i].name;
412 static enum cnxk_gpio_pin_edge
413 cnxk_gpio_name_to_edge(const char *name)
417 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
418 if (!strcmp(cnxk_gpio_edge_name[i].name, name))
422 return cnxk_gpio_edge_name[i].edge;
425 static const struct {
426 enum cnxk_gpio_pin_dir dir;
428 } cnxk_gpio_dir_name[] = {
429 { CNXK_GPIO_PIN_DIR_IN, "in" },
430 { CNXK_GPIO_PIN_DIR_OUT, "out" },
431 { CNXK_GPIO_PIN_DIR_HIGH, "high" },
432 { CNXK_GPIO_PIN_DIR_LOW, "low" },
436 cnxk_gpio_dir_to_name(enum cnxk_gpio_pin_dir dir)
440 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
441 if (cnxk_gpio_dir_name[i].dir == dir)
442 return cnxk_gpio_dir_name[i].name;
448 static enum cnxk_gpio_pin_dir
449 cnxk_gpio_name_to_dir(const char *name)
453 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
454 if (!strcmp(cnxk_gpio_dir_name[i].name, name))
458 return cnxk_gpio_dir_name[i].dir;
462 cnxk_gpio_register_irq(struct cnxk_gpio *gpio, struct cnxk_gpio_irq *irq)
466 ret = cnxk_gpio_irq_request(gpio->num - gpio->gpiochip->base, irq->cpu);
470 gpio->handler = irq->handler;
471 gpio->data = irq->data;
472 gpio->cpu = irq->cpu;
478 cnxk_gpio_unregister_irq(struct cnxk_gpio *gpio)
480 return cnxk_gpio_irq_free(gpio->num - gpio->gpiochip->base);
484 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
486 struct cnxk_gpio_msg *msg = rbuf->buf_addr;
487 enum cnxk_gpio_pin_edge edge;
488 enum cnxk_gpio_pin_dir dir;
489 char buf[CNXK_GPIO_BUFSZ];
493 n = snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH,
497 case CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE:
498 snprintf(buf + n, sizeof(buf) - n, "/value");
499 ret = cnxk_gpio_write_attr_int(buf, !!*(int *)msg->data);
501 case CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE:
502 snprintf(buf + n, sizeof(buf) - n, "/edge");
503 edge = *(enum cnxk_gpio_pin_edge *)msg->data;
504 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_edge_to_name(edge));
506 case CNXK_GPIO_MSG_TYPE_SET_PIN_DIR:
507 snprintf(buf + n, sizeof(buf) - n, "/direction");
508 dir = *(enum cnxk_gpio_pin_dir *)msg->data;
509 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_dir_to_name(dir));
511 case CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW:
512 snprintf(buf + n, sizeof(buf) - n, "/active_low");
513 val = *(int *)msg->data;
514 ret = cnxk_gpio_write_attr_int(buf, val);
516 case CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE:
517 snprintf(buf + n, sizeof(buf) - n, "/value");
518 ret = cnxk_gpio_read_attr_int(buf, &val);
522 rsp = rte_zmalloc(NULL, sizeof(int), 0);
528 case CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE:
529 snprintf(buf + n, sizeof(buf) - n, "/edge");
530 ret = cnxk_gpio_read_attr(buf, buf);
534 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_edge), 0);
538 *(enum cnxk_gpio_pin_edge *)rsp = cnxk_gpio_name_to_edge(buf);
540 case CNXK_GPIO_MSG_TYPE_GET_PIN_DIR:
541 snprintf(buf + n, sizeof(buf) - n, "/direction");
542 ret = cnxk_gpio_read_attr(buf, buf);
546 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_dir), 0);
550 *(enum cnxk_gpio_pin_dir *)rsp = cnxk_gpio_name_to_dir(buf);
552 case CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW:
553 snprintf(buf + n, sizeof(buf) - n, "/active_low");
554 ret = cnxk_gpio_read_attr_int(buf, &val);
558 rsp = rte_zmalloc(NULL, sizeof(int), 0);
564 case CNXK_GPIO_MSG_TYPE_REGISTER_IRQ:
565 ret = cnxk_gpio_register_irq(gpio,
566 (struct cnxk_gpio_irq *)msg->data);
568 case CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ:
569 ret = cnxk_gpio_unregister_irq(gpio);
575 /* get rid of last response if any */
577 RTE_LOG(WARNING, PMD, "previous response got overwritten\n");
586 cnxk_gpio_valid(struct cnxk_gpiochip *gpiochip, int gpio)
588 return gpio < gpiochip->num_gpios && gpiochip->gpios[gpio];
592 cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
593 unsigned int count, rte_rawdev_obj_t context)
595 struct cnxk_gpiochip *gpiochip = dev->dev_private;
596 unsigned int gpio_num = (size_t)context;
597 struct cnxk_gpio *gpio;
603 if (!cnxk_gpio_valid(gpiochip, gpio_num))
605 gpio = gpiochip->gpios[gpio_num];
607 ret = cnxk_gpio_process_buf(gpio, buffers[0]);
615 cnxk_gpio_dequeue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
616 unsigned int count, rte_rawdev_obj_t context)
618 struct cnxk_gpiochip *gpiochip = dev->dev_private;
619 unsigned int gpio_num = (size_t)context;
620 struct cnxk_gpio *gpio;
625 if (!cnxk_gpio_valid(gpiochip, gpio_num))
627 gpio = gpiochip->gpios[gpio_num];
630 buffers[0]->buf_addr = gpio->rsp;
640 cnxk_gpio_dev_close(struct rte_rawdev *dev)
647 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
648 .dev_close = cnxk_gpio_dev_close,
649 .enqueue_bufs = cnxk_gpio_enqueue_bufs,
650 .dequeue_bufs = cnxk_gpio_dequeue_bufs,
651 .queue_def_conf = cnxk_gpio_queue_def_conf,
652 .queue_count = cnxk_gpio_queue_count,
653 .queue_setup = cnxk_gpio_queue_setup,
654 .queue_release = cnxk_gpio_queue_release,
655 .dev_selftest = cnxk_gpio_selftest,
659 cnxk_gpio_probe(struct rte_vdev_device *dev)
661 char name[RTE_RAWDEV_NAME_MAX_LEN];
662 struct cnxk_gpiochip *gpiochip;
663 struct rte_rawdev *rawdev;
664 char buf[CNXK_GPIO_BUFSZ];
667 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
670 cnxk_gpio_format_name(name, sizeof(name));
671 rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip),
674 RTE_LOG(ERR, PMD, "failed to allocate %s rawdev", name);
678 rawdev->dev_ops = &cnxk_gpio_rawdev_ops;
679 rawdev->device = &dev->device;
680 rawdev->driver_name = dev->device.name;
682 gpiochip = rawdev->dev_private;
683 cnxk_gpio_set_defaults(gpiochip);
685 /* defaults may be overwritten by this call */
686 ret = cnxk_gpio_parse_args(gpiochip, rte_vdev_device_args(dev));
690 ret = cnxk_gpio_irq_init(gpiochip);
695 snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH,
697 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->base);
699 RTE_LOG(ERR, PMD, "failed to read %s", buf);
703 /* read number of available gpios */
704 snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH,
706 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->num_gpios);
708 RTE_LOG(ERR, PMD, "failed to read %s", buf);
711 gpiochip->num_queues = gpiochip->num_gpios;
714 ret = cnxk_gpio_parse_allowlist(gpiochip);
721 gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios,
722 sizeof(struct cnxk_gpio *), 0);
723 if (!gpiochip->gpios) {
724 RTE_LOG(ERR, PMD, "failed to allocate gpios memory");
732 rte_free(gpiochip->allowlist);
733 rte_rawdev_pmd_release(rawdev);
739 cnxk_gpio_remove(struct rte_vdev_device *dev)
741 char name[RTE_RAWDEV_NAME_MAX_LEN];
742 struct cnxk_gpiochip *gpiochip;
743 struct rte_rawdev *rawdev;
744 struct cnxk_gpio *gpio;
749 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
752 cnxk_gpio_format_name(name, sizeof(name));
753 rawdev = rte_rawdev_pmd_get_named_dev(name);
757 gpiochip = rawdev->dev_private;
758 for (i = 0; i < gpiochip->num_gpios; i++) {
759 gpio = gpiochip->gpios[i];
764 cnxk_gpio_unregister_irq(gpio);
766 cnxk_gpio_queue_release(rawdev, gpio->num);
769 rte_free(gpiochip->allowlist);
770 rte_free(gpiochip->gpios);
771 cnxk_gpio_irq_fini();
772 rte_rawdev_pmd_release(rawdev);
777 static struct rte_vdev_driver cnxk_gpio_drv = {
778 .probe = cnxk_gpio_probe,
779 .remove = cnxk_gpio_remove,
782 RTE_PMD_REGISTER_VDEV(cnxk_gpio, cnxk_gpio_drv);
783 RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio,