1 背景
开发中,有时候需要我们自己手动去拉gpio,很多人使用led驱动,这也是可以的。
但是直接写一个gpio驱动会更灵活一些,下面就是一个简单的驱动,可放在rk3568/drivers/gpio/gpio-e.c
编译时,别忘了加上makefile
rk3568/kernel/drivers/gpio/Makefile
obj-y = gpio-e.o
2 代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <dt-bindings/gpio/gpio.h>
#define DEBUG
#ifdef DEBUG
#define LOG(fmt, args...) pr_info("[E GPIO]: " fmt, ##args)
#else
#define LOG(fmt, args...)
#endif
struct e_gpio{
int io;
int enable;
int period_ms;
};
static int e_gpio_parse_dt(struct device* dev, struct e_gpio* data)
{
struct device_node* node = dev->of_node;
int gpio;
enum of_gpio_flags flag;
int ret;
gpio = of_get_named_gpio_flags(node, "gpio", 0, &flag);
if(gpio_is_valid(gpio)){
data->io = gpio;
data->enable = (flag == GPIO_ACTIVE_HIGH) ? 1: 0;
}else{
LOG("cannot parse gpio!");
data->io = -1;
return -ENODEV;
}
ret = of_property_read_u32(node, "period-ms", &data->period_ms);
if(ret < 0)
data->period_ms = -1;
return 0;
}
static void e_setup_gpio(struct device* dev, struct e_gpio* data)
{
int ret;
if(gpio_is_valid(data->io)){
ret = devm_gpio_request(dev, data->io, "e-gpio");
//ret = devm_gpio_request_one(dev, data->io, GPIOF_DIR_OUT, NULL);
if(ret < 0){
LOG("failed to get gpio!");
return;
}
gpio_direction_output(data->io, data->enable);
if(data->period_ms > 0){
msleep(data->period_ms);
devm_gpio_free(dev, data->io);
}
}
LOG("GPIO setup done!");
}
static int e_gpio_probe(struct platform_device* pdev)
{
struct device* dev = &pdev->dev;
int ret;
struct e_gpio* data;
data = devm_kzalloc(dev, sizeof(struct e_gpio), GFP_KERNEL);
if(!data)
return -ENOMEM;
ret = e_gpio_parse_dt(dev, data);
if(ret < 0)
return -ENODEV;
e_setup_gpio(dev, data);
return 0;
}
static struct of_device_id e_gpio_of_match[] = {
{.compatible = "e,gpio"},
{}
};
MODULE_DEVICE_TABLE(of, e_gpio_of_match);
static struct platform_driver e_gpio_driver = {
.probe = e_gpio_probe,
.driver = {
.name = "e-gpio",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(e_gpio_of_match),
},
};
static int __init e_gpio_init(void)
{
LOG("e gpio init!");
return platform_driver_register(&e_gpio_driver);
}
module_init(e_gpio_init)
static void __exit e_gpio_exit(void)
{
LOG("e gpio exit");
platform_driver_unregister(&e_gpio_driver);
}
module_exit(e_gpio_exit)
MODULE_AUTHOR("XXX");
MODULE_DESCRIPTION("e gpio driver");
MODULE_LICENSE("GPL");
3 对应的DTS
gpio:e-gpio{
compatible="e,gpio";
gpio = <&gpio2 RK_PD7 GPIO_ACTIVE_HIGH>;
// period-ms = <15>;
status = "okay";
};
整体功能比较简单,唯一需要解释的是period-ms,这代表开机时先把gpio拉高/低一段时间(如例子中为15ms),然后释放掉对应的gpio资源。
原作者:taye_year