Pin 控制器 (Pinctrl)

介绍

架构

pinctrl 驱动程序遵循 Linux 的引脚控制子系统。引脚控制子系统处理以下内容:

  • 枚举和命名可控引脚。

  • 引脚、焊盘、引脚指等的复用。

  • 配置引脚、焊盘、引脚指等,例如通过软件控制特定引脚的偏置,如上拉/下拉、开漏、负载电容。

下面展示了 pinctrl 的软件架构。

../../rst_linux/1_gpio/figures/pinctrl_software_arch.svg

参考 pinctrl driver v5.4 或者 pinctrl driver v6.6 获取更多有关 Linux pinctrl 系统的细节。

实现

pinctrl 驱动程序实现在以下文件:

驱动程序位置

介绍

<linux>/drivers/rtkdrivers/pinctrl/Kconfig

Pinctrl 驱动程序 Kconfig

<linux>/drivers/rtkdrivers/pinctrl/Makefile

Pinctrl 驱动程序 Makefile

<linux>/drivers/rtkdrivers/pinctrl/realtek-pinctrl-ameba.c

Pinctrl 函数表和初始化

<linux>/drivers/rtkdrivers/pinctrl/realtek-pinctrl.c

Pinctrl 函数

<linux>/drivers/rtkdrivers/pinctrl/realtek-pinctrl.h

引脚控制相关的函数声明、宏定义、结构定义以及引用的其他头文件

<linux>/include/dt-bindings/realtek/pinctrl/realtek-ameba-pinfunc.h

Pinctrl 定义

配置

设备树配置

pinctrl 有关的设备树在 <dts>/rtl8730e-pinctrl.dtsi

pinctrl 驱动程序设备树配置

pinctrl 的父部分列在下表中。

属性

描述

默认值

可配置?

compatible

IR 驱动的描述。

realtek,ameba-pinctrl

reg

IR 设备的硬件地址和大小。

<0x42008A00 0x120>

address-cells

表示子节点地址长度,单位为 32 比特。

1

size-cells

表示子节点长度,单位为 32 比特。

1

pinctrl 是一种平台总线设备驱动模型。在 Linux 内核中,当一个平台设备和平台驱动程序匹配时,在执行其驱动/总线探测之前,Linux 内核会自动执行设备和 pinctrl 子系统的绑定,并自动配置相应的引脚功能和特性。

其他驱动程序的 pinctrl 配置

支持其他驱动程序的方法是在 pinctrl 节点下定义一个子节点。格式为:

[driver_name]_pins_[pin_name]: [abbreviation]@[pin_num] {
  pins {
    pinmux = <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>,
      <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>,
      <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>,
      <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>;
    bias-pull-up;
    slew-rate = <0>;
    drive-strength = <0>;
  };
};

如果用户需要添加更多引脚(这里以两个引脚为例),格式为:

[driver_name]_pins_[pin_name]: [abbreviation]@[pin_num] {
  pins1 {
    pinmux = <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>,
    <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>,
    <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>,
    <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>;
    bias-pull-up;
    slew-rate = <0>;
    drive-strength = <0>;
  };
  pins2 {
    pinmux = <REALTEK_PINMUX('[A/B/C]', [pin_num], [hardware_driver_id])>;
    bias-pull-up;
    swd-disable;
    slew-rate = <0>;
    drive-strength = <0>;
  };
};

“[]”中的描述应由驱动程序指定。

  • [driver_name]_pins_[pin_name] 将在驱动程序向其自身设备树节点添加 pinctrl 时使用。

  • [A/B/C] 代表 PA、PB 或 PC 组,详情请参考引脚复用硬件信息。

  • PA1 的 [pin_num] 是 1,详情请参考引脚复用硬件信息。

  • [hardware_driver_id] 可以在 <sdk>/sources/kernel/<linux>/include/dt-bindings/realtek/pinctrl/realtek-ameba-pinfunc.h 中找到。每一个在 realtek-ameba-pinfunc.h 中的 [hardware_driver_id] 都映射到其硬件功能。例如:在添加 I2C 引脚复用时,只需在此处使用 I2C 宏。

属性的其他描述列在下表中。

属性

描述

可配置?

