pinctrl子系统 - 架构和结构体关系(四)

news2024/10/2 12:16:49

一,pinctrl的引入

由于SoC系统越来越复杂、集成度越来越高,SoC中pin的数量也越来越多、功能也越来越复杂,这就对如何管理、使用这些pins提出了挑战。因此,用于管理这些pins的硬件模块(pin controller)就出现了。相应地,linux kernel也出现了对应的驱动(pin controller driver)。

1,pinctrl的作用

想要pinA、B用于GPIO,需要设置IOMUX让它们连接到GPIO模块;要想让pinA、B用于I2C,需要设置IOMUX让它们连接到I2C模块,这里GPIO、I2C应该是并列的关系,它们能够使用之前,需要设置复用关系IOMUX,有时还要配置引脚,比如上拉、下拉、开漏等等。现在芯片一般动辄几百个引脚,在使用到GPIO、I2C等功能时,若一个引脚一个引脚去找对应的寄存器进行配置非常浪费时间和精力,所以内核引入了Pinctrl子系统,把引脚的复用和配置抽象出来,只需要芯片厂商把自家芯片的支持进去,就可以很方便的配置引脚。

Pinctrl:Pin Controller,顾名思义,就是用来控制引脚的:

1)引脚枚举与命名(Enumerating and naming)

2)引脚复用(Multiplexing):比如用作GPIO、I2C或其他功能

3)引脚配置(Configuration):比如上拉、下拉、开漏、驱动强度等

2,pinctrl的重要概念

Pinctrl子系统涉及2个对象:Pin controller devices、Pinctrl client devices。

Pin controller devices:提供服务,可以用它来复用引脚、配置引脚,是一个软件上的概念。

注意:Pin controller和GPIO Controller不同,前者控制的引脚可用于GPIO功能、I2C功能;后者只是把引脚配置为输入、输出等简单的功能。两者的关系是先用Pin controller把引脚配置为GPIO,再用GPIO Controler把引脚配置为输入或输出。

Pinctrl client devices:使用服务,Pinctrl系统的客户,即使用Pinctrl系统的设备。声明自己要使用哪些引脚的哪些功能,怎么配置它们。

在设备树中,上述两个对象被定义成两个节点,pin controller server节点举例如下:

//qcom AOSP pin controller device
tlmm: pinctrl@f000000 {
    compatible = "qcom,diwali-pinctrl";
    reg = <0x0F000000 0x1000000>;
    interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <2>;
    wakeup-parent = <&pdc>;
    qcom,gpios-reserved = <32 33 34 35>;

    //一个device需要用到的所有pinctrl state资源
    pmx_ts_active {
        ts_active: ts_active {
            mux {
                pins = "gpio129", "gpio51";
                function = "gpio";
            };

            config {
                pins = "gpio129", "gpio51";
                drive-strength = <8>;
                bias-pull-up;
            };
        };
    };

    pmx_ts_int_suspend {
        ts_int_suspend: ts_int_suspend {
            mux {
                pins = "gpio51";
                function = "gpio";
            };

            config {
                pins = "gpio51";
                drive-strength = <2>;
                bias-pull-down;
            };
        };
    };

    pmx_ts_reset_suspend {
        ts_reset_suspend: ts_reset_suspend {
            mux {
                pins = "gpio129";
                function = "gpio";
            };

            config {
                pins = "gpio129";
                drive-strength = <2>;
                bias-pull-down;
            };
        };
    };

    pmx_ts_release {
        ts_release: ts_release {
            mux {
                pins = "gpio129", "gpio51";
                function = "gpio";
            };

            config {
                pins = "gpio129", "gpio51";
                drive-strength = <2>;
                bias-disable;
            };
        };
    };

};

pinctrl client 节点举例:

