1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 一 linux驱动开发-8.2-设备树下platform驱动

一 linux驱动开发-8.2-设备树下platform驱动

时间:2023-05-05 17:03:28

相关推荐

一 linux驱动开发-8.2-设备树下platform驱动

一、简介

之前没用设备树的时候,是分别编写并注册platform_device和platform_driver来表示设备和驱动,如果使用设备树,设备的描述就放在设备树中,因此只需要实现platform_driver就可以了,具体如下:

1.1、创建节点

因为platform总线需要通过设备节点的compatible属性值来匹配驱动,所以创建节点的重点是设置好compatible属性值。比如:

1.2、兼容属性

在使用设备树的时候,platform驱动会通过of_match_table来保存兼容属性值,也就表明此驱动兼容哪些设备,可以按照如下设置:

static const struct of_device_id led_of_match[] = {{ .compatible = "atkmini-gpioled"},{}};MODULE_DEVICE_TABLE(of, led_of_match);/**platform平台驱动结构体*/static struct platform_driver led_platform_driver = {.driver = {.name = "imx6ul-led",.of_match_table = led_of_match,},.probe = leddev_probe,.remove = leddev_remove,};

of_device_id是驱动的兼容表,一个驱动可以跟多个设备匹配,这里仅匹配了一个。compatible值跟设备树中的值一致,匹配成功后,对应的probe函数就会执行。

二、驱动编写

#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/uaccess.h>#include <linux/io.h>#include <linux/of.h>#include <linux/of_address.h>#include <linux/of_gpio.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/platform_device.h>#define LEDDEV_CNT1#define LEDDEV_NAME "dtsplatled"#defineLED_ON1#define LED_OFF0//设备结构体struct leddev_dev{dev_t devid;struct cdev cdev;struct class *class;struct device *device;int major;int minor;struct device_node *nd;//设备节点int led_gpio;//led所使用的GPIO编号};struct leddev_dev leddev; static void led_switch(uint8_t sta){if (sta == LED_ON){gpio_set_value(leddev.led_gpio, 0);} else if (sta == LED_OFF) {gpio_set_value(leddev.led_gpio, 1);}}static int leddev_open(struct inode *inode, struct file *filp){filp->private_data = &leddev;printk("leddev open!\n");return 0;}static ssize_t leddev_read(struct file *filp, __user char *buf, size_t count, loff_t *ppos){printk("leddev read\n");return 0;}static ssize_t leddev_write(struct file *filp, const char __user *buf, size_t count, loff_t *oppos){int ret;uint8_t data_buf[1];ret = copy_from_user(data_buf, buf, count);if (ret < 0){printk("write data fail\n");return -EFAULT;}led_switch(data_buf[0]);return 0;}static int leddev_release(struct inode *inode, struct file *filp){printk("led release\n");return 0;}static const struct file_operations leddev_fops = {.owner = THIS_MODULE,.open = leddev_open,.read = leddev_read,.write = leddev_write,.release = leddev_release,};/**platform驱动的probe函数*驱动与设备匹配成功以后此函数就会执行*/static int leddev_probe(struct platform_device *dev){int ret = 0;printk("led driver and device has match\r\n");//通过节点名字查找节点leddev.nd = of_find_node_by_name(NULL, "gpioled");if (leddev.nd == NULL){printk("find %s fail\r\n", "gpioled");return -EINVAL;}//获取GPIO编号leddev.led_gpio = of_get_named_gpio(leddev.nd, "gpio", 0);if (leddev.led_gpio < 0){printk("get gpio fail\r\n");return -EINVAL;}else{printk("led_gpio value is %d", leddev.led_gpio);}//设置led状态ret = gpio_direction_output(leddev.led_gpio, 0);if (ret < 0){printk("set led status fail\r\n");return -EINVAL;}//分配设备号if (leddev.major) {leddev.devid = MKDEV(leddev.major, 0);register_chrdev_region(leddev.devid, LEDDEV_CNT, LEDDEV_NAME);} else {alloc_chrdev_region(&leddev.devid, 0, LEDDEV_CNT, LEDDEV_NAME);leddev.major = MAJOR(leddev.devid);leddev.minor = MINOR(leddev.devid);}printk("leddev major=%d, minor= %d\r\n", leddev.major, leddev.minor);//初始化cdevleddev.cdev.owner = THIS_MODULE;cdev_init(&leddev.cdev, &leddev_fops);//添加cdevcdev_add(&leddev.cdev, leddev.devid, LEDDEV_CNT);//创建类leddev.class = class_create(THIS_MODULE, LEDDEV_NAME);//创建设备leddev.device = device_create(leddev.class, NULL, leddev.devid, NULL, LEDDEV_NAME);return 0;}static int leddev_remove(struct platform_device *dev){led_switch(LED_OFF);//删除设备的类device_destroy(leddev.class, leddev.devid);//删除类class_destroy(leddev.class);//删除设备cdev_del(&leddev.cdev);//注销设备号unregister_chrdev_region(leddev.devid, LEDDEV_CNT);}static const struct of_device_id led_of_match[] = {{ .compatible = "atkmini-gpioled"},{}};/**platform平台驱动结构体*/static struct platform_driver led_driver = {.driver = {.name = "imx6ul-led",.of_match_table = led_of_match,},.probe = leddev_probe,.remove = leddev_remove,};static int __init leddriver_init(void){return platform_driver_register(&led_driver);}static void __exit leddriver_exit(void){platform_driver_unregister(&led_driver);printk("newchrdev exit\n");}module_init(leddriver_init);module_exit(leddriver_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("ZK");

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。