1 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/i2c.h> 4 #include <linux/miscdevice.h> 5 #include <linux/delay.h> 6 #include <linux/fs.h> 7 #include <linux/device.h> 8 9 10 //声明一个i2c client指针--保存probe中的i2c client 11 static struct i2c_client *at24_client; 12 static struct miscdevice e2prom_misc; 13 14 15 //重写类似于i2c_master_send()/i2c_master_recv() 16 int at24_i2c_send(struct i2c_client *client, char *buf, int count) 17 { 18 int ret; 19 20 struct i2c_adapter *adapter = client->adapter; 21 struct i2c_msg msg; 22 23 msg.addr = client->addr; 24 msg.flags = 0; //读1还是写0 25 msg.len = count; 26 msg.buf = buf; 27 //参数1---适配器--来自于i2c client 28 //参数2--数据包 29 //参数3--数据包的个数 30 //返回值--正确返回消息的个数,错误返回负数 31 ret = i2c_transfer(adapter, &msg, 1); 32 33 return ret==1?count:ret; 34 35 } 36 37 int at24_i2c_recv(struct i2c_client *client, char *buf, int count) 38 { 39 int ret; 40 41 struct i2c_adapter *adapter = client->adapter; 42 struct i2c_msg msg; 43 44 msg.addr = client->addr; 45 msg.flags = 1; //读1还是写0 46 msg.len = count; 47 msg.buf = buf; 48 //参数1---适配器--来自于i2c client 49 //参数2--数据包 50 //参数3--数据包的个数 51 //返回值--正确返回消息的个数,错误返回负数 52 ret = i2c_transfer(adapter, &msg, 1); 53 54 return ret==1?count:ret; 55 56 } 57 58 59 const struct file_operations at24_fops = { 60 61 62 }; 63 64 65 int at24_drv_probe(struct i2c_client *client, const struct i2c_device_id *id) 66 { 67 68 printk("id->name = %s, id->driver_data = 0x%x ", id->name, id->driver_data); 69 70 // 0- 保存i2c_client 71 at24_client = client; 72 73 // 1, 与用户交互 74 e2prom_misc.name = "at24_dev"; 75 e2prom_misc.minor = MISC_DYNAMIC_MINOR, 76 e2prom_misc.fops = &at24_fops, 77 misc_register(&e2prom_misc); 78 79 // 2, 与硬件交互(初始化硬件)--最终委托i2c adpater层与硬件打交道 80 // e2prom上电就能工作,并不需要特定一些初始化 81 //以下代码主要演示如何操作从设备 82 83 84 int ret; 85 86 char sendbuf[10] = {0x8/*写的地址*/, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, 0x8b, 0x9b}; 87 88 ret = at24_i2c_send(client, sendbuf, 10); 89 if(ret < 0) 90 { 91 printk("at24_i2c_send error "); 92 misc_deregister(&e2prom_misc); 93 return ret; 94 } 95 96 mdelay(3); 97 //验证是否写入正确 98 //先写地址 99 char addr = 0x8; 100 ret = at24_i2c_send(client, &addr, 1); 101 if(ret < 0) 102 { 103 printk("at24_i2c_send error "); 104 misc_deregister(&e2prom_misc); 105 return ret; 106 } 107 char recvbuf[8]; 108 ret = at24_i2c_recv(client, recvbuf, 8); 109 if(ret < 0) 110 { 111 printk("at24_i2c_recv error "); 112 misc_deregister(&e2prom_misc); 113 return ret; 114 } 115 int i; 116 for(i=0; i<8; i++) 117 printk("recvbuf[%d] = 0x%x ", i, recvbuf[i]); 118 119 120 return 0; 121 122 123 } 124 125 126 127 int at24_drv_remove(struct i2c_client *client) 128 { 129 misc_deregister(&e2prom_misc); 130 131 return 0; 132 } 133 134 135 136 const struct i2c_device_id at24_id_table[] = { 137 {"at24c02", 0x2}, 138 {"at24c04", 0x4}, 139 {"at24c08", 0x5}, 140 {"at24c16", 0x6}, 141 {}, 142 }; 143 144 145 struct i2c_driver at24_i2c_drv = { 146 .probe = at24_drv_probe, 147 .remove = at24_drv_remove, 148 .driver = { 149 .name = "at24_drv", //一定要有--/sys/bus/i2c/drivers/at24_drv 150 }, 151 .id_table = at24_id_table, 152 153 }; 154 155 156 static int __init at24_i2c_drv_init(void) 157 { 158 159 //注册一个i2c driver 160 return i2c_add_driver(&at24_i2c_drv); 161 162 163 } 164 165 static void __exit at24_i2c_drv_exit(void) 166 { 167 i2c_del_driver(&at24_i2c_drv); 168 } 169 170 171 late_initcall(at24_i2c_drv_init); 172 module_exit(at24_i2c_drv_exit); 173 MODULE_LICENSE("GPL");
CROSS_COMPILE = arm-none-linux-gnueabi- CC = $(CROSS_COMPILE)gcc #指定内核源码路径 KERNEL_DIR = /home/kernel/linux-3.0.8 CUR_DIR = $(shell pwd) #MYAPP = plat_led_app MODULE = at24_i2c_drv all: #让make进入内核源码编译,同时将当前目录中的c程序作为内核模块一起编译 make -C $(KERNEL_DIR) M=$(CUR_DIR) modules ifneq ($(MYAPP), ) $(CC) -o $(MYAPP) $(MYAPP).c endif clean: #删除上面编译生成的文件 make -C $(KERNEL_DIR) M=$(CUR_DIR) clean rm -rf $(MYAPP) install: cp *.ko $(MYAPP) /opt/rootfs/drv_module #指定当前目录下哪个文件作为内核模块编 obj-m += $(MODULE).o