Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpiolib: cdev: Add hardware timestamp clock type

This patch adds new clock type for the GPIO controller which can
timestamp gpio lines in using hardware means. To expose such
functionalities to the userspace, code has been added where
during line create or set config API calls, it checks for new
clock type and if requested, calls HTE API. During line change
event, the HTE subsystem pushes timestamp data to userspace
through gpiolib-cdev.

Signed-off-by: Dipen Patel <dipenp@nvidia.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Dipen Patel and committed by
Thierry Reding
2068339a 10e4afd6

+222 -33
+219 -33
drivers/gpio/gpiolib-cdev.c
··· 24 24 #include <linux/timekeeping.h> 25 25 #include <linux/uaccess.h> 26 26 #include <linux/workqueue.h> 27 + #include <linux/hte.h> 27 28 #include <uapi/linux/gpio.h> 28 29 29 30 #include "gpiolib.h" ··· 465 464 * stale value. 466 465 */ 467 466 unsigned int level; 467 + /* 468 + * -- hte specific fields -- 469 + */ 470 + struct hte_ts_desc hdesc; 471 + /* 472 + * HTE provider sets line level at the time of event. The valid 473 + * value is 0 or 1 and negative value for an error. 474 + */ 475 + int raw_level; 476 + /* 477 + * when sw_debounce is set on HTE enabled line, this is running 478 + * counter of the discarded events. 479 + */ 480 + u32 total_discard_seq; 481 + /* 482 + * when sw_debounce is set on HTE enabled line, this variable records 483 + * last sequence number before debounce period expires. 484 + */ 485 + u32 last_seqno; 468 486 }; 469 487 470 488 /** ··· 538 518 GPIO_V2_LINE_DRIVE_FLAGS | \ 539 519 GPIO_V2_LINE_EDGE_FLAGS | \ 540 520 GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME | \ 521 + GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \ 541 522 GPIO_V2_LINE_BIAS_FLAGS) 542 523 543 524 static void linereq_put_event(struct linereq *lr, ··· 563 542 { 564 543 if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &line->desc->flags)) 565 544 return ktime_get_real_ns(); 545 + else if (test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) 546 + return line->timestamp_ns; 566 547 567 548 return ktime_get_ns(); 549 + } 550 + 551 + static enum hte_return process_hw_ts_thread(void *p) 552 + { 553 + struct line *line; 554 + struct linereq *lr; 555 + struct gpio_v2_line_event le; 556 + int level; 557 + u64 eflags; 558 + 559 + if (!p) 560 + return HTE_CB_HANDLED; 561 + 562 + line = p; 563 + lr = line->req; 564 + 565 + memset(&le, 0, sizeof(le)); 566 + 567 + le.timestamp_ns = line->timestamp_ns; 568 + eflags = READ_ONCE(line->eflags); 569 + 570 + if (eflags == GPIO_V2_LINE_FLAG_EDGE_BOTH) { 571 + if (line->raw_level >= 0) { 572 + if (test_bit(FLAG_ACTIVE_LOW, &line->desc->flags)) 573 + level = !line->raw_level; 574 + else 575 + level = line->raw_level; 576 + } else { 577 + level = gpiod_get_value_cansleep(line->desc); 578 + } 579 + 580 + if (level) 581 + le.id = GPIO_V2_LINE_EVENT_RISING_EDGE; 582 + else 583 + le.id = GPIO_V2_LINE_EVENT_FALLING_EDGE; 584 + } else if (eflags == GPIO_V2_LINE_FLAG_EDGE_RISING) { 585 + /* Emit low-to-high event */ 586 + le.id = GPIO_V2_LINE_EVENT_RISING_EDGE; 587 + } else if (eflags == GPIO_V2_LINE_FLAG_EDGE_FALLING) { 588 + /* Emit high-to-low event */ 589 + le.id = GPIO_V2_LINE_EVENT_FALLING_EDGE; 590 + } else { 591 + return HTE_CB_HANDLED; 592 + } 593 + le.line_seqno = line->line_seqno; 594 + le.seqno = (lr->num_lines == 1) ? le.line_seqno : line->req_seqno; 595 + le.offset = gpio_chip_hwgpio(line->desc); 596 + 597 + linereq_put_event(lr, &le); 598 + 599 + return HTE_CB_HANDLED; 600 + } 601 + 602 + static enum hte_return process_hw_ts(struct hte_ts_data *ts, void *p) 603 + { 604 + struct line *line; 605 + struct linereq *lr; 606 + int diff_seqno = 0; 607 + 608 + if (!ts || !p) 609 + return HTE_CB_HANDLED; 610 + 611 + line = p; 612 + line->timestamp_ns = ts->tsc; 613 + line->raw_level = ts->raw_level; 614 + lr = line->req; 615 + 616 + if (READ_ONCE(line->sw_debounced)) { 617 + line->total_discard_seq++; 618 + line->last_seqno = ts->seq; 619 + mod_delayed_work(system_wq, &line->work, 620 + usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us))); 621 + } else { 622 + if (unlikely(ts->seq < line->line_seqno)) 623 + return HTE_CB_HANDLED; 624 + 625 + diff_seqno = ts->seq - line->line_seqno; 626 + line->line_seqno = ts->seq; 627 + if (lr->num_lines != 1) 628 + line->req_seqno = atomic_add_return(diff_seqno, 629 + &lr->seqno); 630 + 631 + return HTE_RUN_SECOND_CB; 632 + } 633 + 634 + return HTE_CB_HANDLED; 568 635 } 569 636 570 637 static irqreturn_t edge_irq_thread(int irq, void *p) ··· 760 651 struct gpio_v2_line_event le; 761 652 struct line *line = container_of(work, struct line, work.work); 762 653 struct linereq *lr; 763 - int level; 654 + int level, diff_seqno; 764 655 u64 eflags; 765 656 766 - level = gpiod_get_raw_value_cansleep(line->desc); 657 + if (test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) { 658 + level = line->raw_level; 659 + if (level < 0) 660 + level = gpiod_get_raw_value_cansleep(line->desc); 661 + } else { 662 + level = gpiod_get_raw_value_cansleep(line->desc); 663 + } 767 664 if (level < 0) { 768 665 pr_debug_ratelimited("debouncer failed to read line value\n"); 769 666 return; ··· 800 685 lr = line->req; 801 686 le.timestamp_ns = line_event_timestamp(line); 802 687 le.offset = gpio_chip_hwgpio(line->desc); 803 - line->line_seqno++; 804 - le.line_seqno = line->line_seqno; 805 - le.seqno = (lr->num_lines == 1) ? 806 - le.line_seqno : atomic_inc_return(&lr->seqno); 688 + if (test_bit(FLAG_EVENT_CLOCK_HTE, &line->desc->flags)) { 689 + /* discard events except the last one */ 690 + line->total_discard_seq -= 1; 691 + diff_seqno = line->last_seqno - line->total_discard_seq - 692 + line->line_seqno; 693 + line->line_seqno = line->last_seqno - line->total_discard_seq; 694 + le.line_seqno = line->line_seqno; 695 + le.seqno = (lr->num_lines == 1) ? 696 + le.line_seqno : atomic_add_return(diff_seqno, &lr->seqno); 697 + } else { 698 + line->line_seqno++; 699 + le.line_seqno = line->line_seqno; 700 + le.seqno = (lr->num_lines == 1) ? 701 + le.line_seqno : atomic_inc_return(&lr->seqno); 702 + } 807 703 808 704 if (level) 809 705 /* Emit low-to-high event */ ··· 826 700 linereq_put_event(lr, &le); 827 701 } 828 702 703 + static int hte_edge_setup(struct line *line, u64 eflags) 704 + { 705 + int ret; 706 + unsigned long flags = 0; 707 + struct hte_ts_desc *hdesc = &line->hdesc; 708 + 709 + if (eflags & GPIO_V2_LINE_FLAG_EDGE_RISING) 710 + flags |= test_bit(FLAG_ACTIVE_LOW, &line->desc->flags) ? 711 + HTE_FALLING_EDGE_TS : HTE_RISING_EDGE_TS; 712 + if (eflags & GPIO_V2_LINE_FLAG_EDGE_FALLING) 713 + flags |= test_bit(FLAG_ACTIVE_LOW, &line->desc->flags) ? 714 + HTE_RISING_EDGE_TS : HTE_FALLING_EDGE_TS; 715 + 716 + line->total_discard_seq = 0; 717 + 718 + hte_init_line_attr(hdesc, desc_to_gpio(line->desc), flags, 719 + NULL, line->desc); 720 + 721 + ret = hte_ts_get(NULL, hdesc, 0); 722 + if (ret) 723 + return ret; 724 + 725 + return hte_request_ts_ns(hdesc, process_hw_ts, 726 + process_hw_ts_thread, line); 727 + } 728 + 829 729 static int debounce_setup(struct line *line, 830 - unsigned int debounce_period_us) 730 + unsigned int debounce_period_us, bool hte_req) 831 731 { 832 732 unsigned long irqflags; 833 733 int ret, level, irq; ··· 873 721 if (level < 0) 874 722 return level; 875 723 876 - irq = gpiod_to_irq(line->desc); 877 - if (irq < 0) 878 - return -ENXIO; 724 + if (!hte_req) { 725 + irq = gpiod_to_irq(line->desc); 726 + if (irq < 0) 727 + return -ENXIO; 728 + 729 + irqflags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; 730 + ret = request_irq(irq, debounce_irq_handler, irqflags, 731 + line->req->label, line); 732 + if (ret) 733 + return ret; 734 + line->irq = irq; 735 + } else { 736 + ret = hte_edge_setup(line, 737 + GPIO_V2_LINE_FLAG_EDGE_RISING | 738 + GPIO_V2_LINE_FLAG_EDGE_FALLING); 739 + if (ret) 740 + return ret; 741 + } 879 742 880 743 WRITE_ONCE(line->level, level); 881 - irqflags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; 882 - ret = request_irq(irq, debounce_irq_handler, irqflags, 883 - line->req->label, line); 884 - if (ret) 885 - return ret; 886 - 887 744 WRITE_ONCE(line->sw_debounced, 1); 888 - line->irq = irq; 889 745 } 890 746 return 0; 891 747 } ··· 926 766 return 0; 927 767 } 928 768 929 - static void edge_detector_stop(struct line *line) 769 + static void edge_detector_stop(struct line *line, bool hte_en) 930 770 { 931 - if (line->irq) { 771 + if (line->irq && !hte_en) { 932 772 free_irq(line->irq, line); 933 773 line->irq = 0; 934 774 } 775 + 776 + if (hte_en) 777 + hte_ts_put(&line->hdesc); 935 778 936 779 cancel_delayed_work_sync(&line->work); 937 780 WRITE_ONCE(line->sw_debounced, 0); ··· 947 784 static int edge_detector_setup(struct line *line, 948 785 struct gpio_v2_line_config *lc, 949 786 unsigned int line_idx, 950 - u64 eflags) 787 + u64 eflags, bool hte_req) 951 788 { 952 789 u32 debounce_period_us; 953 790 unsigned long irqflags = 0; ··· 962 799 WRITE_ONCE(line->eflags, eflags); 963 800 if (gpio_v2_line_config_debounced(lc, line_idx)) { 964 801 debounce_period_us = gpio_v2_line_config_debounce_period(lc, line_idx); 965 - ret = debounce_setup(line, debounce_period_us); 802 + ret = debounce_setup(line, debounce_period_us, hte_req); 966 803 if (ret) 967 804 return ret; 968 805 WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); ··· 971 808 /* detection disabled or sw debouncer will provide edge detection */ 972 809 if (!eflags || READ_ONCE(line->sw_debounced)) 973 810 return 0; 811 + 812 + if (hte_req) 813 + return hte_edge_setup(line, eflags); 974 814 975 815 irq = gpiod_to_irq(line->desc); 976 816 if (irq < 0) ··· 1000 834 static int edge_detector_update(struct line *line, 1001 835 struct gpio_v2_line_config *lc, 1002 836 unsigned int line_idx, 1003 - u64 eflags, bool polarity_change) 837 + u64 flags, bool polarity_change, 838 + bool prev_hte_flag) 1004 839 { 840 + u64 eflags = flags & GPIO_V2_LINE_EDGE_FLAGS; 1005 841 unsigned int debounce_period_us = 1006 - gpio_v2_line_config_debounce_period(lc, line_idx); 842 + gpio_v2_line_config_debounce_period(lc, line_idx); 843 + bool hte_change = (prev_hte_flag != 844 + ((flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) != 0)); 1007 845 1008 846 if ((READ_ONCE(line->eflags) == eflags) && !polarity_change && 1009 - (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us)) 847 + (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us) 848 + && !hte_change) 1010 849 return 0; 1011 850 1012 851 /* sw debounced and still will be...*/ ··· 1022 851 } 1023 852 1024 853 /* reconfiguring edge detection or sw debounce being disabled */ 1025 - if ((line->irq && !READ_ONCE(line->sw_debounced)) || 854 + if ((line->irq && !READ_ONCE(line->sw_debounced)) || prev_hte_flag || 1026 855 (!debounce_period_us && READ_ONCE(line->sw_debounced))) 1027 - edge_detector_stop(line); 856 + edge_detector_stop(line, prev_hte_flag); 1028 857 1029 - return edge_detector_setup(line, lc, line_idx, eflags); 858 + return edge_detector_setup(line, lc, line_idx, eflags, 859 + flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); 1030 860 } 1031 861 1032 862 static u64 gpio_v2_line_config_flags(struct gpio_v2_line_config *lc, ··· 1063 891 /* Return an error if an unknown flag is set */ 1064 892 if (flags & ~GPIO_V2_LINE_VALID_FLAGS) 1065 893 return -EINVAL; 1066 - 1067 894 /* 1068 895 * Do not allow both INPUT and OUTPUT flags to be set as they are 1069 896 * contradictory. 1070 897 */ 1071 898 if ((flags & GPIO_V2_LINE_FLAG_INPUT) && 1072 899 (flags & GPIO_V2_LINE_FLAG_OUTPUT)) 900 + return -EINVAL; 901 + 902 + /* Only allow one event clock source */ 903 + if ((flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME) && 904 + (flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE)) 1073 905 return -EINVAL; 1074 906 1075 907 /* Edge detection requires explicit input. */ ··· 1168 992 1169 993 assign_bit(FLAG_EVENT_CLOCK_REALTIME, flagsp, 1170 994 flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME); 995 + assign_bit(FLAG_EVENT_CLOCK_HTE, flagsp, 996 + flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); 1171 997 } 1172 998 1173 999 static long linereq_get_values(struct linereq *lr, void __user *ip) ··· 1299 1121 unsigned int i; 1300 1122 u64 flags; 1301 1123 bool polarity_change; 1124 + bool prev_hte_flag; 1302 1125 int ret; 1303 1126 1304 1127 for (i = 0; i < lr->num_lines; i++) { ··· 1309 1130 (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) != 1310 1131 ((flags & GPIO_V2_LINE_FLAG_ACTIVE_LOW) != 0)); 1311 1132 1133 + prev_hte_flag = !!test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags); 1134 + 1312 1135 gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags); 1313 1136 /* 1314 1137 * Lines have to be requested explicitly for input ··· 1319 1138 if (flags & GPIO_V2_LINE_FLAG_OUTPUT) { 1320 1139 int val = gpio_v2_line_config_output_value(lc, i); 1321 1140 1322 - edge_detector_stop(&lr->lines[i]); 1141 + edge_detector_stop(&lr->lines[i], prev_hte_flag); 1323 1142 ret = gpiod_direction_output(desc, val); 1324 1143 if (ret) 1325 1144 return ret; ··· 1329 1148 return ret; 1330 1149 1331 1150 ret = edge_detector_update(&lr->lines[i], lc, i, 1332 - flags & GPIO_V2_LINE_EDGE_FLAGS, 1333 - polarity_change); 1151 + flags, polarity_change, prev_hte_flag); 1334 1152 if (ret) 1335 1153 return ret; 1336 1154 } ··· 1458 1278 static void linereq_free(struct linereq *lr) 1459 1279 { 1460 1280 unsigned int i; 1281 + bool hte; 1461 1282 1462 1283 for (i = 0; i < lr->num_lines; i++) { 1463 - edge_detector_stop(&lr->lines[i]); 1284 + hte = !!test_bit(FLAG_EVENT_CLOCK_HTE, 1285 + &lr->lines[i].desc->flags); 1286 + edge_detector_stop(&lr->lines[i], hte); 1464 1287 if (lr->lines[i].desc) 1465 1288 gpiod_free(lr->lines[i].desc); 1466 1289 } ··· 1589 1406 goto out_free_linereq; 1590 1407 1591 1408 ret = edge_detector_setup(&lr->lines[i], lc, i, 1592 - flags & GPIO_V2_LINE_EDGE_FLAGS); 1409 + flags & GPIO_V2_LINE_EDGE_FLAGS, 1410 + flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); 1593 1411 if (ret) 1594 1412 goto out_free_linereq; 1595 1413 } ··· 2143 1959 2144 1960 if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &desc->flags)) 2145 1961 info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; 1962 + else if (test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags)) 1963 + info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; 2146 1964 2147 1965 debounce_period_us = READ_ONCE(desc->debounce_period_us); 2148 1966 if (debounce_period_us) {
+3
include/uapi/linux/gpio.h
··· 66 66 * @GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN: line has pull-down bias enabled 67 67 * @GPIO_V2_LINE_FLAG_BIAS_DISABLED: line has bias disabled 68 68 * @GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME: line events contain REALTIME timestamps 69 + * @GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE: line events contain timestamps from 70 + * hardware timestamp engine 69 71 */ 70 72 enum gpio_v2_line_flag { 71 73 GPIO_V2_LINE_FLAG_USED = _BITULL(0), ··· 82 80 GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN = _BITULL(9), 83 81 GPIO_V2_LINE_FLAG_BIAS_DISABLED = _BITULL(10), 84 82 GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME = _BITULL(11), 83 + GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE = _BITULL(12), 85 84 }; 86 85 87 86 /**