2. 内核PWM子系统核心数据结构
PWM子系统的核心由三个紧密关联的数据结构构成:struct pwm_chip(控制器抽象)、struct pwm_device(通道抽象)和 struct pwm_ops(操作函数集)。理解这三者的定义、字段含义及关联关系,是分析PWM控制器注册耗时的前提。
2.1 struct pwm_chip —— PWM控制器抽象
struct pwm_chip 代表一个物理PWM控制器,是子系统中最顶层的结构。每个PWM控制器驱动在注册时,必须分配并填充该结构,然后调用 pwmchip_add() 或 pwmchip_add_with_polarity() 将其加入内核。
| 字段 | 类型 | 作用说明 |
|---|---|---|
| dev | struct device * | 关联的Linux设备模型节点,用于电源管理、sysfs 和设备树绑定 |
| npwm | unsigned int | 该控制器支持的PWM通道数量,决定 pwm_device 数组大小 |
| pwms | struct pwm_device * | 指向 pwm_device 数组的指针,由 PWM 核心在注册时分配 |
| ops | const struct pwm_ops * | 操作函数集指针,所有通道共享同一套底层硬件操作 |
| of_xlate | of_xlate_func | 设备树解析回调,将 <pwm-specifier> 映射到通道索引 |
| of_pwm_n_cells | int | 设备树PWM说明符的 cell 数量,通常为 2 或 3 |
| base | int | 全局PWM编号的起始值(旧API,新驱动建议设为 -1 动态分配) |
| can_sleep | bool | 标记该控制器的操作是否可能睡眠(影响原子上下文调用) |
性能关注点: npwm 字段直接决定了 pwm_device 数组的分配大小。对于具有大量通道(如 8/16 路)的控制器,内存分配和初始化耗时不可忽略。部分 SoC 的 PWM 控制器在注册阶段会遍历所有通道进行硬件状态同步,进一步增加耗时。
2.2 struct pwm_device —— PWM通道抽象
struct pwm_device 代表一个独立的PWM输出通道,是消费者(consumer)直接操作的对象。每个通道对应一个物理PWM输出引脚。
| 字段 | 类型 | 作用说明 |
|---|---|---|
| chip | struct pwm_chip * | 反向指针,指向所属的 PWM 控制器 |
| pwm | unsigned int | 通道在芯片内的索引(0 ~ npwm-1) |
| period | unsigned int | 当前配置的周期(单位:ns) |
| duty_cycle | unsigned int | 当前配置的占空比(单位:ns) |
| polarity | enum pwm_polarity | 输出极性:PWM_POLARITY_NORMAL 或 PWM_POLARITY_INVERSED |
| enabled | bool | 通道是否已使能 |
| label | const char * | 使用者名称,用于调试和 sysfs 展示 |
| flags | unsigned long | 状态标志位,如 PWMF_REQUESTED、PWMF_EXPORTED 等 |
设计意图: pwm_device 将硬件通道状态缓存到软件层面,避免每次操作都读取硬件寄存器。在注册阶段,核心会为每个通道初始化默认状态(period=0, duty_cycle=0, enabled=false),这部分循环在 npwm 较大时会产生可测量的延迟。
2.3 struct pwm_ops —— 硬件操作函数集
struct pwm_ops 定义了驱动层需要实现的硬件操作回调。PWM核心层通过 pwm_chip.ops 调用这些函数,完成对底层硬件的实际控制。
| 回调函数 | 原型 | 调用时机与作用 |
|---|---|---|
| request | int (*request)(struct pwm_chip *chip, struct pwm_device *pwm) | 通道被申请时调用,用于时钟使能、引脚复用配置 |
| free | void (*free)(struct pwm_chip *chip, struct pwm_device *pwm) | 通道被释放时调用,用于关闭时钟、恢复引脚 |
| config | int (*config)(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) | 配置周期和占空比(旧API,新驱动推荐使用 apply) |
| enable | int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm) | 使能PWM输出,启动波形生成 |
| disable | void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm) | 禁用PWM输出,停止波形 |
| apply | int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) | 原子化应用新状态(新API,一次性设置 period/duty/polarity/enable) |
| get_state | void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) | 读取硬件当前状态,用于状态同步和恢复 |
| set_polarity | int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm, enum pwm_polarity polarity) | 设置输出极性(旧API,新驱动合并到 apply 中) |
注册阶段的关键回调: get_state 回调在 pwmchip_add() 过程中会被调用,用于读取硬件当前状态并同步到 pwm_device 的缓存中。如果该回调实现中包含了慢速寄存器读取(如通过 I2C/SPI 访问 PWM 控制器),将显著增加注册耗时。这是启动阶段优化的重点之一。
2.4 三者关联关系详解
三个数据结构通过指针形成双向引用网络,理解这个网络是分析注册流程的基础:
- 控制器到通道(1:N):
pwm_chip.pwms指向一个连续分配的pwm_device数组,数组长度为npwm。每个元素代表一个物理通道。 - 通道到控制器(1:1): 每个
pwm_device.chip指针反向指向其所属的pwm_chip,使得在通道操作中可以快速获取控制器上下文。 - 控制器到操作集(1:1):
pwm_chip.ops指向一个静态定义的pwm_ops实例,同一芯片的所有通道共享同一套操作函数。 - 设备树解析桥梁:
pwm_chip.of_xlate回调负责将设备树中的<&pwm-controller channel flags>解析为具体的pwm_device指针。
2.5 数据结构关系总结
| 关系对 | 类型 | 方向 | 关键字段 | 注册阶段影响 |
|---|---|---|---|---|
| chip → device | 1:N 聚合 | chip.pwms → device[] | npwm 决定数组大小 | npwm 越大,内存分配和初始化循环耗时越长 |
| device → chip | 1:1 反向引用 | device.chip → chip | chip 指针 | 注册时设置,无额外耗时 |
| chip → ops | 1:1 组合 | chip.ops → ops | ops 指针 | 注册时通过 ops->get_state 产生硬件访问延迟 |
| device → state | 1:1 缓存 | device.period/duty_cycle/enabled | 状态缓存字段 | get_state 回调负责填充,慢速总线场景耗时显著 |