Linux 硬件时间戳引擎 (HTE)

作者:

Dipen Patel

简介

某些设备内置了硬件时间戳引擎,可以实时监控系统信号、线路、总线等的状态变化;在检测到变化时,它们可以自动存储发生时刻的时间戳。与使用软件对应物(例如 ktime 和相关函数)相比,这种功能可能有助于获得更高的时间戳精度。

本文档描述了硬件时间戳引擎提供程序和想要使用硬件时间戳引擎 (HTE) 框架的使用者驱动程序可以使用的 API。使用者和提供者都必须包含 #include <linux/hte.h>

提供者的 HTE 框架 API

int hte_push_ts_ns(const struct hte_chip *chip, u32 xlated_id, struct hte_ts_data *data)

以纳秒为单位推送时间戳数据。

参数

const struct hte_chip *chip

HTE 芯片,在注册期间使用。

u32 xlated_id

子系统和提供程序都理解的实体 ID,这是在请求 API 期间从 xlate 回调中获得的。

struct hte_ts_data *data

时间戳数据。

描述

提供程序使用它来推送时间戳数据。

返回值

成功时返回 0,失败时返回负错误代码。

int devm_hte_register_chip(struct hte_chip *chip)

资源管理 API,用于注册 HTE 芯片。

参数

struct hte_chip *chip

要添加到子系统的 HTE 芯片。

描述

提供程序使用它向 HTE 子系统注册自身。当提供程序退出时,将自动取消注册。

返回值

成功时返回 0,失败时返回负错误代码。

使用者的 HTE 框架 API

int hte_ts_put(struct hte_ts_desc *desc)

释放并禁用给定 desc 的时间戳。

参数

struct hte_ts_desc *desc

时间戳描述符。

上下文

debugfs_remove_recursive() 函数调用可能会使用睡眠锁,不适合从原子上下文调用。

返回值

成功时返回 0,失败时返回负错误代码。

int hte_disable_ts(struct hte_ts_desc *desc)

禁用给定描述符上的时间戳。

参数

struct hte_ts_desc *desc

ts 描述符,这与请求 API 返回的描述符相同。

描述

API 不会释放与 desc 关联的任何资源。

上下文

持有互斥锁,不适合从原子上下文调用。

返回值

成功时返回 0,失败时返回负错误代码。

int hte_enable_ts(struct hte_ts_desc *desc)

启用给定描述符上的时间戳。

参数

struct hte_ts_desc *desc

ts 描述符,这与请求 API 返回的描述符相同。

上下文

持有互斥锁,不适合从原子上下文调用。

返回值

成功时返回 0,失败时返回负错误代码。

int of_hte_req_count(struct device *dev)

返回要加盖时间戳的实体数。

参数

struct device *dev

HTE 使用者。

描述

该函数通过解析设备树返回要加盖时间戳的请求实体的总数。

返回值

成功时返回正数,如果没有条目则返回 -ENOENT,对于其他错误则返回 -EINVAL。

int hte_ts_get(struct device *dev, struct hte_ts_desc *desc, int index)

用于初始化和获取 HTE desc 的函数。

参数

struct device *dev

HTE 使用者/客户端设备,在解析设备树节点时使用。

struct hte_ts_desc *desc

预分配的时间戳描述符。

int index

如果存在节点,该索引将用作从设备树节点解析 line_id 的索引。

描述

该函数初始化使用者提供的 HTE 描述符。如果使用者具有设备树节点,则使用索引来解析行 ID 和其他详细信息。在使用任何请求 API 之前需要调用此函数。

上下文

持有互斥锁。

返回值

成功时返回 0,失败时返回负错误代码。

int hte_request_ts_ns(struct hte_ts_desc *desc, hte_ts_cb_t cb, hte_ts_sec_cb_t tcb, void *data)

请求并启用纳秒级硬件时间戳的 API。

参数

struct hte_ts_desc *desc

预先分配和初始化的时间戳描述符。

hte_ts_cb_t cb

用于将时间戳数据推送到消费者的回调。

hte_ts_sec_cb_t tcb

可选的回调。如果提供了此回调,子系统将初始化工作队列。当 cb 返回 HTE_RUN_SECOND_CB 时,将调用此回调。

void *data

客户端数据,在 cb 和 tcb 回调期间使用。

描述

实体是提供商特定的,例如,GPIO 线、信号、总线等... 该 API 分配必要的资源并启用时间戳。

上下文

持有互斥锁。

