首先修改设备树,添加ap3216c@1e? 节点信息,ap3216c 是支持iic协议的芯片
#include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/gpio.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/of_gpio.h> #include <linux/semaphore.h> #include <linux/timer.h> #include <linux/i2c.h> #include <asm/mach/map.h> #include <asm/uaccess.h> #include <asm/io.h> #include "ap3216creg.h"
#define AP3216C_CNT 1 #define AP3216C_NAME "ap3216c"
struct ap3216c_dev{ ?? ?dev_t devid; //设备号 ?? ?struct cdev cdev; //字符设备 ?? ?struct class *class; //类 ?? ?struct device *device; //设备 ?? ?struct device_node *nd; //设备节点 ?? ?int major; //主设备号 ?? ?int minor; //次设备号 ?? ?void *private_data; //私有数据 ?? ? };
struct ap3216c_dev ap3216cdev;
static int ap3216c_open(struct inode *inode, struct file *filp) { ?? ?filp->private_data = &ap3216cdev; ?? ?printk("ap3216c_open\r\n");
?? ?return 0; }
static ssize_t ap3216c_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off) { ?? ?printk("ap3216c_read\r\n"); ?? ?return 0; }
static int ap3216c_release(struct inode *inode, struct file *filp) { ?? ?printk("ap3216c_release\r\n"); ?? ?return 0; }
//ap3216c操作函数 static const struct file_operations ap3216c_ops = { ?? ?.owner = THIS_MODULE, ?? ?.open = ap3216c_open, ?? ?.read = ap3216c_read, ?? ?.release = ap3216c_release,? };
static int ap3216c_probe(struct i2c_client *client,const struct i2c_device_id *id) { ?? ?int ret = 0; ?? ?printk("ap3216c_probe\r\n");
?? ?//搭建字符设备驱动框架 ?? ?//1.构建设备号 ?? ?if(ap3216cdev.major){ ?? ??? ?ap3216cdev.devid = MKDEV(ap3216cdev.major,0); ?? ??? ?register_chrdev_region(ap3216cdev.devid,AP3216C_CNT,AP3216C_NAME); ?? ?}else{ ?? ??? ?alloc_chrdev_region(&ap3216cdev.devid, 0, AP3216C_CNT, AP3216C_NAME); ?? ??? ?ap3216cdev.major = MAJOR(ap3216cdev.devid); ?? ??? ?ap3216cdev.minor = MINOR(ap3216cdev.devid); ?? ?}
?? ?printk("major:%d\r\n",ap3216cdev.major); ?? ?printk("minor:%d\r\n",ap3216cdev.minor); ?? ?//2.注册设备 ?? ?cdev_init(&ap3216cdev.cdev,&ap3216c_ops); ?? ?cdev_add(&ap3216cdev.cdev,ap3216cdev.devid,AP3216C_CNT);
?? ?//3.创建类 ?? ?ap3216cdev.class = class_create(THIS_MODULE,AP3216C_NAME); ?? ?if(IS_ERR(ap3216cdev.class)){ ?? ??? ?return PTR_ERR(ap3216cdev.class); ?? ?}
?? ?//4.创建设备 ?? ?ap3216cdev.device = device_create(ap3216cdev.class,NULL,ap3216cdev.devid,NULL,AP3216C_NAME); ?? ?if(IS_ERR(ap3216cdev.device)){ ?? ??? ?return PTR_ERR(ap3216cdev.device); ?? ?}
?? ?ap3216cdev.private_data = client;
?? ?return 0; }
static int ap3216c_remove(struct i2c_client *client) { ?? ?//删除设备 ?? ?cdev_del(&ap3216cdev.cdev); ?? ?//删除设备号 ?? ?unregister_chrdev_region(ap3216cdev.devid,AP3216C_CNT); ?? ?//注销类和设备 ?? ?device_destroy(ap3216cdev.class,ap3216cdev.devid); ?? ?class_destroy(ap3216cdev.class);
?? ?return 0; }
//传统匹配方式ID列表 static struct i2c_device_id ap3216c_id[] = { ?? ?{"alientek,ap3216c",0}, ?? ?{} };
//设备树匹配表 static struct of_device_id ap3216c_of_match[] = { ?? ?{.compatible = "alientek,ap3216c"}, ?? ?{} };
//i2c_driver static struct i2c_driver ap3216c_driver = {
?? ?.probe = ap3216c_probe, //匹配成功调用此函数 ?? ?.remove= ap3216c_remove, ?? ?.driver = { ?? ??? ?.name = "ap321c", //没有设备树时用名字和设备匹配 ?? ??? ?.owner = THIS_MODULE, ?? ??? ?.of_match_table = ap3216c_of_match, //匹配表,有设备树时用匹配表和设备树里面的节点进行配对 ?? ?}, ?? ?.id_table = ap3216c_id,
};
//驱动入口函数 static int __init ap3216c_init(void) { ?? ?int ret = 0;
?? ?ret = i2c_add_driver(&ap3216c_driver); ?//向系统注册i2c
?? ?return ret; }
//驱动出口函数 static void __exit ap3216c_exit(void) { ?? ?i2c_del_driver(&ap3216c_driver); }
module_init(ap3216c_init); module_exit(ap3216c_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("DENG");
|