pinctrl_desc结构体注册

news2024/11/24 19:44:55

pinctrl_desc结构体注册


文章目录

  • pinctrl_desc结构体注册
  • pinctrl_register
  • pinctrl_register_pins注册所有的引脚


在这里插入图片描述

pinctrl_register

构建好struct pinctrl_desc结构以后,会调用pinctrl_register函数注册一个pinctrl控制器,得到一个pinctrl_dev

struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
                struct device *dev, void *driver_data);

/**
 * pinctrl_register() - register a pin controller device
 * @pctldesc: descriptor for this pin controller
 * @dev: parent device for this pin controller
 * @driver_data: private pin controller data for this pin controller
 */
struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
                    struct device *dev, void *driver_data)
{
    // 分配内存空间用于存储 pinctrl_dev 结构体
    struct pinctrl_dev *pctldev;
    int ret;

    // 检查 pctldesc 是否为空
    if (!pctldesc)
        return NULL;
    // 检查 pctldesc 的名称是否为空
    if (!pctldesc->name)
        return NULL;

    // 分配内存空间用于存储 pinctrl_dev 结构体
    pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);
    if (pctldev == NULL) {
        dev_err(dev, "failed to alloc struct pinctrl_dev\n");
        return NULL;
    }

    /* 初始化 pin control 设备结构体 */
    pctldev->owner = pctldesc->owner;
    pctldev->desc = pctldesc;
    pctldev->driver_data = driver_data;
    INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
    INIT_LIST_HEAD(&pctldev->gpio_ranges);
    pctldev->dev = dev;
    mutex_init(&pctldev->mutex);

    /* 检查核心操作是否正常 */
    if (pinctrl_check_ops(pctldev)) {
        dev_err(dev, "pinctrl ops lacks necessary functions\n");
        goto out_err;
    }

    /* 如果实现了 pinmuxing,则检查操作是否正常 */
    if (pctldesc->pmxops) {
        if (pinmux_check_ops(pctldev))
            goto out_err;
    }

    /* 如果实现了 pinconfig,则检查操作是否正常 */
    if (pctldesc->confops) {
        if (pinconf_check_ops(pctldev))
            goto out_err;
    }

    /* pinctrl_register_pins注册所有的引脚 */
    dev_dbg(dev, "try to register %d pins ...\n",  pctldesc->npins);
    ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
    if (ret) {
        dev_err(dev, "error during pin registration\n");
        pinctrl_free_pindescs(pctldev, pctldesc->pins,
                      pctldesc->npins);
        goto out_err;
    }

    mutex_lock(&pinctrldev_list_mutex);  // 加锁以保证互斥访问 pinctrldev_list
    list_add_tail(&pctldev->node, &pinctrldev_list);  // 将当前 pctldev 添加到 pinctrldev_list 的尾部
    mutex_unlock(&pinctrldev_list_mutex);  // 解锁 pinctrldev_list

    pctldev->p = pinctrl_get(pctldev->dev);  // 获取 pctldev 的 pinctrl 结构体指针

    if (!IS_ERR(pctldev->p)) {  // 如果 pctldev 的 pinctrl 结构体指针有效
        pctldev->hog_default =  // 获取默认状态的 pinctrl_state 结构体指针
            pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
        if (IS_ERR(pctldev->hog_default)) {  // 如果获取默认状态失败
            dev_dbg(dev, "failed to lookup the default state\n");  // 输出调试信息
        } else {
            if (pinctrl_select_state(pctldev->p,  // 选择默认状态
                        pctldev->hog_default))
                dev_err(dev,
                    "failed to select default state\n");  // 输出错误信息
        }

        pctldev->hog_sleep =  // 获取睡眠状态的 pinctrl_state 结构体指针
            pinctrl_lookup_state(pctldev->p,
                            PINCTRL_STATE_SLEEP);
        if (IS_ERR(pctldev->hog_sleep))  // 如果获取睡眠状态失败
            dev_dbg(dev, "failed to lookup the sleep state\n");  // 输出调试信息
    }

    pinctrl_init_device_debugfs(pctldev);  // 初始化 pctldev 的 debugfs

    return pctldev;  // 返回 pctldev 结构体指针

