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,
29 cnxk_gpio_format_name(char *name, size_t len)
31 snprintf(name, len, "cnxk_gpio");
35 cnxk_gpio_filter_gpiochip(const struct dirent *dirent)
37 const char *pattern = "gpiochip";
39 return !strncmp(dirent->d_name, pattern, strlen(pattern));
43 cnxk_gpio_set_defaults(struct cnxk_gpiochip *gpiochip)
45 struct dirent **namelist;
48 n = scandir(CNXK_GPIO_CLASS_PATH, &namelist, cnxk_gpio_filter_gpiochip,
53 sscanf(namelist[0]->d_name, "gpiochip%d", &gpiochip->num);
60 cnxk_gpio_parse_arg_gpiochip(const char *key __rte_unused, const char *value,
66 val = strtol(value, NULL, 10);
70 *(int *)extra_args = (int)val;
76 cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip,
77 struct rte_devargs *devargs)
79 struct rte_kvargs *kvlist;
82 kvlist = rte_kvargs_parse(devargs->args, cnxk_gpio_args);
86 ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_GPIOCHIP);
88 ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_GPIOCHIP,
89 cnxk_gpio_parse_arg_gpiochip,
97 rte_kvargs_free(kvlist);
103 cnxk_gpio_read_attr(char *attr, char *val)
108 fp = fopen(attr, "r");
112 ret = fscanf(fp, "%s", val);
126 cnxk_gpio_read_attr_int(char *attr, int *val)
128 char buf[CNXK_GPIO_BUFSZ];
131 ret = cnxk_gpio_read_attr(attr, buf);
135 ret = sscanf(buf, "%d", val);
143 cnxk_gpio_write_attr(const char *attr, const char *val)
151 fp = fopen(attr, "w");
155 ret = fprintf(fp, "%s", val);
169 cnxk_gpio_write_attr_int(const char *attr, int val)
171 char buf[CNXK_GPIO_BUFSZ];
173 snprintf(buf, sizeof(buf), "%d", val);
175 return cnxk_gpio_write_attr(attr, buf);
178 static struct cnxk_gpio *
179 cnxk_gpio_lookup(struct cnxk_gpiochip *gpiochip, uint16_t queue)
181 if (queue >= gpiochip->num_gpios)
184 return gpiochip->gpios[queue];
188 cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
189 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
191 struct cnxk_gpiochip *gpiochip = dev->dev_private;
192 char buf[CNXK_GPIO_BUFSZ];
193 struct cnxk_gpio *gpio;
196 RTE_SET_USED(queue_conf);
197 RTE_SET_USED(queue_conf_size);
199 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
203 gpio = rte_zmalloc(NULL, sizeof(*gpio), 0);
206 gpio->num = queue_id + gpiochip->base;
207 gpio->gpiochip = gpiochip;
209 snprintf(buf, sizeof(buf), "%s/export", CNXK_GPIO_CLASS_PATH);
210 ret = cnxk_gpio_write_attr_int(buf, gpio->num);
216 gpiochip->gpios[queue_id] = gpio;
222 cnxk_gpio_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
224 struct cnxk_gpiochip *gpiochip = dev->dev_private;
225 char buf[CNXK_GPIO_BUFSZ];
226 struct cnxk_gpio *gpio;
229 gpio = cnxk_gpio_lookup(gpiochip, queue_id);
233 snprintf(buf, sizeof(buf), "%s/unexport", CNXK_GPIO_CLASS_PATH);
234 ret = cnxk_gpio_write_attr_int(buf, gpiochip->base + queue_id);
238 gpiochip->gpios[queue_id] = NULL;
245 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
246 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
251 RTE_SET_USED(queue_id);
253 if (queue_conf_size != sizeof(*conf))
256 conf = (unsigned int *)queue_conf;
263 cnxk_gpio_queue_count(struct rte_rawdev *dev)
265 struct cnxk_gpiochip *gpiochip = dev->dev_private;
267 return gpiochip->num_gpios;
270 static const struct {
271 enum cnxk_gpio_pin_edge edge;
273 } cnxk_gpio_edge_name[] = {
274 { CNXK_GPIO_PIN_EDGE_NONE, "none" },
275 { CNXK_GPIO_PIN_EDGE_FALLING, "falling" },
276 { CNXK_GPIO_PIN_EDGE_RISING, "rising" },
277 { CNXK_GPIO_PIN_EDGE_BOTH, "both" },
281 cnxk_gpio_edge_to_name(enum cnxk_gpio_pin_edge edge)
285 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
286 if (cnxk_gpio_edge_name[i].edge == edge)
287 return cnxk_gpio_edge_name[i].name;
293 static enum cnxk_gpio_pin_edge
294 cnxk_gpio_name_to_edge(const char *name)
298 for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
299 if (!strcmp(cnxk_gpio_edge_name[i].name, name))
303 return cnxk_gpio_edge_name[i].edge;
306 static const struct {
307 enum cnxk_gpio_pin_dir dir;
309 } cnxk_gpio_dir_name[] = {
310 { CNXK_GPIO_PIN_DIR_IN, "in" },
311 { CNXK_GPIO_PIN_DIR_OUT, "out" },
312 { CNXK_GPIO_PIN_DIR_HIGH, "high" },
313 { CNXK_GPIO_PIN_DIR_LOW, "low" },
317 cnxk_gpio_dir_to_name(enum cnxk_gpio_pin_dir dir)
321 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
322 if (cnxk_gpio_dir_name[i].dir == dir)
323 return cnxk_gpio_dir_name[i].name;
329 static enum cnxk_gpio_pin_dir
330 cnxk_gpio_name_to_dir(const char *name)
334 for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
335 if (!strcmp(cnxk_gpio_dir_name[i].name, name))
339 return cnxk_gpio_dir_name[i].dir;
343 cnxk_gpio_register_irq(struct cnxk_gpio *gpio, struct cnxk_gpio_irq *irq)
347 ret = cnxk_gpio_irq_request(gpio->num - gpio->gpiochip->base, irq->cpu);
351 gpio->handler = irq->handler;
352 gpio->data = irq->data;
353 gpio->cpu = irq->cpu;
359 cnxk_gpio_unregister_irq(struct cnxk_gpio *gpio)
361 return cnxk_gpio_irq_free(gpio->num - gpio->gpiochip->base);
365 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
367 struct cnxk_gpio_msg *msg = rbuf->buf_addr;
368 enum cnxk_gpio_pin_edge edge;
369 enum cnxk_gpio_pin_dir dir;
370 char buf[CNXK_GPIO_BUFSZ];
374 n = snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH,
378 case CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE:
379 snprintf(buf + n, sizeof(buf) - n, "/value");
380 ret = cnxk_gpio_write_attr_int(buf, !!*(int *)msg->data);
382 case CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE:
383 snprintf(buf + n, sizeof(buf) - n, "/edge");
384 edge = *(enum cnxk_gpio_pin_edge *)msg->data;
385 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_edge_to_name(edge));
387 case CNXK_GPIO_MSG_TYPE_SET_PIN_DIR:
388 snprintf(buf + n, sizeof(buf) - n, "/direction");
389 dir = *(enum cnxk_gpio_pin_dir *)msg->data;
390 ret = cnxk_gpio_write_attr(buf, cnxk_gpio_dir_to_name(dir));
392 case CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW:
393 snprintf(buf + n, sizeof(buf) - n, "/active_low");
394 val = *(int *)msg->data;
395 ret = cnxk_gpio_write_attr_int(buf, val);
397 case CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE:
398 snprintf(buf + n, sizeof(buf) - n, "/value");
399 ret = cnxk_gpio_read_attr_int(buf, &val);
403 rsp = rte_zmalloc(NULL, sizeof(int), 0);
409 case CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE:
410 snprintf(buf + n, sizeof(buf) - n, "/edge");
411 ret = cnxk_gpio_read_attr(buf, buf);
415 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_edge), 0);
419 *(enum cnxk_gpio_pin_edge *)rsp = cnxk_gpio_name_to_edge(buf);
421 case CNXK_GPIO_MSG_TYPE_GET_PIN_DIR:
422 snprintf(buf + n, sizeof(buf) - n, "/direction");
423 ret = cnxk_gpio_read_attr(buf, buf);
427 rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_dir), 0);
431 *(enum cnxk_gpio_pin_dir *)rsp = cnxk_gpio_name_to_dir(buf);
433 case CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW:
434 snprintf(buf + n, sizeof(buf) - n, "/active_low");
435 ret = cnxk_gpio_read_attr_int(buf, &val);
439 rsp = rte_zmalloc(NULL, sizeof(int), 0);
445 case CNXK_GPIO_MSG_TYPE_REGISTER_IRQ:
446 ret = cnxk_gpio_register_irq(gpio,
447 (struct cnxk_gpio_irq *)msg->data);
449 case CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ:
450 ret = cnxk_gpio_unregister_irq(gpio);
456 /* get rid of last response if any */
458 RTE_LOG(WARNING, PMD, "previous response got overwritten\n");
467 cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
468 unsigned int count, rte_rawdev_obj_t context)
470 struct cnxk_gpiochip *gpiochip = dev->dev_private;
471 unsigned int queue = (size_t)context;
472 struct cnxk_gpio *gpio;
478 gpio = cnxk_gpio_lookup(gpiochip, queue);
482 ret = cnxk_gpio_process_buf(gpio, buffers[0]);
490 cnxk_gpio_dequeue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
491 unsigned int count, rte_rawdev_obj_t context)
493 struct cnxk_gpiochip *gpiochip = dev->dev_private;
494 unsigned int queue = (size_t)context;
495 struct cnxk_gpio *gpio;
500 gpio = cnxk_gpio_lookup(gpiochip, queue);
505 buffers[0]->buf_addr = gpio->rsp;
515 cnxk_gpio_dev_close(struct rte_rawdev *dev)
522 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
523 .dev_close = cnxk_gpio_dev_close,
524 .enqueue_bufs = cnxk_gpio_enqueue_bufs,
525 .dequeue_bufs = cnxk_gpio_dequeue_bufs,
526 .queue_def_conf = cnxk_gpio_queue_def_conf,
527 .queue_count = cnxk_gpio_queue_count,
528 .queue_setup = cnxk_gpio_queue_setup,
529 .queue_release = cnxk_gpio_queue_release,
530 .dev_selftest = cnxk_gpio_selftest,
534 cnxk_gpio_probe(struct rte_vdev_device *dev)
536 char name[RTE_RAWDEV_NAME_MAX_LEN];
537 struct cnxk_gpiochip *gpiochip;
538 struct rte_rawdev *rawdev;
539 char buf[CNXK_GPIO_BUFSZ];
542 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
545 cnxk_gpio_format_name(name, sizeof(name));
546 rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip),
549 RTE_LOG(ERR, PMD, "failed to allocate %s rawdev", name);
553 rawdev->dev_ops = &cnxk_gpio_rawdev_ops;
554 rawdev->device = &dev->device;
555 rawdev->driver_name = dev->device.name;
557 gpiochip = rawdev->dev_private;
558 cnxk_gpio_set_defaults(gpiochip);
560 /* defaults may be overwritten by this call */
561 ret = cnxk_gpio_parse_args(gpiochip, dev->device.devargs);
565 ret = cnxk_gpio_irq_init(gpiochip);
570 snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH,
572 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->base);
574 RTE_LOG(ERR, PMD, "failed to read %s", buf);
578 /* read number of available gpios */
579 snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH,
581 ret = cnxk_gpio_read_attr_int(buf, &gpiochip->num_gpios);
583 RTE_LOG(ERR, PMD, "failed to read %s", buf);
587 gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios,
588 sizeof(struct cnxk_gpio *), 0);
589 if (!gpiochip->gpios) {
590 RTE_LOG(ERR, PMD, "failed to allocate gpios memory");
597 rte_rawdev_pmd_release(rawdev);
603 cnxk_gpio_remove(struct rte_vdev_device *dev)
605 char name[RTE_RAWDEV_NAME_MAX_LEN];
606 struct cnxk_gpiochip *gpiochip;
607 struct rte_rawdev *rawdev;
608 struct cnxk_gpio *gpio;
613 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
616 cnxk_gpio_format_name(name, sizeof(name));
617 rawdev = rte_rawdev_pmd_get_named_dev(name);
621 gpiochip = rawdev->dev_private;
622 for (i = 0; i < gpiochip->num_gpios; i++) {
623 gpio = gpiochip->gpios[i];
628 cnxk_gpio_unregister_irq(gpio);
630 cnxk_gpio_queue_release(rawdev, gpio->num);
633 rte_free(gpiochip->gpios);
634 cnxk_gpio_irq_fini();
635 rte_rawdev_pmd_release(rawdev);
640 static struct rte_vdev_driver cnxk_gpio_drv = {
641 .probe = cnxk_gpio_probe,
642 .remove = cnxk_gpio_remove,
645 RTE_PMD_REGISTER_VDEV(cnxk_gpio, cnxk_gpio_drv);
646 RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio, "gpiochip=<int>");