Linux pinctrl子系统学习(二)

Linux pinctrl子系统学习(二)

3 Pinctrl子系统与consumer关系

  • 从"pinctrl子系统关系图"中得知,linux kernel中的各种consumer调用了pinctrl子系统的功能。linux kernel中的统一设备驱动模型提供了driver 和device的绑定机制,一旦匹配就会调用driver 的probe函数。
  • 而在调用probe函数时,consumer就会调用pinctrl子系统里的回调函数,进行pin的申请。consumer的probe函数可以通过devm_pinctrl_get获得pinctrl的句柄,再自行调用pinctrl_select_state设置pin state。

3.1 设备树中的pin state

在device tree source 文件中可以在驱动节点中定义该驱动需要用到的pin配置。

device-node-name{
   //定义该device自己的属性
    pinctrl-names= "sleep","default";
    pinctrl-0 = &xxx_state_sleep;
    pinctrl-1 = &xxx_state_default;
}
  • pinctrl-0 pinctrl-1 …表示了该设备的一个个状态,这里我们定义了两个pinctrl-0 pinctrl-1,数字0、1就是pinctrl-names中对应的字符串数组的index。其中pinctrl-0就是“sleep”状态,pinctrl-1就是“default”状态。而xxx_state_sleep,xxx_state_default,xxx_state_idel就是驱动具体的pin配置项了,需要在pinctrl设备节点处定义:

      pinctrl@e01b0000{
            xxx_state_ default:xxx_ default {
                      pins = "PC10", "PC11", "PC12", "PC13", "PC14", "PC15";
      			  function = "spi0";
               };
      };
    
  • Consumer在pinctrl子系统加载时,会调用pinctrl_dt_to_map函数将dts文件中有关pinctrl的配置项解析出来,并根据dts各驱动节点对pinctrl的引用关系,将和自己有关的pinctrl子节点挂到自己驱动的device tree节点上,Consumer就可以获得自己的pinctrl state配置了。

3.2 pinctrl关键词表

3.2.1 pin命名表

pin的命名遵循芯片datasheet上的命名。
在dts中使用关键词“pins”(不同厂商不同)后跟名字数组来定义需要使用哪些pin,
如:

spi0_0: spi0 {
		pins = "PC10", "PC11", "PC12", "PC13", "PC14", "PC15";
		function = "spi0";
	}

3.2.2 MUX pin-function

相同的pin,可以通过设置Mux Function的方式改变IC内部连通性,使得相同的pin用作不同的功能,例如:

gpio0_0: gpio0 {
		pins = "PE0", "PE1", "PE2", "PE3";
		function = "gpio";
	}
	spi2_0: spi2 {
		pins = "PE0", "PE1", "PE2", "PE3";
		function = "spi2";
	};

3.2.3 Mux Group命名表

Mux Group的意义在于,将一些具有相同功能的pin作为一个集合group管理起来,方便consumer在需要配置多个管脚时,更加的简洁方便。
在dts中使用关键词“groups”后跟mux Group名字数组来定义需要使用哪些Mux group,如:

sd0 {
   groups = "mfp2_8_7";
   function = "sd0";
};

3.2.4 MUX Group-function

Mux Group所控制的pin,可以通过设置Mux Function的方式改变IC内部连通性,使得同一组pin用作不同的功能,例如:

jtag {
    groups ="mfp2_8_7";
    function = "jtag";
};

3.2.5 Pin drive

对于某些pin可以设置pin的驱动能力(即供电能力),可以通过配置pin的等级对pin的驱动能力进行配置。
在dts中使用关键词“xxx,drive”后跟驱动能力等级来pin用哪种驱动能力,如:

i2c0_0: i2c0
 {
				pins = "PB0", "PB1";
				function = "i2c0";
				amicro,drive = <xxx_PINCTRL_12_MA>;
				amicro,pull = <xxx_PINCTRL_PULL_UP>;
};

3.2.6 Pin Pull Up/Down

在dts中使用关键词“xxx,pull”后跟上下拉数据定义指定的pin组使用哪种上下拉,如:

i2c0_0: i2c0 {
				pins = "PB0", "PB1";
				function = "i2c0";
				amicro,drive = <xxx_PINCTRL_12_MA>;
				amicro,pull = <xxx_PINCTRL_PULL_UP>;
			};

表示将i2c0这两个pin上拉。
#define xxx_PINCTRL_NO_PULL 0
#define xxx_PINCTRL_PULL_UP 1
#define xxx_PINCTRL_PULL_DOWN 2

3.3 v3s的pin信息表

通过分析pinctrl-sunxi-v3s.c可以看到,v3s的所有pin信息被保存在了一个类型为自定义结构体xxx_pinctrl_desc的数组sunxi_v3s_pinctrl_data中。

static struct sunxi_pinctrl_desc sunxi_v3s_pinctrl_data = {
	.pins   = sunxi_v3s_pins,                /*单个pin的信息表*/
	.npins  = ARRAY_SIZE(sunxi_v3s_pins),  /*pin的总数*/
	.banks  = sunxi_v3s_banks,              /*banks的分组信息*/
	.nbanks = ARRAY_SIZE(sunxi_v3s_banks), /*banks分组数量*/
	.nirqs  = 16,                            /*外部中断线数量*/
};    

单个pin的信息被集合到了一个类型为自定义结构体sunxi_desc_pin的sunxi_v3s_pins数组中去,分析结构体成员可以看看到底保存了什么内容。

struct sunxi_desc_pin {
struct pinctrl_pin_desc    pin;          /*pinctrl通用的结构体,保存pin的编号,名字,以及pinctrl设备私有数据,内核可以识别*/

struct sunxi_desc_function *functions;   /*am780自定义结构体,与功能有关*/
};

struct sunxi_desc_function {
	    const char	*name;                   /*功能名字*/
	    u8		muxval;                      /*datasheet上复用功能编号*/
};

可以看到,v3s的pin信息表所保存的数据包括
1、 pin的编号,如PA0的编号为0,PB0编号为16
2、 pin的名字,如“PA0”,“PE14”
3、 复用功能映射编号,从datasheet中获取,如PA0:gpio为0,adc1为2,spi0为3
这些信息的作用是与各自平台的pinctrl子系统的pinconf和pinmux这些底层回调函数有关,最终的目的是通过这些信息来操作相关寄存器(最底层操作)。

发布了47 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/u013836909/article/details/94209120