Lazy loaded image
pinctrl专题02 -client端使用pinctrl过程的情景分析_基于IMX6ULL
Words 2589Read Time 7 min
2025-4-24
 

pinctrl的系统架构

  • 采用分层设计,将硬件细节与功能驱动分离
  • 包括客户端驱动、pinctrl API、pinctrl核心、pinctrl映射和pinctrl驱动几个层次
客户端与 pinctrl组件关系图如下:
这种设计将硬件细节与功能驱动分离,使得功能驱动无需关心底层引脚配置细节,只需通过简单的 API 就能完成引脚状态管理,大大提高了代码的可维护性和可移植性。

一、数据结构和关系

1.1 数据结构关系图

  1. 客户端与 pinctrl 的关系
      • 客户端设备通过 pinctrl 指针使用 pinctrl 服务
      • 一个客户端设备对应一个 struct pinctrl 实例
  1. pinctrl 与状态的关系
      • 一个 struct pinctrl 包含多个 struct pinctrl_state
      • 这些状态通过 states 链表连接
  1. 状态与设置的关系
      • 一个 struct pinctrl_state 包含多个 struct pinctrl_setting
      • 这些设置通过 settings 链表连接
  1. 设置与控制器的关系
      • 每个 struct pinctrl_setting 引用一个 struct pinctrl_dev
      • 设置通过控制器的操作函数被应用到硬件

1.2 数据结构说明

1. struct pinctrl

功能作用
  • 代表一个客户端设备的 pinctrl 句柄
  • 管理设备的所有 pinctrl 状态和映射
  • 连接客户端设备与 pinctrl 子系统
主要成员
  • dev:指向客户端设备
  • states:包含所有状态的链表
  • dt_maps:包含从设备树解析的映射
使用场景
  • 客户端驱动通过 devm_pinctrl_get() 获取此结构
  • 用于查找和选择不同的引脚状态

2. struct pinctrl_state

功能作用
  • 表示一个特定的引脚配置状态(如 "default"、"sleep")
  • 包含应用此状态所需的所有设置
主要成员
  • name:状态名称(如 "default"、"sleep")
  • settings:包含此状态下所有设置的链表
使用场景
  • 客户端通过 pinctrl_lookup_state() 获取
  • 通过 pinctrl_select_state() 应用状态

3. struct pinctrl_setting

功能作用
  • 表示单个引脚或引脚组的具体设置
  • 可以是复用设置或配置设置
主要成员
  • type:设置类型(PIN_MAP_TYPE_MUX_GROUP 或 PIN_MAP_TYPE_CONFIGS_*)
  • pctldev:指向处理此设置的 pinctrl 控制器
  • data:联合体,包含具体设置数据
使用场景
  • 当应用状态时,每个设置被传递给相应的 pinctrl 驱动

4. struct pinctrl_dev

功能作用
  • 表示一个 pinctrl 控制器设备
  • 提供操作引脚的接口
  • 由 pinctrl 驱动注册
主要成员
  • desc:控制器描述符
  • ops:基本操作函数集(如获取组)
  • pmxops:复用操作函数集
  • confops:配置操作函数集
使用场景
  • 由 pinctrl 驱动通过 pinctrl_register() 注册
  • 处理来自客户端的引脚请求

5. struct client_device

功能作用
  • 表示使用 pinctrl 服务的客户端设备
  • 存储设备的 pinctrl 句柄和常用状态
主要成员
  • pinctrl:指向设备的 pinctrl 句柄
  • default_state:默认状态句柄
  • sleep_state:睡眠状态句柄
使用场景
  • 客户端驱动初始化时获取 pinctrl 和状态
  • 在电源管理时切换状态
 

二、使用流程分析

客户端驱动使用 pinctrl 的过程主要包括两个阶段:
  1. 构造阶段
      • 在设备树中定义 pinctrl 属性
      • 驱动通过 devm_pinctrl_get() 获取 pinctrl 句柄
      • 通过 pinctrl_lookup_state() 查找预定义状态
  1. 使用阶段
      • 通过 pinctrl_select_state() 切换引脚状态
      • 在不同场景(如初始化、休眠、唤醒)选择不同状态

2.1 client 节点的 pinctrl 构造过程

2.1.1 设备树中的 pinctrl 定义

客户端驱动使用 pinctrl 的第一步是在设备树中定义 pinctrl 节点。典型的客户端节点 pinctrl 定义如下:
其中:
  • pinctrl-names 定义了不同的状态名称
  • pinctrl-0pinctrl-1 等对应于不同状态下的引脚配置

2.1.2 构造 pinctrl 过程

时序图
函数调用栈
  1. 客户端获取 pinctrl 句柄
      • devm_pinctrl_get(dev) - 客户端驱动调用此函数获取 pinctrl 句柄
      • 内部调用 pinctrl_get() 进行实际处理
  1. pinctrl_get() 函数处理
    1. 设备树解析
      1. pinctrl_dt_to_map() // 从设备树节点创建映射
    1. 映射创建和转化设置
      1. 映射创建过程
          • 系统从设备树中读取 pinctrl-X 属性,其中 X 是一个数字,表示不同的状态(如默认状态、睡眠状态等)
          • 对每个 pinctrl-X 属性,调用 dt_to_map_one_config() 函数处理
      2. dt_to_map_one_config() 函数
          • 通过 of_find_node_by_phandle() 找到对应的 pinctrl 节点
          • 调用特定 pinctrl 驱动实现的 dt_node_to_map() 函数创建映射
          • 不同的 SoC 有不同的实现,例如:
            • sirfsoc_dt_node_to_map() - SiRF SoC
            • imx_dt_node_to_map() - i.MX SoC
            • stm32_pctrl_dt_subnode_to_map() - STM32 SoC
      3. dt_node_to_map() 函数
          • 创建两种类型的映射:
            • PIN_MAP_TYPE_MUX_GROUP:用于配置引脚复用功能
            • PIN_MAP_TYPE_CONFIGS_PIN:用于配置引脚电气特性(如上拉/下拉、驱动强度等)
      4. pinconf_map_to_setting() 函数
          • pinctrl_map 结构转换为 pinctrl_setting 结构
          • 根据映射类型设置相应的字段
          • 复制配置数据,如您提到的代码片段:
      1. 状态查找
          • 创建 pinctrl_state 结构体表示每个状态
          • 将状态与映射关联起来

      2.2 切换 state 情景分析

      总体的状态转换图

      2.2.1 切换 state 函数调用栈

      2.2.2 详细函数调用分析

      1. 查找状态
          • 客户端调用 pinctrl_lookup_state(p, "default") 查找名为 "default" 的状态
          • 内部调用 find_state() 在已创建的状态列表中查找
      1. 选择状态
          • 客户端调用 pinctrl_select_state(p, state) 应用状态配置
          • 此函数会处理两种类型的设置:复用设置和配置设置
      1. 复用设置处理
        1. 配置设置处理
          1. IMX 平台的实现
              • 对于 IMX 平台,最终会调用 imx_pmx_set() 设置引脚复用
              • 调用 imx_pinconf_set() 设置引脚配置
              • 根据 SoC 类型选择不同的后端实现(内存映射或 SCU)

          2.2.3 常见切换 state 场景

          1. 驱动初始化时
            1. 电源管理场景
               
               
              上一篇
              模板设计模式:让你的代码结构更清晰
              下一篇
              Guide to Linux System

              Comments
              Loading...