//一个device的pinctrl state配置
xxx@xx {
    pinctrl-names = "pmx_ts_active", "pmx_ts_suspend", "pmx_ts_release";
    pinctrl-0 = <&ts_active>;
    pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;                    
    pinctrl-2 = <&ts_release>;    
};

Pin controller节点的格式,没有统一的标准!!!!每家芯片都不一样,甚至上面的group、function关键字也不一定有,但是概念是有的。而client device节点的格式是统一的。

这是由于怎么去解析Pincontroller节点下的子节点完全是有芯片厂商决定,内核Pinctrl驱动框架只定义了解析节点的接口而已,而Client端是由内核代码统一管理的。

二,pin control subsystem的文件列表

1、源文件列表

我们整理linux/drivers/pinctrl目录下pin control subsystem的源文件列表如下:

文件名

描述

core.c core.h

pin control subsystem的core driver

pinctrl-utils.c pinctrl-utils.h

pin control subsystem的一些utility接口函数

pinmux.c pinmux.h

pin control subsystem的core driver(pin muxing部分的代码,也称为pinmux driver)

pinconf.c pinconf.h

pin control subsystem的core driver(pin config部分的代码,也称为pin config driver)

devicetree.c devicetree.h

pin control subsystem的device tree代码

pinctrl-xxxx.c

各种pin controller的low level driver。

在pin controller driver文档中 ,我们以SM8475的pin controller为例,描述了一个具体的low level的driver,这个driver涉及的文件包括pinctrl-diwali.c,pinctrl-diwali.h和pinctrl-msm.c,pinctrl-msm.h。

 

2、和其他内核模块接口头文件

很多内核的其他模块需要用到pin control subsystem的服务,这些头文件就定义了pin control subsystem的外部接口以及相关的数据结构。我们整理linux/include/linux/pinctrl目录下pin control subsystem的外部接口头文件列表如下:

文件名

描述

consumer.h

其他的driver要使用pin control subsystem的下列接口:

a、设置引脚复用功能

b、配置引脚的电气特性

这时候需要include这个头文件

devinfo.h

这是for linux内核的驱动模型模块(driver model)使用的接口。struct device中包括了一个struct dev_pin_info    *pins的成员,这个成员描述了该设备的引脚的初始状态信息,在probe之前,driver model中的core driver在调用driver的probe函数之前会先设定pin state

machine.h

和machine模块的接口。

 

3、Low level pin controller driver接口

我们整理linux/include/linux/pinctrl目录下pin control subsystem提供给底层specific pin controller driver的头文件列表如下:

文件名

描述

pinconf-generic.h

这个接口主要是提供给各种pin controller driver使用的,不是外部接口。

pinconf.h

pin configuration 接口

pinctrl-state.h

pin control state状态定义

pinmux.h

pin mux function接口

 

三,pin control subsystem的软件框架图

1,功能规格

pin control subsystem的主要功能包括:

(1)管理系统中所有可以控制的pin。在系统初始化的时候,枚举所有可以控制的pin,并标识这些pin。

(2)管理这些pin的复用(Multiplexing)。对于SOC而言,其引脚除了配置成普通GPIO之外,若干个引脚还可以组成一个pin group,形成特定的功能。例如pin number是{ 0, 8, 16, 24 }这四个引脚组合形成一个pin group,提供SPI的功能。pin control subsystem要管理所有的pin group。

(3)配置这些pin的特性。例如配置该引脚上的pull-up/down电阻,配置drive strength等

2,pin control subsystem在和其他linux内核模块的接口关系

pin control subsystem会向系统中的其他driver提供接口以便进行该driver的pin config和pin mux的设定。理想的状态是GPIO controll driver也只是像UART,SPI这样driver一样和pin control subsystem进行交互,但是,实际上由于各种源由(后文详述),pin control subsystem和GPIO subsystem必须有交互。

3,pin control subsystem内部block diagram

四,pinctrl子系统主要数据结构

1,pincontroller的数据结构

记住pinctrl的三大作用,有助于理解所涉及的数据结构:

