Linux i2c驱动(eeprom 读写)

转载地址:http://blog.csdn.net/tchonggang77/article/details/7366027

一、M24256简介

1、256 Kbit Serial I²C Bus EEPROM

2、Compatible with I2C Extended Addressing
3、Two Wire I2C Serial Interface
4、Supports 400 kHz Protocol
5、 Hardware Write Control
6、 BYTE and PAGE WRITE (up to 64 Bytes)
7、 RANDOM and SEQUENTIAL READ Modes
8、 Automatic Address Incrementing

9、管脚定义

 

 

二、M24256读写时序

1、写page时序

2、读page时序

 

三、i2c驱动

  1. #include <linux/kernel.h>  
  2. #include <linux/module.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/slab.h>  
  5. #include <linux/smp_lock.h>  
  6. #include <linux/init.h>  
  7. #include <linux/delay.h>  
  8. #include <linux/proc_fs.h>  
  9. #include <linux/i2c.h>  
  10. #include <linux/i2c-dev.h>  
  11. #include <linux/platform_device.h>  
  12. #include <asm/uaccess.h>  
  13. #include <asm/atomic.h>  
  14.   
  15.   
  16. #define EEPROM_MAJOR      247  
  17. #define EEPROM_I2C_MINORS 1  
  18. #define EEPROM_NAME       "eeprom"  
  19. #define I2C_EEPROM_ADDR   (0x54 << 1)  
  20. #define I2C_EEPROM_ID     777  
  21. #define EEPROM_BANK_SIZE  64  
  22. #define I2C_NAME(x)       (x)->name  
  23. #define SET_EEPROM_PAGE_ADDR 1  
  24. #define EEPROM_MAX_ADDR   0x7fff  /* 256Kbit = 32Kbyte */  
  25.   
  26. static DEFINE_SPINLOCK(i2c_dev_array_lock);  
  27. static struct i2c_driver eeprom_driver;  
  28. static struct i2c_dev *i2c_dev_array[EEPROM_I2C_MINORS]= {NULL};  
  29.   
  30. struct i2c_dev  
  31. {  
  32.     int minor;  
  33.     struct i2c_adapter *adap;  
  34.     struct i2c_client *client;  
  35.     atomic_t busy;  
  36.     unsigned short page_address;  
  37. };  
  38.   
  39. static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)  
  40. {  
  41.     struct i2c_dev *i2c_dev = NULL;  
  42.   
  43.     if(adap == NULL)  
  44.     {  
  45.         printk("invalid parameter,adap == NULL\n");  
  46.         return NULL;  
  47.     }  
  48.   
  49.     if( adap->nr >= EEPROM_I2C_MINORS)  
  50.     {  
  51.         printk("invalid parameter,adap->nr = %d\n",adap->nr);  
  52.         return NULL;  
  53.     }  
  54.   
  55.     i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);  
  56.     if(i2c_dev == NULL)  
  57.     {  
  58.         printk("kzalloc i2c_dev error \n");  
  59.         return NULL;  
  60.     }  
  61.   
  62.     spin_lock(&i2c_dev_array_lock);  
  63.     if (i2c_dev_array[adap->nr] != NULL)  
  64.     {  
  65.         spin_unlock(&i2c_dev_array_lock);  
  66.         printk("eeprom already has a device assigned to this adapter\n");  
  67.         goto exit;  
  68.     }  
  69.   
  70.     i2c_dev->minor = adap->nr;  
  71.     i2c_dev_array[adap->nr] = i2c_dev;  
  72.     spin_unlock(&i2c_dev_array_lock);  
  73.   
  74.     return i2c_dev;  
  75. exit:  
  76.     kfree(i2c_dev);  
  77.     return NULL;  
  78. }  
  79.   
  80. static int eeprom_detect_client(struct i2c_adapter *adapter, int address,int kind)  
  81. {  
  82.     struct i2c_client *client = NULL;  
  83.     struct i2c_dev *i2c_dev = NULL;  
  84.     char *dname = NULL;  
  85.     int ret = -1;  
  86.   
  87.     printk("detecte eeprom client on address 0x%x\n",address << 1);  
  88.   
  89.     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))  
  90.     {  
  91.         printk("i2c check functionality failed\n");  
  92.         return -1;  
  93.     }  
  94.   
  95.     client =  kzalloc(sizeof(struct i2c_client), GFP_KERNEL);  
  96.     if (client == 0)  
  97.     {  
  98.         return -ENOMEM;  
  99.     }  
  100.   
  101.     client->addr    = address;  
  102.     client->adapter = adapter;  
  103.     client->driver  = &eeprom_driver;  
  104.     client->flags   = 0;  
  105.   
  106.     if (client->addr == (I2C_EEPROM_ADDR >> 1))  
  107.     {  
  108.         dname = EEPROM_NAME;  
  109.     }  
  110.     else  
  111.     {  
  112.         printk(" detect client: i2c addr error addr = 0x%X \n",client->addr);  
  113.         kfree(client);  
  114.         return -1;  
  115.     }  
  116.   
  117.     strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));  
  118.   
  119.     ret = i2c_attach_client(client);  
  120.     if (ret != 0)  
  121.     {  
  122.         printk(" detect client: i2c_attach_client(),ret = %d \n",ret);  
  123.         kfree(client);  
  124.         return ret;  
  125.     }  
  126.   
  127.     i2c_dev = get_free_i2c_dev(adapter);  
  128.     if (i2c_dev == NULL)  
  129.     {  
  130.         kfree(client);  
  131.         return -1;  
  132.     }  
  133.   
  134.     printk("eeprom adapter [%s] registered as minor %d\n",adapter->name, i2c_dev->minor);  
  135.   
  136.     i2c_dev->adap = adapter;  
  137.     i2c_dev->client = client;  
  138.     atomic_set(&(i2c_dev->busy),1);  
  139.   
  140.     return 0;  
  141. }  
  142.   
  143. static unsigned short normal_i2c[] = {I2C_EEPROM_ADDR >> 1,  I2C_CLIENT_END};  
  144. static unsigned short ignore = I2C_CLIENT_END;  
  145. static struct i2c_client_address_data addr_data =  
  146. {  
  147.     .normal_i2c  = normal_i2c,  
  148.     .probe       = &ignore,  
  149.     .ignore      = &ignore,  
  150. };  
  151.   
  152. static int return_i2c_dev(struct i2c_dev *i2c_dev)  
  153. {  
  154.     if(i2c_dev == NULL)  
  155.     {  
  156.         printk("invalid parameter,i2c_dev == NULL\n");  
  157.         return -1;  
  158.     }  
  159.   
  160.     if(i2c_dev->minor >= EEPROM_I2C_MINORS)  
  161.     {  
  162.         printk("invalid parameter,i2c_dev->minor = %d\n",i2c_dev->minor);  
  163.         return -1;  
  164.     }  
  165.     spin_lock(&i2c_dev_array_lock);  
  166.     i2c_dev_array[i2c_dev->minor] = NULL;  
  167.     spin_unlock(&i2c_dev_array_lock);  
  168.     kfree(i2c_dev);  
  169.   
  170.     return 0;  
  171. }  
  172.   
  173. static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)  
  174. {  
  175.     struct i2c_dev *i2c_dev = NULL;  
  176.   
  177.     if(adap == NULL)  
  178.     {  
  179.         printk("invalid parameter,adap == NULL\n");  
  180.         return NULL;  
  181.     }  
  182.     if(adap->nr >= EEPROM_I2C_MINORS)  
  183.     {  
  184.         printk("invalid parameter,adap->nr = %d\n",adap->nr);  
  185.         return NULL;  
  186.     }  
  187.   
  188.     spin_lock(&i2c_dev_array_lock);  
  189.     if ((i2c_dev_array[adap->nr] != NULL) && (i2c_dev_array[adap->nr]->adap == adap))  
  190.     {  
  191.         i2c_dev = i2c_dev_array[adap->nr];  
  192.     }  
  193.     spin_unlock(&i2c_dev_array_lock);  
  194.   
  195.     return i2c_dev;  
  196. }  
  197.   
  198. static int eeprom_attach_adapter(struct i2c_adapter *adap)  
  199. {  
  200.     printk("start probe for adapter %s (0x%x)\n",I2C_NAME(adap), adap->nr);  
  201.     return i2c_probe(adap, &addr_data, &eeprom_detect_client);  
  202. }  
  203.   
  204. static int eeprom_detach_client(struct i2c_client *client)  
  205. {  
  206.     struct i2c_dev *i2c_dev = NULL;  
  207.     int ret = -1;  
  208.   
  209.     if(client == NULL)  
  210.     {  
  211.         printk("invalid parameter,client == NULL\n");  
  212.         return -1;  
  213.     }  
  214.   
  215.     i2c_dev = i2c_dev_get_by_adapter(client->adapter);  
  216.     if(i2c_dev == NULL)  
  217.     {  
  218.         printk("invalid parameter,i2c_dev == NULL\n");  
  219.         return -1;  
  220.     }  
  221.   
  222.     return_i2c_dev(i2c_dev);  
  223.     ret = i2c_detach_client(client);  
  224.     if (ret != 0)  
  225.     {  
  226.         printk("i2c_detach_client() error,ret == %d\n",ret);  
  227.         return ret;  
  228.     }  
  229.     kfree(client);  
  230.     printk("eeprom detach client success\n");  
  231.   
  232.     return 0;  
  233. }  
  234.   
  235. static struct i2c_driver eeprom_driver =  
  236. {  
  237.     .driver =  
  238.     {  
  239.         .name       = "eeprom_driver",  
  240.     },  
  241.     .id             = I2C_EEPROM_ID,  
  242.     .attach_adapter = eeprom_attach_adapter,  
  243.     .detach_client  = eeprom_detach_client,  
  244. };  
  245.   
  246. static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)  
  247. {  
  248.     struct i2c_dev *i2c_dev = NULL;  
  249.   
  250.     if(index >= EEPROM_I2C_MINORS)  
  251.     {  
  252.         printk("invalid parameter,index = %d\n",index);  
  253.         return NULL;  
  254.     }  
  255.   
  256.     spin_lock(&i2c_dev_array_lock);  
  257.     i2c_dev = i2c_dev_array[index];  
  258.     spin_unlock(&i2c_dev_array_lock);  
  259.   
  260.     return i2c_dev;  
  261. }  
  262.   
  263. static inline int eeprom_read_byte(struct i2c_client *client, u8 reg)  
  264. {  
  265.     if (client == NULL)  
  266.     {  
  267.         printk("invalid parameter,client == NULL\n");  
  268.         return -1;  
  269.     }  
  270.     return i2c_smbus_read_byte_data(client, reg);  
  271. }  
  272.   
  273. static inline int eeprom_write_byte(struct i2c_client *client, u8 reg, u8 value)  
  274. {  
  275.     int ret = -1;  
  276.   
  277.     if (client == NULL)  
  278.     {  
  279.         printk("invalid parameter,client == NULL\n");  
  280.         return -1;  
  281.     }  
  282.   
  283.     ret = i2c_smbus_write_byte_data(client, reg, value);  
  284.     if(ret != 0)  
  285.     {  
  286.         printk("eeprom write addr:0x%x,name:%s,reg:0x%x,value0x%x\n",client->addr,client->name,reg,value);  
  287.     }  
  288.   
  289.     return ret;  
  290. }  
  291.   
  292. static int eeprom_open(struct inode *node,struct file *file)  
  293. {  
  294.     unsigned int minor = iminor(node);  
  295.     struct i2c_dev *i2c_dev = NULL;  
  296.   
  297.     printk("eeprom open\n");  
  298.   
  299.     i2c_dev = i2c_dev_get_by_minor(minor);  
  300.     i2c_dev->page_address = 0;  
  301.     set_wc_bit_high(); /* 写保护信号拉高 */  
  302.     file->private_data = i2c_dev;  
  303.   
  304.     if (atomic_dec_and_test(&i2c_dev->busy) == 0)  
  305.     {  
  306.         atomic_inc(&i2c_dev->busy);  
  307.         return -EBUSY; /* already open */  
  308.     }  
  309.   
  310.     return 0;  
  311. }  
  312.   
  313. static int eeprom_release(struct inode *node,struct file *file)  
  314. {  
  315.     struct i2c_dev * i2c_dev = (struct i2c_dev *)file->private_data;  
  316.   
  317.     if(i2c_dev == NULL)  
  318.     {  
  319.         printk("invalid parameter,i2c_dev == NULL\n");  
  320.         return -1;  
  321.     }  
  322.   
  323.     atomic_inc(&i2c_dev->busy);  
  324.     file->private_data = NULL;  
  325.     printk("eeprom release\n");  
  326.   
  327.     return 0;  
  328. }  
  329.   
  330. static ssize_t eeprom_read(struct file *filp,char *buf, size_t count, loff_t *offset)  
  331. {  
  332.     struct i2c_dev *i2c_dev = (struct i2c_dev *)filp->private_data;  
  333.     struct i2c_client *client = i2c_dev->client;  
  334.     int ret = -1;  
  335.     char my_buf[EEPROM_BANK_SIZE] = {0,};  
  336.     char message[2] = {0,};  
  337.   
  338.     if(i2c_dev->page_address + count > EEPROM_MAX_ADDR)  
  339.     {  
  340.         printk("eeprom read address range beyond\n");  
  341.         i2c_dev->page_address = 0;  
  342.         return -1;  
  343.     }  
  344.   
  345.     set_wc_bit_low(); /* 写保护信号拉低 */  
  346.     mdelay(1);  
  347.   
  348.     message[0] = (u8)(i2c_dev->page_address >> 8);  
  349.     message[1] = (u8)(i2c_dev->page_address);  
  350.     i2c_master_send(client, message, 2);  
  351.     i2c_master_recv(client, my_buf, count);  
  352.   
  353.     set_wc_bit_high(); /* 写保护信号拉高 */  
  354.     copy_to_user(buf, (void *)my_buf, count);  
  355.   
  356.     return count;  
  357. }  
  358.   
  359. static ssize_t eeprom_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)  
  360. {  
  361.     struct i2c_dev *i2c_dev = (struct i2c_dev *)file->private_data;  
  362.     struct i2c_client *client = i2c_dev->client;  
  363.     int ret = -1;  
  364.     char message[EEPROM_BANK_SIZE + 2] = {0,};  
  365.   
  366.     if(i2c_dev->page_address + count > EEPROM_MAX_ADDR)  
  367.     {  
  368.         printk("eeprom write address range beyond\n");  
  369.         i2c_dev->page_address = 0;  
  370.         return -1;  
  371.     }  
  372.   
  373.     if(count > EEPROM_BANK_SIZE)  
  374.     {  
  375.         count = EEPROM_BANK_SIZE;  
  376.     }  
  377.   
  378.     message[0] = (u8)(i2c_dev->page_address >> 8);  
  379.     message[1] = (u8)(i2c_dev->page_address);  
  380.   
  381.     ret = copy_from_user(&message[2], (void *)buf, count);  
  382.     if(ret != 0)  
  383.     {  
  384.         printk("eeprom write copy_from_user failed\n");  
  385.         return -1;  
  386.     }  
  387.   
  388.     set_wc_bit_high(); /* 写保护信号拉低 */  
  389.     mdelay(1);  
  390.   
  391.     i2c_master_send(client, message, count + 2);  
  392.   
  393.     mdelay(1);  
  394.     set_wc_bit_high(); /* 写保护信号拉高 */  
  395.   
  396.     return count;  
  397. }  
  398.   
  399. static int eeprom_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)  
  400. {  
  401.     struct i2c_dev * i2c_dev = (struct i2c_dev *)file->private_data;  
  402.   
  403.     if(i2c_dev == NULL)  
  404.     {  
  405.         printk("invalid parameter,i2c_dev == NULL\n");  
  406.         return -1;  
  407.     }  
  408.   
  409.     switch(cmd)  
  410.     {  
  411.         case SET_EEPROM_PAGE_ADDR:  
  412.             if(arg > EEPROM_MAX_ADDR)  
  413.             {  
  414.                 printk("eeprom address range beyond\n");  
  415.                 i2c_dev->page_address = 0;  
  416.                 return -1;  
  417.             }  
  418.             else  
  419.             {  
  420.                 i2c_dev->page_address = (unsigned short)arg;  
  421.             }  
  422.             break;  
  423.         default:  
  424.             printk("eeprom cmd error!\n");  
  425.             return -1;  
  426.     }  
  427.   
  428.     return 0;  
  429. }  
  430.   
  431. static struct file_operations eeprom_fops =  
  432. {  
  433.     .owner   = THIS_MODULE,  
  434.     .open    = eeprom_open,  
  435.     .release = eeprom_release,  
  436.     .read    = eeprom_read,  
  437.     .write   = eeprom_write,  
  438.     .ioctl   = eeprom_ioctl,  
  439. };  
  440.   
  441. static int __init eeprom_init(void)  
  442. {  
  443.     int ret = -1;  
  444.   
  445.     ret = register_chrdev(EEPROM_MAJOR, EEPROM_NAME, &eeprom_fops);  
  446.     if (ret != 0)  
  447.     {  
  448.         printk("%s: can't get major %d", EEPROM_NAME, EEPROM_MAJOR);  
  449.         goto exit;  
  450.     }  
  451.   
  452.     memset(i2c_dev_array, 0 ,sizeof(i2c_dev_array));  
  453.   
  454.     ret = i2c_add_driver(&eeprom_driver);  
  455.     if (ret != 0)  
  456.     {  
  457.         printk("i2c add eeprom_driver error!\n");  
  458.         goto unregister_chrdev;  
  459.     }  
  460.     return 0;  
  461.   
  462. unregister_chrdev:  
  463.     unregister_chrdev(EEPROM_MAJOR, EEPROM_NAME);  
  464. exit:  
  465.     return ret;  
  466. }  
  467.   
  468. static void __exit eeprom_exit(void)  
  469. {  
  470.     i2c_del_driver(&eeprom_driver);  
  471.     unregister_chrdev(EEPROM_MAJOR, EEPROM_NAME);  
  472. }  
  473.   
  474. MODULE_DESCRIPTION("eeprom driver");  
  475. MODULE_LICENSE("GPL");  
  476.   
  477. module_init(eeprom_init);  
  478. module_exit(eeprom_exit); 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值