概述
本文主要描述Linux内核关于GPIO的DTS配置以及gpiolib,pinctrl驱动框架和接口的介绍使用。
GPIO
gpio配置流程
st=>start: DTS配置解析
op=>operation: 其它模块驱动
con=>condition: pinctrl or gpiolib?
op_pinctrl=>operation: Linux pinctrl
op_gpiolib=>operation: Linux gpiolib
op_platform=>operation: platform pinctrl or gpiolib
op_reg=>operation: 读写平台GPIO寄存器
e=>end: end
st->op->con
con(yes)->op_pinctrl->op_platform->op_reg
con(no)->op_gpiolib->op_platform->op_reg
GPIO配置
devicetree->其它驱动模块:
其它驱动模块->Linux pinctrl: pinctrl
其它驱动模块->Linux gpiolib: gpiolib
Linux pinctrl->平台pinctrl:平台pinctrl
Linux gpiolib->平台gpiolib:平台gpiolib
平台pinctrl->平台GPIO寄存器:
平台gpiolib->平台GPIO寄存器:
pinctrl接口
/* 获取pinctrl结构
*
*/
struct pinctrl * devm_pinctrl_get(struct device *dev);
/*
*
*/
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name);
/*
*
*/
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state);
gpiolib接口
/*
*
*/
int gpio_request(unsigned gpio, const char *label);
/*
*
*/
void gpio_free(unsigned gpio);
/*
*
*/
int gpio_direction_input(unsigned gpio);
/*
*
*/
int gpio_direction_output(unsigned gpio);
/*
*
*/
void gpio_set_value(unsigned int gpio, int value);
/*
*
*/
int gpio_get_value(unsigned int gpio);
/*
*
*/
int of_get_named_gpio(struct device_node *np, const char *propname, int index);
pinctrl devicetree配置
pinctrl用于控制GPIO,但是无法获取GPIO输入值。 关于pinctrl在devicetree中的配置有三个部分:pin controller node(GPIO控制器节点),pinctrl node(pinctrl节点) and device node(设备节点)。
- pin controller node: 主要描述的是芯片GPIO控制器。
pio:pinctrl@10005000 { compatible="pinctrl-test"; reg=<0 0x10005000 0 0x1000>; gpio-controller; #gpio-cells=<2>; };
- pinctrl node: 描述需要配置的GPIO信息,属于pin controller子节点。
&pio{ test_cfg:alspspincfg { pins_cmd_dat { pins = <gpio6>; bias-pull-up=<00>; }; }; test_default:alspsdefaultcgf{ }; };
- device node: 描述设备信息控制GPIO, pinctrl-names配置pinctrl state name,用于匹配pinctrl节点的设置。pinctr-0…匹配pinctrl node label
&als { pinctrl-names="pin_default", "pin_cfg"; pinctrl-0=<&test_default>; pinctrl-1=<&test_cfg>; };
pinctrl 驱动代码示例
- 通过驱动设备节点获取pinctrl
devm_pinctrl_get()
- 通过获取的pinctrl查找pinctrl state
pinctrl_lookup_state()
- 选择要设置的pinctrl state
pinctrl_select_state()
int gpio_setting(struct device *dev) { int ret = 0; struct pinctrl *pinctrl; struct pinctrl_state *pins_default; struct pinctrl_cfg *pins_cfg; pinctrl = devm_pinctrl_get(dev); if(IS_ERR(pinctrl)) return ERROR; //"pin_default"对应devicetree中pinctrl-names 中 state pins_default = pinctrl_lookup_state(pinctrl, "pin_default"); if (IS_ERR(pins_default)) return ERROR; pins_cfg = pinctrl_lookup_state(pinctrl, "pin_cfg"); if (IS_ERR(pins_cfg)) return ERROR; pinctrl_select_state(pinctrl, pins_cfg); }
gpiolib devicetree配置
gpiolibtest:gpio_test {
compatible="gpiolib_test";
gpio_num=<&pio 10 0>;
state="okay";
};
gpiolib驱动代码示例
- get gpio number
- request gpio
- control gpio
- free gpio
int gpio_op_test(void)
{
struct device_node *np = NULL;
int gpio = 0;
int ret = 0;
int value = 0;
np = of_find_compatible_node(NULL, NULL, "gpiolib_test");
if (np == NULL)
return ERROR;
//gpio_num对应devicetree中配置
gpio = of_get_named_gpio(np, "gpio_num", 0);
ret = gpio_request(gpio, "gpiolib_test");
gpio_direction_output(gpio, 0);
gpio_set_value(gpio, 1);
gpio_direction_input(gpio);
value = gpio_get_value(gpio);
gpio_free(gpio);
return ret;
}