Lines Matching +full:chg +full:- +full:gpios
1 // SPDX-License-Identifier: GPL-2.0
33 #include "gpiolib-cdev.h"
36 * Array sizes must ensure 64-bit alignment and not create holes in the
43 * Check that uAPI structs are 64-bit aligned for 32/64-bit compatibility
57 * interface to gpiolib GPIOs via ioctl()s.
71 down_read(&gdev->sem); in call_poll_locked()
73 up_read(&gdev->sem); in call_poll_locked()
84 down_read(&gdev->sem); in call_ioctl_locked()
86 up_read(&gdev->sem); in call_ioctl_locked()
97 down_read(&gdev->sem); in call_read_locked()
99 up_read(&gdev->sem); in call_read_locked()
110 * struct linehandle_state - contains the state of a userspace handle
137 return -EINVAL; in linehandle_validate_flags()
145 return -EINVAL; in linehandle_validate_flags()
154 return -EINVAL; in linehandle_validate_flags()
160 return -EINVAL; in linehandle_validate_flags()
168 return -EINVAL; in linehandle_validate_flags()
176 return -EINVAL; in linehandle_validate_flags()
206 return -EFAULT; in linehandle_set_config()
213 for (i = 0; i < lh->num_descs; i++) { in linehandle_set_config()
214 desc = lh->descs[i]; in linehandle_set_config()
215 linehandle_flags_to_desc_flags(gcnf.flags, &desc->flags); in linehandle_set_config()
241 struct linehandle_state *lh = file->private_data; in linehandle_ioctl_unlocked()
248 if (!lh->gdev->chip) in linehandle_ioctl_unlocked()
249 return -ENODEV; in linehandle_ioctl_unlocked()
255 lh->num_descs, lh->descs, in linehandle_ioctl_unlocked()
261 for (i = 0; i < lh->num_descs; i++) in linehandle_ioctl_unlocked()
265 return -EFAULT; in linehandle_ioctl_unlocked()
273 if (!test_bit(FLAG_IS_OUT, &lh->descs[0]->flags)) in linehandle_ioctl_unlocked()
274 return -EPERM; in linehandle_ioctl_unlocked()
277 return -EFAULT; in linehandle_ioctl_unlocked()
280 for (i = 0; i < lh->num_descs; i++) in linehandle_ioctl_unlocked()
286 lh->num_descs, in linehandle_ioctl_unlocked()
287 lh->descs, in linehandle_ioctl_unlocked()
293 return -EINVAL; in linehandle_ioctl_unlocked()
300 struct linehandle_state *lh = file->private_data; in linehandle_ioctl()
302 return call_ioctl_locked(file, cmd, arg, lh->gdev, in linehandle_ioctl()
318 for (i = 0; i < lh->num_descs; i++) in linehandle_free()
319 if (lh->descs[i]) in linehandle_free()
320 gpiod_free(lh->descs[i]); in linehandle_free()
321 kfree(lh->label); in linehandle_free()
322 gpio_device_put(lh->gdev); in linehandle_free()
328 linehandle_free(file->private_data); in linehandle_release()
351 return -EFAULT; in linehandle_create()
353 return -EINVAL; in linehandle_create()
363 return -ENOMEM; in linehandle_create()
364 lh->gdev = gpio_device_get(gdev); in linehandle_create()
368 lh->label = kstrndup(handlereq.consumer_label, in linehandle_create()
369 sizeof(handlereq.consumer_label) - 1, in linehandle_create()
371 if (!lh->label) { in linehandle_create()
372 ret = -ENOMEM; in linehandle_create()
377 lh->num_descs = handlereq.lines; in linehandle_create()
382 struct gpio_desc *desc = gpiochip_get_desc(gdev->chip, offset); in linehandle_create()
389 ret = gpiod_request_user(desc, lh->label); in linehandle_create()
392 lh->descs[i] = desc; in linehandle_create()
393 linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags); in linehandle_create()
417 dev_dbg(&gdev->dev, "registered chardev handle for line %d\n", in linehandle_create()
427 file = anon_inode_getfile("gpio-linehandle", in linehandle_create()
444 return -EFAULT; in linehandle_create()
449 dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", in linehandle_create()
450 lh->num_descs); in linehandle_create()
463 * struct line - contains the state of a requested line
486 * -- edge detector specific fields --
514 * -- debouncer specific fields --
550 * struct linereq - contains the state of a userspace line request
562 * of configuration, particularly multi-step accesses to desc flags.
618 wake_up_poll(&lr->wait, EPOLLIN | EPOLLERR); in linereq_unregistered_notify()
628 spin_lock(&lr->wait.lock); in linereq_put_event()
629 if (kfifo_is_full(&lr->events)) { in linereq_put_event()
631 kfifo_skip(&lr->events); in linereq_put_event()
633 kfifo_in(&lr->events, le, 1); in linereq_put_event()
634 spin_unlock(&lr->wait.lock); in linereq_put_event()
636 wake_up_poll(&lr->wait, EPOLLIN); in linereq_put_event()
638 pr_debug_ratelimited("event FIFO is full - event dropped\n"); in linereq_put_event()
643 if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &line->desc->flags)) in line_event_timestamp()
646 test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) in line_event_timestamp()
647 return line->timestamp_ns; in line_event_timestamp()
672 lr = line->req; in process_hw_ts_thread()
676 le.timestamp_ns = line->timestamp_ns; in process_hw_ts_thread()
677 edflags = READ_ONCE(line->edflags); in process_hw_ts_thread()
681 level = (line->raw_level >= 0) ? in process_hw_ts_thread()
682 line->raw_level : in process_hw_ts_thread()
683 gpiod_get_raw_value_cansleep(line->desc); in process_hw_ts_thread()
699 le.line_seqno = line->line_seqno; in process_hw_ts_thread()
700 le.seqno = (lr->num_lines == 1) ? le.line_seqno : line->req_seqno; in process_hw_ts_thread()
701 le.offset = gpio_chip_hwgpio(line->desc); in process_hw_ts_thread()
718 line->timestamp_ns = ts->tsc; in process_hw_ts()
719 line->raw_level = ts->raw_level; in process_hw_ts()
720 lr = line->req; in process_hw_ts()
722 if (READ_ONCE(line->sw_debounced)) { in process_hw_ts()
723 line->total_discard_seq++; in process_hw_ts()
724 line->last_seqno = ts->seq; in process_hw_ts()
725 mod_delayed_work(system_wq, &line->work, in process_hw_ts()
726 usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us))); in process_hw_ts()
728 if (unlikely(ts->seq < line->line_seqno)) in process_hw_ts()
731 diff_seqno = ts->seq - line->line_seqno; in process_hw_ts()
732 line->line_seqno = ts->seq; in process_hw_ts()
733 if (lr->num_lines != 1) in process_hw_ts()
734 line->req_seqno = atomic_add_return(diff_seqno, in process_hw_ts()
735 &lr->seqno); in process_hw_ts()
747 struct hte_ts_desc *hdesc = &line->hdesc; in hte_edge_setup()
750 flags |= test_bit(FLAG_ACTIVE_LOW, &line->desc->flags) ? in hte_edge_setup()
754 flags |= test_bit(FLAG_ACTIVE_LOW, &line->desc->flags) ? in hte_edge_setup()
758 line->total_discard_seq = 0; in hte_edge_setup()
760 hte_init_line_attr(hdesc, desc_to_gpio(line->desc), flags, NULL, in hte_edge_setup()
761 line->desc); in hte_edge_setup()
782 struct linereq *lr = line->req; in edge_irq_thread()
788 if (line->timestamp_ns) { in edge_irq_thread()
789 le.timestamp_ns = line->timestamp_ns; in edge_irq_thread()
797 if (lr->num_lines != 1) in edge_irq_thread()
798 line->req_seqno = atomic_inc_return(&lr->seqno); in edge_irq_thread()
800 line->timestamp_ns = 0; in edge_irq_thread()
802 switch (READ_ONCE(line->edflags) & GPIO_V2_LINE_EDGE_FLAGS) { in edge_irq_thread()
804 le.id = line_event_id(gpiod_get_value_cansleep(line->desc)); in edge_irq_thread()
815 line->line_seqno++; in edge_irq_thread()
816 le.line_seqno = line->line_seqno; in edge_irq_thread()
817 le.seqno = (lr->num_lines == 1) ? le.line_seqno : line->req_seqno; in edge_irq_thread()
818 le.offset = gpio_chip_hwgpio(line->desc); in edge_irq_thread()
828 struct linereq *lr = line->req; in edge_irq_handler()
834 line->timestamp_ns = line_event_timestamp(line); in edge_irq_handler()
836 if (lr->num_lines != 1) in edge_irq_handler()
837 line->req_seqno = atomic_inc_return(&lr->seqno); in edge_irq_handler()
850 * minor race - debouncer may be stopped here, so edge_detector_stop() in debounced_value()
854 value = READ_ONCE(line->level); in debounced_value()
856 if (test_bit(FLAG_ACTIVE_LOW, &line->desc->flags)) in debounced_value()
866 mod_delayed_work(system_wq, &line->work, in debounce_irq_handler()
867 usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us))); in debounce_irq_handler()
877 u64 eflags, edflags = READ_ONCE(line->edflags); in debounce_work_func()
878 int level = -1; in debounce_work_func()
883 level = line->raw_level; in debounce_work_func()
886 level = gpiod_get_raw_value_cansleep(line->desc); in debounce_work_func()
892 if (READ_ONCE(line->level) == level) in debounce_work_func()
895 WRITE_ONCE(line->level, level); in debounce_work_func()
897 /* -- edge detection -- */ in debounce_work_func()
902 /* switch from physical level to logical - if they differ */ in debounce_work_func()
914 lr = line->req; in debounce_work_func()
916 le.offset = gpio_chip_hwgpio(line->desc); in debounce_work_func()
920 line->total_discard_seq -= 1; in debounce_work_func()
921 diff_seqno = line->last_seqno - line->total_discard_seq - in debounce_work_func()
922 line->line_seqno; in debounce_work_func()
923 line->line_seqno = line->last_seqno - line->total_discard_seq; in debounce_work_func()
924 le.line_seqno = line->line_seqno; in debounce_work_func()
925 le.seqno = (lr->num_lines == 1) ? in debounce_work_func()
926 le.line_seqno : atomic_add_return(diff_seqno, &lr->seqno); in debounce_work_func()
930 line->line_seqno++; in debounce_work_func()
931 le.line_seqno = line->line_seqno; in debounce_work_func()
932 le.seqno = (lr->num_lines == 1) ? in debounce_work_func()
933 le.line_seqno : atomic_inc_return(&lr->seqno); in debounce_work_func()
947 ret = gpiod_set_debounce(line->desc, debounce_period_us); in debounce_setup()
949 WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); in debounce_setup()
952 if (ret != -ENOTSUPP) in debounce_setup()
957 level = gpiod_get_raw_value_cansleep(line->desc); in debounce_setup()
962 test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags))) { in debounce_setup()
963 irq = gpiod_to_irq(line->desc); in debounce_setup()
965 return -ENXIO; in debounce_setup()
969 line->req->label, line); in debounce_setup()
972 line->irq = irq; in debounce_setup()
979 WRITE_ONCE(line->level, level); in debounce_setup()
980 WRITE_ONCE(line->sw_debounced, 1); in debounce_setup()
991 for (i = 0; i < lc->num_attrs; i++) { in gpio_v2_line_config_debounced()
992 if ((lc->attrs[i].attr.id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE) && in gpio_v2_line_config_debounced()
993 (lc->attrs[i].mask & mask)) in gpio_v2_line_config_debounced()
1005 for (i = 0; i < lc->num_attrs; i++) { in gpio_v2_line_config_debounce_period()
1006 if ((lc->attrs[i].attr.id == GPIO_V2_LINE_ATTR_ID_DEBOUNCE) && in gpio_v2_line_config_debounce_period()
1007 (lc->attrs[i].mask & mask)) in gpio_v2_line_config_debounce_period()
1008 return lc->attrs[i].attr.debounce_period_us; in gpio_v2_line_config_debounce_period()
1015 if (line->irq) { in edge_detector_stop()
1016 free_irq(line->irq, line); in edge_detector_stop()
1017 line->irq = 0; in edge_detector_stop()
1021 if (READ_ONCE(line->edflags) & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) in edge_detector_stop()
1022 hte_ts_put(&line->hdesc); in edge_detector_stop()
1025 cancel_delayed_work_sync(&line->work); in edge_detector_stop()
1026 WRITE_ONCE(line->sw_debounced, 0); in edge_detector_stop()
1027 WRITE_ONCE(line->edflags, 0); in edge_detector_stop()
1028 if (line->desc) in edge_detector_stop()
1029 WRITE_ONCE(line->desc->debounce_period_us, 0); in edge_detector_stop()
1030 /* do not change line->level - see comment in debounced_value() */ in edge_detector_stop()
1043 if (eflags && !kfifo_initialized(&line->req->events)) { in edge_detector_setup()
1044 ret = kfifo_alloc(&line->req->events, in edge_detector_setup()
1045 line->req->event_buffer_size, GFP_KERNEL); in edge_detector_setup()
1054 WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); in edge_detector_setup()
1058 if (!eflags || READ_ONCE(line->sw_debounced)) in edge_detector_setup()
1065 irq = gpiod_to_irq(line->desc); in edge_detector_setup()
1067 return -ENXIO; in edge_detector_setup()
1070 irqflags |= test_bit(FLAG_ACTIVE_LOW, &line->desc->flags) ? in edge_detector_setup()
1073 irqflags |= test_bit(FLAG_ACTIVE_LOW, &line->desc->flags) ? in edge_detector_setup()
1079 irqflags, line->req->label, line); in edge_detector_setup()
1083 line->irq = irq; in edge_detector_setup()
1091 u64 active_edflags = READ_ONCE(line->edflags); in edge_detector_update()
1096 (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us)) in edge_detector_update()
1100 if (debounce_period_us && READ_ONCE(line->sw_debounced)) { in edge_detector_update()
1101 WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); in edge_detector_update()
1106 if ((line->irq && !READ_ONCE(line->sw_debounced)) || in edge_detector_update()
1108 (!debounce_period_us && READ_ONCE(line->sw_debounced))) in edge_detector_update()
1120 for (i = 0; i < lc->num_attrs; i++) { in gpio_v2_line_config_flags()
1121 if ((lc->attrs[i].attr.id == GPIO_V2_LINE_ATTR_ID_FLAGS) && in gpio_v2_line_config_flags()
1122 (lc->attrs[i].mask & mask)) in gpio_v2_line_config_flags()
1123 return lc->attrs[i].attr.flags; in gpio_v2_line_config_flags()
1125 return lc->flags; in gpio_v2_line_config_flags()
1134 for (i = 0; i < lc->num_attrs; i++) { in gpio_v2_line_config_output_value()
1135 if ((lc->attrs[i].attr.id == GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES) && in gpio_v2_line_config_output_value()
1136 (lc->attrs[i].mask & mask)) in gpio_v2_line_config_output_value()
1137 return !!(lc->attrs[i].attr.values & mask); in gpio_v2_line_config_output_value()
1146 return -EINVAL; in gpio_v2_line_flags_validate()
1150 return -EOPNOTSUPP; in gpio_v2_line_flags_validate()
1158 return -EINVAL; in gpio_v2_line_flags_validate()
1164 return -EINVAL; in gpio_v2_line_flags_validate()
1169 return -EINVAL; in gpio_v2_line_flags_validate()
1178 return -EINVAL; in gpio_v2_line_flags_validate()
1183 return -EINVAL; in gpio_v2_line_flags_validate()
1188 return -EINVAL; in gpio_v2_line_flags_validate()
1196 return -EINVAL; in gpio_v2_line_flags_validate()
1208 if (lc->num_attrs > GPIO_V2_LINE_NUM_ATTRS_MAX) in gpio_v2_line_config_validate()
1209 return -EINVAL; in gpio_v2_line_config_validate()
1211 if (memchr_inv(lc->padding, 0, sizeof(lc->padding))) in gpio_v2_line_config_validate()
1212 return -EINVAL; in gpio_v2_line_config_validate()
1223 return -EINVAL; in gpio_v2_line_config_validate()
1273 return -EFAULT; in linereq_get_values()
1275 for (num_get = 0, i = 0; i < lr->num_lines; i++) { in linereq_get_values()
1278 descs = &lr->lines[i].desc; in linereq_get_values()
1283 return -EINVAL; in linereq_get_values()
1288 return -ENOMEM; in linereq_get_values()
1289 for (didx = 0, i = 0; i < lr->num_lines; i++) { in linereq_get_values()
1291 descs[didx] = lr->lines[i].desc; in linereq_get_values()
1305 for (didx = 0, i = 0; i < lr->num_lines; i++) { in linereq_get_values()
1307 if (lr->lines[i].sw_debounced) in linereq_get_values()
1308 val = debounced_value(&lr->lines[i]); in linereq_get_values()
1318 return -EFAULT; in linereq_get_values()
1332 for (num_set = 0, i = 0; i < lr->num_lines; i++) { in linereq_set_values_unlocked()
1333 if (lv->mask & BIT_ULL(i)) { in linereq_set_values_unlocked()
1334 if (!test_bit(FLAG_IS_OUT, &lr->lines[i].desc->flags)) in linereq_set_values_unlocked()
1335 return -EPERM; in linereq_set_values_unlocked()
1336 if (lv->bits & BIT_ULL(i)) in linereq_set_values_unlocked()
1339 descs = &lr->lines[i].desc; in linereq_set_values_unlocked()
1343 return -EINVAL; in linereq_set_values_unlocked()
1349 return -ENOMEM; in linereq_set_values_unlocked()
1350 for (didx = 0, i = 0; i < lr->num_lines; i++) { in linereq_set_values_unlocked()
1351 if (lv->mask & BIT_ULL(i)) { in linereq_set_values_unlocked()
1352 descs[didx] = lr->lines[i].desc; in linereq_set_values_unlocked()
1371 return -EFAULT; in linereq_set_values()
1373 mutex_lock(&lr->config_mutex); in linereq_set_values()
1377 mutex_unlock(&lr->config_mutex); in linereq_set_values()
1391 for (i = 0; i < lr->num_lines; i++) { in linereq_set_config_unlocked()
1392 line = &lr->lines[i]; in linereq_set_config_unlocked()
1393 desc = lr->lines[i].desc; in linereq_set_config_unlocked()
1395 gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags); in linereq_set_config_unlocked()
1418 WRITE_ONCE(line->edflags, edflags); in linereq_set_config_unlocked()
1431 return -EFAULT; in linereq_set_config()
1433 ret = gpio_v2_line_config_validate(&lc, lr->num_lines); in linereq_set_config()
1437 mutex_lock(&lr->config_mutex); in linereq_set_config()
1441 mutex_unlock(&lr->config_mutex); in linereq_set_config()
1449 struct linereq *lr = file->private_data; in linereq_ioctl_unlocked()
1452 if (!lr->gdev->chip) in linereq_ioctl_unlocked()
1453 return -ENODEV; in linereq_ioctl_unlocked()
1463 return -EINVAL; in linereq_ioctl_unlocked()
1470 struct linereq *lr = file->private_data; in linereq_ioctl()
1472 return call_ioctl_locked(file, cmd, arg, lr->gdev, in linereq_ioctl()
1487 struct linereq *lr = file->private_data; in linereq_poll_unlocked()
1490 if (!lr->gdev->chip) in linereq_poll_unlocked()
1493 poll_wait(file, &lr->wait, wait); in linereq_poll_unlocked()
1495 if (!kfifo_is_empty_spinlocked_noirqsave(&lr->events, in linereq_poll_unlocked()
1496 &lr->wait.lock)) in linereq_poll_unlocked()
1505 struct linereq *lr = file->private_data; in linereq_poll()
1507 return call_poll_locked(file, wait, lr->gdev, linereq_poll_unlocked); in linereq_poll()
1513 struct linereq *lr = file->private_data; in linereq_read_unlocked()
1518 if (!lr->gdev->chip) in linereq_read_unlocked()
1519 return -ENODEV; in linereq_read_unlocked()
1522 return -EINVAL; in linereq_read_unlocked()
1525 spin_lock(&lr->wait.lock); in linereq_read_unlocked()
1526 if (kfifo_is_empty(&lr->events)) { in linereq_read_unlocked()
1528 spin_unlock(&lr->wait.lock); in linereq_read_unlocked()
1532 if (file->f_flags & O_NONBLOCK) { in linereq_read_unlocked()
1533 spin_unlock(&lr->wait.lock); in linereq_read_unlocked()
1534 return -EAGAIN; in linereq_read_unlocked()
1537 ret = wait_event_interruptible_locked(lr->wait, in linereq_read_unlocked()
1538 !kfifo_is_empty(&lr->events)); in linereq_read_unlocked()
1540 spin_unlock(&lr->wait.lock); in linereq_read_unlocked()
1545 ret = kfifo_out(&lr->events, &le, 1); in linereq_read_unlocked()
1546 spin_unlock(&lr->wait.lock); in linereq_read_unlocked()
1549 * This should never happen - we were holding the in linereq_read_unlocked()
1553 ret = -EIO; in linereq_read_unlocked()
1558 return -EFAULT; in linereq_read_unlocked()
1568 struct linereq *lr = file->private_data; in linereq_read()
1570 return call_read_locked(file, buf, count, f_ps, lr->gdev, in linereq_read()
1578 if (lr->device_unregistered_nb.notifier_call) in linereq_free()
1579 blocking_notifier_chain_unregister(&lr->gdev->device_notifier, in linereq_free()
1580 &lr->device_unregistered_nb); in linereq_free()
1582 for (i = 0; i < lr->num_lines; i++) { in linereq_free()
1583 if (lr->lines[i].desc) { in linereq_free()
1584 edge_detector_stop(&lr->lines[i]); in linereq_free()
1585 gpiod_free(lr->lines[i].desc); in linereq_free()
1588 kfifo_free(&lr->events); in linereq_free()
1589 kfree(lr->label); in linereq_free()
1590 gpio_device_put(lr->gdev); in linereq_free()
1596 struct linereq *lr = file->private_data; in linereq_release()
1605 struct linereq *lr = file->private_data; in linereq_show_fdinfo()
1606 struct device *dev = &lr->gdev->dev; in linereq_show_fdinfo()
1609 seq_printf(out, "gpio-chip:\t%s\n", dev_name(dev)); in linereq_show_fdinfo()
1611 for (i = 0; i < lr->num_lines; i++) in linereq_show_fdinfo()
1612 seq_printf(out, "gpio-line:\t%d\n", in linereq_show_fdinfo()
1613 gpio_chip_hwgpio(lr->lines[i].desc)); in linereq_show_fdinfo()
1643 return -EFAULT; in linereq_create()
1646 return -EINVAL; in linereq_create()
1649 return -EINVAL; in linereq_create()
1658 return -ENOMEM; in linereq_create()
1660 lr->gdev = gpio_device_get(gdev); in linereq_create()
1663 lr->lines[i].req = lr; in linereq_create()
1664 WRITE_ONCE(lr->lines[i].sw_debounced, 0); in linereq_create()
1665 INIT_DELAYED_WORK(&lr->lines[i].work, debounce_work_func); in linereq_create()
1670 lr->label = kstrndup(ulr.consumer, sizeof(ulr.consumer) - 1, in linereq_create()
1672 if (!lr->label) { in linereq_create()
1673 ret = -ENOMEM; in linereq_create()
1678 mutex_init(&lr->config_mutex); in linereq_create()
1679 init_waitqueue_head(&lr->wait); in linereq_create()
1680 lr->event_buffer_size = ulr.event_buffer_size; in linereq_create()
1681 if (lr->event_buffer_size == 0) in linereq_create()
1682 lr->event_buffer_size = ulr.num_lines * 16; in linereq_create()
1683 else if (lr->event_buffer_size > GPIO_V2_LINES_MAX * 16) in linereq_create()
1684 lr->event_buffer_size = GPIO_V2_LINES_MAX * 16; in linereq_create()
1686 atomic_set(&lr->seqno, 0); in linereq_create()
1687 lr->num_lines = ulr.num_lines; in linereq_create()
1692 struct gpio_desc *desc = gpiochip_get_desc(gdev->chip, offset); in linereq_create()
1699 ret = gpiod_request_user(desc, lr->label); in linereq_create()
1703 lr->lines[i].desc = desc; in linereq_create()
1705 gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags); in linereq_create()
1727 ret = edge_detector_setup(&lr->lines[i], lc, i, in linereq_create()
1733 lr->lines[i].edflags = edflags; in linereq_create()
1737 dev_dbg(&gdev->dev, "registered chardev handle for line %d\n", in linereq_create()
1741 lr->device_unregistered_nb.notifier_call = linereq_unregistered_notify; in linereq_create()
1742 ret = blocking_notifier_chain_register(&gdev->device_notifier, in linereq_create()
1743 &lr->device_unregistered_nb); in linereq_create()
1753 file = anon_inode_getfile("gpio-line", &line_fileops, lr, in linereq_create()
1768 return -EFAULT; in linereq_create()
1773 dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", in linereq_create()
1774 lr->num_lines); in linereq_create()
1792 * struct lineevent_state - contains the state of a userspace event
1824 struct lineevent_state *le = file->private_data; in lineevent_poll_unlocked()
1827 if (!le->gdev->chip) in lineevent_poll_unlocked()
1830 poll_wait(file, &le->wait, wait); in lineevent_poll_unlocked()
1832 if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock)) in lineevent_poll_unlocked()
1841 struct lineevent_state *le = file->private_data; in lineevent_poll()
1843 return call_poll_locked(file, wait, le->gdev, lineevent_poll_unlocked); in lineevent_poll()
1852 wake_up_poll(&le->wait, EPOLLIN | EPOLLERR); in lineevent_unregistered_notify()
1865 struct lineevent_state *le = file->private_data; in lineevent_read_unlocked()
1871 if (!le->gdev->chip) in lineevent_read_unlocked()
1872 return -ENODEV; in lineevent_read_unlocked()
1888 return -EINVAL; in lineevent_read_unlocked()
1891 spin_lock(&le->wait.lock); in lineevent_read_unlocked()
1892 if (kfifo_is_empty(&le->events)) { in lineevent_read_unlocked()
1894 spin_unlock(&le->wait.lock); in lineevent_read_unlocked()
1898 if (file->f_flags & O_NONBLOCK) { in lineevent_read_unlocked()
1899 spin_unlock(&le->wait.lock); in lineevent_read_unlocked()
1900 return -EAGAIN; in lineevent_read_unlocked()
1903 ret = wait_event_interruptible_locked(le->wait, in lineevent_read_unlocked()
1904 !kfifo_is_empty(&le->events)); in lineevent_read_unlocked()
1906 spin_unlock(&le->wait.lock); in lineevent_read_unlocked()
1911 ret = kfifo_out(&le->events, &ge, 1); in lineevent_read_unlocked()
1912 spin_unlock(&le->wait.lock); in lineevent_read_unlocked()
1915 * This should never happen - we were holding the lock in lineevent_read_unlocked()
1919 ret = -EIO; in lineevent_read_unlocked()
1924 return -EFAULT; in lineevent_read_unlocked()
1934 struct lineevent_state *le = file->private_data; in lineevent_read()
1936 return call_read_locked(file, buf, count, f_ps, le->gdev, in lineevent_read()
1942 if (le->device_unregistered_nb.notifier_call) in lineevent_free()
1943 blocking_notifier_chain_unregister(&le->gdev->device_notifier, in lineevent_free()
1944 &le->device_unregistered_nb); in lineevent_free()
1945 if (le->irq) in lineevent_free()
1946 free_irq(le->irq, le); in lineevent_free()
1947 if (le->desc) in lineevent_free()
1948 gpiod_free(le->desc); in lineevent_free()
1949 kfree(le->label); in lineevent_free()
1950 gpio_device_put(le->gdev); in lineevent_free()
1956 lineevent_free(file->private_data); in lineevent_release()
1963 struct lineevent_state *le = file->private_data; in lineevent_ioctl_unlocked()
1967 if (!le->gdev->chip) in lineevent_ioctl_unlocked()
1968 return -ENODEV; in lineevent_ioctl_unlocked()
1979 val = gpiod_get_value_cansleep(le->desc); in lineevent_ioctl_unlocked()
1985 return -EFAULT; in lineevent_ioctl_unlocked()
1989 return -EINVAL; in lineevent_ioctl_unlocked()
1995 struct lineevent_state *le = file->private_data; in lineevent_ioctl()
1997 return call_ioctl_locked(file, cmd, arg, le->gdev, in lineevent_ioctl()
2034 if (!le->timestamp) in lineevent_irq_thread()
2037 ge.timestamp = le->timestamp; in lineevent_irq_thread()
2039 if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE in lineevent_irq_thread()
2040 && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { in lineevent_irq_thread()
2041 int level = gpiod_get_value_cansleep(le->desc); in lineevent_irq_thread()
2044 /* Emit low-to-high event */ in lineevent_irq_thread()
2047 /* Emit high-to-low event */ in lineevent_irq_thread()
2049 } else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) { in lineevent_irq_thread()
2050 /* Emit low-to-high event */ in lineevent_irq_thread()
2052 } else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { in lineevent_irq_thread()
2053 /* Emit high-to-low event */ in lineevent_irq_thread()
2059 ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge, in lineevent_irq_thread()
2060 1, &le->wait.lock); in lineevent_irq_thread()
2062 wake_up_poll(&le->wait, EPOLLIN); in lineevent_irq_thread()
2064 pr_debug_ratelimited("event FIFO is full - event dropped\n"); in lineevent_irq_thread()
2077 le->timestamp = ktime_get_ns(); in lineevent_irq_handler()
2096 return -EFAULT; in lineevent_create()
2102 desc = gpiochip_get_desc(gdev->chip, offset); in lineevent_create()
2109 return -EINVAL; in lineevent_create()
2115 return -EINVAL; in lineevent_create()
2123 return -EINVAL; in lineevent_create()
2127 return -ENOMEM; in lineevent_create()
2128 le->gdev = gpio_device_get(gdev); in lineevent_create()
2132 le->label = kstrndup(eventreq.consumer_label, in lineevent_create()
2133 sizeof(eventreq.consumer_label) - 1, in lineevent_create()
2135 if (!le->label) { in lineevent_create()
2136 ret = -ENOMEM; in lineevent_create()
2141 ret = gpiod_request_user(desc, le->label); in lineevent_create()
2144 le->desc = desc; in lineevent_create()
2145 le->eflags = eflags; in lineevent_create()
2147 linehandle_flags_to_desc_flags(lflags, &desc->flags); in lineevent_create()
2157 ret = -ENODEV; in lineevent_create()
2162 irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? in lineevent_create()
2165 irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? in lineevent_create()
2169 INIT_KFIFO(le->events); in lineevent_create()
2170 init_waitqueue_head(&le->wait); in lineevent_create()
2172 le->device_unregistered_nb.notifier_call = lineevent_unregistered_notify; in lineevent_create()
2173 ret = blocking_notifier_chain_register(&gdev->device_notifier, in lineevent_create()
2174 &le->device_unregistered_nb); in lineevent_create()
2183 le->label, in lineevent_create()
2188 le->irq = irq; in lineevent_create()
2196 file = anon_inode_getfile("gpio-event", in lineevent_create()
2213 return -EFAULT; in lineevent_create()
2230 u64 flagsv2 = info_v2->flags; in gpio_v2_line_info_to_v1()
2232 memcpy(info_v1->name, info_v2->name, sizeof(info_v1->name)); in gpio_v2_line_info_to_v1()
2233 memcpy(info_v1->consumer, info_v2->consumer, sizeof(info_v1->consumer)); in gpio_v2_line_info_to_v1()
2234 info_v1->line_offset = info_v2->offset; in gpio_v2_line_info_to_v1()
2235 info_v1->flags = 0; in gpio_v2_line_info_to_v1()
2238 info_v1->flags |= GPIOLINE_FLAG_KERNEL; in gpio_v2_line_info_to_v1()
2241 info_v1->flags |= GPIOLINE_FLAG_IS_OUT; in gpio_v2_line_info_to_v1()
2244 info_v1->flags |= GPIOLINE_FLAG_ACTIVE_LOW; in gpio_v2_line_info_to_v1()
2247 info_v1->flags |= GPIOLINE_FLAG_OPEN_DRAIN; in gpio_v2_line_info_to_v1()
2249 info_v1->flags |= GPIOLINE_FLAG_OPEN_SOURCE; in gpio_v2_line_info_to_v1()
2252 info_v1->flags |= GPIOLINE_FLAG_BIAS_PULL_UP; in gpio_v2_line_info_to_v1()
2254 info_v1->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; in gpio_v2_line_info_to_v1()
2256 info_v1->flags |= GPIOLINE_FLAG_BIAS_DISABLE; in gpio_v2_line_info_to_v1()
2264 gpio_v2_line_info_to_v1(&lic_v2->info, &lic_v1->info); in gpio_v2_line_info_changed_to_v1()
2265 lic_v1->timestamp = lic_v2->timestamp_ns; in gpio_v2_line_info_changed_to_v1()
2266 lic_v1->event_type = lic_v2->event_type; in gpio_v2_line_info_changed_to_v1()
2274 struct gpio_chip *gc = desc->gdev->chip; in gpio_desc_to_lineinfo()
2281 info->offset = gpio_chip_hwgpio(desc); in gpio_desc_to_lineinfo()
2287 * FIXME: find a non-racy way to retrieve this information. Maybe a in gpio_desc_to_lineinfo()
2291 pinctrl_gpio_can_use_line(gc->base + info->offset); in gpio_desc_to_lineinfo()
2295 if (desc->name) in gpio_desc_to_lineinfo()
2296 strscpy(info->name, desc->name, sizeof(info->name)); in gpio_desc_to_lineinfo()
2298 if (desc->label) in gpio_desc_to_lineinfo()
2299 strscpy(info->consumer, desc->label, sizeof(info->consumer)); in gpio_desc_to_lineinfo()
2305 info->flags = 0; in gpio_desc_to_lineinfo()
2306 if (test_bit(FLAG_REQUESTED, &desc->flags) || in gpio_desc_to_lineinfo()
2307 test_bit(FLAG_IS_HOGGED, &desc->flags) || in gpio_desc_to_lineinfo()
2308 test_bit(FLAG_USED_AS_IRQ, &desc->flags) || in gpio_desc_to_lineinfo()
2309 test_bit(FLAG_EXPORT, &desc->flags) || in gpio_desc_to_lineinfo()
2310 test_bit(FLAG_SYSFS, &desc->flags) || in gpio_desc_to_lineinfo()
2311 !gpiochip_line_is_valid(gc, info->offset) || in gpio_desc_to_lineinfo()
2313 info->flags |= GPIO_V2_LINE_FLAG_USED; in gpio_desc_to_lineinfo()
2315 if (test_bit(FLAG_IS_OUT, &desc->flags)) in gpio_desc_to_lineinfo()
2316 info->flags |= GPIO_V2_LINE_FLAG_OUTPUT; in gpio_desc_to_lineinfo()
2318 info->flags |= GPIO_V2_LINE_FLAG_INPUT; in gpio_desc_to_lineinfo()
2320 if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) in gpio_desc_to_lineinfo()
2321 info->flags |= GPIO_V2_LINE_FLAG_ACTIVE_LOW; in gpio_desc_to_lineinfo()
2323 if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) in gpio_desc_to_lineinfo()
2324 info->flags |= GPIO_V2_LINE_FLAG_OPEN_DRAIN; in gpio_desc_to_lineinfo()
2325 if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) in gpio_desc_to_lineinfo()
2326 info->flags |= GPIO_V2_LINE_FLAG_OPEN_SOURCE; in gpio_desc_to_lineinfo()
2328 if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) in gpio_desc_to_lineinfo()
2329 info->flags |= GPIO_V2_LINE_FLAG_BIAS_DISABLED; in gpio_desc_to_lineinfo()
2330 if (test_bit(FLAG_PULL_DOWN, &desc->flags)) in gpio_desc_to_lineinfo()
2331 info->flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN; in gpio_desc_to_lineinfo()
2332 if (test_bit(FLAG_PULL_UP, &desc->flags)) in gpio_desc_to_lineinfo()
2333 info->flags |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP; in gpio_desc_to_lineinfo()
2335 if (test_bit(FLAG_EDGE_RISING, &desc->flags)) in gpio_desc_to_lineinfo()
2336 info->flags |= GPIO_V2_LINE_FLAG_EDGE_RISING; in gpio_desc_to_lineinfo()
2337 if (test_bit(FLAG_EDGE_FALLING, &desc->flags)) in gpio_desc_to_lineinfo()
2338 info->flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; in gpio_desc_to_lineinfo()
2340 if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &desc->flags)) in gpio_desc_to_lineinfo()
2341 info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; in gpio_desc_to_lineinfo()
2342 else if (test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags)) in gpio_desc_to_lineinfo()
2343 info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; in gpio_desc_to_lineinfo()
2345 debounce_period_us = READ_ONCE(desc->debounce_period_us); in gpio_desc_to_lineinfo()
2347 info->attrs[num_attrs].id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; in gpio_desc_to_lineinfo()
2348 info->attrs[num_attrs].debounce_period_us = debounce_period_us; in gpio_desc_to_lineinfo()
2351 info->num_attrs = num_attrs; in gpio_desc_to_lineinfo()
2370 struct gpio_device *gdev = cdev->gdev; in chipinfo_get()
2375 strscpy(chipinfo.name, dev_name(&gdev->dev), sizeof(chipinfo.name)); in chipinfo_get()
2376 strscpy(chipinfo.label, gdev->label, sizeof(chipinfo.label)); in chipinfo_get()
2377 chipinfo.lines = gdev->ngpio; in chipinfo_get()
2379 return -EFAULT; in chipinfo_get()
2390 int abiv = atomic_cmpxchg(&cdata->watch_abi_version, 0, version); in lineinfo_ensure_abi_version()
2406 return -EFAULT; in lineinfo_get_v1()
2409 desc = gpiochip_get_desc(cdev->gdev->chip, lineinfo.line_offset); in lineinfo_get_v1()
2415 return -EPERM; in lineinfo_get_v1()
2417 if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines)) in lineinfo_get_v1()
2418 return -EBUSY; in lineinfo_get_v1()
2426 clear_bit(lineinfo.line_offset, cdev->watched_lines); in lineinfo_get_v1()
2427 return -EFAULT; in lineinfo_get_v1()
2441 return -EFAULT; in lineinfo_get()
2444 return -EINVAL; in lineinfo_get()
2446 desc = gpiochip_get_desc(cdev->gdev->chip, lineinfo.offset); in lineinfo_get()
2453 return -EPERM; in lineinfo_get()
2455 if (test_and_set_bit(lineinfo.offset, cdev->watched_lines)) in lineinfo_get()
2456 return -EBUSY; in lineinfo_get()
2462 clear_bit(lineinfo.offset, cdev->watched_lines); in lineinfo_get()
2463 return -EFAULT; in lineinfo_get()
2474 return -EFAULT; in lineinfo_unwatch()
2476 if (offset >= cdev->gdev->ngpio) in lineinfo_unwatch()
2477 return -EINVAL; in lineinfo_unwatch()
2479 if (!test_and_clear_bit(offset, cdev->watched_lines)) in lineinfo_unwatch()
2480 return -EBUSY; in lineinfo_unwatch()
2486 * gpio_ioctl() - ioctl handler for the GPIO chardev
2490 struct gpio_chardev_data *cdev = file->private_data; in gpio_ioctl()
2491 struct gpio_device *gdev = cdev->gdev; in gpio_ioctl()
2495 if (!gdev->chip) in gpio_ioctl()
2496 return -ENODEV; in gpio_ioctl()
2521 return -EINVAL; in gpio_ioctl()
2538 struct gpio_v2_line_info_changed chg; in lineinfo_changed_notify() local
2542 if (!test_bit(gpio_chip_hwgpio(desc), cdev->watched_lines)) in lineinfo_changed_notify()
2545 memset(&chg, 0, sizeof(chg)); in lineinfo_changed_notify()
2546 chg.event_type = action; in lineinfo_changed_notify()
2547 chg.timestamp_ns = ktime_get_ns(); in lineinfo_changed_notify()
2548 gpio_desc_to_lineinfo(desc, &chg.info); in lineinfo_changed_notify()
2550 ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock); in lineinfo_changed_notify()
2552 wake_up_poll(&cdev->wait, EPOLLIN); in lineinfo_changed_notify()
2554 pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n"); in lineinfo_changed_notify()
2566 wake_up_poll(&cdev->wait, EPOLLIN | EPOLLERR); in gpio_device_unregistered_notify()
2574 struct gpio_chardev_data *cdev = file->private_data; in lineinfo_watch_poll_unlocked()
2577 if (!cdev->gdev->chip) in lineinfo_watch_poll_unlocked()
2580 poll_wait(file, &cdev->wait, pollt); in lineinfo_watch_poll_unlocked()
2582 if (!kfifo_is_empty_spinlocked_noirqsave(&cdev->events, in lineinfo_watch_poll_unlocked()
2583 &cdev->wait.lock)) in lineinfo_watch_poll_unlocked()
2592 struct gpio_chardev_data *cdev = file->private_data; in lineinfo_watch_poll()
2594 return call_poll_locked(file, pollt, cdev->gdev, in lineinfo_watch_poll()
2601 struct gpio_chardev_data *cdev = file->private_data; in lineinfo_watch_read_unlocked()
2607 if (!cdev->gdev->chip) in lineinfo_watch_read_unlocked()
2608 return -ENODEV; in lineinfo_watch_read_unlocked()
2613 return -EINVAL; in lineinfo_watch_read_unlocked()
2617 spin_lock(&cdev->wait.lock); in lineinfo_watch_read_unlocked()
2618 if (kfifo_is_empty(&cdev->events)) { in lineinfo_watch_read_unlocked()
2620 spin_unlock(&cdev->wait.lock); in lineinfo_watch_read_unlocked()
2624 if (file->f_flags & O_NONBLOCK) { in lineinfo_watch_read_unlocked()
2625 spin_unlock(&cdev->wait.lock); in lineinfo_watch_read_unlocked()
2626 return -EAGAIN; in lineinfo_watch_read_unlocked()
2629 ret = wait_event_interruptible_locked(cdev->wait, in lineinfo_watch_read_unlocked()
2630 !kfifo_is_empty(&cdev->events)); in lineinfo_watch_read_unlocked()
2632 spin_unlock(&cdev->wait.lock); in lineinfo_watch_read_unlocked()
2638 if (atomic_read(&cdev->watch_abi_version) == 2) in lineinfo_watch_read_unlocked()
2643 spin_unlock(&cdev->wait.lock); in lineinfo_watch_read_unlocked()
2644 return -EINVAL; in lineinfo_watch_read_unlocked()
2647 ret = kfifo_out(&cdev->events, &event, 1); in lineinfo_watch_read_unlocked()
2648 spin_unlock(&cdev->wait.lock); in lineinfo_watch_read_unlocked()
2650 ret = -EIO; in lineinfo_watch_read_unlocked()
2658 return -EFAULT; in lineinfo_watch_read_unlocked()
2665 return -EFAULT; in lineinfo_watch_read_unlocked()
2669 return -EFAULT; in lineinfo_watch_read_unlocked()
2680 struct gpio_chardev_data *cdev = file->private_data; in lineinfo_watch_read()
2682 return call_read_locked(file, buf, count, off, cdev->gdev, in lineinfo_watch_read()
2687 * gpio_chrdev_open() - open the chardev for ioctl operations
2694 struct gpio_device *gdev = container_of(inode->i_cdev, in gpio_chrdev_open()
2697 int ret = -ENOMEM; in gpio_chrdev_open()
2699 down_read(&gdev->sem); in gpio_chrdev_open()
2702 if (!gdev->chip) { in gpio_chrdev_open()
2703 ret = -ENODEV; in gpio_chrdev_open()
2711 cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); in gpio_chrdev_open()
2712 if (!cdev->watched_lines) in gpio_chrdev_open()
2715 init_waitqueue_head(&cdev->wait); in gpio_chrdev_open()
2716 INIT_KFIFO(cdev->events); in gpio_chrdev_open()
2717 cdev->gdev = gpio_device_get(gdev); in gpio_chrdev_open()
2719 cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify; in gpio_chrdev_open()
2720 ret = blocking_notifier_chain_register(&gdev->line_state_notifier, in gpio_chrdev_open()
2721 &cdev->lineinfo_changed_nb); in gpio_chrdev_open()
2725 cdev->device_unregistered_nb.notifier_call = in gpio_chrdev_open()
2727 ret = blocking_notifier_chain_register(&gdev->device_notifier, in gpio_chrdev_open()
2728 &cdev->device_unregistered_nb); in gpio_chrdev_open()
2732 file->private_data = cdev; in gpio_chrdev_open()
2738 up_read(&gdev->sem); in gpio_chrdev_open()
2743 blocking_notifier_chain_unregister(&gdev->device_notifier, in gpio_chrdev_open()
2744 &cdev->device_unregistered_nb); in gpio_chrdev_open()
2746 blocking_notifier_chain_unregister(&gdev->line_state_notifier, in gpio_chrdev_open()
2747 &cdev->lineinfo_changed_nb); in gpio_chrdev_open()
2750 bitmap_free(cdev->watched_lines); in gpio_chrdev_open()
2754 up_read(&gdev->sem); in gpio_chrdev_open()
2759 * gpio_chrdev_release() - close chardev after ioctl operations
2766 struct gpio_chardev_data *cdev = file->private_data; in gpio_chrdev_release()
2767 struct gpio_device *gdev = cdev->gdev; in gpio_chrdev_release()
2769 bitmap_free(cdev->watched_lines); in gpio_chrdev_release()
2770 blocking_notifier_chain_unregister(&gdev->device_notifier, in gpio_chrdev_release()
2771 &cdev->device_unregistered_nb); in gpio_chrdev_release()
2772 blocking_notifier_chain_unregister(&gdev->line_state_notifier, in gpio_chrdev_release()
2773 &cdev->lineinfo_changed_nb); in gpio_chrdev_release()
2797 cdev_init(&gdev->chrdev, &gpio_fileops); in gpiolib_cdev_register()
2798 gdev->chrdev.owner = THIS_MODULE; in gpiolib_cdev_register()
2799 gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id); in gpiolib_cdev_register()
2801 ret = cdev_device_add(&gdev->chrdev, &gdev->dev); in gpiolib_cdev_register()
2805 chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n", in gpiolib_cdev_register()
2806 MAJOR(devt), gdev->id); in gpiolib_cdev_register()
2813 cdev_device_del(&gdev->chrdev, &gdev->dev); in gpiolib_cdev_unregister()
2814 blocking_notifier_call_chain(&gdev->device_notifier, 0, NULL); in gpiolib_cdev_unregister()