虚拟 GPIO 消费者

虚拟 GPIO 消费者模块允许用户实例化请求 GPIO 并通过 debugfs 控制其行为的虚拟设备。虚拟消费者设备可以从设备树或通过 configfs 实例化。

虚拟消费者使用面向驱动程序的 GPIO API,并允许通过用户空间驱动的自动化测试来覆盖它。GPIO 是使用 gpiod_get_array() 请求的,因此我们支持每个连接器 ID 多个 GPIO。

创建 GPIO 消费者

gpio-consumer 模块注册了一个名为 'gpio-virtuser' 的 configfs 子系统。有关 configfs 文件系统的详细信息,请参阅 configfs 文档。

用户可以创建 configfs 组和项的层次结构,以及修改公开属性的值。一旦消费者实例化,这个层次结构将被转换为适当的设备属性。一般结构是

组: /config/gpio-virtuser

这是 gpio-consumer configfs 树的顶级目录。

组: /config/gpio-consumer/example-name

属性: /config/gpio-consumer/example-name/live

属性: /config/gpio-consumer/example-name/dev_name

这是一个表示 GPIO 消费者设备的目录。

只读的 dev_name 属性公开了设备在平台总线上系统中将显示的名称。这对于在 /sys/kernel/debug/gpio-virtuser/$dev_name 下定位关联的 debugfs 目录非常有用。

'live' 属性允许在设备完全配置后触发其实际创建。接受的值为:'1' 用于启用虚拟设备,'0' 用于禁用和拆除它。

创建 GPIO 查找表

用户可以在设备组下创建多个 configfs 组

组: /config/gpio-consumer/example-name/con_id

'con_id' 目录表示一个单独的 GPIO 查找,其值映射到 gpiod_get() 函数的 'con_id' 参数。例如:con_id == 'reset' 映射到 reset-gpios 设备属性。

用户可以为每个查找分配多个 GPIO。每个 GPIO 都是 'con_id' 组下带有用户定义名称的子目录。

属性: /config/gpio-consumer/example-name/con_id/0/key

属性: /config/gpio-consumer/example-name/con_id/0/offset

属性: /config/gpio-consumer/example-name/con_id/0/drive

属性: /config/gpio-consumer/example-name/con_id/0/pull

属性: /config/gpio-consumer/example-name/con_id/0/active_low

属性: /config/gpio-consumer/example-name/con_id/0/transitory

这是一个描述 con_id-gpios 属性中单个 GPIO 的组。

对于使用 configfs 创建的虚拟消费者,我们使用机器查找表,因此这个组可以被视为文件系统和 'struct gpiod_lookup' 中单个条目字段之间的映射。

'key' 属性表示此 GPIO 所属芯片的名称或 GPIO 线名称。这取决于 'offset' 属性的值:如果其值 >= 0,则 'key' 表示要查找的芯片的标签,而 'offset' 表示该芯片中线的偏移量。如果 'offset' < 0,则 'key' 表示线的名称。

其余属性映射到 GPIO 查找结构体的 'flags' 字段。前两个属性接受字符串值作为参数

``’drive’``: 'push-pull''open-drain''open-source' ``’pull’``: 'pull-up''pull-down''pull-disabled''as-is'

'active_low''transitory' 是布尔属性。

激活 GPIO 消费者

配置完成后,必须将 'live' 属性设置为 1 以实例化消费者。可以将其设置回 0 以销毁虚拟设备。模块将同步等待新的模拟设备成功探测,如果未发生,则写入 'live' 将导致错误。

设备树

虚拟 GPIO 消费者也可以在设备树中定义。兼容字符串必须是:"gpio-virtuser",并且至少有一个属性遵循标准化的 GPIO 模式。

定义虚拟 GPIO 消费者的设备树代码示例

gpio-virt-consumer {
    compatible = "gpio-virtuser";

    foo-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>, <&gpio1 2 0>;
    bar-gpios = <&gpio0 6 0>;
};

控制虚拟 GPIO 消费者

一旦激活,设备将导出 debugfs 属性,用于控制 GPIO 数组以及每个请求的 GPIO 线。让我们考虑以下设备属性:foo-gpios = <&gpio0 0 0>, <&gpio0 4 0>;

将创建以下 debugfs 属性组

组: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/

这是将包含整个 GPIO 数组属性的组。

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values_atomic

这两个属性都允许读取和设置 GPIO 值数组。用户必须以包含零和一的字符串形式传递数组中包含的值的确切数量,分别代表非活动和活动 GPIO 状态。在此示例中:echo 11 > values

values_atomic 属性的工作方式与 values 相同,但内核将在中断上下文中执行 GPIO 驱动程序回调。

组: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/

这是一个表示单个 GPIO 的组,其中 $index 是其在数组中的偏移量。

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/consumer

允许设置和读取 GPIO 线的消费者标签。

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/debounce

允许设置和读取 GPIO 线的去抖周期。

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction_atomic

这两个属性允许设置 GPIO 线的方向。它们接受“input”(输入)和“output”(输出)作为值。原子变体在中断上下文中执行驱动程序回调。

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/interrupts

如果以输入模式请求该线,则向此属性写入 1 将使模块监听 GPIO 上的边沿中断。写入 0 将禁用监视。读取此属性将返回当前注册的中断数(两个边沿)。

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value

属性: /sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value_atomic

这两个属性都允许读取和设置单个请求的 GPIO 线的值。它们接受以下值:10