引脚枚举与命名(Enumerating and naming)

引脚复用(Multiplexing):比如用作GPIO、I2C或其他功能

引脚配置(Configuration):比如上拉、下来、open drain、驱动强度等。

2,pin controller的概念和软件抽象

Kernel pinctrl core使用struct pinctrl_desc抽象一个pin controller。

2.1 Pin

kernel的pin controller子系统要想管理好系统的pin资源,第一个要搞明白的问题就是:系统中到底有多少个pin?用软件语言来表述就是:要把系统中所有的pin描述出来,并建立索引。这由上面struct pinctrl_desc结构中pins和npins来完成。

对pinctrl core来说,它只关心系统中有多少个pin,并使用自然数为这些pin编号,后续的操作,都是以这些编号为操作对象。至于编号怎样和具体的pin对应上,完全是pinctrl driver自己的事情。

因此,pinctrl driver需要根据实际情况,将系统中所有的pin组织成一个struct pinctrl_pin_desc类型的数组,该类型的定义为:

struct pinctrl_pin_desc {
    unsigned number;
    const char *name;
    void *drv_data;
};

 number和name完全由driver自己决定,不过要遵循有利于代码编写、有利于理解等原则。另外,为了便于driver的编写,可以在drv_data中保存driver的私有数据结构(可以包含相关的寄存器偏移等信息)。

2.2 Pin groups

在SoC系统中,有时需要将很多pin组合在一起,以实现特定的功能,例如SPI接口、I2C接口等。因此pin controller需要以group为单位,访问、控制多个pin,这就是pin groups。相应地,pin controller subsystem需要提供一些机制,来获取系统中到底有多少groups、每个groups包含哪些pins、等等。

因此,pinctrl core在struct pinctrl_ops中抽象出三个回调函数,用来获取pin groups相关信息,如下:

struct pinctrl_ops {
    //获取系统中pin groups的个数,后续的操作,将以相应的索引为单位(类似数组的下标,个数为数组的大小)
    int (*get_groups_count) (struct pinctrl_dev *pctldev);
    //获取指定group(由索引selector指定)的名称
    const char *(*get_group_name) (struct pinctrl_dev *pctldev,
                       unsigned selector);
    //获取指定group的所有pins(由索引selector指定),结果保存在pins(指针数组)和num_pins(指针)中
    int (*get_group_pins) (struct pinctrl_dev *pctldev,
                   unsigned selector,
                   const unsigned **pins,
                   unsigned *num_pins);
    void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,
              unsigned offset);
    int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
                   struct device_node *np_config,
                   struct pinctrl_map **map, unsigned *num_maps);
    void (*dt_free_map) (struct pinctrl_dev *pctldev,
                 struct pinctrl_map *map, unsigned num_maps);
};

当然,最终的group信息是由pinctrl driver提供的,至于driver怎么组织这些group,那是driver自己的事情了(这里存储在soc data中)。

2.3 Pin multiplexing(对象是pin或者pin group)

为了照顾不同类型的产品、不同的应用场景,SoC中的很多管脚可以配置为不同的功能,例如A2和B5两个管脚,既可以当作普通的GPIO使用,又可以配置为I2C0的的SCL和SDA,也可以配置为UART5的TX和RX,这称作管脚的复用(pin multiplexing,简称为pinmux)。kernel pinctrl subsystem使用struct pinmux_ops来抽象pinmux有关的操作,如下:

