文档:内核 Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
s3c2440-pinctrl.dtsi
/*
* Samsung S3C2416 pinctrl settings
*
* Copyright (c) 2013 Heiko Stuebner
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include
&pinctrl_0 {
/*
* Pin banks
*/
gpa: gpa {
gpio-controller;
#gpio-cells = <2>;
};
gpb: gpb {
gpio-controller;
#gpio-cells = <2>;
};
gpc: gpc {
gpio-controller;
#gpio-cells = <2>;
};
gpd: gpd {
gpio-controller;
#gpio-cells = <2>;
};
gpe: gpe {
gpio-controller;
#gpio-cells = <2>;
};
gpf: gpf {
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpg: gpg {
gpio-controller;//gpio控制器
#gpio-cells = <2>;
interrupt-controller;//中断控制器
#interrupt-cells = <2>;
};
gph: gph {
gpio-controller;
#gpio-cells = <2>;
};
gpj: gpj {
gpio-controller;
#gpio-cells = <2>;
};
/*
* Pin groups
*/
uart0_data: uart0-data {
samsung,pins = "gph-0", "gph-1";
samsung,pin-function = <2>;
};
i2c0_bus: i2c0-bus {
samsung,pins = "gpe-14", "gpe-15";
samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
};
nand_pinctrl: nand_pinctrl {
samsung,pins = "gpa-17", "gpa-18", "gpa-19",
"gpa-20", "gpa-22";
samsung,pin-function = <1>;
};
lcd_pinctrl: lcd_pinctrl {
samsung,pins = "gpc-8", "gpc-9", "gpc-10", "gpc-11", "gpc-12", "gpc-13", "gpc-14", "gpc-15",
"gpd-0", "gpd-1", "gpd-2", "gpd-3", "gpd-4", "gpd-5", "gpd-6", "gpd-7",
"gpd-8", "gpd-9", "gpd-10", "gpd-11", "gpd-12", "gpd-13", "gpd-14", "gpd-15",
"gpc-1", "gpc-2", "gpc-3", "gpc-4";
samsung,pin-function = <2>;
};
lcd_backlight: lcd_backlight {
samsung,pins = "gpg-4";
samsung,pin-function = <3>;
};
uda1340_codec_pinctrl: uda1340_codec_pinctrl {
samsung,pins = "gpb-4", "gpb-3", "gpb-2";
samsung,pin-function = <1>;
};
s3c2440_iis_pinctrl: s3c2440_iis_pinctrl {
samsung,pins = "gpe-0", "gpe-1", "gpe-2", "gpe-3", "gpe-4";
samsung,pin-function = <2>;
};
};
几个概念:
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引脚。
a. 设备树中pinctrl节点:
1.它定义了各种 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>;
};
};
它还定义了各种group(组合), 某种功能所涉及的引脚称为group,
比如串口0要用到2个引脚: gph0, gph1:
uart0_data: uart0-data {
samsung,pins = “gph-0”, “gph-1”;
samsung,pin-function = <2>;
};
uart0_sleep: uart0_sleep {
samsung,pins = “gph-0”, “gph-1”;
samsung,pin-function = <0>; /* 0 — 输入功能*/
};
/* 在GPHCON寄存器中gph0,gph1可以设置以下值:
0 — 输入功能00
1 — 输出功能01
2 — 串口功能10
我们要使用串口功能, samsung,pin-function 设置为2
b. 设备节点中要使用某一个 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
c. 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", 即先绑定、设置引脚
d. 驱动中想选择、设置某个状态的引脚:
devm_pinctrl_get_select_default(struct device *dev); // 使用"default"状态的引脚
pinctrl_get_select(struct device *dev, const char *name); // 根据name选择某种状态的引脚
pinctrl_put(struct pinctrl *p); // 不再使用, 退出时调用