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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'hte/for-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux

Pull hardware timestamping subsystem from Thierry Reding:
"This contains the new HTE (hardware timestamping engine) subsystem
that has been in the works for a couple of months now.

The infrastructure provided allows for drivers to register as hardware
timestamp providers, while consumers will be able to request events
that they are interested in (such as GPIOs and IRQs) to be timestamped
by the hardware providers.

Note that this currently supports only one provider, but there seems
to be enough interest in this functionality and we expect to see more
drivers added once this is merged"

[ Linus Walleij mentions the Intel PMC in the Elkhart and Tiger Lake
platforms as another future timestamp provider ]

* tag 'hte/for-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
dt-bindings: timestamp: Correct id path
dt-bindings: Renamed hte directory to timestamp
hte: Uninitialized variable in hte_ts_get()
hte: Fix off by one in hte_push_ts_ns()
hte: Fix possible use-after-free in tegra_hte_test_remove()
hte: Remove unused including <linux/version.h>
MAINTAINERS: Add HTE Subsystem
hte: Add Tegra HTE test driver
tools: gpio: Add new hardware clock type
gpiolib: cdev: Add hardware timestamp clock type
gpio: tegra186: Add HTE support
gpiolib: Add HTE support
dt-bindings: Add HTE bindings
hte: Add Tegra194 HTE kernel provider
drivers: Add hardware timestamp engine (HTE) subsystem
Documentation: Add HTE subsystem guide

+2930 -37
+29
Documentation/devicetree/bindings/timestamp/hardware-timestamps-common.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/timestamp/hardware-timestamps-common.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Hardware timestamp providers 8 + 9 + maintainers: 10 + - Dipen Patel <dipenp@nvidia.com> 11 + 12 + description: 13 + Some devices/SoCs have hardware timestamp engines (HTE) which can use 14 + hardware means to timestamp entity in realtime. The entity could be anything 15 + from GPIOs, IRQs, Bus and so on. The hardware timestamp engine present 16 + itself as a provider with the bindings described in this document. 17 + 18 + properties: 19 + $nodename: 20 + pattern: "^timestamp(@.*|-[0-9a-f])?$" 21 + 22 + "#timestamp-cells": 23 + description: 24 + Number of cells in a HTE specifier. 25 + 26 + required: 27 + - "#timestamp-cells" 28 + 29 + additionalProperties: true
+39
Documentation/devicetree/bindings/timestamp/hte-consumer.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/timestamp/hte-consumer.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: HTE Consumer Device Tree Bindings 8 + 9 + maintainers: 10 + - Dipen Patel <dipenp@nvidia.com> 11 + 12 + select: true 13 + 14 + properties: 15 + timestamps: 16 + $ref: /schemas/types.yaml#/definitions/phandle-array 17 + description: 18 + The list of HTE provider phandle. The first cell must represent the 19 + provider phandle followed by the line identifiers. The meaning of the 20 + line identifier and exact number of arguments must be specified in the 21 + HTE provider device tree binding document. 22 + 23 + timestamp-names: 24 + $ref: /schemas/types.yaml#/definitions/string-array 25 + description: 26 + An optional string property to label each line specifier present in the 27 + timestamp property. 28 + 29 + dependencies: 30 + timestamp-names: [ timestamps ] 31 + 32 + additionalProperties: true 33 + 34 + examples: 35 + - | 36 + hte_tegra_consumer { 37 + timestamps = <&tegra_hte_aon 0x9>, <&tegra_hte_lic 0x19>; 38 + timestamp-names = "hte-gpio", "hte-i2c"; 39 + };
+88
Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/timestamp/nvidia,tegra194-hte.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Tegra194 on chip generic hardware timestamping engine (HTE) 8 + 9 + maintainers: 10 + - Dipen Patel <dipenp@nvidia.com> 11 + 12 + description: 13 + Tegra SoC has two instances of generic hardware timestamping engines (GTE) 14 + known as GTE GPIO and GTE IRQ, which can monitor subset of GPIO and on chip 15 + IRQ lines for the state change respectively, upon detection it will record 16 + timestamp (taken from system counter) in its internal hardware FIFO. It has 17 + a bitmap array arranged in 32bit slices where each bit represent signal/line 18 + to enable or disable for the hardware timestamping. The GTE GPIO monitors 19 + GPIO lines from the AON (always on) GPIO controller. 20 + 21 + properties: 22 + compatible: 23 + enum: 24 + - nvidia,tegra194-gte-aon 25 + - nvidia,tegra194-gte-lic 26 + 27 + reg: 28 + maxItems: 1 29 + 30 + interrupts: 31 + maxItems: 1 32 + 33 + nvidia,int-threshold: 34 + $ref: /schemas/types.yaml#/definitions/uint32 35 + description: 36 + HTE device generates its interrupt based on this u32 FIFO threshold 37 + value. The recommended value is 1. 38 + minimum: 1 39 + maximum: 256 40 + 41 + nvidia,slices: 42 + $ref: /schemas/types.yaml#/definitions/uint32 43 + description: 44 + HTE lines are arranged in 32 bit slice where each bit represents different 45 + line/signal that it can enable/configure for the timestamp. It is u32 46 + property and depends on the HTE instance in the chip. The value 3 is for 47 + GPIO GTE and 11 for IRQ GTE. 48 + enum: [3, 11] 49 + 50 + '#timestamp-cells': 51 + description: 52 + This represents number of line id arguments as specified by the 53 + consumers. For the GTE IRQ, this is IRQ number as mentioned in the 54 + SoC technical reference manual. For the GTE GPIO, its value is same as 55 + mentioned in the nvidia GPIO device tree binding document. 56 + const: 1 57 + 58 + required: 59 + - compatible 60 + - reg 61 + - interrupts 62 + - nvidia,slices 63 + - "#timestamp-cells" 64 + 65 + additionalProperties: false 66 + 67 + examples: 68 + - | 69 + tegra_hte_aon: timestamp@c1e0000 { 70 + compatible = "nvidia,tegra194-gte-aon"; 71 + reg = <0xc1e0000 0x10000>; 72 + interrupts = <0 13 0x4>; 73 + nvidia,int-threshold = <1>; 74 + nvidia,slices = <3>; 75 + #timestamp-cells = <1>; 76 + }; 77 + 78 + - | 79 + tegra_hte_lic: timestamp@3aa0000 { 80 + compatible = "nvidia,tegra194-gte-lic"; 81 + reg = <0x3aa0000 0x10000>; 82 + interrupts = <0 11 0x4>; 83 + nvidia,int-threshold = <1>; 84 + nvidia,slices = <11>; 85 + #timestamp-cells = <1>; 86 + }; 87 + 88 + ...
+79
Documentation/hte/hte.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + ============================================ 4 + The Linux Hardware Timestamping Engine (HTE) 5 + ============================================ 6 + 7 + :Author: Dipen Patel 8 + 9 + Introduction 10 + ------------ 11 + 12 + Certain devices have built in hardware timestamping engines which can 13 + monitor sets of system signals, lines, buses etc... in realtime for state 14 + change; upon detecting the change they can automatically store the timestamp at 15 + the moment of occurrence. Such functionality may help achieve better accuracy 16 + in obtaining timestamps than using software counterparts i.e. ktime and 17 + friends. 18 + 19 + This document describes the API that can be used by hardware timestamping 20 + engine provider and consumer drivers that want to use the hardware timestamping 21 + engine (HTE) framework. Both consumers and providers must include 22 + ``#include <linux/hte.h>``. 23 + 24 + The HTE framework APIs for the providers 25 + ---------------------------------------- 26 + 27 + .. kernel-doc:: drivers/hte/hte.c 28 + :functions: devm_hte_register_chip hte_push_ts_ns 29 + 30 + The HTE framework APIs for the consumers 31 + ---------------------------------------- 32 + 33 + .. kernel-doc:: drivers/hte/hte.c 34 + :functions: hte_init_line_attr hte_ts_get hte_ts_put devm_hte_request_ts_ns hte_request_ts_ns hte_enable_ts hte_disable_ts of_hte_req_count hte_get_clk_src_info 35 + 36 + The HTE framework public structures 37 + ----------------------------------- 38 + .. kernel-doc:: include/linux/hte.h 39 + 40 + More on the HTE timestamp data 41 + ------------------------------ 42 + The ``struct hte_ts_data`` is used to pass timestamp details between the 43 + consumers and the providers. It expresses timestamp data in nanoseconds in 44 + u64. An example of the typical timestamp data life cycle, for the GPIO line is 45 + as follows:: 46 + 47 + - Monitors GPIO line change. 48 + - Detects the state change on GPIO line. 49 + - Converts timestamps in nanoseconds. 50 + - Stores GPIO raw level in raw_level variable if the provider has that 51 + hardware capability. 52 + - Pushes this hte_ts_data object to HTE subsystem. 53 + - HTE subsystem increments seq counter and invokes consumer provided callback. 54 + Based on callback return value, the HTE core invokes secondary callback in 55 + the thread context. 56 + 57 + HTE subsystem debugfs attributes 58 + -------------------------------- 59 + HTE subsystem creates debugfs attributes at ``/sys/kernel/debug/hte/``. 60 + It also creates line/signal-related debugfs attributes at 61 + ``/sys/kernel/debug/hte/<provider>/<label or line id>/``. Note that these 62 + attributes are read-only. 63 + 64 + `ts_requested` 65 + The total number of entities requested from the given provider, 66 + where entity is specified by the provider and could represent 67 + lines, GPIO, chip signals, buses etc... 68 + The attribute will be available at 69 + ``/sys/kernel/debug/hte/<provider>/``. 70 + 71 + `total_ts` 72 + The total number of entities supported by the provider. 73 + The attribute will be available at 74 + ``/sys/kernel/debug/hte/<provider>/``. 75 + 76 + `dropped_timestamps` 77 + The dropped timestamps for a given line. 78 + The attribute will be available at 79 + ``/sys/kernel/debug/hte/<provider>/<label or line id>/``.
+22
Documentation/hte/index.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ============================================ 4 + The Linux Hardware Timestamping Engine (HTE) 5 + ============================================ 6 + 7 + The HTE Subsystem 8 + ================= 9 + 10 + .. toctree:: 11 + :maxdepth: 1 12 + 13 + hte 14 + 15 + HTE Tegra Provider 16 + ================== 17 + 18 + .. toctree:: 19 + :maxdepth: 1 20 + 21 + tegra194-hte 22 +
+49
Documentation/hte/tegra194-hte.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + HTE Kernel provider driver 4 + ========================== 5 + 6 + Description 7 + ----------- 8 + The Nvidia tegra194 HTE provider driver implements two GTE 9 + (Generic Timestamping Engine) instances: 1) GPIO GTE and 2) LIC 10 + (Legacy Interrupt Controller) IRQ GTE. Both GTE instances get the 11 + timestamp from the system counter TSC which has 31.25MHz clock rate, and the 12 + driver converts clock tick rate to nanoseconds before storing it as timestamp 13 + value. 14 + 15 + GPIO GTE 16 + -------- 17 + 18 + This GTE instance timestamps GPIO in real time. For that to happen GPIO 19 + needs to be configured as input. The always on (AON) GPIO controller instance 20 + supports timestamping GPIOs in real time and it has 39 GPIO lines. The GPIO GTE 21 + and AON GPIO controller are tightly coupled as it requires very specific bits 22 + to be set in GPIO config register before GPIO GTE can be used, for that GPIOLIB 23 + adds two optional APIs as below. The GPIO GTE code supports both kernel 24 + and userspace consumers. The kernel space consumers can directly talk to HTE 25 + subsystem while userspace consumers timestamp requests go through GPIOLIB CDEV 26 + framework to HTE subsystem. 27 + 28 + .. kernel-doc:: drivers/gpio/gpiolib.c 29 + :functions: gpiod_enable_hw_timestamp_ns gpiod_disable_hw_timestamp_ns 30 + 31 + For userspace consumers, GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE flag must be 32 + specified during IOCTL calls. Refer to ``tools/gpio/gpio-event-mon.c``, which 33 + returns the timestamp in nanoseconds. 34 + 35 + LIC (Legacy Interrupt Controller) IRQ GTE 36 + ----------------------------------------- 37 + 38 + This GTE instance timestamps LIC IRQ lines in real time. There are 352 IRQ 39 + lines which this instance can add timestamps to in real time. The hte 40 + devicetree binding described at ``Documentation/devicetree/bindings/hte/`` 41 + provides an example of how a consumer can request an IRQ line. Since it is a 42 + one-to-one mapping with IRQ GTE provider, consumers can simply specify the IRQ 43 + number that they are interested in. There is no userspace consumer support for 44 + this GTE instance in the HTE framework. 45 + 46 + The provider source code of both IRQ and GPIO GTE instances is located at 47 + ``drivers/hte/hte-tegra194.c``. The test driver 48 + ``drivers/hte/hte-tegra194-test.c`` demonstrates HTE API usage for both IRQ 49 + and GPIO GTE.
+1
Documentation/index.rst
··· 137 137 scheduler/index 138 138 mhi/index 139 139 peci/index 140 + hte/index 140 141 141 142 Architecture-agnostic documentation 142 143 -----------------------------------
+8
MAINTAINERS
··· 9077 9077 S: Maintained 9078 9078 F: drivers/input/touchscreen/htcpen.c 9079 9079 9080 + HTE SUBSYSTEM 9081 + M: Dipen Patel <dipenp@nvidia.com> 9082 + S: Maintained 9083 + F: Documentation/devicetree/bindings/timestamp/ 9084 + F: Documentation/hte/ 9085 + F: drivers/hte/ 9086 + F: include/linux/hte.h 9087 + 9080 9088 HTS221 TEMPERATURE-HUMIDITY IIO DRIVER 9081 9089 M: Lorenzo Bianconi <lorenzo@kernel.org> 9082 9090 L: linux-iio@vger.kernel.org
+2
drivers/Kconfig
··· 237 237 238 238 source "drivers/peci/Kconfig" 239 239 240 + source "drivers/hte/Kconfig" 241 + 240 242 endmenu
+1
drivers/Makefile
··· 187 187 obj-$(CONFIG_COUNTER) += counter/ 188 188 obj-$(CONFIG_MOST) += most/ 189 189 obj-$(CONFIG_PECI) += peci/ 190 + obj-$(CONFIG_HTE) += hte/
+80 -1
drivers/gpio/gpio-tegra186.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * Copyright (c) 2016-2017 NVIDIA Corporation 3 + * Copyright (c) 2016-2022 NVIDIA Corporation 4 4 * 5 5 * Author: Thierry Reding <treding@nvidia.com> 6 + * Dipen Patel <dpatel@nvidia.com> 6 7 */ 7 8 8 9 #include <linux/gpio/driver.h> ··· 12 11 #include <linux/module.h> 13 12 #include <linux/of_device.h> 14 13 #include <linux/platform_device.h> 14 + #include <linux/hte.h> 15 15 16 16 #include <dt-bindings/gpio/tegra186-gpio.h> 17 17 #include <dt-bindings/gpio/tegra194-gpio.h> ··· 38 36 #define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL BIT(4) 39 37 #define TEGRA186_GPIO_ENABLE_CONFIG_DEBOUNCE BIT(5) 40 38 #define TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT BIT(6) 39 + #define TEGRA186_GPIO_ENABLE_CONFIG_TIMESTAMP_FUNC BIT(7) 41 40 42 41 #define TEGRA186_GPIO_DEBOUNCE_CONTROL 0x04 43 42 #define TEGRA186_GPIO_DEBOUNCE_CONTROL_THRESHOLD(x) ((x) & 0xff) ··· 79 76 const struct tegra186_pin_range *pin_ranges; 80 77 unsigned int num_pin_ranges; 81 78 const char *pinmux; 79 + bool has_gte; 82 80 }; 83 81 84 82 struct tegra_gpio { ··· 192 188 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG); 193 189 value |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE; 194 190 value |= TEGRA186_GPIO_ENABLE_CONFIG_OUT; 191 + writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); 192 + 193 + return 0; 194 + } 195 + 196 + #define HTE_BOTH_EDGES (HTE_RISING_EDGE_TS | HTE_FALLING_EDGE_TS) 197 + 198 + static int tegra186_gpio_en_hw_ts(struct gpio_chip *gc, u32 offset, 199 + unsigned long flags) 200 + { 201 + struct tegra_gpio *gpio; 202 + void __iomem *base; 203 + int value; 204 + 205 + if (!gc) 206 + return -EINVAL; 207 + 208 + gpio = gpiochip_get_data(gc); 209 + if (!gpio) 210 + return -ENODEV; 211 + 212 + base = tegra186_gpio_get_base(gpio, offset); 213 + if (WARN_ON(base == NULL)) 214 + return -EINVAL; 215 + 216 + value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG); 217 + value |= TEGRA186_GPIO_ENABLE_CONFIG_TIMESTAMP_FUNC; 218 + 219 + if (flags == HTE_BOTH_EDGES) { 220 + value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE; 221 + } else if (flags == HTE_RISING_EDGE_TS) { 222 + value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE; 223 + value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL; 224 + } else if (flags == HTE_FALLING_EDGE_TS) { 225 + value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE; 226 + } 227 + 228 + writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); 229 + 230 + return 0; 231 + } 232 + 233 + static int tegra186_gpio_dis_hw_ts(struct gpio_chip *gc, u32 offset, 234 + unsigned long flags) 235 + { 236 + struct tegra_gpio *gpio; 237 + void __iomem *base; 238 + int value; 239 + 240 + if (!gc) 241 + return -EINVAL; 242 + 243 + gpio = gpiochip_get_data(gc); 244 + if (!gpio) 245 + return -ENODEV; 246 + 247 + base = tegra186_gpio_get_base(gpio, offset); 248 + if (WARN_ON(base == NULL)) 249 + return -EINVAL; 250 + 251 + value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG); 252 + value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TIMESTAMP_FUNC; 253 + if (flags == HTE_BOTH_EDGES) { 254 + value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE; 255 + } else if (flags == HTE_RISING_EDGE_TS) { 256 + value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE; 257 + value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL; 258 + } else if (flags == HTE_FALLING_EDGE_TS) { 259 + value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE; 260 + } 195 261 writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); 196 262 197 263 return 0; ··· 821 747 gpio->gpio.set = tegra186_gpio_set; 822 748 gpio->gpio.set_config = tegra186_gpio_set_config; 823 749 gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges; 750 + if (gpio->soc->has_gte) { 751 + gpio->gpio.en_hw_timestamp = tegra186_gpio_en_hw_ts; 752 + gpio->gpio.dis_hw_timestamp = tegra186_gpio_dis_hw_ts; 753 + } 824 754 825 755 gpio->gpio.base = -1; 826 756 ··· 1069 991 .name = "tegra194-gpio-aon", 1070 992 .instance = 1, 1071 993 .num_irqs_per_bank = 8, 994 + .has_gte = true, 1072 995 }; 1073 996 1074 997 #define TEGRA234_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
+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 } ··· 1460 1280 static void linereq_free(struct linereq *lr) 1461 1281 { 1462 1282 unsigned int i; 1283 + bool hte; 1463 1284 1464 1285 for (i = 0; i < lr->num_lines; i++) { 1465 - edge_detector_stop(&lr->lines[i]); 1286 + hte = !!test_bit(FLAG_EVENT_CLOCK_HTE, 1287 + &lr->lines[i].desc->flags); 1288 + edge_detector_stop(&lr->lines[i], hte); 1466 1289 if (lr->lines[i].desc) 1467 1290 gpiod_free(lr->lines[i].desc); 1468 1291 } ··· 1591 1408 goto out_free_linereq; 1592 1409 1593 1410 ret = edge_detector_setup(&lr->lines[i], lc, i, 1594 - flags & GPIO_V2_LINE_EDGE_FLAGS); 1411 + flags & GPIO_V2_LINE_EDGE_FLAGS, 1412 + flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); 1595 1413 if (ret) 1596 1414 goto out_free_linereq; 1597 1415 } ··· 2145 1961 2146 1962 if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &desc->flags)) 2147 1963 info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; 1964 + else if (test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags)) 1965 + info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; 2148 1966 2149 1967 debounce_period_us = READ_ONCE(desc->debounce_period_us); 2150 1968 if (debounce_period_us) {
+58
drivers/gpio/gpiolib.c
··· 2454 2454 EXPORT_SYMBOL_GPL(gpiod_direction_output); 2455 2455 2456 2456 /** 2457 + * gpiod_enable_hw_timestamp_ns - Enable hardware timestamp in nanoseconds. 2458 + * 2459 + * @desc: GPIO to enable. 2460 + * @flags: Flags related to GPIO edge. 2461 + * 2462 + * Return 0 in case of success, else negative error code. 2463 + */ 2464 + int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags) 2465 + { 2466 + int ret = 0; 2467 + struct gpio_chip *gc; 2468 + 2469 + VALIDATE_DESC(desc); 2470 + 2471 + gc = desc->gdev->chip; 2472 + if (!gc->en_hw_timestamp) { 2473 + gpiod_warn(desc, "%s: hw ts not supported\n", __func__); 2474 + return -ENOTSUPP; 2475 + } 2476 + 2477 + ret = gc->en_hw_timestamp(gc, gpio_chip_hwgpio(desc), flags); 2478 + if (ret) 2479 + gpiod_warn(desc, "%s: hw ts request failed\n", __func__); 2480 + 2481 + return ret; 2482 + } 2483 + EXPORT_SYMBOL_GPL(gpiod_enable_hw_timestamp_ns); 2484 + 2485 + /** 2486 + * gpiod_disable_hw_timestamp_ns - Disable hardware timestamp. 2487 + * 2488 + * @desc: GPIO to disable. 2489 + * @flags: Flags related to GPIO edge, same value as used during enable call. 2490 + * 2491 + * Return 0 in case of success, else negative error code. 2492 + */ 2493 + int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags) 2494 + { 2495 + int ret = 0; 2496 + struct gpio_chip *gc; 2497 + 2498 + VALIDATE_DESC(desc); 2499 + 2500 + gc = desc->gdev->chip; 2501 + if (!gc->dis_hw_timestamp) { 2502 + gpiod_warn(desc, "%s: hw ts not supported\n", __func__); 2503 + return -ENOTSUPP; 2504 + } 2505 + 2506 + ret = gc->dis_hw_timestamp(gc, gpio_chip_hwgpio(desc), flags); 2507 + if (ret) 2508 + gpiod_warn(desc, "%s: hw ts release failed\n", __func__); 2509 + 2510 + return ret; 2511 + } 2512 + EXPORT_SYMBOL_GPL(gpiod_disable_hw_timestamp_ns); 2513 + 2514 + /** 2457 2515 * gpiod_set_config - sets @config for a GPIO 2458 2516 * @desc: descriptor of the GPIO for which to set the configuration 2459 2517 * @config: Same packed config format as generic pinconf
+1
drivers/gpio/gpiolib.h
··· 161 161 #define FLAG_EDGE_RISING 16 /* GPIO CDEV detects rising edge events */ 162 162 #define FLAG_EDGE_FALLING 17 /* GPIO CDEV detects falling edge events */ 163 163 #define FLAG_EVENT_CLOCK_REALTIME 18 /* GPIO CDEV reports REALTIME timestamps in events */ 164 + #define FLAG_EVENT_CLOCK_HTE 19 /* GPIO CDEV reports hardware timestamps in events */ 164 165 165 166 /* Connection label */ 166 167 const char *label;
+33
drivers/hte/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + menuconfig HTE 3 + bool "Hardware Timestamping Engine (HTE) Support" 4 + help 5 + Hardware Timestamping Engine (HTE) Support. 6 + 7 + Some devices provide a hardware timestamping engine which can 8 + timestamp certain device lines/signals in realtime. It comes with a 9 + benefit for the applications needing accurate timestamping event with 10 + less jitter. This framework provides a generic interface to such HTE 11 + providers and consumer devices. 12 + 13 + If unsure, say no. 14 + 15 + if HTE 16 + 17 + config HTE_TEGRA194 18 + tristate "NVIDIA Tegra194 HTE Support" 19 + depends on ARCH_TEGRA_194_SOC 20 + help 21 + Enable this option for integrated hardware timestamping engine also 22 + known as generic timestamping engine (GTE) support on NVIDIA Tegra194 23 + systems-on-chip. The driver supports 352 LIC IRQs and 39 AON GPIOs 24 + lines for timestamping in realtime. 25 + 26 + config HTE_TEGRA194_TEST 27 + tristate "NVIDIA Tegra194 HTE Test" 28 + depends on HTE_TEGRA194 29 + help 30 + The NVIDIA Tegra194 GTE test driver demonstrates how to use HTE 31 + framework to timestamp GPIO and LIC IRQ lines. 32 + 33 + endif
+3
drivers/hte/Makefile
··· 1 + obj-$(CONFIG_HTE) += hte.o 2 + obj-$(CONFIG_HTE_TEGRA194) += hte-tegra194.o 3 + obj-$(CONFIG_HTE_TEGRA194_TEST) += hte-tegra194-test.o
+238
drivers/hte/hte-tegra194-test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2021-2022 NVIDIA Corporation 4 + * 5 + * Author: Dipen Patel <dipenp@nvidia.com> 6 + */ 7 + 8 + #include <linux/err.h> 9 + #include <linux/module.h> 10 + #include <linux/moduleparam.h> 11 + #include <linux/interrupt.h> 12 + #include <linux/gpio.h> 13 + #include <linux/timer.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/workqueue.h> 16 + #include <linux/hte.h> 17 + 18 + /* 19 + * This sample HTE GPIO test driver demonstrates HTE API usage by enabling 20 + * hardware timestamp on gpio_in and specified LIC IRQ lines. 21 + * 22 + * Note: gpio_out and gpio_in need to be shorted externally in order for this 23 + * test driver to work for the GPIO monitoring. The test driver has been 24 + * tested on Jetson AGX Xavier platform by shorting pin 32 and 16 on 40 pin 25 + * header. 26 + * 27 + * Device tree snippet to activate this driver: 28 + * tegra_hte_test { 29 + * compatible = "nvidia,tegra194-hte-test"; 30 + * in-gpio = <&gpio_aon TEGRA194_AON_GPIO(BB, 1)>; 31 + * out-gpio = <&gpio_aon TEGRA194_AON_GPIO(BB, 0)>; 32 + * timestamps = <&tegra_hte_aon TEGRA194_AON_GPIO(BB, 1)>, 33 + * <&tegra_hte_lic 0x19>; 34 + * timestamp-names = "hte-gpio", "hte-i2c-irq"; 35 + * status = "okay"; 36 + * }; 37 + * 38 + * How to run test driver: 39 + * - Load test driver. 40 + * - For the GPIO, at regular interval gpio_out pin toggles triggering 41 + * HTE for rising edge on gpio_in pin. 42 + * 43 + * - For the LIC IRQ line, it uses 0x19 interrupt which is i2c controller 1. 44 + * - Run i2cdetect -y 1 1>/dev/null, this command will generate i2c bus 45 + * transactions which creates timestamp data. 46 + * - It prints below message for both the lines. 47 + * HW timestamp(<line id>:<ts seq number>): <timestamp>, edge: <edge>. 48 + * - Unloading the driver disables and deallocate the HTE. 49 + */ 50 + 51 + static struct tegra_hte_test { 52 + int gpio_in_irq; 53 + struct device *pdev; 54 + struct gpio_desc *gpio_in; 55 + struct gpio_desc *gpio_out; 56 + struct hte_ts_desc *desc; 57 + struct timer_list timer; 58 + struct kobject *kobj; 59 + } hte; 60 + 61 + static enum hte_return process_hw_ts(struct hte_ts_data *ts, void *p) 62 + { 63 + char *edge; 64 + struct hte_ts_desc *desc = p; 65 + 66 + if (!ts || !p) 67 + return HTE_CB_HANDLED; 68 + 69 + if (ts->raw_level < 0) 70 + edge = "Unknown"; 71 + 72 + pr_info("HW timestamp(%u: %llu): %llu, edge: %s\n", 73 + desc->attr.line_id, ts->seq, ts->tsc, 74 + (ts->raw_level >= 0) ? ((ts->raw_level == 0) ? 75 + "falling" : "rising") : edge); 76 + 77 + return HTE_CB_HANDLED; 78 + } 79 + 80 + static void gpio_timer_cb(struct timer_list *t) 81 + { 82 + (void)t; 83 + 84 + gpiod_set_value(hte.gpio_out, !gpiod_get_value(hte.gpio_out)); 85 + mod_timer(&hte.timer, jiffies + msecs_to_jiffies(8000)); 86 + } 87 + 88 + static irqreturn_t tegra_hte_test_gpio_isr(int irq, void *data) 89 + { 90 + (void)irq; 91 + (void)data; 92 + 93 + return IRQ_HANDLED; 94 + } 95 + 96 + static const struct of_device_id tegra_hte_test_of_match[] = { 97 + { .compatible = "nvidia,tegra194-hte-test"}, 98 + { } 99 + }; 100 + MODULE_DEVICE_TABLE(of, tegra_hte_test_of_match); 101 + 102 + static int tegra_hte_test_probe(struct platform_device *pdev) 103 + { 104 + int ret = 0; 105 + int i, cnt; 106 + 107 + dev_set_drvdata(&pdev->dev, &hte); 108 + hte.pdev = &pdev->dev; 109 + 110 + hte.gpio_out = gpiod_get(&pdev->dev, "out", 0); 111 + if (IS_ERR(hte.gpio_out)) { 112 + dev_err(&pdev->dev, "failed to get gpio out\n"); 113 + ret = -EINVAL; 114 + goto out; 115 + } 116 + 117 + hte.gpio_in = gpiod_get(&pdev->dev, "in", 0); 118 + if (IS_ERR(hte.gpio_in)) { 119 + dev_err(&pdev->dev, "failed to get gpio in\n"); 120 + ret = -EINVAL; 121 + goto free_gpio_out; 122 + } 123 + 124 + ret = gpiod_direction_output(hte.gpio_out, 0); 125 + if (ret) { 126 + dev_err(&pdev->dev, "failed to set output\n"); 127 + ret = -EINVAL; 128 + goto free_gpio_in; 129 + } 130 + 131 + ret = gpiod_direction_input(hte.gpio_in); 132 + if (ret) { 133 + dev_err(&pdev->dev, "failed to set input\n"); 134 + ret = -EINVAL; 135 + goto free_gpio_in; 136 + } 137 + 138 + ret = gpiod_to_irq(hte.gpio_in); 139 + if (ret < 0) { 140 + dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret); 141 + ret = -ENXIO; 142 + goto free_gpio_in; 143 + } 144 + 145 + hte.gpio_in_irq = ret; 146 + ret = request_irq(ret, tegra_hte_test_gpio_isr, 147 + IRQF_TRIGGER_RISING, 148 + "tegra_hte_gpio_test_isr", &hte); 149 + if (ret) { 150 + dev_err(&pdev->dev, "failed to acquire IRQ\n"); 151 + ret = -ENXIO; 152 + goto free_irq; 153 + } 154 + 155 + cnt = of_hte_req_count(hte.pdev); 156 + if (cnt < 0) 157 + goto free_irq; 158 + 159 + dev_info(&pdev->dev, "Total requested lines:%d\n", cnt); 160 + 161 + hte.desc = devm_kzalloc(hte.pdev, sizeof(*hte.desc) * cnt, GFP_KERNEL); 162 + if (!hte.desc) { 163 + ret = -ENOMEM; 164 + goto free_irq; 165 + } 166 + 167 + for (i = 0; i < cnt; i++) { 168 + if (i == 0) 169 + /* 170 + * GPIO hte init, line_id and name will be parsed from 171 + * the device tree node. The edge_flag is implicitly 172 + * set by request_irq call. Only line_data is needed to be 173 + * set. 174 + */ 175 + hte_init_line_attr(&hte.desc[i], 0, 0, NULL, 176 + hte.gpio_in); 177 + else 178 + /* 179 + * same comment as above except that IRQ does not need 180 + * line data. 181 + */ 182 + hte_init_line_attr(&hte.desc[i], 0, 0, NULL, NULL); 183 + 184 + ret = hte_ts_get(hte.pdev, &hte.desc[i], i); 185 + if (ret) 186 + goto ts_put; 187 + 188 + ret = devm_hte_request_ts_ns(hte.pdev, &hte.desc[i], 189 + process_hw_ts, NULL, 190 + &hte.desc[i]); 191 + if (ret) /* no need to ts_put, request API takes care */ 192 + goto free_irq; 193 + } 194 + 195 + timer_setup(&hte.timer, gpio_timer_cb, 0); 196 + mod_timer(&hte.timer, jiffies + msecs_to_jiffies(5000)); 197 + 198 + return 0; 199 + 200 + ts_put: 201 + cnt = i; 202 + for (i = 0; i < cnt; i++) 203 + hte_ts_put(&hte.desc[i]); 204 + free_irq: 205 + free_irq(hte.gpio_in_irq, &hte); 206 + free_gpio_in: 207 + gpiod_put(hte.gpio_in); 208 + free_gpio_out: 209 + gpiod_put(hte.gpio_out); 210 + out: 211 + 212 + return ret; 213 + } 214 + 215 + static int tegra_hte_test_remove(struct platform_device *pdev) 216 + { 217 + (void)pdev; 218 + 219 + free_irq(hte.gpio_in_irq, &hte); 220 + gpiod_put(hte.gpio_in); 221 + gpiod_put(hte.gpio_out); 222 + del_timer_sync(&hte.timer); 223 + 224 + return 0; 225 + } 226 + 227 + static struct platform_driver tegra_hte_test_driver = { 228 + .probe = tegra_hte_test_probe, 229 + .remove = tegra_hte_test_remove, 230 + .driver = { 231 + .name = "tegra_hte_test", 232 + .of_match_table = tegra_hte_test_of_match, 233 + }, 234 + }; 235 + module_platform_driver(tegra_hte_test_driver); 236 + 237 + MODULE_AUTHOR("Dipen Patel <dipenp@nvidia.com>"); 238 + MODULE_LICENSE("GPL");
+730
drivers/hte/hte-tegra194.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2021-2022 NVIDIA Corporation 4 + * 5 + * Author: Dipen Patel <dipenp@nvidia.com> 6 + */ 7 + 8 + #include <linux/err.h> 9 + #include <linux/io.h> 10 + #include <linux/module.h> 11 + #include <linux/slab.h> 12 + #include <linux/stat.h> 13 + #include <linux/interrupt.h> 14 + #include <linux/of.h> 15 + #include <linux/of_device.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/hte.h> 18 + #include <linux/uaccess.h> 19 + #include <linux/gpio/driver.h> 20 + #include <linux/gpio/consumer.h> 21 + 22 + #define HTE_SUSPEND 0 23 + 24 + /* HTE source clock TSC is 31.25MHz */ 25 + #define HTE_TS_CLK_RATE_HZ 31250000ULL 26 + #define HTE_CLK_RATE_NS 32 27 + #define HTE_TS_NS_SHIFT __builtin_ctz(HTE_CLK_RATE_NS) 28 + 29 + #define NV_AON_SLICE_INVALID -1 30 + #define NV_LINES_IN_SLICE 32 31 + 32 + /* AON HTE line map For slice 1 */ 33 + #define NV_AON_HTE_SLICE1_IRQ_GPIO_28 12 34 + #define NV_AON_HTE_SLICE1_IRQ_GPIO_29 13 35 + 36 + /* AON HTE line map For slice 2 */ 37 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_0 0 38 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_1 1 39 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_2 2 40 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_3 3 41 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_4 4 42 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_5 5 43 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_6 6 44 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_7 7 45 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_8 8 46 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_9 9 47 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_10 10 48 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_11 11 49 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_12 12 50 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_13 13 51 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_14 14 52 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_15 15 53 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_16 16 54 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_17 17 55 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_18 18 56 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_19 19 57 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_20 20 58 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_21 21 59 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_22 22 60 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_23 23 61 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_24 24 62 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_25 25 63 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_26 26 64 + #define NV_AON_HTE_SLICE2_IRQ_GPIO_27 27 65 + 66 + #define HTE_TECTRL 0x0 67 + #define HTE_TETSCH 0x4 68 + #define HTE_TETSCL 0x8 69 + #define HTE_TESRC 0xC 70 + #define HTE_TECCV 0x10 71 + #define HTE_TEPCV 0x14 72 + #define HTE_TECMD 0x1C 73 + #define HTE_TESTATUS 0x20 74 + #define HTE_SLICE0_TETEN 0x40 75 + #define HTE_SLICE1_TETEN 0x60 76 + 77 + #define HTE_SLICE_SIZE (HTE_SLICE1_TETEN - HTE_SLICE0_TETEN) 78 + 79 + #define HTE_TECTRL_ENABLE_ENABLE 0x1 80 + 81 + #define HTE_TECTRL_OCCU_SHIFT 0x8 82 + #define HTE_TECTRL_INTR_SHIFT 0x1 83 + #define HTE_TECTRL_INTR_ENABLE 0x1 84 + 85 + #define HTE_TESRC_SLICE_SHIFT 16 86 + #define HTE_TESRC_SLICE_DEFAULT_MASK 0xFF 87 + 88 + #define HTE_TECMD_CMD_POP 0x1 89 + 90 + #define HTE_TESTATUS_OCCUPANCY_SHIFT 8 91 + #define HTE_TESTATUS_OCCUPANCY_MASK 0xFF 92 + 93 + enum tegra_hte_type { 94 + HTE_TEGRA_TYPE_GPIO = 1U << 0, 95 + HTE_TEGRA_TYPE_LIC = 1U << 1, 96 + }; 97 + 98 + struct hte_slices { 99 + u32 r_val; 100 + unsigned long flags; 101 + /* to prevent lines mapped to same slice updating its register */ 102 + spinlock_t s_lock; 103 + }; 104 + 105 + struct tegra_hte_line_mapped { 106 + int slice; 107 + u32 bit_index; 108 + }; 109 + 110 + struct tegra_hte_line_data { 111 + unsigned long flags; 112 + void *data; 113 + }; 114 + 115 + struct tegra_hte_data { 116 + enum tegra_hte_type type; 117 + u32 map_sz; 118 + u32 sec_map_sz; 119 + const struct tegra_hte_line_mapped *map; 120 + const struct tegra_hte_line_mapped *sec_map; 121 + }; 122 + 123 + struct tegra_hte_soc { 124 + int hte_irq; 125 + u32 itr_thrshld; 126 + u32 conf_rval; 127 + struct hte_slices *sl; 128 + const struct tegra_hte_data *prov_data; 129 + struct tegra_hte_line_data *line_data; 130 + struct hte_chip *chip; 131 + struct gpio_chip *c; 132 + void __iomem *regs; 133 + }; 134 + 135 + static const struct tegra_hte_line_mapped tegra194_aon_gpio_map[] = { 136 + /* gpio, slice, bit_index */ 137 + /* AA port */ 138 + [0] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_11}, 139 + [1] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_10}, 140 + [2] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_9}, 141 + [3] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_8}, 142 + [4] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_7}, 143 + [5] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_6}, 144 + [6] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_5}, 145 + [7] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_4}, 146 + /* BB port */ 147 + [8] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_3}, 148 + [9] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_2}, 149 + [10] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_1}, 150 + [11] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_0}, 151 + /* CC port */ 152 + [12] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_22}, 153 + [13] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_21}, 154 + [14] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_20}, 155 + [15] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_19}, 156 + [16] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_18}, 157 + [17] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_17}, 158 + [18] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_16}, 159 + [19] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_15}, 160 + /* DD port */ 161 + [20] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_14}, 162 + [21] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_13}, 163 + [22] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_12}, 164 + /* EE port */ 165 + [23] = {1, NV_AON_HTE_SLICE1_IRQ_GPIO_29}, 166 + [24] = {1, NV_AON_HTE_SLICE1_IRQ_GPIO_28}, 167 + [25] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_27}, 168 + [26] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_26}, 169 + [27] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_25}, 170 + [28] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_24}, 171 + [29] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_23}, 172 + }; 173 + 174 + static const struct tegra_hte_line_mapped tegra194_aon_gpio_sec_map[] = { 175 + /* gpio, slice, bit_index */ 176 + /* AA port */ 177 + [0] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_11}, 178 + [1] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_10}, 179 + [2] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_9}, 180 + [3] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_8}, 181 + [4] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_7}, 182 + [5] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_6}, 183 + [6] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_5}, 184 + [7] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_4}, 185 + /* BB port */ 186 + [8] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_3}, 187 + [9] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_2}, 188 + [10] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_1}, 189 + [11] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_0}, 190 + [12] = {NV_AON_SLICE_INVALID, 0}, 191 + [13] = {NV_AON_SLICE_INVALID, 0}, 192 + [14] = {NV_AON_SLICE_INVALID, 0}, 193 + [15] = {NV_AON_SLICE_INVALID, 0}, 194 + /* CC port */ 195 + [16] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_22}, 196 + [17] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_21}, 197 + [18] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_20}, 198 + [19] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_19}, 199 + [20] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_18}, 200 + [21] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_17}, 201 + [22] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_16}, 202 + [23] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_15}, 203 + /* DD port */ 204 + [24] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_14}, 205 + [25] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_13}, 206 + [26] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_12}, 207 + [27] = {NV_AON_SLICE_INVALID, 0}, 208 + [28] = {NV_AON_SLICE_INVALID, 0}, 209 + [29] = {NV_AON_SLICE_INVALID, 0}, 210 + [30] = {NV_AON_SLICE_INVALID, 0}, 211 + [31] = {NV_AON_SLICE_INVALID, 0}, 212 + /* EE port */ 213 + [32] = {1, NV_AON_HTE_SLICE1_IRQ_GPIO_29}, 214 + [33] = {1, NV_AON_HTE_SLICE1_IRQ_GPIO_28}, 215 + [34] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_27}, 216 + [35] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_26}, 217 + [36] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_25}, 218 + [37] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_24}, 219 + [38] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_23}, 220 + [39] = {NV_AON_SLICE_INVALID, 0}, 221 + }; 222 + 223 + static const struct tegra_hte_data aon_hte = { 224 + .map_sz = ARRAY_SIZE(tegra194_aon_gpio_map), 225 + .map = tegra194_aon_gpio_map, 226 + .sec_map_sz = ARRAY_SIZE(tegra194_aon_gpio_sec_map), 227 + .sec_map = tegra194_aon_gpio_sec_map, 228 + .type = HTE_TEGRA_TYPE_GPIO, 229 + }; 230 + 231 + static const struct tegra_hte_data lic_hte = { 232 + .map_sz = 0, 233 + .map = NULL, 234 + .type = HTE_TEGRA_TYPE_LIC, 235 + }; 236 + 237 + static inline u32 tegra_hte_readl(struct tegra_hte_soc *hte, u32 reg) 238 + { 239 + return readl(hte->regs + reg); 240 + } 241 + 242 + static inline void tegra_hte_writel(struct tegra_hte_soc *hte, u32 reg, 243 + u32 val) 244 + { 245 + writel(val, hte->regs + reg); 246 + } 247 + 248 + static int tegra_hte_map_to_line_id(u32 eid, 249 + const struct tegra_hte_line_mapped *m, 250 + u32 map_sz, u32 *mapped) 251 + { 252 + 253 + if (m) { 254 + if (eid > map_sz) 255 + return -EINVAL; 256 + if (m[eid].slice == NV_AON_SLICE_INVALID) 257 + return -EINVAL; 258 + 259 + *mapped = (m[eid].slice << 5) + m[eid].bit_index; 260 + } else { 261 + *mapped = eid; 262 + } 263 + 264 + return 0; 265 + } 266 + 267 + static int tegra_hte_line_xlate(struct hte_chip *gc, 268 + const struct of_phandle_args *args, 269 + struct hte_ts_desc *desc, u32 *xlated_id) 270 + { 271 + int ret = 0; 272 + u32 line_id; 273 + struct tegra_hte_soc *gs; 274 + const struct tegra_hte_line_mapped *map = NULL; 275 + u32 map_sz = 0; 276 + 277 + if (!gc || !desc || !xlated_id) 278 + return -EINVAL; 279 + 280 + if (args) { 281 + if (gc->of_hte_n_cells < 1) 282 + return -EINVAL; 283 + 284 + if (args->args_count != gc->of_hte_n_cells) 285 + return -EINVAL; 286 + 287 + desc->attr.line_id = args->args[0]; 288 + } 289 + 290 + gs = gc->data; 291 + if (!gs || !gs->prov_data) 292 + return -EINVAL; 293 + 294 + /* 295 + * 296 + * There are two paths GPIO consumers can take as follows: 297 + * 1) The consumer (gpiolib-cdev for example) which uses GPIO global 298 + * number which gets assigned run time. 299 + * 2) The consumer passing GPIO from the DT which is assigned 300 + * statically for example by using TEGRA194_AON_GPIO gpio DT binding. 301 + * 302 + * The code below addresses both the consumer use cases and maps into 303 + * HTE/GTE namespace. 304 + */ 305 + if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO && !args) { 306 + line_id = desc->attr.line_id - gs->c->base; 307 + map = gs->prov_data->map; 308 + map_sz = gs->prov_data->map_sz; 309 + } else if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO && args) { 310 + line_id = desc->attr.line_id; 311 + map = gs->prov_data->sec_map; 312 + map_sz = gs->prov_data->sec_map_sz; 313 + } else { 314 + line_id = desc->attr.line_id; 315 + } 316 + 317 + ret = tegra_hte_map_to_line_id(line_id, map, map_sz, xlated_id); 318 + if (ret < 0) { 319 + dev_err(gc->dev, "line_id:%u mapping failed\n", 320 + desc->attr.line_id); 321 + return ret; 322 + } 323 + 324 + if (*xlated_id > gc->nlines) 325 + return -EINVAL; 326 + 327 + dev_dbg(gc->dev, "requested id:%u, xlated id:%u\n", 328 + desc->attr.line_id, *xlated_id); 329 + 330 + return 0; 331 + } 332 + 333 + static int tegra_hte_line_xlate_plat(struct hte_chip *gc, 334 + struct hte_ts_desc *desc, u32 *xlated_id) 335 + { 336 + return tegra_hte_line_xlate(gc, NULL, desc, xlated_id); 337 + } 338 + 339 + static int tegra_hte_en_dis_common(struct hte_chip *chip, u32 line_id, bool en) 340 + { 341 + u32 slice, sl_bit_shift, line_bit, val, reg; 342 + struct tegra_hte_soc *gs; 343 + 344 + sl_bit_shift = __builtin_ctz(HTE_SLICE_SIZE); 345 + 346 + if (!chip) 347 + return -EINVAL; 348 + 349 + gs = chip->data; 350 + 351 + if (line_id > chip->nlines) { 352 + dev_err(chip->dev, 353 + "line id: %u is not supported by this controller\n", 354 + line_id); 355 + return -EINVAL; 356 + } 357 + 358 + slice = line_id >> sl_bit_shift; 359 + line_bit = line_id & (HTE_SLICE_SIZE - 1); 360 + reg = (slice << sl_bit_shift) + HTE_SLICE0_TETEN; 361 + 362 + spin_lock(&gs->sl[slice].s_lock); 363 + 364 + if (test_bit(HTE_SUSPEND, &gs->sl[slice].flags)) { 365 + spin_unlock(&gs->sl[slice].s_lock); 366 + dev_dbg(chip->dev, "device suspended"); 367 + return -EBUSY; 368 + } 369 + 370 + val = tegra_hte_readl(gs, reg); 371 + if (en) 372 + val = val | (1 << line_bit); 373 + else 374 + val = val & (~(1 << line_bit)); 375 + tegra_hte_writel(gs, reg, val); 376 + 377 + spin_unlock(&gs->sl[slice].s_lock); 378 + 379 + dev_dbg(chip->dev, "line: %u, slice %u, line_bit %u, reg:0x%x\n", 380 + line_id, slice, line_bit, reg); 381 + 382 + return 0; 383 + } 384 + 385 + static int tegra_hte_enable(struct hte_chip *chip, u32 line_id) 386 + { 387 + if (!chip) 388 + return -EINVAL; 389 + 390 + return tegra_hte_en_dis_common(chip, line_id, true); 391 + } 392 + 393 + static int tegra_hte_disable(struct hte_chip *chip, u32 line_id) 394 + { 395 + if (!chip) 396 + return -EINVAL; 397 + 398 + return tegra_hte_en_dis_common(chip, line_id, false); 399 + } 400 + 401 + static int tegra_hte_request(struct hte_chip *chip, struct hte_ts_desc *desc, 402 + u32 line_id) 403 + { 404 + int ret; 405 + struct tegra_hte_soc *gs; 406 + struct hte_line_attr *attr; 407 + 408 + if (!chip || !chip->data || !desc) 409 + return -EINVAL; 410 + 411 + gs = chip->data; 412 + attr = &desc->attr; 413 + 414 + if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO) { 415 + if (!attr->line_data) 416 + return -EINVAL; 417 + 418 + ret = gpiod_enable_hw_timestamp_ns(attr->line_data, 419 + attr->edge_flags); 420 + if (ret) 421 + return ret; 422 + 423 + gs->line_data[line_id].data = attr->line_data; 424 + gs->line_data[line_id].flags = attr->edge_flags; 425 + } 426 + 427 + return tegra_hte_en_dis_common(chip, line_id, true); 428 + } 429 + 430 + static int tegra_hte_release(struct hte_chip *chip, struct hte_ts_desc *desc, 431 + u32 line_id) 432 + { 433 + struct tegra_hte_soc *gs; 434 + struct hte_line_attr *attr; 435 + int ret; 436 + 437 + if (!chip || !chip->data || !desc) 438 + return -EINVAL; 439 + 440 + gs = chip->data; 441 + attr = &desc->attr; 442 + 443 + if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO) { 444 + ret = gpiod_disable_hw_timestamp_ns(attr->line_data, 445 + gs->line_data[line_id].flags); 446 + if (ret) 447 + return ret; 448 + 449 + gs->line_data[line_id].data = NULL; 450 + gs->line_data[line_id].flags = 0; 451 + } 452 + 453 + return tegra_hte_en_dis_common(chip, line_id, false); 454 + } 455 + 456 + static int tegra_hte_clk_src_info(struct hte_chip *chip, 457 + struct hte_clk_info *ci) 458 + { 459 + (void)chip; 460 + 461 + if (!ci) 462 + return -EINVAL; 463 + 464 + ci->hz = HTE_TS_CLK_RATE_HZ; 465 + ci->type = CLOCK_MONOTONIC; 466 + 467 + return 0; 468 + } 469 + 470 + static int tegra_hte_get_level(struct tegra_hte_soc *gs, u32 line_id) 471 + { 472 + struct gpio_desc *desc; 473 + 474 + if (gs->prov_data->type == HTE_TEGRA_TYPE_GPIO) { 475 + desc = gs->line_data[line_id].data; 476 + if (desc) 477 + return gpiod_get_raw_value(desc); 478 + } 479 + 480 + return -1; 481 + } 482 + 483 + static void tegra_hte_read_fifo(struct tegra_hte_soc *gs) 484 + { 485 + u32 tsh, tsl, src, pv, cv, acv, slice, bit_index, line_id; 486 + u64 tsc; 487 + struct hte_ts_data el; 488 + 489 + while ((tegra_hte_readl(gs, HTE_TESTATUS) >> 490 + HTE_TESTATUS_OCCUPANCY_SHIFT) & 491 + HTE_TESTATUS_OCCUPANCY_MASK) { 492 + tsh = tegra_hte_readl(gs, HTE_TETSCH); 493 + tsl = tegra_hte_readl(gs, HTE_TETSCL); 494 + tsc = (((u64)tsh << 32) | tsl); 495 + 496 + src = tegra_hte_readl(gs, HTE_TESRC); 497 + slice = (src >> HTE_TESRC_SLICE_SHIFT) & 498 + HTE_TESRC_SLICE_DEFAULT_MASK; 499 + 500 + pv = tegra_hte_readl(gs, HTE_TEPCV); 501 + cv = tegra_hte_readl(gs, HTE_TECCV); 502 + acv = pv ^ cv; 503 + while (acv) { 504 + bit_index = __builtin_ctz(acv); 505 + line_id = bit_index + (slice << 5); 506 + el.tsc = tsc << HTE_TS_NS_SHIFT; 507 + el.raw_level = tegra_hte_get_level(gs, line_id); 508 + hte_push_ts_ns(gs->chip, line_id, &el); 509 + acv &= ~BIT(bit_index); 510 + } 511 + tegra_hte_writel(gs, HTE_TECMD, HTE_TECMD_CMD_POP); 512 + } 513 + } 514 + 515 + static irqreturn_t tegra_hte_isr(int irq, void *dev_id) 516 + { 517 + struct tegra_hte_soc *gs = dev_id; 518 + (void)irq; 519 + 520 + tegra_hte_read_fifo(gs); 521 + 522 + return IRQ_HANDLED; 523 + } 524 + 525 + static bool tegra_hte_match_from_linedata(const struct hte_chip *chip, 526 + const struct hte_ts_desc *hdesc) 527 + { 528 + struct tegra_hte_soc *hte_dev = chip->data; 529 + 530 + if (!hte_dev || (hte_dev->prov_data->type != HTE_TEGRA_TYPE_GPIO)) 531 + return false; 532 + 533 + return hte_dev->c == gpiod_to_chip(hdesc->attr.line_data); 534 + } 535 + 536 + static const struct of_device_id tegra_hte_of_match[] = { 537 + { .compatible = "nvidia,tegra194-gte-lic", .data = &lic_hte}, 538 + { .compatible = "nvidia,tegra194-gte-aon", .data = &aon_hte}, 539 + { } 540 + }; 541 + MODULE_DEVICE_TABLE(of, tegra_hte_of_match); 542 + 543 + static const struct hte_ops g_ops = { 544 + .request = tegra_hte_request, 545 + .release = tegra_hte_release, 546 + .enable = tegra_hte_enable, 547 + .disable = tegra_hte_disable, 548 + .get_clk_src_info = tegra_hte_clk_src_info, 549 + }; 550 + 551 + static void tegra_gte_disable(void *data) 552 + { 553 + struct platform_device *pdev = data; 554 + struct tegra_hte_soc *gs = dev_get_drvdata(&pdev->dev); 555 + 556 + tegra_hte_writel(gs, HTE_TECTRL, 0); 557 + } 558 + 559 + static int tegra_get_gpiochip_from_name(struct gpio_chip *chip, void *data) 560 + { 561 + return !strcmp(chip->label, data); 562 + } 563 + 564 + static int tegra_hte_probe(struct platform_device *pdev) 565 + { 566 + int ret; 567 + u32 i, slices, val = 0; 568 + u32 nlines; 569 + struct device *dev; 570 + struct tegra_hte_soc *hte_dev; 571 + struct hte_chip *gc; 572 + 573 + dev = &pdev->dev; 574 + 575 + ret = of_property_read_u32(dev->of_node, "nvidia,slices", &slices); 576 + if (ret != 0) { 577 + dev_err(dev, "Could not read slices\n"); 578 + return -EINVAL; 579 + } 580 + nlines = slices << 5; 581 + 582 + hte_dev = devm_kzalloc(dev, sizeof(*hte_dev), GFP_KERNEL); 583 + if (!hte_dev) 584 + return -ENOMEM; 585 + 586 + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); 587 + if (!gc) 588 + return -ENOMEM; 589 + 590 + dev_set_drvdata(&pdev->dev, hte_dev); 591 + hte_dev->prov_data = of_device_get_match_data(&pdev->dev); 592 + 593 + hte_dev->regs = devm_platform_ioremap_resource(pdev, 0); 594 + if (IS_ERR(hte_dev->regs)) 595 + return PTR_ERR(hte_dev->regs); 596 + 597 + ret = of_property_read_u32(dev->of_node, "nvidia,int-threshold", 598 + &hte_dev->itr_thrshld); 599 + if (ret != 0) 600 + hte_dev->itr_thrshld = 1; 601 + 602 + hte_dev->sl = devm_kcalloc(dev, slices, sizeof(*hte_dev->sl), 603 + GFP_KERNEL); 604 + if (!hte_dev->sl) 605 + return -ENOMEM; 606 + 607 + ret = platform_get_irq(pdev, 0); 608 + if (ret < 0) { 609 + dev_err_probe(dev, ret, "failed to get irq\n"); 610 + return ret; 611 + } 612 + hte_dev->hte_irq = ret; 613 + ret = devm_request_irq(dev, hte_dev->hte_irq, tegra_hte_isr, 0, 614 + dev_name(dev), hte_dev); 615 + if (ret < 0) { 616 + dev_err(dev, "request irq failed.\n"); 617 + return ret; 618 + } 619 + 620 + gc->nlines = nlines; 621 + gc->ops = &g_ops; 622 + gc->dev = dev; 623 + gc->data = hte_dev; 624 + gc->xlate_of = tegra_hte_line_xlate; 625 + gc->xlate_plat = tegra_hte_line_xlate_plat; 626 + gc->of_hte_n_cells = 1; 627 + 628 + if (hte_dev->prov_data && 629 + hte_dev->prov_data->type == HTE_TEGRA_TYPE_GPIO) { 630 + hte_dev->line_data = devm_kcalloc(dev, nlines, 631 + sizeof(*hte_dev->line_data), 632 + GFP_KERNEL); 633 + if (!hte_dev->line_data) 634 + return -ENOMEM; 635 + 636 + gc->match_from_linedata = tegra_hte_match_from_linedata; 637 + 638 + hte_dev->c = gpiochip_find("tegra194-gpio-aon", 639 + tegra_get_gpiochip_from_name); 640 + if (!hte_dev->c) 641 + return dev_err_probe(dev, -EPROBE_DEFER, 642 + "wait for gpio controller\n"); 643 + } 644 + 645 + hte_dev->chip = gc; 646 + 647 + ret = devm_hte_register_chip(hte_dev->chip); 648 + if (ret) { 649 + dev_err(gc->dev, "hte chip register failed"); 650 + return ret; 651 + } 652 + 653 + for (i = 0; i < slices; i++) { 654 + hte_dev->sl[i].flags = 0; 655 + spin_lock_init(&hte_dev->sl[i].s_lock); 656 + } 657 + 658 + val = HTE_TECTRL_ENABLE_ENABLE | 659 + (HTE_TECTRL_INTR_ENABLE << HTE_TECTRL_INTR_SHIFT) | 660 + (hte_dev->itr_thrshld << HTE_TECTRL_OCCU_SHIFT); 661 + tegra_hte_writel(hte_dev, HTE_TECTRL, val); 662 + 663 + ret = devm_add_action_or_reset(&pdev->dev, tegra_gte_disable, pdev); 664 + if (ret) 665 + return ret; 666 + 667 + dev_dbg(gc->dev, "lines: %d, slices:%d", gc->nlines, slices); 668 + 669 + return 0; 670 + } 671 + 672 + static int __maybe_unused tegra_hte_resume_early(struct device *dev) 673 + { 674 + u32 i; 675 + struct tegra_hte_soc *gs = dev_get_drvdata(dev); 676 + u32 slices = gs->chip->nlines / NV_LINES_IN_SLICE; 677 + u32 sl_bit_shift = __builtin_ctz(HTE_SLICE_SIZE); 678 + 679 + tegra_hte_writel(gs, HTE_TECTRL, gs->conf_rval); 680 + 681 + for (i = 0; i < slices; i++) { 682 + spin_lock(&gs->sl[i].s_lock); 683 + tegra_hte_writel(gs, 684 + ((i << sl_bit_shift) + HTE_SLICE0_TETEN), 685 + gs->sl[i].r_val); 686 + clear_bit(HTE_SUSPEND, &gs->sl[i].flags); 687 + spin_unlock(&gs->sl[i].s_lock); 688 + } 689 + 690 + return 0; 691 + } 692 + 693 + static int __maybe_unused tegra_hte_suspend_late(struct device *dev) 694 + { 695 + u32 i; 696 + struct tegra_hte_soc *gs = dev_get_drvdata(dev); 697 + u32 slices = gs->chip->nlines / NV_LINES_IN_SLICE; 698 + u32 sl_bit_shift = __builtin_ctz(HTE_SLICE_SIZE); 699 + 700 + gs->conf_rval = tegra_hte_readl(gs, HTE_TECTRL); 701 + for (i = 0; i < slices; i++) { 702 + spin_lock(&gs->sl[i].s_lock); 703 + gs->sl[i].r_val = tegra_hte_readl(gs, 704 + ((i << sl_bit_shift) + HTE_SLICE0_TETEN)); 705 + set_bit(HTE_SUSPEND, &gs->sl[i].flags); 706 + spin_unlock(&gs->sl[i].s_lock); 707 + } 708 + 709 + return 0; 710 + } 711 + 712 + static const struct dev_pm_ops tegra_hte_pm = { 713 + SET_LATE_SYSTEM_SLEEP_PM_OPS(tegra_hte_suspend_late, 714 + tegra_hte_resume_early) 715 + }; 716 + 717 + static struct platform_driver tegra_hte_driver = { 718 + .probe = tegra_hte_probe, 719 + .driver = { 720 + .name = "tegra_hte", 721 + .pm = &tegra_hte_pm, 722 + .of_match_table = tegra_hte_of_match, 723 + }, 724 + }; 725 + 726 + module_platform_driver(tegra_hte_driver); 727 + 728 + MODULE_AUTHOR("Dipen Patel <dipenp@nvidia.com>"); 729 + MODULE_DESCRIPTION("NVIDIA Tegra HTE (Hardware Timestamping Engine) driver"); 730 + MODULE_LICENSE("GPL");
+947
drivers/hte/hte.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2021-2022 NVIDIA Corporation 4 + * 5 + * Author: Dipen Patel <dipenp@nvidia.com> 6 + */ 7 + 8 + #include <linux/kernel.h> 9 + #include <linux/module.h> 10 + #include <linux/err.h> 11 + #include <linux/slab.h> 12 + #include <linux/of.h> 13 + #include <linux/of_device.h> 14 + #include <linux/mutex.h> 15 + #include <linux/uaccess.h> 16 + #include <linux/hte.h> 17 + #include <linux/delay.h> 18 + #include <linux/debugfs.h> 19 + 20 + #define HTE_TS_NAME_LEN 10 21 + 22 + /* Global list of the HTE devices */ 23 + static DEFINE_SPINLOCK(hte_lock); 24 + static LIST_HEAD(hte_devices); 25 + 26 + enum { 27 + HTE_TS_REGISTERED, 28 + HTE_TS_REQ, 29 + HTE_TS_DISABLE, 30 + HTE_TS_QUEUE_WK, 31 + }; 32 + 33 + /** 34 + * struct hte_ts_info - Information related to requested timestamp. 35 + * 36 + * @xlated_id: Timestamp ID as understood between HTE subsys and HTE provider, 37 + * See xlate callback API. 38 + * @flags: Flags holding state information. 39 + * @hte_cb_flags: Callback related flags. 40 + * @seq: Timestamp sequence counter. 41 + * @line_name: HTE allocated line name. 42 + * @free_attr_name: If set, free the attr name. 43 + * @cb: A nonsleeping callback function provided by clients. 44 + * @tcb: A secondary sleeping callback function provided by clients. 45 + * @dropped_ts: Dropped timestamps. 46 + * @slock: Spin lock to synchronize between disable/enable, 47 + * request/release APIs. 48 + * @cb_work: callback workqueue, used when tcb is specified. 49 + * @req_mlock: Lock during timestamp request/release APIs. 50 + * @ts_dbg_root: Root for the debug fs. 51 + * @gdev: HTE abstract device that this timestamp information belongs to. 52 + * @cl_data: Client specific data. 53 + */ 54 + struct hte_ts_info { 55 + u32 xlated_id; 56 + unsigned long flags; 57 + unsigned long hte_cb_flags; 58 + u64 seq; 59 + char *line_name; 60 + bool free_attr_name; 61 + hte_ts_cb_t cb; 62 + hte_ts_sec_cb_t tcb; 63 + atomic_t dropped_ts; 64 + spinlock_t slock; 65 + struct work_struct cb_work; 66 + struct mutex req_mlock; 67 + struct dentry *ts_dbg_root; 68 + struct hte_device *gdev; 69 + void *cl_data; 70 + }; 71 + 72 + /** 73 + * struct hte_device - HTE abstract device 74 + * @nlines: Number of entities this device supports. 75 + * @ts_req: Total number of entities requested. 76 + * @sdev: Device used at various debug prints. 77 + * @dbg_root: Root directory for debug fs. 78 + * @list: List node to store hte_device for each provider. 79 + * @chip: HTE chip providing this HTE device. 80 + * @owner: helps prevent removal of modules when in use. 81 + * @ei: Timestamp information. 82 + */ 83 + struct hte_device { 84 + u32 nlines; 85 + atomic_t ts_req; 86 + struct device *sdev; 87 + struct dentry *dbg_root; 88 + struct list_head list; 89 + struct hte_chip *chip; 90 + struct module *owner; 91 + struct hte_ts_info ei[]; 92 + }; 93 + 94 + #ifdef CONFIG_DEBUG_FS 95 + 96 + static struct dentry *hte_root; 97 + 98 + static int __init hte_subsys_dbgfs_init(void) 99 + { 100 + /* creates /sys/kernel/debug/hte/ */ 101 + hte_root = debugfs_create_dir("hte", NULL); 102 + 103 + return 0; 104 + } 105 + subsys_initcall(hte_subsys_dbgfs_init); 106 + 107 + static void hte_chip_dbgfs_init(struct hte_device *gdev) 108 + { 109 + const struct hte_chip *chip = gdev->chip; 110 + const char *name = chip->name ? chip->name : dev_name(chip->dev); 111 + 112 + gdev->dbg_root = debugfs_create_dir(name, hte_root); 113 + 114 + debugfs_create_atomic_t("ts_requested", 0444, gdev->dbg_root, 115 + &gdev->ts_req); 116 + debugfs_create_u32("total_ts", 0444, gdev->dbg_root, 117 + &gdev->nlines); 118 + } 119 + 120 + static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei) 121 + { 122 + if (!ei->gdev->dbg_root || !name) 123 + return; 124 + 125 + ei->ts_dbg_root = debugfs_create_dir(name, ei->gdev->dbg_root); 126 + 127 + debugfs_create_atomic_t("dropped_timestamps", 0444, ei->ts_dbg_root, 128 + &ei->dropped_ts); 129 + } 130 + 131 + #else 132 + 133 + static void hte_chip_dbgfs_init(struct hte_device *gdev) 134 + { 135 + } 136 + 137 + static void hte_ts_dbgfs_init(const char *name, struct hte_ts_info *ei) 138 + { 139 + } 140 + 141 + #endif 142 + 143 + /** 144 + * hte_ts_put() - Release and disable timestamp for the given desc. 145 + * 146 + * @desc: timestamp descriptor. 147 + * 148 + * Context: debugfs_remove_recursive() function call may use sleeping locks, 149 + * not suitable from atomic context. 150 + * Returns: 0 on success or a negative error code on failure. 151 + */ 152 + int hte_ts_put(struct hte_ts_desc *desc) 153 + { 154 + int ret = 0; 155 + unsigned long flag; 156 + struct hte_device *gdev; 157 + struct hte_ts_info *ei; 158 + 159 + if (!desc) 160 + return -EINVAL; 161 + 162 + ei = desc->hte_data; 163 + 164 + if (!ei || !ei->gdev) 165 + return -EINVAL; 166 + 167 + gdev = ei->gdev; 168 + 169 + mutex_lock(&ei->req_mlock); 170 + 171 + if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && 172 + !test_bit(HTE_TS_REGISTERED, &ei->flags))) { 173 + dev_info(gdev->sdev, "id:%d is not requested\n", 174 + desc->attr.line_id); 175 + ret = -EINVAL; 176 + goto unlock; 177 + } 178 + 179 + if (unlikely(!test_bit(HTE_TS_REQ, &ei->flags) && 180 + test_bit(HTE_TS_REGISTERED, &ei->flags))) { 181 + dev_info(gdev->sdev, "id:%d is registered but not requested\n", 182 + desc->attr.line_id); 183 + ret = -EINVAL; 184 + goto unlock; 185 + } 186 + 187 + if (test_bit(HTE_TS_REQ, &ei->flags) && 188 + !test_bit(HTE_TS_REGISTERED, &ei->flags)) { 189 + clear_bit(HTE_TS_REQ, &ei->flags); 190 + desc->hte_data = NULL; 191 + ret = 0; 192 + goto mod_put; 193 + } 194 + 195 + ret = gdev->chip->ops->release(gdev->chip, desc, ei->xlated_id); 196 + if (ret) { 197 + dev_err(gdev->sdev, "id: %d free failed\n", 198 + desc->attr.line_id); 199 + goto unlock; 200 + } 201 + 202 + kfree(ei->line_name); 203 + if (ei->free_attr_name) 204 + kfree_const(desc->attr.name); 205 + 206 + debugfs_remove_recursive(ei->ts_dbg_root); 207 + 208 + spin_lock_irqsave(&ei->slock, flag); 209 + 210 + if (test_bit(HTE_TS_QUEUE_WK, &ei->flags)) { 211 + spin_unlock_irqrestore(&ei->slock, flag); 212 + flush_work(&ei->cb_work); 213 + spin_lock_irqsave(&ei->slock, flag); 214 + } 215 + 216 + atomic_dec(&gdev->ts_req); 217 + atomic_set(&ei->dropped_ts, 0); 218 + 219 + ei->seq = 1; 220 + ei->flags = 0; 221 + desc->hte_data = NULL; 222 + 223 + spin_unlock_irqrestore(&ei->slock, flag); 224 + 225 + ei->cb = NULL; 226 + ei->tcb = NULL; 227 + ei->cl_data = NULL; 228 + 229 + mod_put: 230 + module_put(gdev->owner); 231 + unlock: 232 + mutex_unlock(&ei->req_mlock); 233 + dev_dbg(gdev->sdev, "release id: %d\n", desc->attr.line_id); 234 + 235 + return ret; 236 + } 237 + EXPORT_SYMBOL_GPL(hte_ts_put); 238 + 239 + static int hte_ts_dis_en_common(struct hte_ts_desc *desc, bool en) 240 + { 241 + u32 ts_id; 242 + struct hte_device *gdev; 243 + struct hte_ts_info *ei; 244 + int ret; 245 + unsigned long flag; 246 + 247 + if (!desc) 248 + return -EINVAL; 249 + 250 + ei = desc->hte_data; 251 + 252 + if (!ei || !ei->gdev) 253 + return -EINVAL; 254 + 255 + gdev = ei->gdev; 256 + ts_id = desc->attr.line_id; 257 + 258 + mutex_lock(&ei->req_mlock); 259 + 260 + if (!test_bit(HTE_TS_REGISTERED, &ei->flags)) { 261 + dev_dbg(gdev->sdev, "id:%d is not registered", ts_id); 262 + ret = -EUSERS; 263 + goto out; 264 + } 265 + 266 + spin_lock_irqsave(&ei->slock, flag); 267 + 268 + if (en) { 269 + if (!test_bit(HTE_TS_DISABLE, &ei->flags)) { 270 + ret = 0; 271 + goto out_unlock; 272 + } 273 + 274 + spin_unlock_irqrestore(&ei->slock, flag); 275 + ret = gdev->chip->ops->enable(gdev->chip, ei->xlated_id); 276 + if (ret) { 277 + dev_warn(gdev->sdev, "id: %d enable failed\n", 278 + ts_id); 279 + goto out; 280 + } 281 + 282 + spin_lock_irqsave(&ei->slock, flag); 283 + clear_bit(HTE_TS_DISABLE, &ei->flags); 284 + } else { 285 + if (test_bit(HTE_TS_DISABLE, &ei->flags)) { 286 + ret = 0; 287 + goto out_unlock; 288 + } 289 + 290 + spin_unlock_irqrestore(&ei->slock, flag); 291 + ret = gdev->chip->ops->disable(gdev->chip, ei->xlated_id); 292 + if (ret) { 293 + dev_warn(gdev->sdev, "id: %d disable failed\n", 294 + ts_id); 295 + goto out; 296 + } 297 + 298 + spin_lock_irqsave(&ei->slock, flag); 299 + set_bit(HTE_TS_DISABLE, &ei->flags); 300 + } 301 + 302 + out_unlock: 303 + spin_unlock_irqrestore(&ei->slock, flag); 304 + out: 305 + mutex_unlock(&ei->req_mlock); 306 + return ret; 307 + } 308 + 309 + /** 310 + * hte_disable_ts() - Disable timestamp on given descriptor. 311 + * 312 + * The API does not release any resources associated with desc. 313 + * 314 + * @desc: ts descriptor, this is the same as returned by the request API. 315 + * 316 + * Context: Holds mutex lock, not suitable from atomic context. 317 + * Returns: 0 on success or a negative error code on failure. 318 + */ 319 + int hte_disable_ts(struct hte_ts_desc *desc) 320 + { 321 + return hte_ts_dis_en_common(desc, false); 322 + } 323 + EXPORT_SYMBOL_GPL(hte_disable_ts); 324 + 325 + /** 326 + * hte_enable_ts() - Enable timestamp on given descriptor. 327 + * 328 + * @desc: ts descriptor, this is the same as returned by the request API. 329 + * 330 + * Context: Holds mutex lock, not suitable from atomic context. 331 + * Returns: 0 on success or a negative error code on failure. 332 + */ 333 + int hte_enable_ts(struct hte_ts_desc *desc) 334 + { 335 + return hte_ts_dis_en_common(desc, true); 336 + } 337 + EXPORT_SYMBOL_GPL(hte_enable_ts); 338 + 339 + static void hte_do_cb_work(struct work_struct *w) 340 + { 341 + unsigned long flag; 342 + struct hte_ts_info *ei = container_of(w, struct hte_ts_info, cb_work); 343 + 344 + if (unlikely(!ei->tcb)) 345 + return; 346 + 347 + ei->tcb(ei->cl_data); 348 + 349 + spin_lock_irqsave(&ei->slock, flag); 350 + clear_bit(HTE_TS_QUEUE_WK, &ei->flags); 351 + spin_unlock_irqrestore(&ei->slock, flag); 352 + } 353 + 354 + static int __hte_req_ts(struct hte_ts_desc *desc, hte_ts_cb_t cb, 355 + hte_ts_sec_cb_t tcb, void *data) 356 + { 357 + int ret; 358 + struct hte_device *gdev; 359 + struct hte_ts_info *ei = desc->hte_data; 360 + 361 + gdev = ei->gdev; 362 + /* 363 + * There is a chance that multiple consumers requesting same entity, 364 + * lock here. 365 + */ 366 + mutex_lock(&ei->req_mlock); 367 + 368 + if (test_bit(HTE_TS_REGISTERED, &ei->flags) || 369 + !test_bit(HTE_TS_REQ, &ei->flags)) { 370 + dev_dbg(gdev->chip->dev, "id:%u req failed\n", 371 + desc->attr.line_id); 372 + ret = -EUSERS; 373 + goto unlock; 374 + } 375 + 376 + ei->cb = cb; 377 + ei->tcb = tcb; 378 + if (tcb) 379 + INIT_WORK(&ei->cb_work, hte_do_cb_work); 380 + 381 + ret = gdev->chip->ops->request(gdev->chip, desc, ei->xlated_id); 382 + if (ret < 0) { 383 + dev_err(gdev->chip->dev, "ts request failed\n"); 384 + goto unlock; 385 + } 386 + 387 + ei->cl_data = data; 388 + ei->seq = 1; 389 + 390 + atomic_inc(&gdev->ts_req); 391 + 392 + ei->line_name = NULL; 393 + if (!desc->attr.name) { 394 + ei->line_name = kzalloc(HTE_TS_NAME_LEN, GFP_KERNEL); 395 + if (ei->line_name) 396 + scnprintf(ei->line_name, HTE_TS_NAME_LEN, "ts_%u", 397 + desc->attr.line_id); 398 + } 399 + 400 + hte_ts_dbgfs_init(desc->attr.name == NULL ? 401 + ei->line_name : desc->attr.name, ei); 402 + set_bit(HTE_TS_REGISTERED, &ei->flags); 403 + 404 + dev_dbg(gdev->chip->dev, "id: %u, xlated id:%u", 405 + desc->attr.line_id, ei->xlated_id); 406 + 407 + ret = 0; 408 + 409 + unlock: 410 + mutex_unlock(&ei->req_mlock); 411 + 412 + return ret; 413 + } 414 + 415 + static int hte_bind_ts_info_locked(struct hte_ts_info *ei, 416 + struct hte_ts_desc *desc, u32 x_id) 417 + { 418 + int ret = 0; 419 + 420 + mutex_lock(&ei->req_mlock); 421 + 422 + if (test_bit(HTE_TS_REQ, &ei->flags)) { 423 + dev_dbg(ei->gdev->chip->dev, "id:%u is already requested\n", 424 + desc->attr.line_id); 425 + ret = -EUSERS; 426 + goto out; 427 + } 428 + 429 + set_bit(HTE_TS_REQ, &ei->flags); 430 + desc->hte_data = ei; 431 + ei->xlated_id = x_id; 432 + 433 + out: 434 + mutex_unlock(&ei->req_mlock); 435 + 436 + return ret; 437 + } 438 + 439 + static struct hte_device *of_node_to_htedevice(struct device_node *np) 440 + { 441 + struct hte_device *gdev; 442 + 443 + spin_lock(&hte_lock); 444 + 445 + list_for_each_entry(gdev, &hte_devices, list) 446 + if (gdev->chip && gdev->chip->dev && 447 + gdev->chip->dev->of_node == np) { 448 + spin_unlock(&hte_lock); 449 + return gdev; 450 + } 451 + 452 + spin_unlock(&hte_lock); 453 + 454 + return ERR_PTR(-ENODEV); 455 + } 456 + 457 + static struct hte_device *hte_find_dev_from_linedata(struct hte_ts_desc *desc) 458 + { 459 + struct hte_device *gdev; 460 + 461 + spin_lock(&hte_lock); 462 + 463 + list_for_each_entry(gdev, &hte_devices, list) 464 + if (gdev->chip && gdev->chip->match_from_linedata) { 465 + if (!gdev->chip->match_from_linedata(gdev->chip, desc)) 466 + continue; 467 + spin_unlock(&hte_lock); 468 + return gdev; 469 + } 470 + 471 + spin_unlock(&hte_lock); 472 + 473 + return ERR_PTR(-ENODEV); 474 + } 475 + 476 + /** 477 + * of_hte_req_count - Return the number of entities to timestamp. 478 + * 479 + * The function returns the total count of the requested entities to timestamp 480 + * by parsing device tree. 481 + * 482 + * @dev: The HTE consumer. 483 + * 484 + * Returns: Positive number on success, -ENOENT if no entries, 485 + * -EINVAL for other errors. 486 + */ 487 + int of_hte_req_count(struct device *dev) 488 + { 489 + int count; 490 + 491 + if (!dev || !dev->of_node) 492 + return -EINVAL; 493 + 494 + count = of_count_phandle_with_args(dev->of_node, "timestamps", 495 + "#timestamp-cells"); 496 + 497 + return count ? count : -ENOENT; 498 + } 499 + EXPORT_SYMBOL_GPL(of_hte_req_count); 500 + 501 + static inline struct hte_device *hte_get_dev(struct hte_ts_desc *desc) 502 + { 503 + return hte_find_dev_from_linedata(desc); 504 + } 505 + 506 + static struct hte_device *hte_of_get_dev(struct device *dev, 507 + struct hte_ts_desc *desc, 508 + int index, 509 + struct of_phandle_args *args, 510 + bool *free_name) 511 + { 512 + int ret; 513 + struct device_node *np; 514 + char *temp; 515 + 516 + if (!dev->of_node) 517 + return ERR_PTR(-EINVAL); 518 + 519 + np = dev->of_node; 520 + 521 + if (!of_find_property(np, "timestamp-names", NULL)) { 522 + /* Let hte core construct it during request time */ 523 + desc->attr.name = NULL; 524 + } else { 525 + ret = of_property_read_string_index(np, "timestamp-names", 526 + index, &desc->attr.name); 527 + if (ret) { 528 + pr_err("can't parse \"timestamp-names\" property\n"); 529 + return ERR_PTR(ret); 530 + } 531 + *free_name = false; 532 + if (desc->attr.name) { 533 + temp = skip_spaces(desc->attr.name); 534 + if (!*temp) 535 + desc->attr.name = NULL; 536 + } 537 + } 538 + 539 + ret = of_parse_phandle_with_args(np, "timestamps", "#timestamp-cells", 540 + index, args); 541 + if (ret) { 542 + pr_err("%s(): can't parse \"timestamps\" property\n", 543 + __func__); 544 + return ERR_PTR(ret); 545 + } 546 + 547 + of_node_put(args->np); 548 + 549 + return of_node_to_htedevice(args->np); 550 + } 551 + 552 + /** 553 + * hte_ts_get() - The function to initialize and obtain HTE desc. 554 + * 555 + * The function initializes the consumer provided HTE descriptor. If consumer 556 + * has device tree node, index is used to parse the line id and other details. 557 + * The function needs to be called before using any request APIs. 558 + * 559 + * @dev: HTE consumer/client device, used in case of parsing device tree node. 560 + * @desc: Pre-allocated timestamp descriptor. 561 + * @index: The index will be used as an index to parse line_id from the 562 + * device tree node if node is present. 563 + * 564 + * Context: Holds mutex lock. 565 + * Returns: Returns 0 on success or negative error code on failure. 566 + */ 567 + int hte_ts_get(struct device *dev, struct hte_ts_desc *desc, int index) 568 + { 569 + struct hte_device *gdev; 570 + struct hte_ts_info *ei; 571 + const struct fwnode_handle *fwnode; 572 + struct of_phandle_args args; 573 + u32 xlated_id; 574 + int ret; 575 + bool free_name = false; 576 + 577 + if (!desc) 578 + return -EINVAL; 579 + 580 + fwnode = dev ? dev_fwnode(dev) : NULL; 581 + 582 + if (is_of_node(fwnode)) 583 + gdev = hte_of_get_dev(dev, desc, index, &args, &free_name); 584 + else 585 + gdev = hte_get_dev(desc); 586 + 587 + if (IS_ERR(gdev)) { 588 + pr_err("%s() no hte dev found\n", __func__); 589 + return PTR_ERR(gdev); 590 + } 591 + 592 + if (!try_module_get(gdev->owner)) 593 + return -ENODEV; 594 + 595 + if (!gdev->chip) { 596 + pr_err("%s(): requested id does not have provider\n", 597 + __func__); 598 + ret = -ENODEV; 599 + goto put; 600 + } 601 + 602 + if (is_of_node(fwnode)) { 603 + if (!gdev->chip->xlate_of) 604 + ret = -EINVAL; 605 + else 606 + ret = gdev->chip->xlate_of(gdev->chip, &args, 607 + desc, &xlated_id); 608 + } else { 609 + if (!gdev->chip->xlate_plat) 610 + ret = -EINVAL; 611 + else 612 + ret = gdev->chip->xlate_plat(gdev->chip, desc, 613 + &xlated_id); 614 + } 615 + 616 + if (ret < 0) 617 + goto put; 618 + 619 + ei = &gdev->ei[xlated_id]; 620 + 621 + ret = hte_bind_ts_info_locked(ei, desc, xlated_id); 622 + if (ret) 623 + goto put; 624 + 625 + ei->free_attr_name = free_name; 626 + 627 + return 0; 628 + 629 + put: 630 + module_put(gdev->owner); 631 + return ret; 632 + } 633 + EXPORT_SYMBOL_GPL(hte_ts_get); 634 + 635 + static void __devm_hte_release_ts(void *res) 636 + { 637 + hte_ts_put(res); 638 + } 639 + 640 + /** 641 + * hte_request_ts_ns() - The API to request and enable hardware timestamp in 642 + * nanoseconds. 643 + * 644 + * The entity is provider specific for example, GPIO lines, signals, buses 645 + * etc...The API allocates necessary resources and enables the timestamp. 646 + * 647 + * @desc: Pre-allocated and initialized timestamp descriptor. 648 + * @cb: Callback to push the timestamp data to consumer. 649 + * @tcb: Optional callback. If its provided, subsystem initializes 650 + * workqueue. It is called when cb returns HTE_RUN_SECOND_CB. 651 + * @data: Client data, used during cb and tcb callbacks. 652 + * 653 + * Context: Holds mutex lock. 654 + * Returns: Returns 0 on success or negative error code on failure. 655 + */ 656 + int hte_request_ts_ns(struct hte_ts_desc *desc, hte_ts_cb_t cb, 657 + hte_ts_sec_cb_t tcb, void *data) 658 + { 659 + int ret; 660 + struct hte_ts_info *ei; 661 + 662 + if (!desc || !desc->hte_data || !cb) 663 + return -EINVAL; 664 + 665 + ei = desc->hte_data; 666 + if (!ei || !ei->gdev) 667 + return -EINVAL; 668 + 669 + ret = __hte_req_ts(desc, cb, tcb, data); 670 + if (ret < 0) { 671 + dev_err(ei->gdev->chip->dev, 672 + "failed to request id: %d\n", desc->attr.line_id); 673 + return ret; 674 + } 675 + 676 + return 0; 677 + } 678 + EXPORT_SYMBOL_GPL(hte_request_ts_ns); 679 + 680 + /** 681 + * devm_hte_request_ts_ns() - Resource managed API to request and enable 682 + * hardware timestamp in nanoseconds. 683 + * 684 + * The entity is provider specific for example, GPIO lines, signals, buses 685 + * etc...The API allocates necessary resources and enables the timestamp. It 686 + * deallocates and disables automatically when the consumer exits. 687 + * 688 + * @dev: HTE consumer/client device. 689 + * @desc: Pre-allocated and initialized timestamp descriptor. 690 + * @cb: Callback to push the timestamp data to consumer. 691 + * @tcb: Optional callback. If its provided, subsystem initializes 692 + * workqueue. It is called when cb returns HTE_RUN_SECOND_CB. 693 + * @data: Client data, used during cb and tcb callbacks. 694 + * 695 + * Context: Holds mutex lock. 696 + * Returns: Returns 0 on success or negative error code on failure. 697 + */ 698 + int devm_hte_request_ts_ns(struct device *dev, struct hte_ts_desc *desc, 699 + hte_ts_cb_t cb, hte_ts_sec_cb_t tcb, 700 + void *data) 701 + { 702 + int err; 703 + 704 + if (!dev) 705 + return -EINVAL; 706 + 707 + err = hte_request_ts_ns(desc, cb, tcb, data); 708 + if (err) 709 + return err; 710 + 711 + err = devm_add_action_or_reset(dev, __devm_hte_release_ts, desc); 712 + if (err) 713 + return err; 714 + 715 + return 0; 716 + } 717 + EXPORT_SYMBOL_GPL(devm_hte_request_ts_ns); 718 + 719 + /** 720 + * hte_init_line_attr() - Initialize line attributes. 721 + * 722 + * Zeroes out line attributes and initializes with provided arguments. 723 + * The function needs to be called before calling any consumer facing 724 + * functions. 725 + * 726 + * @desc: Pre-allocated timestamp descriptor. 727 + * @line_id: line id. 728 + * @edge_flags: edge flags related to line_id. 729 + * @name: name of the line. 730 + * @data: line data related to line_id. 731 + * 732 + * Context: Any. 733 + * Returns: 0 on success or negative error code for the failure. 734 + */ 735 + int hte_init_line_attr(struct hte_ts_desc *desc, u32 line_id, 736 + unsigned long edge_flags, const char *name, void *data) 737 + { 738 + if (!desc) 739 + return -EINVAL; 740 + 741 + memset(&desc->attr, 0, sizeof(desc->attr)); 742 + 743 + desc->attr.edge_flags = edge_flags; 744 + desc->attr.line_id = line_id; 745 + desc->attr.line_data = data; 746 + if (name) { 747 + name = kstrdup_const(name, GFP_KERNEL); 748 + if (!name) 749 + return -ENOMEM; 750 + } 751 + 752 + desc->attr.name = name; 753 + 754 + return 0; 755 + } 756 + EXPORT_SYMBOL_GPL(hte_init_line_attr); 757 + 758 + /** 759 + * hte_get_clk_src_info() - Get the clock source information for a ts 760 + * descriptor. 761 + * 762 + * @desc: ts descriptor, same as returned from request API. 763 + * @ci: The API fills this structure with the clock information data. 764 + * 765 + * Context: Any context. 766 + * Returns: 0 on success else negative error code on failure. 767 + */ 768 + int hte_get_clk_src_info(const struct hte_ts_desc *desc, 769 + struct hte_clk_info *ci) 770 + { 771 + struct hte_chip *chip; 772 + struct hte_ts_info *ei; 773 + 774 + if (!desc || !desc->hte_data || !ci) { 775 + pr_debug("%s:%d\n", __func__, __LINE__); 776 + return -EINVAL; 777 + } 778 + 779 + ei = desc->hte_data; 780 + if (!ei->gdev || !ei->gdev->chip) 781 + return -EINVAL; 782 + 783 + chip = ei->gdev->chip; 784 + if (!chip->ops->get_clk_src_info) 785 + return -EOPNOTSUPP; 786 + 787 + return chip->ops->get_clk_src_info(chip, ci); 788 + } 789 + EXPORT_SYMBOL_GPL(hte_get_clk_src_info); 790 + 791 + /** 792 + * hte_push_ts_ns() - Push timestamp data in nanoseconds. 793 + * 794 + * It is used by the provider to push timestamp data. 795 + * 796 + * @chip: The HTE chip, used during the registration. 797 + * @xlated_id: entity id understood by both subsystem and provider, this is 798 + * obtained from xlate callback during request API. 799 + * @data: timestamp data. 800 + * 801 + * Returns: 0 on success or a negative error code on failure. 802 + */ 803 + int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id, 804 + struct hte_ts_data *data) 805 + { 806 + enum hte_return ret; 807 + int st = 0; 808 + struct hte_ts_info *ei; 809 + unsigned long flag; 810 + 811 + if (!chip || !data || !chip->gdev) 812 + return -EINVAL; 813 + 814 + if (xlated_id >= chip->nlines) 815 + return -EINVAL; 816 + 817 + ei = &chip->gdev->ei[xlated_id]; 818 + 819 + spin_lock_irqsave(&ei->slock, flag); 820 + 821 + /* timestamp sequence counter */ 822 + data->seq = ei->seq++; 823 + 824 + if (!test_bit(HTE_TS_REGISTERED, &ei->flags) || 825 + test_bit(HTE_TS_DISABLE, &ei->flags)) { 826 + dev_dbg(chip->dev, "Unknown timestamp push\n"); 827 + atomic_inc(&ei->dropped_ts); 828 + st = -EINVAL; 829 + goto unlock; 830 + } 831 + 832 + ret = ei->cb(data, ei->cl_data); 833 + if (ret == HTE_RUN_SECOND_CB && ei->tcb) { 834 + queue_work(system_unbound_wq, &ei->cb_work); 835 + set_bit(HTE_TS_QUEUE_WK, &ei->flags); 836 + } 837 + 838 + unlock: 839 + spin_unlock_irqrestore(&ei->slock, flag); 840 + 841 + return st; 842 + } 843 + EXPORT_SYMBOL_GPL(hte_push_ts_ns); 844 + 845 + static int hte_register_chip(struct hte_chip *chip) 846 + { 847 + struct hte_device *gdev; 848 + u32 i; 849 + 850 + if (!chip || !chip->dev || !chip->dev->of_node) 851 + return -EINVAL; 852 + 853 + if (!chip->ops || !chip->ops->request || !chip->ops->release) { 854 + dev_err(chip->dev, "Driver needs to provide ops\n"); 855 + return -EINVAL; 856 + } 857 + 858 + gdev = kzalloc(struct_size(gdev, ei, chip->nlines), GFP_KERNEL); 859 + if (!gdev) 860 + return -ENOMEM; 861 + 862 + gdev->chip = chip; 863 + chip->gdev = gdev; 864 + gdev->nlines = chip->nlines; 865 + gdev->sdev = chip->dev; 866 + 867 + for (i = 0; i < chip->nlines; i++) { 868 + gdev->ei[i].gdev = gdev; 869 + mutex_init(&gdev->ei[i].req_mlock); 870 + spin_lock_init(&gdev->ei[i].slock); 871 + } 872 + 873 + if (chip->dev->driver) 874 + gdev->owner = chip->dev->driver->owner; 875 + else 876 + gdev->owner = THIS_MODULE; 877 + 878 + of_node_get(chip->dev->of_node); 879 + 880 + INIT_LIST_HEAD(&gdev->list); 881 + 882 + spin_lock(&hte_lock); 883 + list_add_tail(&gdev->list, &hte_devices); 884 + spin_unlock(&hte_lock); 885 + 886 + hte_chip_dbgfs_init(gdev); 887 + 888 + dev_dbg(chip->dev, "Added hte chip\n"); 889 + 890 + return 0; 891 + } 892 + 893 + static int hte_unregister_chip(struct hte_chip *chip) 894 + { 895 + struct hte_device *gdev; 896 + 897 + if (!chip) 898 + return -EINVAL; 899 + 900 + gdev = chip->gdev; 901 + 902 + spin_lock(&hte_lock); 903 + list_del(&gdev->list); 904 + spin_unlock(&hte_lock); 905 + 906 + gdev->chip = NULL; 907 + 908 + of_node_put(chip->dev->of_node); 909 + debugfs_remove_recursive(gdev->dbg_root); 910 + kfree(gdev); 911 + 912 + dev_dbg(chip->dev, "Removed hte chip\n"); 913 + 914 + return 0; 915 + } 916 + 917 + static void _hte_devm_unregister_chip(void *chip) 918 + { 919 + hte_unregister_chip(chip); 920 + } 921 + 922 + /** 923 + * devm_hte_register_chip() - Resource managed API to register HTE chip. 924 + * 925 + * It is used by the provider to register itself with the HTE subsystem. 926 + * The unregistration is done automatically when the provider exits. 927 + * 928 + * @chip: the HTE chip to add to subsystem. 929 + * 930 + * Returns: 0 on success or a negative error code on failure. 931 + */ 932 + int devm_hte_register_chip(struct hte_chip *chip) 933 + { 934 + int err; 935 + 936 + err = hte_register_chip(chip); 937 + if (err) 938 + return err; 939 + 940 + err = devm_add_action_or_reset(chip->dev, _hte_devm_unregister_chip, 941 + chip); 942 + if (err) 943 + return err; 944 + 945 + return 0; 946 + } 947 + EXPORT_SYMBOL_GPL(devm_hte_register_chip);
+14 -2
include/linux/gpio/consumer.h
··· 109 109 int gpiod_direction_input(struct gpio_desc *desc); 110 110 int gpiod_direction_output(struct gpio_desc *desc, int value); 111 111 int gpiod_direction_output_raw(struct gpio_desc *desc, int value); 112 + int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); 113 + int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags); 112 114 113 115 /* Value get/set from non-sleeping context */ 114 116 int gpiod_get_value(const struct gpio_desc *desc); ··· 352 350 WARN_ON(desc); 353 351 return -ENOSYS; 354 352 } 355 - 356 - 353 + static inline int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, 354 + unsigned long flags) 355 + { 356 + WARN_ON(desc); 357 + return -ENOSYS; 358 + } 359 + static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, 360 + unsigned long flags) 361 + { 362 + WARN_ON(desc); 363 + return -ENOSYS; 364 + } 357 365 static inline int gpiod_get_value(const struct gpio_desc *desc) 358 366 { 359 367 /* GPIO can never have been requested */
+10
include/linux/gpio/driver.h
··· 333 333 * @add_pin_ranges: optional routine to initialize pin ranges, to be used when 334 334 * requires special mapping of the pins that provides GPIO functionality. 335 335 * It is called after adding GPIO chip and before adding IRQ chip. 336 + * @en_hw_timestamp: Dependent on GPIO chip, an optional routine to 337 + * enable hardware timestamp. 338 + * @dis_hw_timestamp: Dependent on GPIO chip, an optional routine to 339 + * disable hardware timestamp. 336 340 * @base: identifies the first GPIO number handled by this chip; 337 341 * or, if negative during registration, requests dynamic ID allocation. 338 342 * DEPRECATION: providing anything non-negative and nailing the base ··· 433 429 434 430 int (*add_pin_ranges)(struct gpio_chip *gc); 435 431 432 + int (*en_hw_timestamp)(struct gpio_chip *gc, 433 + u32 offset, 434 + unsigned long flags); 435 + int (*dis_hw_timestamp)(struct gpio_chip *gc, 436 + u32 offset, 437 + unsigned long flags); 436 438 int base; 437 439 u16 ngpio; 438 440 u16 offset;
+271
include/linux/hte.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #ifndef __LINUX_HTE_H 4 + #define __LINUX_HTE_H 5 + 6 + #include <linux/errno.h> 7 + 8 + struct hte_chip; 9 + struct hte_device; 10 + struct of_phandle_args; 11 + 12 + /** 13 + * enum hte_edge - HTE line edge flags. 14 + * 15 + * @HTE_EDGE_NO_SETUP: No edge setup. In this case consumer will setup edges, 16 + * for example during request irq call. 17 + * @HTE_RISING_EDGE_TS: Rising edge. 18 + * @HTE_FALLING_EDGE_TS: Falling edge. 19 + * 20 + */ 21 + enum hte_edge { 22 + HTE_EDGE_NO_SETUP = 1U << 0, 23 + HTE_RISING_EDGE_TS = 1U << 1, 24 + HTE_FALLING_EDGE_TS = 1U << 2, 25 + }; 26 + 27 + /** 28 + * enum hte_return - HTE subsystem return values used during callback. 29 + * 30 + * @HTE_CB_HANDLED: The consumer handled the data. 31 + * @HTE_RUN_SECOND_CB: The consumer needs further processing, in that case 32 + * HTE subsystem calls secondary callback provided by the consumer where it 33 + * is allowed to sleep. 34 + */ 35 + enum hte_return { 36 + HTE_CB_HANDLED, 37 + HTE_RUN_SECOND_CB, 38 + }; 39 + 40 + /** 41 + * struct hte_ts_data - HTE timestamp data. 42 + * 43 + * @tsc: Timestamp value. 44 + * @seq: Sequence counter of the timestamps. 45 + * @raw_level: Level of the line at the timestamp if provider supports it, 46 + * -1 otherwise. 47 + */ 48 + struct hte_ts_data { 49 + u64 tsc; 50 + u64 seq; 51 + int raw_level; 52 + }; 53 + 54 + /** 55 + * struct hte_clk_info - Clock source info that HTE provider uses to timestamp. 56 + * 57 + * @hz: Supported clock rate in HZ, for example 1KHz clock = 1000. 58 + * @type: Supported clock type. 59 + */ 60 + struct hte_clk_info { 61 + u64 hz; 62 + clockid_t type; 63 + }; 64 + 65 + /** 66 + * typedef hte_ts_cb_t - HTE timestamp data processing primary callback. 67 + * 68 + * The callback is used to push timestamp data to the client and it is 69 + * not allowed to sleep. 70 + * 71 + * @ts: HW timestamp data. 72 + * @data: Client supplied data. 73 + */ 74 + typedef enum hte_return (*hte_ts_cb_t)(struct hte_ts_data *ts, void *data); 75 + 76 + /** 77 + * typedef hte_ts_sec_cb_t - HTE timestamp data processing secondary callback. 78 + * 79 + * This is used when the client needs further processing where it is 80 + * allowed to sleep. 81 + * 82 + * @data: Client supplied data. 83 + * 84 + */ 85 + typedef enum hte_return (*hte_ts_sec_cb_t)(void *data); 86 + 87 + /** 88 + * struct hte_line_attr - Line attributes. 89 + * 90 + * @line_id: The logical ID understood by the consumers and providers. 91 + * @line_data: Line data related to line_id. 92 + * @edge_flags: Edge setup flags. 93 + * @name: Descriptive name of the entity that is being monitored for the 94 + * hardware timestamping. If null, HTE core will construct the name. 95 + * 96 + */ 97 + struct hte_line_attr { 98 + u32 line_id; 99 + void *line_data; 100 + unsigned long edge_flags; 101 + const char *name; 102 + }; 103 + 104 + /** 105 + * struct hte_ts_desc - HTE timestamp descriptor. 106 + * 107 + * This structure is a communication token between consumers to subsystem 108 + * and subsystem to providers. 109 + * 110 + * @attr: The line attributes. 111 + * @hte_data: Subsystem's private data, set by HTE subsystem. 112 + */ 113 + struct hte_ts_desc { 114 + struct hte_line_attr attr; 115 + void *hte_data; 116 + }; 117 + 118 + /** 119 + * struct hte_ops - HTE operations set by providers. 120 + * 121 + * @request: Hook for requesting a HTE timestamp. Returns 0 on success, 122 + * non-zero for failures. 123 + * @release: Hook for releasing a HTE timestamp. Returns 0 on success, 124 + * non-zero for failures. 125 + * @enable: Hook to enable the specified timestamp. Returns 0 on success, 126 + * non-zero for failures. 127 + * @disable: Hook to disable specified timestamp. Returns 0 on success, 128 + * non-zero for failures. 129 + * @get_clk_src_info: Hook to get the clock information the provider uses 130 + * to timestamp. Returns 0 for success and negative error code for failure. On 131 + * success HTE subsystem fills up provided struct hte_clk_info. 132 + * 133 + * xlated_id parameter is used to communicate between HTE subsystem and the 134 + * providers and is translated by the provider. 135 + */ 136 + struct hte_ops { 137 + int (*request)(struct hte_chip *chip, struct hte_ts_desc *desc, 138 + u32 xlated_id); 139 + int (*release)(struct hte_chip *chip, struct hte_ts_desc *desc, 140 + u32 xlated_id); 141 + int (*enable)(struct hte_chip *chip, u32 xlated_id); 142 + int (*disable)(struct hte_chip *chip, u32 xlated_id); 143 + int (*get_clk_src_info)(struct hte_chip *chip, 144 + struct hte_clk_info *ci); 145 + }; 146 + 147 + /** 148 + * struct hte_chip - Abstract HTE chip. 149 + * 150 + * @name: functional name of the HTE IP block. 151 + * @dev: device providing the HTE. 152 + * @ops: callbacks for this HTE. 153 + * @nlines: number of lines/signals supported by this chip. 154 + * @xlate_of: Callback which translates consumer supplied logical ids to 155 + * physical ids, return 0 for the success and negative for the failures. 156 + * It stores (between 0 to @nlines) in xlated_id parameter for the success. 157 + * @xlate_plat: Same as above but for the consumers with no DT node. 158 + * @match_from_linedata: Match HTE device using the line_data. 159 + * @of_hte_n_cells: Number of cells used to form the HTE specifier. 160 + * @gdev: HTE subsystem abstract device, internal to the HTE subsystem. 161 + * @data: chip specific private data. 162 + */ 163 + struct hte_chip { 164 + const char *name; 165 + struct device *dev; 166 + const struct hte_ops *ops; 167 + u32 nlines; 168 + int (*xlate_of)(struct hte_chip *gc, 169 + const struct of_phandle_args *args, 170 + struct hte_ts_desc *desc, u32 *xlated_id); 171 + int (*xlate_plat)(struct hte_chip *gc, struct hte_ts_desc *desc, 172 + u32 *xlated_id); 173 + bool (*match_from_linedata)(const struct hte_chip *chip, 174 + const struct hte_ts_desc *hdesc); 175 + u8 of_hte_n_cells; 176 + 177 + struct hte_device *gdev; 178 + void *data; 179 + }; 180 + 181 + #if IS_ENABLED(CONFIG_HTE) 182 + /* HTE APIs for the providers */ 183 + int devm_hte_register_chip(struct hte_chip *chip); 184 + int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id, 185 + struct hte_ts_data *data); 186 + 187 + /* HTE APIs for the consumers */ 188 + int hte_init_line_attr(struct hte_ts_desc *desc, u32 line_id, 189 + unsigned long edge_flags, const char *name, 190 + void *data); 191 + int hte_ts_get(struct device *dev, struct hte_ts_desc *desc, int index); 192 + int hte_ts_put(struct hte_ts_desc *desc); 193 + int hte_request_ts_ns(struct hte_ts_desc *desc, hte_ts_cb_t cb, 194 + hte_ts_sec_cb_t tcb, void *data); 195 + int devm_hte_request_ts_ns(struct device *dev, struct hte_ts_desc *desc, 196 + hte_ts_cb_t cb, hte_ts_sec_cb_t tcb, void *data); 197 + int of_hte_req_count(struct device *dev); 198 + int hte_enable_ts(struct hte_ts_desc *desc); 199 + int hte_disable_ts(struct hte_ts_desc *desc); 200 + int hte_get_clk_src_info(const struct hte_ts_desc *desc, 201 + struct hte_clk_info *ci); 202 + 203 + #else /* !CONFIG_HTE */ 204 + static inline int devm_hte_register_chip(struct hte_chip *chip) 205 + { 206 + return -EOPNOTSUPP; 207 + } 208 + 209 + static inline int hte_push_ts_ns(const struct hte_chip *chip, 210 + u32 xlated_id, 211 + const struct hte_ts_data *data) 212 + { 213 + return -EOPNOTSUPP; 214 + } 215 + 216 + static inline int hte_init_line_attr(struct hte_ts_desc *desc, u32 line_id, 217 + unsigned long edge_flags, 218 + const char *name, void *data) 219 + { 220 + return -EOPNOTSUPP; 221 + } 222 + 223 + static inline int hte_ts_get(struct device *dev, struct hte_ts_desc *desc, 224 + int index) 225 + { 226 + return -EOPNOTSUPP; 227 + } 228 + 229 + static inline int hte_ts_put(struct hte_ts_desc *desc) 230 + { 231 + return -EOPNOTSUPP; 232 + } 233 + 234 + static inline int hte_request_ts_ns(struct hte_ts_desc *desc, hte_ts_cb_t cb, 235 + hte_ts_sec_cb_t tcb, void *data) 236 + { 237 + return -EOPNOTSUPP; 238 + } 239 + 240 + static inline int devm_hte_request_ts_ns(struct device *dev, 241 + struct hte_ts_desc *desc, 242 + hte_ts_cb_t cb, 243 + hte_ts_sec_cb_t tcb, 244 + void *data) 245 + { 246 + return -EOPNOTSUPP; 247 + } 248 + 249 + static inline int of_hte_req_count(struct device *dev) 250 + { 251 + return -EOPNOTSUPP; 252 + } 253 + 254 + static inline int hte_enable_ts(struct hte_ts_desc *desc) 255 + { 256 + return -EOPNOTSUPP; 257 + } 258 + 259 + static inline int hte_disable_ts(struct hte_ts_desc *desc) 260 + { 261 + return -EOPNOTSUPP; 262 + } 263 + 264 + static inline int hte_get_clk_src_info(const struct hte_ts_desc *desc, 265 + struct hte_clk_info *ci) 266 + { 267 + return -EOPNOTSUPP; 268 + } 269 + #endif /* !CONFIG_HTE */ 270 + 271 + #endif
+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 /**
+5 -1
tools/gpio/gpio-event-mon.c
··· 149 149 " -r Listen for rising edges\n" 150 150 " -f Listen for falling edges\n" 151 151 " -w Report the wall-clock time for events\n" 152 + " -t Report the hardware timestamp for events\n" 152 153 " -b <n> Debounce the line with period n microseconds\n" 153 154 " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" 154 155 " -? This helptext\n" ··· 175 174 176 175 memset(&config, 0, sizeof(config)); 177 176 config.flags = GPIO_V2_LINE_FLAG_INPUT; 178 - while ((c = getopt(argc, argv, "c:n:o:b:dsrfw?")) != -1) { 177 + while ((c = getopt(argc, argv, "c:n:o:b:dsrfwt?")) != -1) { 179 178 switch (c) { 180 179 case 'c': 181 180 loops = strtoul(optarg, NULL, 10); ··· 208 207 break; 209 208 case 'w': 210 209 config.flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; 210 + break; 211 + case 't': 212 + config.flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; 211 213 break; 212 214 case '?': 213 215 print_usage();