嵌入式开发记录-day43 设备树-pinctrl子系统框架
1、在pinctrl子系统出现之前,管理设备树都是在platform下管理的,在该平台下管理设备封装了一套API就是GPIO子系统接口gpiolib;很繁杂;
为了节省代码,方便管理设备,引入了设备树后,管理物理引脚,在管脚封装得基础上,对外提供简洁的API接口;该接口直接定义物理管脚,
对上给GPIO子系统调用;因此,在物理硬件与GPIO子系统之间,搭起了一个桥梁;该桥梁就是pinctrl子系统;
因此,在引入设备树之后,GPIO子系统是通过pinctrl子系统来实现的,这一点要牢记。

2、gpio子系统与pinctrl子系统对比
1、pinctrl子系统和GPIO子系统的结构和功能类似,内部结构有所差异
2、在引入设备树之后,GPIO子系统是通过pinctrl子系统来实现的,这一点要牢记。
3、pinctrl子系统相比gpio子系统,增加了引脚复用和pin脚状态设置这两个功能。
1、GPIO子系统系统结构--参考图1 通过GPIO子系统功能: 引脚功能的配置(设置为GPIO,特殊功能,GPIO的方向,设置为中断等等); 实现软硬件的分离(分离出硬件差异,有厂商提供底层支持;软件分层,驱动只需要调用接口API即可操作GPIO); iommu内存管理(直接调用宏即可操作GPIO)。 GPIO子系统提供一系列的API对外调用, 2、pinctrl子系统内部结构--参考图4 pinctrl的内部主要分为两部分功能:pin config管脚配置和pin mux管脚复用 驱动调用pin脚(不仅指GPIO,例如uart也需要用到pin脚),那么需要用到两部分硬件的功能: A: 设置引脚功能的复用; B:配置pin脚的状态。 在以前驱动移植中,经常会遇到,调试很久的驱动,发现管脚的初始化出了问题(这是经常会遇到的问题)。 传统模式中,管脚初始化在uboot中或者在内核中增加额外的初始化代码(不同的平台版本有区别),也有可能在驱动中额外增加初始化代码。 在驱动中,可以直接而通用的实现管脚功能复用和配置,这样驱动的移植工作会更加简单。
3、驱动为什么要移植,而不能直接使用?
一方面是:上层应用接口的变化,不过这种情况很少;
另外一方面:主要是因为硬件差异,现在更多的硬件管脚差异--pinctrl的初始化和配置放到了设备树中
(不仅仅是pin这部分硬件差异在设备树中),所以很多移植只需要修改下设备树文件即可。
4、pinctrl子系统
pinctrl的内部主要分为两部分功能:pin config管脚配置和pin mux管脚复用
驱动调用pin脚(不仅指GPIO,例如uart也需要用到pin脚),那么需要用到两部分硬件的功能:
A: 设置引脚功能的复用;
B:配置pin脚的状态。
pinctrl子系统相比gpio子系统,增加了引脚复用和pin脚状态设置这两个功能。管脚更容易配置、以及初始化
传统模式中,使用GPIO子系统配置管脚,管脚初始化在uboot中或者在内核中增加额外的初始化代码(不同的平台版本有区别),也有可能在驱动中额外增加初始化代码。
pinctrl子系统引入了设置引脚功能复用和配置pin脚,这个功能需要和设备树文件结合使用。
在驱动中,可以直接而通用的实现管脚功能复用和配置,这样驱动的移植工作会更加简单。
3、pinctrl参考文档
1、设备树文件:arch/arm/boot/dts/exynos4412-pinctrl.dtsi
参考文档:Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
cd Documentation find ./ -name "pinctrl" 显示./devicetree/bindings/pinctrl/ cd /devicetree/bindings/pinctrl/ vim samsung-pinctrl.txt
为什么肯定会存在这样的文档:三星给设备树中添加属性节点,必须要添加相关的说明文档,否则
Linux官方肯定不允许三星给设备树添加设备节点。这样的规范是Linux官方提出的;
4、pinctrl的属性
1、compatible:compatible: should be one of the following. 三星提供了一系列支持的节点名称
2、reg:reg: Base address of the pin controller hardware module and length of the address space it occupies;包含有基地址和偏移地址;
3、Pin banks 它是pinctrl的子节点,Pin banks子节点必须要有的属性:
-- gpio-controller: identifies the node as a gpio controller and pin bank -- #gpio-cells: number of cells in GPIO specifier. // 引用时候必须要有的参数 例子: Eg: <&gpx2 6 0> <[phandle of the gpio controller node] [pin number within the gpio controller] [flags]> Values for gpio specifier: - Pin number: is a value between 0 to 7. - Flags: 0 - Active High 1 - Active Low 前面gpio的例程,设备树中增加如下: gpl2: gpl2 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; // 有两个参数可以选择 }; leds_test_node:leds_test_node { // 加个冒号表示可以被引用 compatible = "leds_test"; status = "disabled"; gpios1 = <&gpl2 0 GPIO_ACTIVE_HIGH>; --gpl2引用的pinctrl文件下的gpl2, gpios2 = <&gpk1 1 GPIO_ACTIVE_HIGH>; };
4、Pin mux/config groups ,它是pinctrl的子节点,Pin banks子节点实现的功能: The pin mux (selecting pin function mode) and pin config (pull up/down, driver strength) settings are represented as child nodes of the pin-controller node.
子节点的要求和语法: The child node should contain a list of pin(s) on which a particular pin function selection or pin configuration (or both) have to applied. list of pins的写法: A the property name "samsung,pins" B 引用管脚using pin names:"[pin bank name]-[pin number within the bank]"。eg:"gpa0-0", "gpa0-1", "gpa0-2" and so on C 功能复用属性:"samsung,pin-function" The pin function selection that should be applied on the pins listed in the child node is specified using the "samsung,pin-function" property. D 配置属性: - samsung,pin-val: Initial value of pin output buffer. - samsung,pin-pud: Pull up/down configuration. - samsung,pin-drv: Drive strength configuration. - samsung,pin-pud-pdn: Pull up/down configuration in power down mode. - samsung,pin-drv-pdn: Drive strength configuration in power down mode. 语法还要遵守"pinctrl-bindings.txt"文件的规则 其中中断部分,后续介绍,这部分只是以GPIO功能为例
5、设备树文档中的例程
例子1:为什么function是1,val是1... #include <dt-bindings/pinctrl/samsung.h> leds_gpios1:leds-gpios1{ // 有冒号 代表这个节点可以被引用 samsung,pins = "gpl2-0" ; samsung,pin-function = <1>; samsung,pin-val = <1>; samsung,pin-pud = <EXYNOS_PIN_PULL_UP>; }; 例子2:以下代码添加到arch/arm/boot/dts/exynos4412-pinctrl.dtsi leds_gpios1{ leds_gpios1_on:leds_gpios1-on { samsung,pins = "gpl2-0" ; samsung,pin-function = <1>; // <1>里面的1 表示,引用的时候必须要有一个参数; 这个参数就是,配置该管脚为输出 samsung,pin-val = <1>; samsung,pin-pud = <EXYNOS_PIN_PULL_UP>; }; leds_gpios1_off:leds_gpios1-off { samsung,pins = "gpl2-0" ; samsung,pin-function = <1>; samsung,pin-val = <0>; samsung,pin-pud = <EXYNOS_PIN_PULL_UP>; }; };

浙公网安备 33010602011771号