struct pinmux_ops {
    //检查某个pin是否已作它用,用于管脚复用时的互斥(避免多个功能同时使用某个pin而不知道,导致奇怪的错误)
    int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
    int (*free) (struct pinctrl_dev *pctldev, unsigned offset);
    //获取系统中function的个数
    int (*get_functions_count) (struct pinctrl_dev *pctldev);
    //获取指定function的名称
    const char *(*get_function_name) (struct pinctrl_dev *pctldev,
                      unsigned selector);
    //获取指定function所占用的pin group(可以有多个)
    int (*get_function_groups) (struct pinctrl_dev *pctldev,
                  unsigned selector,
                  const char * const **groups,
                  unsigned *num_groups);
    //将指定的pin group(group_selector)设置为指定的function(func_selector)
    int (*set_mux) (struct pinctrl_dev *pctldev, unsigned func_selector,
            unsigned group_selector);
    int (*gpio_request_enable) (struct pinctrl_dev *pctldev,
                    struct pinctrl_gpio_range *range,
                    unsigned offset);
    void (*gpio_disable_free) (struct pinctrl_dev *pctldev,
                   struct pinctrl_gpio_range *range,
                   unsigned offset);
    int (*gpio_set_direction) (struct pinctrl_dev *pctldev,
                   struct pinctrl_gpio_range *range,
                   unsigned offset,
                   bool input);
    bool strict;
};

pinctrl core不关心function的具体形态,只要求pinctrl driver将SoC的所有可能的function枚举出来(格式自行定义,不过需要有编号、名称等内容),并注册给pinctrl core。后续pinctrl core将会通过function的索引,访问、控制相应的function。

2.4 Pin configuration(对象是pin或者pin group)

2.1和2.2中介绍了pinctrl subsystem中的操作对象(pin or pin group)以及抽象方法。嵌入式系统的工程师都知道,SoC中的管脚有些属性可以配置,例如上拉、下拉、高阻、驱动能力等。pinctrl subsystem使用pin configuration来封装这些功能,具体体现在struct pinconf_ops数据结构中,如下:

struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONF
    bool is_generic;
#endif
    //获取指定pin(管脚的编号,由2.1中pin的注册信息获得)当前配置,保存在config指针中(配置的具体含义,只有pinctrl driver自己知道,下同)
    int (*pin_config_get) (struct pinctrl_dev *pctldev,
                   unsigned pin,
                   unsigned long *config);
    //设置指定pin的配置(可以同时配置多个config,具体意义要由相应pinctrl driver解释)
    int (*pin_config_set) (struct pinctrl_dev *pctldev,
                   unsigned pin,
                   unsigned long *configs,
                   unsigned num_configs);
    //获取或者设置指定pin group的配置项
    int (*pin_config_group_get) (struct pinctrl_dev *pctldev,
                     unsigned selector,
                     unsigned long *config);
    //获取或者设置指定pin group的配置项
    int (*pin_config_group_set) (struct pinctrl_dev *pctldev,
                     unsigned selector,
                     unsigned long *configs,
                     unsigned num_configs);
    void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev,
                     struct seq_file *s,
                     unsigned offset);
    void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev,
                       struct seq_file *s,
                       unsigned selector);
    void (*pin_config_config_dbg_show) (struct pinctrl_dev *pctldev,
                        struct seq_file *s,
                        unsigned long config);
};

kernel pinctrl subsystem并不关心configuration的具体内容是什么,它只提供pin configuration get/set的通用机制,至于get到的东西,以及set的东西,到底是什么,是pinctrl driver自己的事情。

3,pinctrl client的数据结构
3.1 device结构体

设备节点要么被转换为platform_device,或者其他结构体(比如i2c_client),但是里面都会有一个device结构体:

3.2 pin control state holder

每个device结构体里都有一个dev_pin_info结构体,用来保存设备的pinctrl信息,为了方便管理pin control state,我们又提出了一个pin control state holder的概念,用来管理一个设备的所有的pin control状态 -- struct pinctrl ,系统中的每一个需要和pin control subsystem进行交互的设备在进行设定之前都需要首先获取这个句柄。而属于该设备的所有的状态都是挂入到一个链表中,链表头就是pin control state holder的states成员。

参考链接:

pinctrl 子系统介绍_pinctrl子系统_kenny_wju的博客-CSDN博客