out_err:
    mutex_destroy(&pctldev->mutex);  // 销毁互斥锁
    kfree(pctldev);  // 释放内存空间
    return NULL;  // 返回空指针
}
EXPORT_SYMBOL_GPL(pinctrl_register);

这是一个名为 pinctrl_register 的函数,用于注册一个引脚控制器设备。以下是该函数的详细分析:
首先,函数会检查传入的 pctldesc 是否为空,以及 pctldesc->name 是否为空,如果为空,则返回空指针。
接着,函数会分配内存空间来存储 pinctrl_dev 结构体,并对分配的内存空间进行初始化。如果分配内存失败,则会打印错误信息并返回空指针。
然后,函数会对 pctldev 结构体的各个成员进行初始化,包括 owner、desc、driver_data、pin_desc_tree、gpio_ranges、dev 和 mutex 等。
接下来,函数会检查引脚控制器的操作函数是否正常。如果检查不通过,则会打印错误信息并跳转到错误处理标签 out_err。
如果引脚控制器实现了引脚复用操作 (pinmux),则会检查引脚复用操作的函数是否正常。如果检查不通过,则会跳转到错误处理标签 out_err。
如果引脚控制器实现了引脚配置操作 (pinconfig),则会检查引脚配置操作的函数是否正常。如果检查不通过,则会跳转到错误处理标签 out_err。
接着,函数会注册所有的引脚,调用 pinctrl_register_pins 函数进行引脚的注册。如果注册过程中发生错误,则会打印错误信息,释放已注册的引脚描述符,并跳转到错误处理标签 out_err。
在互斥锁保护下,将当前的 pctldev 添加到全局链表 pinctrldev_list 的尾部。
获取 pctldev 的 pinctrl 结构体指针,并尝试选择默认状态和睡眠状态。
初始化 pctldev 的 debugfs 接口,用于调试和配置。
返回 pctldev 结构体指针,表示引脚控制器注册成功。
如果在注册过程中发生错误,会清理已分配的资源,包括销毁互斥锁和释放内存空间,并返回空指针。

综上所述,pinctrl_register 函数用于注册一个引脚控制器设备,并进行必要的初始化操作。它会校验和初始化设备结构体,注册引脚,选择默认状态和睡眠状态,并提供调试接口。

pinctrl_register_pins注册所有的引脚

static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
                    unsigned number, const char *name)
{
    // 获取pin描述符
    struct pin_desc *pindesc;

    // 检查pin是否已经在pinctrldev上注册
    pindesc = pin_desc_get(pctldev, number);
    if (pindesc != NULL) {
        pr_err("pin %d already registered on %s\n", number,
               pctldev->desc->name);
        return -EINVAL;
    }

    // 分配并初始化pin描述符
    pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
    if (pindesc == NULL) {
        dev_err(pctldev->dev, "failed to alloc struct pin_desc\n");
        return -ENOMEM;
    }

    /* 设置拥有者 */
    pindesc->pctldev = pctldev;

    /* 复制基本的pin信息 */
    if (name) {
        pindesc->name = name;
    } else {
        pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number);
        if (pindesc->name == NULL) {
            kfree(pindesc);
            return -ENOMEM;
        }
        pindesc->dynamic_name = true;
    }

    // 将pin描述符插入到pin描述符树中
    radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);
    pr_debug("registered pin %d (%s) on %s\n",
         number, pindesc->name, pctldev->desc->name);
    return 0;
}

static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
                 struct pinctrl_pin_desc const *pins,
                 unsigned num_descs)
{
    unsigned i;
    int ret = 0;

    // 遍历所有的pin描述符
    for (i = 0; i < num_descs; i++) {
        // 注册单个pin
        ret = pinctrl_register_one_pin(pctldev,
                           pins[i].number, pins[i].name);
        if (ret)
            return ret;
    }

    return 0;
}

这里给出了两个函数:pinctrl_register_one_pin 和 pinctrl_register_pins,它们用于在引脚控制器中注册引脚。
函数 pinctrl_register_one_pin 的功能是注册单个引脚。它的主要步骤包括:
首先,函数会检查该引脚是否已经在引脚控制器上注册过,通过调用 pin_desc_get 函数来获取对应引脚的描述符。如果已经注册过,则会打印错误信息并返回错误码 -EINVAL。
如果该引脚还未注册过,函数会分配内存空间来存储引脚描述符,并对分配的内存空间进行初始化。

