前言
注: 所有文章基于linux-3.13以上,本系列主要介绍 GPIO的一些基本知识,驱动操作GPIO的接口,应用层通过sysfs操作GPIO的接口,GPIO一些debug信息查看,以及对高通相关GPIO的寄存器操作。分享给刚刚接触外设bsp的小伙伴们。当然后面有时间还会分享GPIO子系统框架和pinctrl子系统框架,先知道黑盒怎么使用,然后咱再打开仔细瞅瞅。
本篇为驱动申请GPIO和操作GPIO接口篇,分别介绍驱动通过GPIO子系统和PINCTRL 子系统提供的接口对GPIO的操作
GPIO 子系统操作GPIO
GPIO子系统接口简介
相关实现在driver/gpio/gpiolib.c 下
1、gpio_request 申请GPIO
int gpio_request(unsigned gpio, const char *label)
参数解析:
gpio: gpio编号
label: 名称
返回值: 成功返回0,失败返回负值
2、gpio_request_one 申请GPIO,同时制定配置方式 输出或输入模式
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
3、gpio_free 释放GPIO
void gpio_free(unsigned gpio)
参数解析:
gpio: gpio编号
4、gpio_direction_input 设置GPIO为输入模式
int gpio_direction_input(unsigned gpio)
参数解析:
gpio: gpio编号
返回值: 成功返回0,失败返回负值
5、gpio_direction_output 设置GPIO为输出模式
int gpio_direction_output(unsigned gpio, int value)
参数解析:
gpio: gpio编号
value: 设置为输出模式时的初始值
返回值: 成功返回0,失败返回负值
6、gpio_set_value 设置(写)GPIO的值
void __gpio_set_value(unsigned gpio, int value) #define gpio_set_value __gpio_set_value
gpio: gpio编号
value: 设置的值
返回值: 成功返回0,失败返回负值
7、gpio_get_value 获取(读)GPIO的值
int __gpio_get_value(unsigned gpio) #define gpio_get_value __gpio_get_value
gpio: gpio编号
返回值: 获取的值
8、gpio_to_irq 内核通过调用该函数将gpio端口转换为中断
int gpio_to_irq(unsigned gpio);
gpio: gpio编号
返回值:中断编号可以传给request_irq()和free_irq()
举个例子:单个GPIO
申请gpio4,输出模式,输出高(从设备树配置)
设备树设置
gpio_test{ status="ok"; gpio_req=<&tlmn 4 0>;
代码实现
struct device dev; gpio4 = of_get_named_gpio(dev.of_node,"gpio_req", 0); err = gpio_request(gpio4, "qti-can-reset"); if (err < 0) { return err; } gpio_direction_output(gpio4, 0); gpio_set_value(gpio4,1);
GPIO数组申请一个gpio数组 [36,42,132],主要是设备树 设备树
gpios = <&tlmm 36 0>, <&tlmm 42 0>, <&tlmm 132 0>; qcom,gpio-reset = <1>; qcom,gpio-standby = <2>; qcom,gpio-req-tbl-num = <0 1 2>; qcom,gpio-req-tbl-flags = <1 0 0>; qcom,gpio-req-tbl-label = "CAMIF_MCLK2", "CAM_RESET2", "CAM_STANDBY2";
解析:
PINCTRL 子系统操作GPIO
pinctrl 子系统相关接口
1、devm_pinctrl_get 解析对应的设备树,获取pinctrl资源
struct pinctrl *devm_pinctrl_get(struct device *dev)
dev: 驱动设备结构体
返回值:pinctrl节点
2、pinctrl_lookup_state 获取各种state的gpio配置
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)
p: pinctrl节点
name:gpio配置的名字
3、pinctrl_select_state 将上面获取的指定state状态设置到硬件中*/
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
举个例子
高通的配置为例子
在pinctrl设备树添加一个节点
&tlmn{ pin_teset_default:pin_teset_default{ mux { pins = "gpio0", "gpio1"; function = "qup00"; }; config { pins = "gpio0", "gpio1"; drive-strength = <2>; bias-disable; }; } }
在xxx.dtsi中添加一个设备 使用
pinctrl_test{ status="ok"; pinctrl-name="default"; pinctrl-0=<&pin_teset_default>; }
代码实现
dev->pins->p = devm_pinctrl_get(dev); dev->pins->default_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_DEFAULT); pinctrl_select_state(dev->pins->p, dev->pins->default_state);
probe自动配置pinctrl
如上个例子中,我们是不需要自己进行pinctrl适配的,device和驱动在匹配之后会进行适配。调用我们驱动的probe时,pinctrl相关已经初始化好了。获取相关状态和设置相关状态
__device_attach bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver); __device_attach_driver driver_match_device(drv, dev); driver_probe_device(struct device_driver *drv, struct device *dev) really_probe pinctrl_bind_pins drv->probe(dev) int pinctrl_bind_pins(struct device *dev) { dev->pins->p = devm_pinctrl_get(dev); dev->pins->default_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_DEFAULT); dev->pins->init_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_INIT); if (IS_ERR(dev->pins->init_state)) { ret = pinctrl_select_state(dev->pins->p, dev->pins->default_state); } else { ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state); } #ifdef CONFIG_PM dev->pins->sleep_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_SLEEP); dev->pins->idle_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_IDLE); #endif return 0; }
审核编辑:汤梓红
评论
查看更多