linux内核中的GPIO系统之(2):pin control subsystem

 

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

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

相关文章

MySQL读写分离之一主一从

原理 MySQL 的主从复制&#xff0c;是基于二进制日志&#xff08; binlog &#xff09;实现的。 准备 主机 角色 用户名 密码 192.168.2.3 master root newPwd520 192.168.2.4 slave root newPwd520 主从复制的搭建&#xff0c;可以参考 MYSQL的主从复制-CSDN博客 一主一从读…

【K8S】集群中部署nginx应用 运行手写yaml文件报错排查过程

文章目录 ❌报错信息&#x1f50e;排查过程✅问题解决 ❌报错信息 提取报错信息【 unknown field “spec.selector.replicas”】【 unknown field “spec.selector.template”】 [rootmaster ~]# kubectl apply -f nginx-deployment.yaml Error from server (BadRequest): erro…

CCF CSP认证 历年题目自练Day30

题目一 试题编号&#xff1a; 202203-1 试题名称&#xff1a; 未初始化警告 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 问题描述&#xff1a; 题目背景 一个未经初始化的变量&#xff0c;里面存储的值可能是任意的。因此直接使用未初始化的变量&#xff0c;比…

通过API接口进行商品价格监控,可以按照以下步骤进行操作

要实现通过API接口进行商品价格监控&#xff0c;可以按照以下步骤进行操作&#xff1a; 申请平台账号并选择API接口&#xff1a;根据需要的功能&#xff0c;选择相应的API接口&#xff0c;例如商品API接口、店铺API接口、订单API接口等&#xff0c;这一步骤通常需要我们在相应…

MyBatis(中)

1、动态sql&#xff1a; 1、if标签&#xff1a; mapper接口: //if 标签 多条件查询List<Car> selectByMultiConditional(Param("brand") String brand,Param("guidePrice") Double guidePrice,Param("carType") String carType); map…

ATF(TF-A)之UBSAN动态代码分析

