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);
208 cnxk_gpio_read_attr_int(char *attr, int *val)
210 char buf[CNXK_GPIO_BUFSZ];
213 ret = cnxk_gpio_read_attr(attr, buf);
217 ret = sscanf(buf, "%d", val);
225 cnxk_gpio_write_attr(const char *attr, const char *val)
233 fp = fopen(attr, "w");
237 ret = fprintf(fp, "%s", val);
251 cnxk_gpio_write_attr_int(const char *attr, int val)
253 char buf[CNXK_GPIO_BUFSZ];
255 snprintf(buf, sizeof(buf), "%d", val);
257 return cnxk_gpio_write_attr(attr, buf);
261 cnxk_gpio_queue_valid(struct cnxk_gpiochip *gpiochip, uint16_t queue)
263 return queue < gpiochip->num_queues;
267 cnxk_queue_to_gpio(struct cnxk_gpiochip *gpiochip, uint16_t queue)
269 return gpiochip->allowlist ? gpiochip->allowlist[queue] : queue;
272 static struct cnxk_gpio *
273 cnxk_gpio_lookup(struct cnxk_gpiochip *gpiochip, uint16_t queue)
275 int gpio = cnxk_queue_to_gpio(gpiochip, queue);
277 return gpiochip->gpios[gpio];
281 cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
282 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
284 struct cnxk_gpiochip *gpiochip = dev->dev_private;
285 char buf[CNXK_GPIO_BUFSZ];
286 struct cnxk_gpio *gpio;
289 RTE_SET_USED(queue_conf);
290 RTE_SET_USED(queue_conf_size);
292 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
295 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
299 gpio = rte_zmalloc(NULL, sizeof(*gpio), 0);
303 num = cnxk_queue_to_gpio(gpiochip, queue_id);
304 gpio->num = num + gpiochip->base;
305 gpio->gpiochip = gpiochip;
307 snprintf(buf, sizeof(buf), "%s/export", CNXK_GPIO_CLASS_PATH);
308 ret = cnxk_gpio_write_attr_int(buf, gpio->num);
314 gpiochip->gpios[num] = gpio;
320 cnxk_gpio_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
322 struct cnxk_gpiochip *gpiochip = dev->dev_private;
323 char buf[CNXK_GPIO_BUFSZ];
324 struct cnxk_gpio *gpio;
327 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
330 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
334 snprintf(buf, sizeof(buf), "%s/unexport", CNXK_GPIO_CLASS_PATH);
335 ret = cnxk_gpio_write_attr_int(buf, gpio->num);
339 num = cnxk_queue_to_gpio(gpiochip, queue_id);
340 gpiochip->gpios[num] = NULL;
347 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
348 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
350 struct cnxk_gpiochip *gpiochip = dev->dev_private;
351 struct cnxk_gpio_queue_conf *conf = queue_conf;
353 if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
356 if (queue_conf_size != sizeof(*conf))
360 conf->gpio = cnxk_queue_to_gpio(gpiochip, queue_id);
366 cnxk_gpio_queue_count(struct rte_rawdev *dev)
368 struct cnxk_gpiochip *gpiochip = dev->dev_private;
370 return gpiochip->num_queues;
373 static const struct {
374 enum cnxk_gpio_pin_edge edge;
376 } cnxk_gpio_edge_name[] = {
377 { CNXK_GPIO_PIN_EDGE_NONE, "none" },
378 { CNXK_GPIO_PIN_EDGE_FALLING, "falling" },
379 { CNXK_GPIO_PIN_EDGE_RISING, "rising" },
380 { CNXK_GPIO_PIN_EDGE_BOTH, "both" },
384 cnxk_gpio_edge_to_name(enum cnxk_gpio_pin_edge edge)
388 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
389 if (cnxk_gpio_edge_name[i].edge == edge)
390 return cnxk_gpio_edge_name[i].name;
396 static enum cnxk_gpio_pin_edge
397 cnxk_gpio_name_to_edge(const char *name)
401 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
402 if (!strcmp(cnxk_gpio_edge_name[i].name, name))
406 return cnxk_gpio_edge_name[i].edge;
409 static const struct {
410 enum cnxk_gpio_pin_dir dir;
412 } cnxk_gpio_dir_name[] = {
413 { CNXK_GPIO_PIN_DIR_IN, "in" },
414 { CNXK_GPIO_PIN_DIR_OUT, "out" },
415 { CNXK_GPIO_PIN_DIR_HIGH, "high" },
416 { CNXK_GPIO_PIN_DIR_LOW, "low" },
420 cnxk_gpio_dir_to_name(enum cnxk_gpio_pin_dir dir)
424 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
425 if (cnxk_gpio_dir_name[i].dir == dir)
426 return cnxk_gpio_dir_name[i].name;
432 static enum cnxk_gpio_pin_dir
433 cnxk_gpio_name_to_dir(const char *name)
437 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
438 if (!strcmp(cnxk_gpio_dir_name[i].name, name))
442 return cnxk_gpio_dir_name[i].dir;
446 cnxk_gpio_register_irq(struct cnxk_gpio *gpio, struct cnxk_gpio_irq *irq)
450 ret = cnxk_gpio_irq_request(gpio->num - gpio->gpiochip->base, irq->cpu);
454 gpio->handler = irq->handler;
455 gpio->data = irq->data;
456 gpio->cpu = irq->cpu;
462 cnxk_gpio_unregister_irq(struct cnxk_gpio *gpio)
464 return cnxk_gpio_irq_free(gpio->num - gpio->gpiochip->base);
468 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
470 struct cnxk_gpio_msg *msg = rbuf->buf_addr;
471 enum cnxk_gpio_pin_edge edge;
472 enum cnxk_gpio_pin_dir dir;
473 char buf[CNXK_GPIO_BUFSZ];
477 n = snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH,
481 case CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE:
482 snprintf(buf + n, sizeof(buf) - n, "/value");
483 ret = cnxk_gpio_write_attr_int(buf, !!*(int *)msg->data);
485 case CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE:
486 snprintf(buf + n, sizeof(buf) - n, "/edge");
487 edge = *(enum cnxk_gpio_pin_edge *)msg->data;
488 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_edge_to_name(edge));
490 case CNXK_GPIO_MSG_TYPE_SET_PIN_DIR:
491 snprintf(buf + n, sizeof(buf) - n, "/direction");
492 dir = *(enum cnxk_gpio_pin_dir *)msg->data;
493 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_dir_to_name(dir));
495 case CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW:
496 snprintf(buf + n, sizeof(buf) - n, "/active_low");
497 val = *(int *)msg->data;
498 ret = cnxk_gpio_write_attr_int(buf, val);
500 case CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE:
501 snprintf(buf + n, sizeof(buf) - n, "/value");
502 ret = cnxk_gpio_read_attr_int(buf, &val);
506 rsp = rte_zmalloc(NULL, sizeof(int), 0);
512 case CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE:
513 snprintf(buf + n, sizeof(buf) - n, "/edge");
514 ret = cnxk_gpio_read_attr(buf, buf);
518 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_edge), 0);
522 *(enum cnxk_gpio_pin_edge *)rsp = cnxk_gpio_name_to_edge(buf);
524 case CNXK_GPIO_MSG_TYPE_GET_PIN_DIR:
525 snprintf(buf + n, sizeof(buf) - n, "/direction");
526 ret = cnxk_gpio_read_attr(buf, buf);
530 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_dir), 0);
534 *(enum cnxk_gpio_pin_dir *)rsp = cnxk_gpio_name_to_dir(buf);
536 case CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW:
537 snprintf(buf + n, sizeof(buf) - n, "/active_low");
538 ret = cnxk_gpio_read_attr_int(buf, &val);
542 rsp = rte_zmalloc(NULL, sizeof(int), 0);
548 case CNXK_GPIO_MSG_TYPE_REGISTER_IRQ:
549 ret = cnxk_gpio_register_irq(gpio,
550 (struct cnxk_gpio_irq *)msg->data);
552 case CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ:
553 ret = cnxk_gpio_unregister_irq(gpio);
559 /* get rid of last response if any */
561 RTE_LOG(WARNING, PMD, "previous response got overwritten\n");
570 cnxk_gpio_valid(struct cnxk_gpiochip *gpiochip, int gpio)
572 return gpio < gpiochip->num_gpios && gpiochip->gpios[gpio];
576 cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
577 unsigned int count, rte_rawdev_obj_t context)
579 struct cnxk_gpiochip *gpiochip = dev->dev_private;
580 unsigned int gpio_num = (size_t)context;
581 struct cnxk_gpio *gpio;
587 if (!cnxk_gpio_valid(gpiochip, gpio_num))
589 gpio = gpiochip->gpios[gpio_num];
591 ret = cnxk_gpio_process_buf(gpio, buffers[0]);
599 cnxk_gpio_dequeue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
600 unsigned int count, rte_rawdev_obj_t context)
602 struct cnxk_gpiochip *gpiochip = dev->dev_private;
603 unsigned int gpio_num = (size_t)context;
604 struct cnxk_gpio *gpio;
609 if (!cnxk_gpio_valid(gpiochip, gpio_num))
611 gpio = gpiochip->gpios[gpio_num];
614 buffers[0]->buf_addr = gpio->rsp;
624 cnxk_gpio_dev_close(struct rte_rawdev *dev)
631 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
632 .dev_close = cnxk_gpio_dev_close,
633 .enqueue_bufs = cnxk_gpio_enqueue_bufs,
634 .dequeue_bufs = cnxk_gpio_dequeue_bufs,
635 .queue_def_conf = cnxk_gpio_queue_def_conf,
636 .queue_count = cnxk_gpio_queue_count,
637 .queue_setup = cnxk_gpio_queue_setup,
638 .queue_release = cnxk_gpio_queue_release,
639 .dev_selftest = cnxk_gpio_selftest,
643 cnxk_gpio_probe(struct rte_vdev_device *dev)
645 char name[RTE_RAWDEV_NAME_MAX_LEN];
646 struct cnxk_gpiochip *gpiochip;
647 struct rte_rawdev *rawdev;
648 char buf[CNXK_GPIO_BUFSZ];
651 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
654 cnxk_gpio_format_name(name, sizeof(name));
655 rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip),
658 RTE_LOG(ERR, PMD, "failed to allocate %s rawdev", name);
662 rawdev->dev_ops = &cnxk_gpio_rawdev_ops;
663 rawdev->device = &dev->device;
664 rawdev->driver_name = dev->device.name;
666 gpiochip = rawdev->dev_private;
667 cnxk_gpio_set_defaults(gpiochip);
669 /* defaults may be overwritten by this call */
670 ret = cnxk_gpio_parse_args(gpiochip, rte_vdev_device_args(dev));
674 ret = cnxk_gpio_irq_init(gpiochip);
679 snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH,
681 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->base);
683 RTE_LOG(ERR, PMD, "failed to read %s", buf);
687 /* read number of available gpios */
688 snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH,
690 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->num_gpios);
692 RTE_LOG(ERR, PMD, "failed to read %s", buf);
695 gpiochip->num_queues = gpiochip->num_gpios;
698 ret = cnxk_gpio_parse_allowlist(gpiochip);
705 gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios,
706 sizeof(struct cnxk_gpio *), 0);
707 if (!gpiochip->gpios) {
708 RTE_LOG(ERR, PMD, "failed to allocate gpios memory");
716 rte_free(gpiochip->allowlist);
717 rte_rawdev_pmd_release(rawdev);
723 cnxk_gpio_remove(struct rte_vdev_device *dev)
725 char name[RTE_RAWDEV_NAME_MAX_LEN];
726 struct cnxk_gpiochip *gpiochip;
727 struct rte_rawdev *rawdev;
728 struct cnxk_gpio *gpio;
733 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
736 cnxk_gpio_format_name(name, sizeof(name));
737 rawdev = rte_rawdev_pmd_get_named_dev(name);
741 gpiochip = rawdev->dev_private;
742 for (i = 0; i < gpiochip->num_gpios; i++) {
743 gpio = gpiochip->gpios[i];
748 cnxk_gpio_unregister_irq(gpio);
750 cnxk_gpio_queue_release(rawdev, gpio->num);
753 rte_free(gpiochip->allowlist);
754 rte_free(gpiochip->gpios);
755 cnxk_gpio_irq_fini();
756 rte_rawdev_pmd_release(rawdev);
761 static struct rte_vdev_driver cnxk_gpio_drv = {
762 .probe = cnxk_gpio_probe,
763 .remove = cnxk_gpio_remove,
766 RTE_PMD_REGISTER_VDEV(cnxk_gpio, cnxk_gpio_drv);
767 RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio,