标签:adapter module 时钟 clean probe device ops rtc detach
以用i2c通信的实时时钟为例
框架入口源文件:i2c_m41t11.c
(可根据入口源文件,再按着框架到内核走一遍)
内核版本:linux_2.6.22.6 硬件平台:JZ2440
以下是驱动框架:
以下是驱动代码 i2c_m41t11.c :
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/jiffies.h> #include <linux/i2c.h> #include <linux/mutex.h> #include <linux/fs.h> static unsigned short normal_i2c[] = {0x68,I2C_CLIENT_END}; //只有七位 0xd0 >> 1 static unsigned short probe[] = {I2C_CLIENT_END}; static unsigned short ignore[] = {I2C_CLIENT_END}; //定义一个 client 地址数据 static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, .probe = probe, .ignore = ignore, }; //定义 client static struct i2c_client *i2c_m41t11_client; //定义 主设备号 static int major; //定义一个 i2c 字符驱动 static struct i2c_driver i2c_m41t11_driver; static ssize_t i2c_m41t11_read(struct file *file, char __user *buf, size_t size, loff_t * offset) { printk(" <========= this is m41t11 RTC chip =========> \n"); return 0; } static ssize_t i2c_m41t11_write(struct file *file, const char __user *buf, size_t size, loff_t * offset) { printk(" <========== this is m41t11 RTC chip =========> \n"); return 0; } //定义字符操作函数 static struct file_operations i2c_m41t11_fops = { .owner = THIS_MODULE, .read = i2c_m41t11_read, .write = i2c_m41t11_write, }; //定义一个字符设备类 static struct class *i2c_m41t11_class; //匹配处理函数 static int m41t11_match_fun(struct i2c_adapter* adpater,int addr ,int kind) { printk("match m41t11 RTC chip successfully \n"); //初始化 client 结构体 i2c_m41t11_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); i2c_m41t11_client->adapter = adpater; i2c_m41t11_client->driver = &i2c_m41t11_driver; i2c_m41t11_client->addr = addr; strcpy(i2c_m41t11_client->name, "i2c_m41t11_client"); i2c_attach_client(i2c_m41t11_client); //注册字符设备 major = register_chrdev(0,"i2c_m41t11", &i2c_m41t11_fops); i2c_m41t11_class = class_create(THIS_MODULE,"i2c_m41t11_class"); // /sys/class/i2c_m41t11_class class_device_create(i2c_m41t11_class, NULL, MKDEV(major, 0), NULL,"i2c_m41t11_dev"); // /dev/i2c_m41t11_dev return 0; } static int i2c_m41t11_attach(struct i2c_adapter *adapter) { printk("trying to match m41t11 RTC chip \n"); return i2c_probe( adapter , &addr_data , m41t11_match_fun ); } static int i2c_m41t11_detach(struct i2c_client *client) { printk("delect m41t11 RTC chip \n"); //字符设备 unregister_chrdev(major, "i2c_m41t11"); class_destroy(i2c_m41t11_class); class_device_destroy(i2c_m41t11_class,MKDEV(major, 0)); //client i2c_detach_client(client); kfree(i2c_get_clientdata(client)); return 0; } //初始化 i2c_m41t11_driver static struct i2c_driver i2c_m41t11_driver = { .driver = { .name = "i2c_m41t11", }, .attach_adapter = i2c_m41t11_attach, .detach_client = i2c_m41t11_detach, }; static int i2c_m41t11_init(void) { i2c_add_driver(&i2c_m41t11_driver); return 0; } static void i2c_m41t11_exit(void) { i2c_del_driver(&i2c_m41t11_driver); } module_init(i2c_m41t11_init); module_exit(i2c_m41t11_exit); MODULE_LICENSE("GPL");
以下是编译驱动的Makefile:
KER_DIR=/work/systems/kernel/linux-2/linux-2.6.22.6
all:
make -C $(KER_DIR) M=`pwd` modules
clean:
make -C $(KER_DIR) M=`pwd` modules clean
rm -fr modules.order
obj-m += i2c_m41t11.o
标签:adapter module 时钟 clean probe device ops rtc detach
原文地址:https://www.cnblogs.com/zsy12138/p/10392810.html