返回值

成功时返回 0,失败时返回负错误代码。

int devm_hte_request_ts_ns(struct device *dev, struct hte_ts_desc *desc, hte_ts_cb_t cb, hte_ts_sec_cb_t tcb, void *data)

资源管理的 API,用于请求和启用纳秒级硬件时间戳。

参数

struct device *dev

HTE 消费者/客户端设备。

struct hte_ts_desc *desc

预先分配和初始化的时间戳描述符。

hte_ts_cb_t cb

用于将时间戳数据推送到消费者的回调。

hte_ts_sec_cb_t tcb

可选的回调。如果提供了此回调,子系统将初始化工作队列。当 cb 返回 HTE_RUN_SECOND_CB 时,将调用此回调。

void *data

客户端数据,在 cb 和 tcb 回调期间使用。

描述

实体是提供商特定的,例如,GPIO 线、信号、总线等... 该 API 分配必要的资源并启用时间戳。当消费者退出时,它会自动释放资源并禁用时间戳。

上下文

持有互斥锁。

返回值

成功时返回 0,失败时返回负错误代码。

int hte_init_line_attr(struct hte_ts_desc *desc, u32 line_id, unsigned long edge_flags, const char *name, void *data)

初始化线路属性。

参数

struct hte_ts_desc *desc

预分配的时间戳描述符。

u32 line_id

线路 ID。

unsigned long edge_flags

与 line_id 相关的边沿标志。

const char *name

线路的名称。

void *data

与 line_id 相关的线路数据。

描述

清零线路属性并使用提供的参数进行初始化。在调用任何面向消费者的函数之前,需要调用此函数。

上下文

任意上下文。

返回值

成功返回 0,失败返回负错误代码。

int hte_get_clk_src_info(const struct hte_ts_desc *desc, struct hte_clk_info *ci)

获取时间戳描述符的时钟源信息。

参数

const struct hte_ts_desc *desc

时间戳描述符,与请求 API 返回的相同。

struct hte_clk_info *ci

该 API 使用时钟信息数据填充此结构。

上下文

任意上下文。

返回值

成功返回 0,否则失败返回负错误代码。

HTE 框架公共结构

enum hte_edge

HTE 线路边沿标志。

常量

HTE_EDGE_NO_SETUP

无边沿设置。在这种情况下,消费者将设置边沿,例如在请求 irq 调用期间。

HTE_RISING_EDGE_TS

上升沿。

HTE_FALLING_EDGE_TS

下降沿。

enum hte_return

在回调期间使用的 HTE 子系统返回值。

常量

HTE_CB_HANDLED

消费者处理了数据。

HTE_RUN_SECOND_CB

消费者需要进一步处理,在这种情况下,HTE 子系统会调用消费者提供的辅助回调,该回调允许休眠。

struct hte_ts_data

HTE 时间戳数据。

定义:

struct hte_ts_data {
    u64 tsc;
    u64 seq;
    int raw_level;
};

成员

tsc

时间戳值。

seq

时间戳的序列计数器。

raw_level

如果提供商支持,则在时间戳时的线路电平,否则为 -1。

struct hte_clk_info

HTE 提供商用于时间戳的时钟源信息。

定义:

struct hte_clk_info {
    u64 hz;
    clockid_t type;
};

成员

hz

支持的 HZ 时钟速率,例如,1KHz 时钟 = 1000。

type

支持的时钟类型。

hte_ts_cb_t

Typedef:HTE 时间戳数据处理主回调。

语法

enum hte_return hte_ts_cb_t (struct hte_ts_data *ts, void *data)

参数

struct hte_ts_data *ts

硬件时间戳数据。

void *data

客户端提供的数据。

描述

此回调用于将时间戳数据推送到客户端,并且不允许休眠。

hte_ts_sec_cb_t

Typedef:HTE 时间戳数据处理辅助回调。

语法

enum hte_return hte_ts_sec_cb_t (void *data)

参数

void *data

客户端提供的数据。

描述

当客户端需要进一步处理(允许休眠)时使用。

struct hte_line_attr

线路属性。

定义:

struct hte_line_attr {
    u32 line_id;
    void *line_data;
    unsigned long edge_flags;
    const char *name;
};

成员

line_id

消费者和提供商理解的逻辑 ID。

line_data

与 line_id 相关的线路数据。

edge_flags

边沿设置标志。

name

正在监视以进行硬件时间戳的实体的描述性名称。如果为空,HTE 核心将构造该名称。

