Platform: RK3568
OS: Android 12
Kernel: v4.19.206
SDK Version:android-12.0-mid-rkr1
Module: gpio
前言
GPIO(General Purpose Input/Output)通用输入/输出,是一种可灵活软件控制的通用数字引脚,在芯片中广泛地使用。通过软件我们可以配置其输入或者输出模式,控制其输出高低电平,还可设置为中断脚。一般简单使用可以通过export方式导出对应引脚节点来控制。
目标
刚开始先设定一个小目标:实现一个简单的gpio驱动,在dts中配置一个gpio的节点属性,在驱动中控制该io口的状态。
步骤
- 选取一个空置的gpio,此处以gpio0_c3(gpio0-19)为例,在dts中添加配置:
//terry add for tw-gpio driver test
tw_gpio: tw-gpio {
status = "okay";
compatible = "terrywang,rk356x-gpio";
tw-gpio = <&gpio0 RK_PC3 GPIO_ACTIVE_LOW>;
};
- 在drivers/gpio/目录下添加gpio-tw.c驱动文件,并配置Makefile,Kconfig和rockchip_defconfig
obj-$(CONFIG_GPIO_TW) += gpio-tw.o
config GPIO_TW
tristate "Terry.W gpio driver test"
default y
help
Say Y here if you want to use gpio-tw driver
CONFIG_GPIO_TW=y
3.gpio-tw.c驱动基于platform_driver框架,主要函数有probe,of_device_id,init,exit等。下面主要分析下probe函数:
struct tw_gpio_info {
int tw_gpio;
int gpio_enable_value;
};
static int tw_gpio_probe(struct platform_device *pdev)
{
int gpio;
enum of_gpio_flags flag;
struct tw_gpio_info *gpio_info;
struct device_node *tw_gpio_node = pdev->dev.of_node;
pr_info("%s:terry GPIO TEST Driver Probe",__func__);
gpio_info = devm_kzalloc(&pdev->dev,sizeof(struct tw_gpio_info *), GFP_KERNEL);
if (!gpio_info) {
dev_err(&pdev->dev, "devm_kzalloc failed!\n");
return -ENOMEM;
}
gpio = of_get_named_gpio_flags(tw_gpio_node, "tw-gpio", 0, &flag);
if (!gpio_is_valid(gpio)) {
dev_err(&pdev->dev, "tw-gpio: %d is invalid\n", gpio);
return -ENODEV;
}
if (gpio_request(gpio, "tw-gpio")) {
dev_err(&pdev->dev, "tw-gpio: %d request failed!\n", gpio);
gpio_free(gpio);
return -ENODEV;
}
gpio_info->tw_gpio = gpio;
gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
gpio_direction_output(gpio_info->tw_gpio, gpio_info->gpio_enable_value);
pr_info("terry gpio set output\n");
return 0;
}
devm_kzalloc
为struct tw_gpio_info分配内存;
of_get_named_gpio_flags
从dts中根据配置的name(此处为"tw-gpio")获取对应gpio的id和flag;
gpio_is_valid
判断gpio的有效性;
gpio_request
申请占用该gpio,若申请失败则用gpio_free释放资源;
flag == OF_GPIO_ACTIVE_LOW
根据dts中设置的GPIO_ACTIVE_HIGH/LOW
来判断输出电平高低;
gpio_direction_output
设置gpio输出模式,并根据flag值来设置输出电平,如果要设置输入模式可用gpio_direction_input
。
- 测试结果如下,正确配置gpio输出高电平
[0.192309] tw_gpio_probe:terry GPIO TEST Driver Probe
[0.192336] terry gpio set outputgpio-19 ( |tw-gpio ) out hi
pin 19 (gpio0-19): (MUX UNCLAIMED) gpio0:19
小结与展望
参考下列资料已实现了最简单的gpio驱动,可以在驱动中控制单个gpio的状态。接下来想要实现添加sysfs节点,以便上层通过读写节点的方式来控制gpio的direction和value。
如有谬误欢迎指正,感谢阅读~