上次用的是节点搜索,这次用platform形式的
首先是设备树
/ { model = "Luckfox Pico Max"; compatible = "rockchip,rv1103g-38x38-ipc-v10", "rockchip,rv1106"; gpio1pc7:gpio1pc7 { compatible = "gpio1_pc7"; pinctrl-names = "default"; status = "okay"; pinctrl-0 = <&gpio1_pc7>; gpios = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>; regulator-name = "gpio1_pc7"; regulator-always-on; }; }; /* GPIO */ &pinctrl { gpio1-pc7 { gpio1_pc7:gpio1-pc7 { rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>; }; }; };
然后就是根据设备树,编写驱动代码
#include <linux/err.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/gpio/consumer.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/device.h> #include <asm/uaccess.h> #define GPIO_CNT 1 #define GPIO_NAME "gpio1_pc7" struct gpio1_pc7_dev { dev_t devid; struct cdev cdev; struct class *class; struct device *device; int major; int minor; struct device_node *nd; int gpio1_pc7; }; struct gpio1_pc7_dev gpio1_pc7; static int gpio1_pc7_open(struct inode *inode,struct file *filp) { /* 设置为私有数据 */ filp->private_data = &gpio1_pc7; return 0; } static int gpio1_pc7_read(struct file *filp,char __user *buf,size_t cnt,loff_t *offt) { return 0; } static ssize_t gpio1_pc7_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) { int ret; unsigned char databuf[1]; unsigned char ledstat; struct gpio1_pc7_dev *dev = filp->private_data; ret = copy_from_user(databuf, buf, cnt); if(ret<0) { printk("kernel write failed "); return -EFAULT; } ledstat = databuf[0]; if(ledstat == 1) { gpio_set_value(dev->gpio1_pc7,1); } else if(ledstat == 0) { gpio_set_value(dev->gpio1_pc7,0); } return 0; } static int gpio1_pc7_release(struct inode *inode,struct file *flip) { return 0; } static struct file_operations gpio1_pc7_fops = { .owner = THIS_MODULE, .open = gpio1_pc7_open, .read = gpio1_pc7_read, .write = gpio1_pc7_write, .release = gpio1_pc7_release, }; static int gpio1_pc7_probe(struct platform_device *dev) { int ret = 0; printk("gpio1_pc7 driver and device was matched "); /* 1、设置设备号 */ if(gpio1_pc7.major) { gpio1_pc7.devid = MKDEV(gpio1_pc7.major,0); ret = register_chrdev_region(gpio1_pc7.devid,GPIO_CNT,GPIO_NAME); } else { alloc_chrdev_region(&gpio1_pc7.devid,0,GPIO_CNT,GPIO_NAME);/* 申请设备号 */ gpio1_pc7.major = MAJOR(gpio1_pc7.devid); gpio1_pc7.minor = MINOR(gpio1_pc7.devid); } printk("gpio1_pc7 major = %dgpio1_pc7_init,minor=%d ",gpio1_pc7.major,gpio1_pc7.minor); //gpio1_pc7.cdev.owner = THIS_MODULE; /* 2、注册设备 */ cdev_init(&gpio1_pc7.cdev,&gpio1_pc7_fops); cdev_add(&gpio1_pc7.cdev,gpio1_pc7.devid,GPIO_CNT); /* 3、创建类 */ gpio1_pc7.class = class_create(THIS_MODULE,GPIO_NAME); if(IS_ERR(gpio1_pc7.class)) { return PTR_ERR(gpio1_pc7.class); } /* 4、创建设备 */ gpio1_pc7.device = device_create(gpio1_pc7.class, NULL, gpio1_pc7.devid, NULL, GPIO_NAME); if(IS_ERR(gpio1_pc7.device)) { return PTR_ERR(gpio1_pc7.device); } /* 5、初始化IO */ gpio1_pc7.nd = of_find_node_by_path("/gpio1pc7"); if(gpio1_pc7.nd == NULL) { printk("gpio1pc7 node can't not found "); return -EINVAL; } else { printk("gpio1pc7 node has been found "); } gpio1_pc7.gpio1_pc7 = of_get_named_gpio(gpio1_pc7.nd,"gpios",0); if(gpio1_pc7.gpio1_pc7 < 0) { printk("can't get gpio1_pc7 "); return -EINVAL; } printk("gpio1_pc7 num = %d ", gpio1_pc7.gpio1_pc7); /* 8、请求GPIO,设置输出 */ ret = gpio_request(gpio1_pc7.gpio1_pc7,GPIO_NAME); if(ret) { printk("can't request gpio "); } ret = gpio_direction_output(gpio1_pc7.gpio1_pc7,1); if(ret < 0) { printk("can't set gpio "); } return 0; } static int gpio1_pc7_remove(struct platform_device *dev) { gpio_free(gpio1_pc7.gpio1_pc7); /* 删除cdev */ cdev_del(&gpio1_pc7.cdev); /* 注销 */ unregister_chrdev_region(gpio1_pc7.devid, GPIO_CNT); device_destroy(gpio1_pc7.class, gpio1_pc7.devid); class_destroy(gpio1_pc7.class); return 0; } /* 匹配列表 */ static const struct of_device_id gpio_of_match[] = { { .compatible = "gpio1_pc7" }, //{ .status = "gpio1_pc7" }, {}, }; MODULE_DEVICE_TABLE(of, gpio_of_match); /* platform驱动结构体 */ static struct platform_driver gpio1_pc7_driver = { .driver = { .name = GPIO_NAME, /* 驱动名字 */ .of_match_table = gpio_of_match, /* 设备树匹配表 */ }, .probe = gpio1_pc7_probe, .remove = gpio1_pc7_remove, }; static int __init gpio1_pc7_init(void) { return platform_driver_register(&gpio1_pc7_driver); } static void __exit gpio1_pc7_exit(void) { platform_driver_unregister(&gpio1_pc7_driver); } module_init(gpio1_pc7_init); module_exit(gpio1_pc7_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luckfox"); MODULE_VERSION("V1.0");
上面是通过.compatible来搜索关键信息,找到设备树的节点
最后载入驱动
# insmod gpio_platform.ko # dmesg
运用insmod载入,然后运用dmesg来查看内核打印的消息