基于dts的platform驱动框架
在模块加载xxxdriver_init()里的platform_driver_register(& xxx_driver)
其中platform_driver_register()传入的是结构体指针 xxx_driver, of_match_table数组用来对设备进行匹配,匹配成功后会自动调用probe函数
static struct platform_driver xxx_driver = {
.driver = {
.name = "xxx",
.of_match_table = xxx_of_match,
},
.probe = xxx_probe,
.remove = xxx_remove,
};
xxx_probe()函数里:
/* 1、设置设备号 */
if (xxxdev.major) {
xxxdev.devid = MKDEV(xxxdev.major, 0);
register_chrdev_region(xxxdev.devid, LEDDEV_CNT,LEDDEV_NAME);
} else {
alloc_chrdev_region(&xxxdev.devid, 0, LEDDEV_CNT,LEDDEV_NAME);
xxxdev.major = MAJOR(xxxdev.devid);}
/* 2、注册设备 */
cdev_init(&xxxdev.cdev, &xxx_fops);
cdev_add(&xxxdev.cdev, xxxdev.devid, LEDDEV_CNT); /* #define LEDDEV_CNT 1 */
/* 3、创建类 */
xxxdev.class = class_create(THIS_MODULE, LEDDEV_NAME); /* #define LEDDEV_NAME gpioled */
/* 4、创建设备 */
xxxdev.device = device_create(xxxdev.class, NULL, xxxdev.devid,NULL, LEDDEV_NAME);
/* 5、初始化 IO */
xxxdev.node = of_find_node_by_path("/gpioled");
xxxdev.led0 = of_get_named_gpio(xxxdev.node, "led-gpio", 0);
gpio_request(xxxdev.led0, "led0");
gpio_direction_output(xxxdev.led0, 1); /*设置为输出,默认高电平 */
示例代码34.2.2.5 platform驱动框架
/* 设备结构体 */
1 struct xxx_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
struct device_node *node; /* LED 设备节点 */
int led0; /* LED 灯 GPIO 标号 */
/* 设备结构体其他具体内容 */
4 };
5
6 struct xxx_dev xxxdev; /* 定义个设备结构体变量 */
7
8 static int xxx_open(struct inode *inode, struct file *filp)
9 {
10 /* 函数具体内容 */
11 return 0;
12 }
13
14 static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
15 {
16 /* 函数具体内容 */
17 return 0;
18 }
19
20 /*
21 * 字符设备驱动操作集
22 */
23 static struct file_operations xxx_fops = {
24 .owner = THIS_MODULE,
25 .open = xxx_open,
26 .write = xxx_write,
27 };
28
29 /*
30 * platform驱动的probe函数
31 * 驱动与设备匹配成功以后此函数就会执行
32 */
33 static int xxx_probe(struct platform_device *dev)
34 {
printk("led driver and device was matched!\r\n");
/* 1、设置设备号 */
if (xxxdev.major) {
xxxdev.devid = MKDEV(xxxdev.major, 0);
register_chrdev_region(xxxdev.devid, LEDDEV_CNT,LEDDEV_NAME);
} else {
alloc_chrdev_region(&xxxdev.devid, 0, LEDDEV_CNT,LEDDEV_NAME);
xxxdev.major = MAJOR(xxxdev.devid);}
/* 2、注册设备 */
cdev_init(&xxxdev.cdev, &xxx_fops);
cdev_add(&xxxdev.cdev, xxxdev.devid, LEDDEV_CNT); /* #define LEDDEV_CNT 1 */
/* 3、创建类 */
xxxdev.class = class_create(THIS_MODULE, LEDDEV_NAME); /* #define LEDDEV_NAME gpioled */
if (IS_ERR(xxxdev.class)) {
return PTR_ERR(xxxdev.class);
}
/* 4、创建设备 */
xxxdev.device = device_create(xxxdev.class, NULL, xxxdev.devid,NULL, LEDDEV_NAME);
if (IS_ERR(xxxdev.device)) {
return PTR_ERR(xxxdev.device);
}
/* 5、初始化 IO */
xxxdev.node = of_find_node_by_path("/gpioled");
if (xxxdev.node == NULL){
printk("gpioled node nost find!\r\n");
return -EINVAL;
}
xxxdev.led0 = of_get_named_gpio(xxxdev.node, "led-gpio", 0);
if (xxxdev.led0 < 0) {
printk("can't get led-gpio\r\n");
return -EINVAL;
}
gpio_request(xxxdev.led0, "led0");
gpio_direction_output(xxxdev.led0, 1); /*设置为输出,默认高电平 */
return 0;
}
40
41 static int xxx_remove(struct platform_device *dev)
42 {
43 ......
44 cdev_del(&xxxdev.cdev);/* 删除cdev */
45 /* 函数具体内容 */
46 return 0;
47 }
48
49 /* 匹配列表 */
50 static const struct of_device_id xxx_of_match[] = {
51 { .compatible = "xxx-gpio" },
52 { /* Sentinel */ }
53 };
54
55 /*
56 * platform平台驱动结构体
57 */
58 static struct platform_driver xxx_driver = {
59 .driver = {
60 .name = "xxx",
61 .of_match_table = xxx_of_match,
62 },
63 .probe = xxx_probe,
64 .remove = xxx_remove,
65 };
66
67 /* 驱动模块加载 */
68 static int __init xxxdriver_init(void)
69 {
70 return platform_driver_register(&xxx_driver);
71 }
72
73 /* 驱动模块卸载 */
74 static void __exit xxxdriver_exit(void)
75 {
76 platform_driver_unregister(&xxx_driver);
77 }
78
79 module_init(xxxdriver_init);
80 module_exit(xxxdriver_exit);
81 MODULE_LICENSE("GPL");
82 MODULE_AUTHOR("zuozhongkai");
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 351134995@qq.com