pinctrl 驱动的初始化

这行代码是 Linux 内核中用于动态分配引脚描述符(pin descriptor)数组的典型实现,常见于 pinctrl 驱动的初始化阶段。以下是逐层解析:


1. 函数原型解析

pindesc = devm_kcalloc(&pdev->dev, info->ctrl->nr_pins, sizeof(*pindesc), GFP_KERNEL);
1.1 devm_kcalloc 函数
  • 作用:内核设备管理(Device Managed)的内存分配函数,用于分配连续内存块,并自动绑定到设备生命周期。
  • 特性
    • 内存会在设备驱动卸载时自动释放,无需手动调用 kfree
    • 分配的内存初始化为零(等效于 kcalloc)。
  • 参数
    1. &pdev->dev:指向当前设备的 struct device 指针,标记内存所属设备。
    2. info->ctrl->nr_pins:要分配的元素数量(即引脚总数)。
    3. sizeof(*pindesc):每个元素的大小(pindesc 指向的结构体大小)。
    4. GFP_KERNEL:内存分配标志,表示在内核上下文中分配,可能触发睡眠。

2. 关键数据结构

2.1 pdev(Platform Device)
  • 类型:struct platform_device *
  • 含义:表示当前平台设备(如 SoC 上的 pinctrl 控制器)。
  • &pdev->dev:获取设备的 struct device 结构体,用于资源管理。
2.2 info(控制器信息)
  • 类型:通常为 struct example_pinctrl *(驱动私有数据)。
  • info->ctrl:指向控制器描述符(如 struct example_pinctrl_ctrl),包含:
    • nr_pins:控制器管理的引脚总数。
2.3 pindesc(引脚描述符数组)
  • 类型:struct pin_desc *(假设 pin_desc 是引脚描述符结构体)。
  • 含义:存储每个引脚的配置信息(如引脚号、功能、电气参数等)。

3. 代码逻辑

3.1 分配内存
  • 目的:为控制器管理的所有引脚分配存储空间。
  • 示例:若 nr_pins = 32,则分配 32 * sizeof(struct pin_desc) 字节的内存。
  • 内存布局
    
    

    struct pin_desc {
        unsigned int pin;       // 引脚编号(如 GPIO0)
        unsigned long function;  // 功能复用配置(如 UART_TX)
        unsigned long config;   // 电气参数(如上拉、驱动强度)
        // ... 其他字段
    };
3.2 绑定到设备生命周期
  • 通过 devm_kcalloc 分配的内存会自动绑定到 pdev->dev
  • 当设备驱动卸载时(如 remove 函数被调用),内核会自动释放该内存,避免泄漏。

4. 典型使用场景

在 pinctrl 驱动的 probe 函数中,分配引脚描述符数组以初始化控制器:

static int example_pinctrl_probe(struct platform_device *pdev) {
    struct example_pinctrl *info;
    struct pin_desc *pindesc;

    // 1. 分配驱动私有数据
    info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);

    // 2. 从设备树解析控制器信息(如引脚总数)
    info->ctrl = parse_controller_dt(pdev);

    // 3. 分配引脚描述符数组
    pindesc = devm_kcalloc(&pdev->dev, info->ctrl->nr_pins,
                          sizeof(*pindesc), GFP_KERNEL);

    // 4. 填充引脚描述符(如解析设备树中的引脚配置)
    for (int i = 0; i < info->ctrl->nr_pins; i++) {
        pindesc[i].pin = i;
        pindesc[i].function = PIN_FUNCTION_GPIO;
    }

    // 5. 注册 pinctrl 设备
    info->pctldev = pinctrl_register(&example_pinctrl_desc, &pdev->dev, info);

    return 0;
}

5. 内存管理优势

  • 自动释放:无需在 remove 函数中手动释放 pindesc
  • 避免泄漏:即使驱动初始化失败,内核也会清理已分配的内存。
  • 简化代码:减少内存管理代码量,提升可维护性。

6. 替代方案对比

函数行为适用场景
devm_kcalloc分配并清零,自动释放驱动初始化时分配长期使用的内存
kzalloc分配并清零,需手动释放临时内存或非设备相关的内存
devm_kmalloc分配,自动释放无需清零的内存(如结构体指针)

总结

这行代码通过 devm_kcalloc 为 pinctrl 控制器分配了一个引脚描述符数组,实现了:

  1. 硬件抽象:为每个引脚存储配置信息,供后续引脚复用和电气参数配置使用。
  2. 资源安全:利用设备管理的内存分配,避免内存泄漏。
  3. 代码简洁:减少手动内存管理代码,聚焦核心逻辑(如寄存器操作)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值