设备树
led {
compatible = "gpio-leds";
label = "green";
led-gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>;
status = "okay";
};
驱动
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PLATFORMLED_NAME "platformled"
#define PLATFORMLED_CNT 1
#define LEDOFF 0
#define LEDON 1
/* platform_led 设备结构体 */
struct platformled_dev
{
dev_t devid; /* 设备号 */
int major; /* 主设备号 */
struct cdev cdev; /* 字符设备 */
struct class *class; /* 类 */
struct device *device; /* 设备 */
struct device_node *node; /* 设备节点 */
int led0; /* LED 灯 GPIO 标号 */
};
/* 定义设备结构体变量 */
struct platformled_dev platformled;
/* open 函数 */
static int gpioled_open(struct inode *inode, struct file *filp)
{
filp->private_data = &platformled; /* 设置私有数据 */
return 0;
}
/* write 函数 */
static ssize_t gpioled_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
//struct platformled_dev *dev = (struct platformled_dev *)filp->private_data;
int ret;
unsigned char databuf[1];
ret = copy_from_user(databuf, buf, cnt);
if (ret < 0)
{
printk("kernel write failed!\r\n");
return -EFAULT;
}
if (databuf[0] == LEDON)
{
gpio_set_value(platformled.led0, 0);
}
else if (databuf[0] == LEDOFF)
{
gpio_set_value(platformled.led0, 1);
}
return 0;
}
/* 字符设备操作集合 */
static struct file_operations platformled_fops = {
.owner = THIS_MODULE,
.open = gpioled_open,
.write = gpioled_write,
};
//匹配设备结构体
static const struct of_device_id led_of_match_table[] = {
{.compatible = "gpio-leds"},
};
static int platformled_probe(struct platform_device *dev)
{
printk("led driver and device was matched!\r\n");
/* 1、设置设备号 */
if (platformled.major) {
platformled.devid = MKDEV(platformled.major, 0);
register_chrdev_region(platformled.devid, PLATFORMLED_CNT, PLATFORMLED_NAME);
} else {
alloc_chrdev_region(&platformled.devid, 0, PLATFORMLED_CNT, PLATFORMLED_NAME);
platformled.major = MAJOR(platformled.devid);
}
/* 2、注册设备 */
cdev_init(&platformled.cdev, &platformled_fops);
cdev_add(&platformled.cdev, platformled.devid, PLATFORMLED_CNT);
/* 3、创建类 */
platformled.class = class_create(THIS_MODULE, PLATFORMLED_NAME);
if (IS_ERR(platformled.class)) {
return PTR_ERR(platformled.class);
}
/* 4、创建设备 */
platformled.device = device_create(platformled.class, NULL, platformled.devid, NULL, PLATFORMLED_NAME);
if (IS_ERR(platformled.device)) {
return PTR_ERR(platformled.device);
}
/* 5、初始化 IO */
platformled.node = of_find_node_by_path("/led");
if (platformled.node == NULL){
printk("gpioled node nost find!\r\n");
return -EINVAL;
}
platformled.led0 = of_get_named_gpio(platformled.node, "led-gpios", 0);
if (platformled.led0 < 0) {
printk("can't get led-gpio\r\n");
return -EINVAL;
}
gpio_request(platformled.led0, "led0");
gpio_direction_output(platformled.led0, 1); /*设置为输出,默认高电平 */
return 0;
}
static int platformled_remove(struct platform_device *dev)
{
/* 注销设备的时候关闭 LED 灯 */
gpio_set_value(platformled.led0, 1);
/* 删除 cdev */
cdev_del(&platformled.cdev);
/* 删除 cdev */
unregister_chrdev_region(platformled.devid, PLATFORMLED_CNT);
/* 删除 cdev */
device_destroy(platformled.class, platformled.devid);
/* 删除 cdev */
class_destroy(platformled.class);
return 0;
}
/* platform 驱动结构体 */
static struct platform_driver platform_driver_led = {
.driver = {
.name = "platform_driver_led",//驱动名字
.of_match_table = led_of_match_table,//设备树匹配表
},
.probe = platformled_probe,
.remove = platformled_remove,
};
/* 入口函数 */
static int __init platformled_init(void)
{
/* 注册平台级设备驱动 */
return platform_driver_register(&platform_driver_led);
}
/* 出口函数 */
static void __exit platformled_exit(void)
{
/* 卸载平台级设备驱动 */
platform_driver_unregister(&platform_driver_led);
}
module_init(platformled_init);
module_exit(platformled_exit);
MODULE_AUTHOR("chen");
MODULE_LICENSE("GPL");