目录
1 关于引脚的几个概念
2 设备树中pinctrl节点
2.1 定义各种pin bank
2.2 定义各种group
3 设备节点中要使用某一个 pin group
4 platform_device, platform_driver匹配
5 驱动中想选择、设置某个状态的引脚
6 总结
7 参考文档
1 关于引脚的几个概念
Bank: 以引脚名为依据, 这些引脚分为若干组, 每组称为一个Bank
比如s3c2440里有GPA、GPB、GPC等Bank,
每个Bank中有若干个引脚, 比如GPA0,GPA1, ..., GPC0, GPC1,...等引脚
Group: 以功能为依据, 具有相同功能的引脚称为一个Group
比如s3c2440中串口0的TxD、RxD引脚使用 GPH2,GPH3, 那这2个引脚可以列为一组
比如s3c2440中串口0的流量控制引脚使用 GPH0,GPH1, 那这2个引脚也可以列为一组
State: 设备的某种状态, 比如内核自己定义的"default","init","idel","sleep"状态;
也可以是其他自己定义的状态, 比如串口的"flow_ctrl"状态(使用流量控制)
设备处于某种状态时, 它可以使用若干个Group引脚
2 设备树中pinctrl节点
2.1 定义各种pin bank
它定义了各种 pin bank, 比如s3c2440有GPA,GPB,GPC,...,GPB各种BANK, 每个BANK中有若干引脚:
pinctrl_0: pinctrl@56000000 {
reg = <0x56000000 0x1000>;
gpa: gpa {
gpio-controller;
#gpio-cells = <2>; /* 以后想使用gpa bank中的引脚时, 需要2个u32来指定引脚 */
};
gpb: gpb {
gpio-controller;
#gpio-cells = <2>;
};
gpc: gpc {
gpio-controller;
#gpio-cells = <2>;
};
gpd: gpd {
gpio-controller;
#gpio-cells = <2>;
};
};
2.2 定义各种group
它还定义了各种group(组合), 某种功能所涉及的引脚称为group,比如串口0要用到2个引脚: gph0, gph1:
uart0_data: uart0-data {
samsung,pins = "gph-0", "gph-0";
samsung,pin-function = <2>; /* 这里的2其实就是寄存器要设置的值,在GPHCON寄存器中gph0,gph1可以设置以下值:
0 --- 输入功能
1 --- 输出功能
2 --- 串口功能
我们要使用串口功能,
samsung,pin-function 设置为2
*/
};
uart0_sleep: uart0_sleep {
samsung,pins = "gph-0", "gph-1";
samsung,pin-function = <0>; /* 这里的0其实就是寄存器要设置的值,在GPHCON寄存器中gph0,gph1可以设置以下值:
0 --- 输入功能
1 --- 输出功能
2 --- 串口功能
我们要使用输入功能,
samsung,pin-function 设置为0
*/
};
3 设备节点中要使用某一个 pin group
serial@50000000 {
......
pinctrl-names = "default", "sleep"; /* 既是名字, 也称为state(状态) */
pinctrl-0 = <&uart0_data>;
pinctrl-1 = <&uart0_sleep>;
};
pinctrl-names中定义了2种state: default 和 sleep,
default 对应的引脚是: pinctrl-0, 它指定了使用哪些pin group: uart0_data
sleep 对应的引脚是: pinctrl-1, 它指定了使用哪些pin group: uart0_sleep
4 platform_device, platform_driver匹配
"第3课第06节_platform_device跟platform_driver的匹配" 中讲解了platform_device和platform_driver的匹配过程,
最终都会调用到 really_probe (drivers/base/dd.c)
really_probe:
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev);
dev->pins->default_state = pinctrl_lookup_state(dev->pins->p,
PINCTRL_STATE_DEFAULT); /* 获得"default"状态的pinctrl */
dev->pins->init_state = pinctrl_lookup_state(dev->pins->p,
PINCTRL_STATE_INIT); /* 获得"init"状态的pinctrl */
ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state); /* 优先设置"init"状态的引脚 */
ret = pinctrl_select_state(dev->pins->p, dev->pins->default_state); /* 如果没有init状态, 则设置"default"状态的引脚 */
......
ret = drv->probe(dev);
所以: 如果设备节点中指定了pinctrl, 在对应的probe函数被调用之前, 先"bind pins", 即先绑定、设置引脚
5 驱动中想选择、设置某个状态的引脚
devm_pinctrl_get_select_default(struct device *dev); // 使用"default"状态的引脚
pinctrl_get_select(struct device *dev, const char *name); // 根据name选择某种状态的引脚
pinctrl_put(struct pinctrl *p); // 不再使用, 退出时调用
6 总结
7 参考文档
内核 Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt