以用 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
来源: http://www.bubuko.com/infodetail-2958447.html