设置引脚描述符的拥有者为当前的引脚控制器。

复制基本的引脚信息,包括引脚名称。如果名称已经提供,则直接使用提供的名称;否则,会生成一个默认的名称,并将其存储在引脚描述符中。如果生成默认名称的过程中出现内存分配失败,则会释放已分配的内存空间并返回错误码 -ENOMEM。

将引脚描述符插入到引脚描述符树中,使用引脚的编号作为键值。

打印调试信息,表示成功注册了该引脚。

返回 0,表示引脚注册成功。

函数 pinctrl_register_pins 的功能是注册一组引脚。它的主要步骤包括:
遍历所有的引脚描述符。

对于每个引脚描述符,调用 pinctrl_register_one_pin 函数来注册单个引脚。如果注册过程中发生错误,则直接返回错误码。
如果所有引脚都成功注册,则返回 0,表示引脚注册成功。

综上所述,这两个函数用于在引脚控制器中注册引脚。首先,pinctrl_register_one_pin 函数用于注册单个引脚,它分配内存并初始化引脚描述符,然后将其插入到引脚描述符树中。其次,pinctrl_register_pins 函数用于注册一组引脚,它遍历引脚描述符数组并调用 pinctrl_register_one_pin 函数来逐个注册引脚。这些函数为引脚控制器的引脚注册提供了必要的功能和接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/845354.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【大数据】Flink 详解(二):核心篇 Ⅰ

Flink 详解&#xff08;二&#xff09;&#xff1a;核心篇 Ⅰ 14、Flink 的四大基石是什么&#xff1f; ​ Flink 的四大基石分别是&#xff1a; Checkpoint&#xff08;检查点&#xff09;State&#xff08;状态&#xff09;Time&#xff08;时间&#xff09;Window&#xff…

【机器学习2】什么是Jupyter notebook 新手使用Jupter notebook

什么是Jupyter notebook? Jupyter Notebook&#xff08;此前被称为 IPython notebook&#xff09;是一个交互式笔记本&#xff0c;支持运行 40 多种编程语言。 Jupyter Notebook 的本质是一个 Web 应用程序&#xff0c;便于创建和共享程序文档&#xff0c;支持实时代码&#x…

Redis 7.X Linux 环境安装

Redis 简介 作为一名开发人员&#xff0c;想必大家对Redis一定是耳熟能详&#xff0c;因此在此只做简单介绍。 Remote Dictionary Server(远程字典服务)是完全开源的&#xff0c;使用ANSIC语言编写遵守BSD协议&#xff0c;是一个高性能的Key-Value内存数据库&#xff0c;它提…

命令模式(C++)

定义 将一个请求(行为)封装为一个对象&#xff0c;从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志&#xff0c;以及支持可撤销的操作。 应用场景 在软件构建过程中&#xff0c;“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合——比…

iPhone苹果手机地震预警功能怎么开启?

iPhone苹果手机地震预警功能怎么开启&#xff1f; 1、打开iPhone苹果手机设置&#xff1b; 2、在iPhone苹果手机设置内找到辅助功能&#xff1b; 3、在辅助功能内找到触控&#xff1b; 4、在iPhone苹果手机辅助功能触控内找到振动&#xff0c;如果是关闭状态请启&#xff1b; …

jdk1.7与jdk1.8中String.split()方法问题

split切割字符串的坑&#xff0c;会有索引越界的风险。 在jdk1.8中 public static void main(String[] args) { String card "abcdefgh"; System.out.println(card.split("").length); } 结果&#xff1a;8 在jdk1.7中&#xff0c;同样的代码 …

kubectl 详解(陈述式资源管理与声明式资源管理)

目录 一、kubectl简介 二、kubectl基础命令 三、基本信息查看 1.查看标签信息 ​2. 查看 master 节点状态 3. 查看命名空间 4.创建、删除命名空间app 5.在命名空间kube-public 创建副本控制器&#xff08;deployment&#xff09;来启动Pod&#xff08;nginx-www&#xf…

网关 GateWay 的使用详解、路由、过滤器、跨域配置

一、网关的基本概念 SpringCloudGateway网关是所有微服务的统一入口。 1.1 它的主要作用是&#xff1a; 反向代理&#xff08;请求的转发&#xff09; 路由和负载均衡 身份认证和权限控制 对请求限流 1.2 相比于Zuul的优势&#xff1a; SpringCloudGateway基于Spring5中…