安全之安全(security)博客目录导读 目录 一、UBSAN简介 二、TF-A中UBSAN配置选项 一、UBSAN简介 未定义行为消毒器(Undefined Behavior Sanitizer&#xff0c;UBSAN)是Linux内核的未定义行为动态检测器。 详细信息可参考&#xff1a;https://github.com/google/kernel-sanit…

3D 生成重建007-Fantasia3D和Magic3d两阶段玩转文生3D

3D生成重建3D 生成重建007-Fantasia3D和magic3d 文章目录 0 论文工作1 论文方法1.1 magic3d1.2 Fantasia3D 2 效果2.1 magic3d2.2 fantasia3d 0 论文工作 两篇论文都是两阶段法进行文生3d&#xff0c;其中fantasia3D主要对形状和外表进行解耦&#xff0c;然后先对geometry进行…

第五章 图

第五章 图 图的基本概念图的应用背景图的定义和术语 图的存储结构邻接矩阵邻接表 图的遍历连通图的深度优先搜索连通图的广度优先搜索 图的应用最小生成树拓扑排序 小试牛刀 图的基本概念 图结构中&#xff0c;任意两个结点之间都可能相关&#xff1b;而在树中&#xff0c;结点…

接口自动化测试,完整入门篇

1. 什么是接口测试 顾名思义&#xff0c;接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型&#xff0c;测试类型又主…

Web安全基础:常见的Web安全威胁及防御方法 |青训营

Web安全基础&#xff1a;常见的Web安全威胁及防御方法 在现代Web开发中&#xff0c;安全性至关重要。Web应用面临各种潜在的威胁&#xff0c;包括跨站脚本&#xff08;XSS&#xff09;、跨站请求伪造&#xff08;CSRF&#xff09;等。了解这些威胁以及如何防御它们&#xff0c…

c语言练习87:合并两个有序数组

合并两个有序数组 合并两个有序数组https://leetcode.cn/problems/merge-sorted-array/ 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff…

Excel 自动提取某一列不重复值

IFERROR(INDEX($A$1:$A$14,MATCH(0,COUNTIF($C$1:C1,$A$1:$A$14),0)),"")注意&#xff1a;C1要空置&#xff0c;从C2输入公式 参考&#xff1a; https://blog.csdn.net/STR_Liang/article/details/105182654 https://zhuanlan.zhihu.com/p/55219017?utm_id0

超越平凡:Topaz Photo AI for Mac带您领略人工智能降噪的魅力

在这个充满噪点和高频信息的时代&#xff0c;照片和视频的降噪成为了一个重要而迫切的需求。Mac用户现在有了一个强大的新工具——Topaz Photo AI for Mac&#xff0c;这是一款利用人工智能技术进行降噪和优化的软件。通过这款软件&#xff0c;您可以轻松地改善图像质量&#x…

呈现高效的软件测试技术 助力软件研发提升10倍质量

像大多数软件工程一样&#xff0c;软件测试是一门艺术。在过去十年中&#xff0c;自动化测试是测试软件的最佳方式。计算机可在瞬间运行数百个测试&#xff0c;而这样的测试集使公司能自信地每天发布数十个版本的软件。有大量资源(书籍、教程和在线课程)可用于解释如何进行自动…

金蝶EAS代码执行漏洞

【漏洞概述】 金蝶 EAS 及 EAS Cloud 是金蝶软件公司推出的一套企业级应用软件套件&#xff0c;旨在帮助企业实现全面的管理和业务流程优化。 【漏洞介绍】 金蝶 EAS 及 EAS Cloud 存在远程代码执行漏洞 【影响版本】 金蝶 EAS 8.0&#xff0c;8.1&#xff0c;8.2&#xf…

【Java学习之道】Java常用集合框架

引言 在Java中&#xff0c;集合框架是一个非常重要的概念。它提供了一种方式&#xff0c;让你可以方便地存储和操作数据。Java中的集合框架包括各种集合类和接口&#xff0c;这些类和接口提供了不同的功能和特性。通过学习和掌握Java的集合框架&#xff0c;你可以更好地管理和…

【python】anaconda中创建虚拟环境

创建虚拟环境 查看当前所有环境 首先打开Anaconda Prompt 初始进入的是base环境&#xff0c;如下。但是我们需要创建一个新的虚拟环境。 查看当前所有虚拟环境 conda env list 创建虚拟环境 conda create -n 虚拟环境名称 python3.10.1 这里使用conda create -n test python…

opencv dnn模块 示例(18) 目标检测 object_detection 之 pp-yolo、pp-yolov2和pp-yolo tiny

文章目录 1、PP-YOLO1.1、网络架构1.1.1、BackBone骨干网络1.1.2、DetectionNeck1.1.3、DetectionHead 1.2、Tricks的选择1.2.1、更大的batchsize1.2.2、滑动平均1.2.3、DropBlock1.2.4、IOU Loss1.2.5、IOU Aware1.2.6、GRID Sensitive1.2.7、Matrix NMS1.2.8、CoordConv1.2.9…

出差学知识No3:ubuntu查询文件大小|文件包大小|磁盘占用情况等

1、查询单个文件占用内存大小2、显示一个目录下所有文件和文件包的大小3、显示ubuntu所有磁盘的占用情况4、查看ubuntu单个包的占用情况 1、查询单个文件占用内存大小 使用指令&#xff1a;ls -lh 文件 2、显示一个目录下所有文件和文件包的大小 指令&#xff1a;du -sh* 3…

FastAdmin表格添加统计信息

如上图&#xff0c;在列表顶部添加订单统计信息&#xff0c;统计符合当前筛选条件的记录。 列表页html中&#xff1a; <div class"panel-body"><div id"myTabContent" class"tab-content"><div class"tab-pane fade active…