struct hte_ts_desc

HTE 时间戳描述符。

定义:

struct hte_ts_desc {
    struct hte_line_attr attr;
    void *hte_data;
};

成员

attr

线路属性。

hte_data

子系统的私有数据,由 HTE 子系统设置。

描述

此结构是消费者到子系统以及子系统到提供商之间的通信令牌。

struct hte_ops

提供商设置的 HTE 操作。

定义:

struct hte_ops {
    int (*request)(struct hte_chip *chip, struct hte_ts_desc *desc, u32 xlated_id);
    int (*release)(struct hte_chip *chip, struct hte_ts_desc *desc, u32 xlated_id);
    int (*enable)(struct hte_chip *chip, u32 xlated_id);
    int (*disable)(struct hte_chip *chip, u32 xlated_id);
    int (*get_clk_src_info)(struct hte_chip *chip, struct hte_clk_info *ci);
};

成员

request

请求 HTE 时间戳的钩子。成功返回 0,失败返回非零值。

release

释放 HTE 时间戳的钩子。成功返回 0,失败返回非零值。

enable

启用指定时间戳的钩子。成功返回 0,失败返回非零值。

disable

禁用指定时间戳的钩子。成功返回 0,失败返回非零值。

get_clk_src_info

获取提供商用于时间戳的时钟信息的钩子。成功返回 0,失败返回负错误代码。成功时,HTE 子系统会填充提供的 struct hte_clk_info

描述

xlated_id 参数用于在 HTE 子系统和提供商之间进行通信,并由提供商转换。

struct hte_chip

抽象 HTE 芯片。

定义:

struct hte_chip {
    const char *name;
    struct device *dev;
    const struct hte_ops *ops;
    u32 nlines;
    int (*xlate_of)(struct hte_chip *gc,const struct of_phandle_args *args, struct hte_ts_desc *desc, u32 *xlated_id);
    int (*xlate_plat)(struct hte_chip *gc, struct hte_ts_desc *desc, u32 *xlated_id);
    bool (*match_from_linedata)(const struct hte_chip *chip, const struct hte_ts_desc *hdesc);
    u8 of_hte_n_cells;
    struct hte_device *gdev;
    void *data;
};

成员

name

HTE IP 块的功能名称。

dev

提供 HTE 的设备。

ops

此 HTE 的回调。

nlines

此芯片支持的线路/信号数量。

xlate_of

回调函数,用于将消费者提供的逻辑 ID 转换为物理 ID,成功时返回 0,失败时返回负值。成功时,会将转换后的 ID(介于 0 到 nlines 之间)存储在 xlated_id 参数中。

xlate_plat

与上述相同,但适用于没有 DT 节点的消费者。

match_from_linedata

使用 line_data 匹配 HTE 设备。

of_hte_n_cells

用于构成 HTE 说明符的单元格数量。

gdev

HTE 子系统抽象设备,HTE 子系统内部使用。

data

芯片特定的私有数据。

关于 HTE 时间戳数据的更多信息

struct hte_ts_data 用于在消费者和提供者之间传递时间戳详细信息。它以 u64 中的纳秒表示时间戳数据。以下是 GPIO 线典型时间戳数据生命周期的示例

- Monitors GPIO line change.
- Detects the state change on GPIO line.
- Converts timestamps in nanoseconds.
- Stores GPIO raw level in raw_level variable if the provider has that
hardware capability.
- Pushes this hte_ts_data object to HTE subsystem.
- HTE subsystem increments seq counter and invokes consumer provided callback.
Based on callback return value, the HTE core invokes secondary callback in
the thread context.

HTE 子系统 debugfs 属性

HTE 子系统在 /sys/kernel/debug/hte/ 创建 debugfs 属性。它还在 /sys/kernel/debug/hte/<提供者>/<标签 线路 ID>/ 创建与线路/信号相关的 debugfs 属性。请注意,这些属性是只读的。

ts_requested

从给定提供者请求的实体总数,其中实体由提供者指定,可以表示线路、GPIO、芯片信号、总线等... 该属性将在 /sys/kernel/debug/hte/<提供者>/ 中可用。

total_ts

提供者支持的实体总数。该属性将在 /sys/kernel/debug/hte/<提供者>/ 中可用。

dropped_timestamps

给定线路的丢弃的时间戳。该属性将在 /sys/kernel/debug/hte/<提供者>/<标签 线路 ID>/ 中可用。