pinmux

定义引脚组、编号和功能。

pull type

拉低拉高类型,可以设置为以下其中之一:

  • bias-disable: 表示禁用拉低拉高

  • bias-pull-up: 表示拉高

  • bias-pull-down: 表示拉低

slew rate

PAD 转换速率控制,可以设置为 0 或 1

0/1

drive-strength

PAD 驱动能力控制,可以设置为 0 或 1

swd-disable

禁用 pad SWD 功能

可选

audio-share-enable

禁用 pad 音频功能

可选

备注

  • Pins 表示一组引脚功能和属性。如果设备有多个属性,子节点可以被命名为 pins1、pins2……而不是 pins。

  • 如果 PA13 或 PA14 未用于设置 SWD 功能,则需要添加属性 swd-disable

  • 如果 PA18 到 PB6 没有设置为音频功能,则需要添加属性 audio-share-enable

pinctrl 引述

驱动程序的引脚复用(pinmux)是特定于板子的。为特定的驱动程序配置引脚复用时,步骤如下:

  1. 在目录 <dts> 中通过板子的名称找到特定的板级设备树。例子:对于 256M nand 通用板,设备树文件为 rtl8730elh-va8-xxx.dts

  2. 找到该驱动程序 [driver_name] 的完整名称,例如 i2c0。

  3. 添加 pinctrl 引述:

    &[driver_name]{
      pinctrl-names = "default";
      pinctrl-0 = <&[driver_name]_pins_[pin_name]>;
    };
    

    [driver_name]_pins_[pin_name]: 参考 其他驱动程序的 pinctrl 配置

  4. 将会有多个引脚复用组,它们具有不同的 [pin_name] 但相同的 [driver_name]。请根据板子的布局选择正确的组。更多细节请参考硬件用户指南。

  5. 如果特定的引脚复用没有在 pinctrl 设备树中列出,请找到相应的 [driver_name],并根据 其他驱动程序的 pinctrl 配置 中的指导修改 [A/B/C] 和 [pin_num]。

当存在多个引脚控制状态和 phandle 列表时,需要按如下方式配置节点:

&[driver_name]{
pinctrl-names = "default", "sleep";
pinctrl-0 = [driver_name]_pins_[pin_name]>;
pinctrl-1 = [driver_name]_pins_[pin_name];
};

编译配置

选择 Device Drivers > Drivers for Realtek > pinctrl driver:

../../rst_linux/1_gpio/figures/pinctrl_driver.png

APIs

用户空间的 APIs

无。

内核空间的 APIs

描述

pinctrl_get

检索设备的引脚控制句柄

pinctrl_put

减少之前声明的引脚控制句柄的使用计数

devm_pinctrl_get

资源管理 pinctrl_get()

devm_pinctrl_put

资源管理 pinctrl_put()

pinctrl_loopup_state

从引脚控制句柄中检索状态句柄

pinctrl_select_state

选择/激活/编程硬件的引脚控制状态

pinctrl_get_select_default

检索设备的引脚控制句柄,并将引脚控制句柄设置为默认状态

pinctrl_get_select

检索设备的引脚控制句柄,并将其设置为选择状态

devm_pinctrl_get_select_default

资源管理 pinctrl_get_select_default()

devm_pinctrl_get_select

资源管理 pinctrl_get_select()

devm_pinctrl_register

pinctrl_register() 的资源管理版本

pinctrl_register

注册一个 pinctrl

pinctrl_unregister

注销 pinmux

为了使用 pinmux,你可以按照下面步骤执行:

  1. 请求全部 pinctrl 资源。

    devm_pinctrl_get_select_default(dev)
    
  2. 获取 pinctrl 句柄。

    pinctrl = pinctrl_get(dev);
    
  3. 从引脚控制句柄中检索状态句柄,例如“default”状态。

    pinctrl_lookup_state(pinctrl, "default");
    
  4. 选择一个 pinctrl 状态到硬件。

    pinctrl_select_state(pinctrl, state);
    
  5. 释放 pinctrl 句柄。

    pinctrl_put(pinctrl);
    

参考 pinctrl driver api v5.4 或者 pinctrl driver api v6.6 获取更多细节。