Linux 的 PTP 硬件时钟基础设施

此补丁集引入了 Linux 中对 IEEE 1588 PTP 时钟的支持。与 SO_TIMESTAMPING 套接字选项一起,这为开发 PTP 用户空间程序、将 Linux 与外部时钟同步以及使用 PTP 硬件时钟的辅助功能提供了一种标准化的方法。

一个新的类驱动程序为特定的时钟驱动程序和一个用户空间接口导出一个内核接口。该基础设施支持一套完整的 PTP 硬件时钟功能。

  • 基本时钟操作 - 设置时间 - 获取时间 - 以原子方式按给定的偏移量移动时钟 - 调整时钟频率

  • 辅助时钟功能 - 外部事件的时间戳 - 可从用户空间配置的周期输出信号 - 从用户空间访问低通滤波器 (LPF) - 通过 PPS 子系统同步 Linux 系统时间

PTP 硬件时钟内核 API

PTP 时钟驱动程序向类驱动程序注册自身。类驱动程序处理所有与用户空间的交互。时钟驱动程序的作者只需实现时钟硬件的编程细节。时钟驱动程序通过一个简单的消息传递接口通知类驱动程序异步事件(警报和外部时间戳)。

类驱动程序支持多个 PTP 时钟驱动程序。在正常用例中,只需要一个 PTP 时钟。但是,为了进行测试和开发,在一个系统中拥有多个时钟可能很有用,以便进行性能比较。

PTP 硬件时钟用户空间 API

类驱动程序还为每个注册的时钟创建一个字符设备。用户空间可以使用来自字符设备的打开文件描述符作为 POSIX 时钟 ID,并可以调用 clock_gettime、clock_settime 和 clock_adjtime。这些调用实现了基本时钟操作。

用户空间程序可以使用标准化的 ioctl 来控制时钟。程序可以查询、启用、配置和禁用辅助时钟功能。用户空间可以通过阻塞 read() 和 poll() 接收时间戳事件。

编写时钟驱动程序

时钟驱动程序包含 include/linux/ptp_clock_kernel.h,并通过向注册方法呈现“struct ptp_clock_info”来注册自身。时钟驱动程序必须实现接口中的所有函数。如果时钟不提供特定的辅助功能,则驱动程序应从这些函数返回 -EOPNOTSUPP。

驱动程序必须确保接口中的所有方法都是可重入的。由于大多数硬件实现将时间值视为以两个 32 位寄存器访问的 64 位整数,因此驱动程序应使用 spin_lock_irqsave/spin_unlock_irqrestore 来防止并发访问。此锁定不能在类驱动程序中完成,因为时钟驱动程序的中断服务例程也可能需要该锁。

PTP 硬件时钟对“.adjphase”的要求

“struct ptp_clock_info”接口具有一个“.adjphase”函数。此函数对 PHC 有一组要求,以便实现。

  • PHC 在内部实现一个伺服算法,用于校正“.adjphase”调用中传递的偏移量。

  • 当调用其他 PTP 调整函数时,PHC 伺服算法将被禁用。

注意:“.adjphase”不是一个简单的时间调整功能,它会根据提供的偏移量“跳跃”PHC 时钟时间。它应该使用内部算法校正提供的偏移量。

支持的硬件

  • 飞思卡尔 eTSEC gianfar

    • 2 个时间戳外部触发器,可编程极性(可选中断)

    • 2 个警报寄存器(可选中断)

    • 3 个周期信号(可选中断)

  • 国家半导体 DP83640

    • 6 个 GPIO 可编程为输入或输出

    • 6 个具有专用功能(LED/JTAG/时钟)的 GPIO 也可以用作通用输入或输出

    • GPIO 输入可以为外部触发器添加时间戳

    • GPIO 输出可以产生周期信号

    • 1 个中断引脚

  • 英特尔 IXP465

    • 辅助从/主模式快照(可选中断)

    • 目标时间(可选中断)

  • 瑞萨 (IDT) ClockMatrix™

    • 最多 4 个独立的 PHC 通道

    • 集成低通滤波器 (LPF),通过 .adjPhase 访问(符合 ITU-T G.8273.2)

    • 可编程输出周期信号

    • 可编程输入可以为外部触发器添加时间戳

    • 通过固件 (idtcm.bin) 进行驱动程序和/或硬件配置
      • LPF 设置(带宽、相位限制、自动保持、物理层辅助(符合 ITU-T G.8273.2))

      • 可编程输出 PTP 时钟,任何频率高达 1GHz(到其他 PHY/MAC 时间戳器,refclk 到 ASSP/SoC/FPGA)

      • 锁定到 GNSS 输入,在 GNSS 和用户空间 PHC 控制之间自动切换(可选)

  • NVIDIA Mellanox

    • GPIO
      • ConnectX-6 Dx 及更高版本的某些变体支持一个 GPIO,它可以为外部触发器添加时间戳,以及一个 GPIO,用于产生周期信号。

      • ConnectX-5 及更早版本的某些变体支持一个 GPIO,配置为为外部触发器添加时间戳或产生周期信号。

    • PHC 实例
      • 所有 ConnectX 设备都有一个自由运行的计数器

      • ConnectX-6 Dx 及更高版本的设备具有 UTC 格式的计数器