Linux 内核中 pinctrl 驱动解析设备树(Device Tree)函数节点

// 遍历每个子节点,解析函数信息
for_each_child_of_node(np, child) {
    // 如果节点不是函数节点,则继续下一个节点
    if (!is_function_node(child))
        continue;
    // 解析函数信息并存储到 info 结构体中
    ret = rockchip_pinctrl_parse_functions(child, info, i++);
    if (ret) {
        dev_err(&pdev->dev, "failed to parse function\n");
        of_node_put(child);
        return ret;
    }
}

这段代码是 Linux 内核中 pinctrl 驱动解析设备树(Device Tree)函数节点的典型实现,用于提取硬件引脚功能配置。以下是逐层解析:


1. 代码功能概述

  • 目标:遍历设备树中 pinctrl 控制器的子节点,识别并解析所有定义引脚功能的节点(如 UART、SPI、I2C 等)。
  • 核心操作
    1. 跳过非函数节点。
    2. 解析函数节点配置(如引脚组、复用设置)。
    3. 存储解析结果到驱动私有数据结构 info
    4. 错误处理(如节点解析失败)。

2. 关键代码逻辑

2.1 遍历子节点

for_each_child_of_node(np, child) {
    // ...
}
  • 作用:遍历设备树节点 np 的所有子节点(child)。
  • 典型场景np 是 pinctrl 控制器的设备树节点(如 rockchip,pinctrl),其子节点定义具体功能(如 uart0_pinsspi1_pins)。
2.2 过滤函数节点

if (!is_function_node(child))
    continue;
  • is_function_node 函数
    • 判断子节点是否为函数节点(Function Node)。
    • 常见实现:检查节点名称是否以 "functions" 开头,或是否有特定属性(如 function = "uart")。
    • 示例设备树片段

      pinctrl_example: pinctrl@ff770000 {
          compatible = "rockchip,pinctrl";
          // 子节点定义具体功能
          uart0_pins: uart0-pins {
              rockchip,function = "uart0";
              rockchip,pins = <PINMUX_GPIO0_A0>;
          };
      };
2.3 解析函数节点

ret = rockchip_pinctrl_parse_functions(child, info, i++);
  • rockchip_pinctrl_parse_functions 函数
    • 输入:当前子节点 child、驱动私有数据 info、当前函数索引 i
    • 操作
      1. 读取节点属性(如 rockchip,functionrockchip,pins)。
      2. 解析引脚组(Pin Group)和复用配置。
      3. 将配置存储到 info->functions[i] 数组中。
    • 示例解析逻辑

      // 解析函数名称
      of_property_read_string(child, "rockchip,function", &func_name);
      // 解析关联的引脚组
      of_property_read_u32_array(child, "rockchip,pins", pins, num_pins);
      // 存储到 info 结构体
      info->functions[i].name = func_name;
      info->functions[i].pins = pins;
2.4 错误处理

if (ret) {
    dev_err(&pdev->dev, "failed to parse function\n");
    of_node_put(child);
    return ret;
}
  • 释放资源of_node_put(child) 减少设备树节点的引用计数,避免内存泄漏。
  • 错误传播:返回错误码,终止驱动初始化。

3. 数据结构关联

3.1 info 结构体
  • 定义:存储 pinctrl 控制器的配置信息(如支持的功能、引脚组)。
  • 典型字段
    
    

    struct rockchip_pinctrl_info {
        struct pinctrl_desc pctl_desc;
        struct rockchip_pin_bank *banks;
        struct rockchip_pin_function *functions;
        int num_functions;
        // ...
    };

  • functions 数组:存储解析后的所有函数配置,索引由 i 指定。
3.2 函数节点与驱动的关联
  • 设备树到驱动的映射
    • 设备树中的每个函数节点(如 uart0_pins)对应驱动中的一个 struct rockchip_pin_function
    • 驱动通过 info->functions 数组管理所有可用功能,供后续引脚复用配置使用。

4. 实际应用场景

4.1 驱动初始化阶段
  • probe 函数:在设备绑定时调用,完成硬件配置的初始化。
  • 流程示例
    1. 解析设备树根节点(np)。
    2. 遍历子节点,提取所有函数配置。
    3. 注册 pinctrl 设备(pinctrl_register)。
4.2 运行时配置
  • 引脚复用:通过 pinctrl_select_state 选择预定义的函数配置。

    // 选择 uart0 功能
    pinctrl_state = pinctrl_lookup_state(pctldev, "uart0");
    pinctrl_select_state(pctldev, pinctrl_state);

5. 代码设计意图

  • 硬件抽象:通过设备树描述硬件功能,驱动代码与具体芯片解耦。
  • 可扩展性:新增功能只需修改设备树,无需修改驱动代码。
  • 错误安全:严格检查解析结果,避免无效配置导致系统不稳定。

总结

这段代码是 pinctrl 驱动中设备树解析的核心部分,通过遍历和解析函数节点,将硬件引脚功能配置抽象为驱动可用的数据结构,实现了:

  1. 硬件配置的灵活管理:通过设备树动态定义功能,适应不同硬件变体。
  2. 驱动与硬件的解耦:驱动代码不依赖具体芯片,提升可移植性。
  3. 错误早期发现:在初始化阶段验证配置有效性,减少运行时风险。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值