libcurl网络库的函数接口使用

文章目录 1、libcurl简介2、libcurl的使用3、函数简介4、 curl_easy_setopt函数部分选项介绍5、curl_easy_perform 函数说明&#xff08;error 状态码&#xff09;6、简单实例,包含库文件&#xff0c;头文件即可 1、libcurl简介 libcurl是一个跨平台的网络协议库&#xff0c;支…

【福建事业单位-推理判断】02图形推理(数量-空间重构)

【福建事业单位-推理判断】02图形推理&#xff08;数量-空间重构&#xff09; 一、数量规律1.1点&#xff08;交点、切点&#xff09;点的细化考法总结 1.2线条&#xff08;线条的数量&#xff09;线的细化考点一笔画&#xff08;重点&#xff09;一笔画的判定 总结 1.3 面面的…

PWNlab靶机渗透

安装靶机 下载地址&#xff1a;https://www/vulnhub.com/entry/pwnlab-init,158/ 信息收集&#xff1a; 收集靶机ip地址&#xff0c;由于搭建在本地使用kali自带命令 arp-scan -l nmap 扫描端口&#xff0c;服务 nmap -sV -p 1-65535 -A 靶机ip地址 漏洞探测 访问80端口地…

LeetCode--HOT100题(21)

目录 题目描述&#xff1a;240. 搜索二维矩阵 II&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;240. 搜索二维矩阵 II&#xff08;中等&#xff09; 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&am…

2023 RISC-V中国峰会 安全相关议题汇总

安全相关议题 1、The practical use cases of the RISC-V IOPMP 2、构建安全可信、稳定可靠的RISC-V安全体系 3、Enhancing RISC-V Debug Security with hardware-based isolation 4、Closing a side door: Designing high-performance RISC-V core resilient to branch pr…

javascript:js介绍初体验和变量以及数据类型的使用。

目录 一.介绍 1概念 2作用 3组成 二.js初体验 1.js的书写位置 a.行间引入 b.内部引入 c.外部引入​编辑 2.js的注释 3.js的结束符 4.输入输出语句 输出语法 输入语法 三.变量及数据类型 ​ 1.字面量 2.变量 ​编辑 变量的使用 ​编辑 let和var的区别…

力扣17(电话号码中的字符组合)

题目表述 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例1 输入&#xff1a;digits "23" 输出&#xff1…

用html+javascript打造公文一键排版系统16:更新单个附件说明排版,实现多个附件说明排版

利用公休的时间继续完善。 一、更新单个附件说明排版 之前实现单个附件说明排版时&#xff0c;我们只考虑了“附件&#xff1a;”中冒号为半角的情况&#xff0c;而没有考虑存在多任余空格的情况&#xff0c;我们今天先针对存在多任余空格的情况进行完善&#xff0c;增加了温…

安装element-plus报错:Conflicting peer dependency: eslint-plugin-vue@7.20.0

VSCode安装element-plus报错&#xff1a; D:\My Programs\app_demo>npm i element-plus npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: vue/eslint-config-standard6.1.0 npm ERR! Found: eslint-plugin-vue8.7.1 npm E…

如何离线安装ModHeader - Modify HTTP headers Chrome插件?

如何离线安装ModHeader - Modify HTTP headers Chrome插件&#xff1f; 1.1 前言1.2 打开Chrome浏览器的开发者模式1.3 下载并解压打包好的插件1.4 解压下载好的压缩包1.5 加载插件1.6 如何使用插件? 1.1 前言 ModHeader 是一个非常好用的Chrome浏览器插件&#xff0c;可以用…

scala连接mysql数据库

scala中通常是通过JDBC组件来连接Mysql。JDBC, 全称为Java DataBase Connectivity standard。 加载依赖 其中包含 JDBC driver <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29&l…

pl/sql函数如何返回多行数据

用游标即可&#xff1a; SQL code ? 1 2 3 4 5 6 7 8 9 10 11 12 Create or REPLACE FUNCTION getCursorList( P_USER_ID_I IN VARCHAR2 --接收输入参数 ) RETURN SYS_REFCURSOR AS P_RESULT_SET_O SYS_REFCURSOR…