linux gpio模拟i2c的使用/用GPIO模拟I2C总线-2

在drivers/i2c/busses下包含各种I2C总线驱动,如S3C2440的I2C总线驱动i2c-s3c2410.c,使用GPIO模拟I2C总线的驱动i2c-gpio.c,这里只分析i2c-gpio.c。

i2c-gpio.c它是gpio模拟I2C总线的驱动,总线也是个设备,在这里将总线当作平台设备处理,那驱动当然是平台设备驱动,看它的驱动注册和注销函数。

[html] view plaincopyprint?

  1.  1. static int __init i2c_gpio_init(void)    
  2.  2. {    
  3.  3.     int ret;    
  4.  4.     
  5.  5.     ret = platform_driver_register(&i2c_gpio_driver);    
  6.  6.     if (ret)    
  7.  7.         printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);    
  8.  8.     
  9.  9.     return ret;    
  10. 10. }    
  11. 11. module_init(i2c_gpio_init);    
  12. 12.     
  13. 13. static void __exit i2c_gpio_exit(void)    
  14. 14. {    
  15. 15.     platform_driver_unregister(&i2c_gpio_driver);    
  16. 16. }    
  17. 17. module_exit(i2c_gpio_exit);    

 

没有什么好说的,它的初始化和注销函数就是注册和注销一个平台设备驱动,直接看它的platform_driver结构i2c_gpio_driver

[html] view plaincopyprint?

  1. 1. static struct platform_driver i2c_gpio_driver = {    
  2. 2.     .driver     = {    
  3. 3.         .name   = "i2c-gpio",    
  4. 4.         .owner  = THIS_MODULE,    
  5. 5.     },    
  6. 6.     .probe      = i2c_gpio_probe,    
  7. 7.     .remove     = __devexit_p(i2c_gpio_remove),    
  8. 8. };    

 

平台驱动设备放在arch/arm/mach-xxxx/board-xxx.c中

 

 

[html] view plaincopyprint?

  1.  1. #if defined(CONFIG_I2C_GPIO) | \     
  2.  2.     defined(CONFIG_I2C_GPIO_MODULE)     
  3.  3. static struct i2c_gpio_platform_data i2c_gpio_adapter_data = {     
  4.  4.     .sda_pin = PINID_GPMI_D05,     
  5.  5.     .scl_pin = PINID_GPMI_D04,     
  6.  6.     .udelay = 5, //100KHz     
  7.  7.     .timeout = 100,     
  8.  8.     .sda_is_open_drain = 1,     
  9.  9.     .scl_is_open_drain = 1,     
  10. 10. };     
  11. 11.     
  12. 12. static struct platform_device i2c_gpio = {     
  13. 13.     .name = "i2c-gpio",     
  14. 14.     .id = 0,     
  15. 15.     .dev = {     
  16. 16.         .platform_data = &i2c_gpio_adapter_data,     
  17. 17.         .release = mxs_nop_release,     
  18. 18.         },     
  19. 19. };     
  20. 20. #endif    


在这里struct platform_device结构中的name字段要和struct platform_driver中driver字段中name字段要相同,因为平台总线就是通过这个来判断设备和驱动是否匹配的。注意这里的id将它赋值了0,至于到底有什么用,后面再来细看。这个结构里面还包含一个最重要的数据i2c_gpio_adapter_data,它struct i2c_gpio_platform_data结构类型变量,这个结构体类型定义在include/linux/i2c-gpio.h中。

[html] view plaincopyprint?

  1. 1. struct i2c_gpio_platform_data {    
  2. 2.     unsigned int    sda_pin;    
  3. 3.     unsigned int    scl_pin;    
  4. 4.     int     udelay;    
  5. 5.     int     timeout;    
  6. 6.     unsigned int    sda_is_open_drain:1;    
  7. 7.     unsigned int    scl_is_open_drain:1;    
  8. 8.     unsigned int    scl_is_output_only:1;    
  9. 9. };    

这个结构体主要描述gpio模拟i2c总线,sda_pin和scl_pin表示使用哪两个IO管脚来模拟I2C总线,udelay和timeout分别为它的时钟频率和超时时间,sda_is_open_drain和scl_is_open_drain表示sda、scl这两个管脚是否是开漏(opendrain)电路,如果是设置为1,scl_is_output_only表示scl这个管脚是否只是作为输出,如果是设置为1。

回到驱动中,看其中最重要的i2c_gpio_probe。

[html] view plaincopyprint?

  1.  1. static int __devinit i2c_gpio_probe(struct platform_device *pdev)    
  2.  2. {    
  3.  3.     struct i2c_gpio_platform_data *pdata;    
  4.  4.     struct i2c_algo_bit_data *bit_data;    
  5.  5.     struct i2c_adapter *adap;    
  6.  6.     int ret;    
  7.  7.     
  8.  8.     pdata = pdev->dev.platform_data;    
  9.  9.     if (!pdata)    
  10. 10.         return -ENXIO;    
  11. 11.     
  12. 12.     ret = -ENOMEM;    
  13. 13.     adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);    
  14. 14.     if (!adap)    
  15. 15.         goto err_alloc_adap;    
  16. 16.     bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL);    
  17. 17.     if (!bit_data)    
  18. 18.         goto err_alloc_bit_data;    
  19. 19.     
  20. 20.     ret = gpio_request(pdata->sda_pin, "sda");    
  21. 21.     if (ret)    
  22. 22.         goto err_request_sda;    
  23. 23.     ret = gpio_request(pdata->scl_pin, "scl");    
  24. 24.     if (ret)    
  25. 25.         goto err_request_scl;    
  26. 26.     
  27. 27.     if (pdata->sda_is_open_drain) {    
  28. 28.         gpio_direction_output(pdata->sda_pin, 1);    
  29. 29.         bit_data->setsda = i2c_gpio_setsda_val;    
  30. 30.     } else {    
  31. 31.         gpio_direction_input(pdata->sda_pin);    
  32. 32.         bit_data->setsda = i2c_gpio_setsda_dir;    
  33. 33.     }    
  34. 34.     
  35. 35.     if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {    
  36. 36.         gpio_direction_output(pdata->scl_pin, 1);    
  37. 37.         bit_data->setscl = i2c_gpio_setscl_val;    
  38. 38.     } else {    
  39. 39.         gpio_direction_input(pdata->scl_pin);    
  40. 40.         bit_data->setscl = i2c_gpio_setscl_dir;    
  41. 41.     }    
  42. 42.     
  43. 43.     if (!pdata->scl_is_output_only)    
  44. 44.         bit_data->getscl = i2c_gpio_getscl;    
  45. 45.     bit_data->getsda = i2c_gpio_getsda;    
  46. 46.     
  47. 47.     if (pdata->udelay)    
  48. 48.         bit_data->udelay = pdata->udelay;    
  49. 49.     else if (pdata->scl_is_output_only)    
  50. 50.         bit_data->udelay = 50;           /* 10 kHz */    
  51. 51.     else    
  52. 52.         bit_data->udelay = 5;            /* 100 kHz */    
  53. 53.     
  54. 54.     if (pdata->timeout)    
  55. 55.         bit_data->timeout = pdata->timeout;    
  56. 56.     else    
  57. 57.         bit_data->timeout = HZ / 10;     /* 100 ms */    
  58. 58.     
  59. 59.     bit_data->data = pdata;    
  60. 60.     
  61. 61.     adap->owner = THIS_MODULE;    
  62. 62.     snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);    
  63. 63.     adap->algo_data = bit_data;    
  64. 64.     adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;    
  65. 65.     adap->dev.parent = &pdev->dev;    
  66. 66.     
  67. 67.     /*   
  68. 68.      * If "dev->id" is negative we consider it as zero.   
  69. 69.      * The reason to do so is to avoid sysfs names that only make   
  70. 70.      * sense when there are multiple adapters.   
  71. 71.      */    
  72. 72.     adap->nr = (pdev->id != -1) ? pdev->id : 0;    
  73. 73.     ret = i2c_bit_add_numbered_bus(adap);    
  74. 74.     if (ret)    
  75. 75.         goto err_add_bus;    
  76. 76.     
  77. 77.     platform_set_drvdata(pdev, adap);    
  78. 78.     
  79. 79.     dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",    
  80. 80.          pdata->sda_pin, pdata->scl_pin,    
  81. 81.          pdata->scl_is_output_only    
  82. 82.          ? ", no clock stretching" : "");    
  83. 83.     
  84. 84.     return 0;    
  85. 85.     
  86. 86. err_add_bus:    
  87. 87.     gpio_free(pdata->scl_pin);    
  88. 88. err_request_scl:    
  89. 89.     gpio_free(pdata->sda_pin);    
  90. 90. err_request_sda:    
  91. 91.     kfree(bit_data);    
  92. 92. err_alloc_bit_data:    
  93. 93.     kfree(adap);    
  94. 94. err_alloc_adap:    
  95. 95.     return ret;    
  96. 96. }    

 

从这句开始pdata= pdev->dev.platform_data;这不正是我们在平台设备结构中定义的数据吗。然后是使用kzalloc申请两段内存空间,一个是为结构struct i2c_adapter申请的,另一个是为结构structi2c_algo_bit_data申请的。

struct i2c_adapter结构定义在include/linux/i2c.h中

[html] view plaincopyprint?

  1.  1. struct i2c_adapter {    
  2.  2.     struct module *owner;    
  3.  3.     unsigned int id;    
  4.  4.     unsigned int class;       /* classes to allow probing for */    
  5.  5.     const struct i2c_algorithm *algo; /* the algorithm to access the bus */    
  6.  6.     void *algo_data;    
  7.  7.     
  8.  8.     /* data fields that are valid for all devices   */    
  9.  9.     u8 level;           /* nesting level for lockdep */    
  10. 10.     struct mutex bus_lock;    
  11. 11.     
  12. 12.     int timeout;            /* in jiffies */    
  13. 13.     int retries;    
  14. 14.     struct device dev;      /* the adapter device */    
  15. 15.     
  16. 16.     int nr;    
  17. 17.     char name[48];    
  18. 18.     struct completion dev_released;    
  19. 19. };    

在I2C子系统中,I2C适配器使用结构struct i2c_adapter描述,代表一条实际的I2C总线。

struct i2c_algo_bit_data结构定义在include/linux/i2c-algo-bit.h中

[html] view plaincopyprint?

  1.  1. struct i2c_algo_bit_data {    
  2.  2.     void *data;     /* private data for lowlevel routines */    
  3.  3.     void (*setsda) (void *data, int state);    
  4.  4.     void (*setscl) (void *data, int state);    
  5.  5.     int  (*getsda) (void *data);    
  6.  6.     int  (*getscl) (void *data);    
  7.  7.     
  8.  8.     /* local settings */    
  9.  9.     int udelay;     /* half clock cycle time in us,   
  10. 10.                    minimum 2 us for fast-mode I2C,   
  11. 11.                    minimum 5 us for standard-mode I2C and SMBus,   
  12. 12.                    maximum 50 us for SMBus */    
  13. 13.     int timeout;        /* in jiffies */    
  14. 14. };    

 

这个结构主要用来定义对GPIO管脚的一些操作,还是回到probe中

接下来使用gpio_request去申请这个两个GPIO管脚,申请的目的是为了防止重复使用管脚。然后是根据struct i2c_gpio_platform_data结构中定义的后面三个数据对struct i2c_algo_bit_data结构中的函数指针做一些赋值操作。接下来是I2C时钟频率和超时设置,如果在struct i2c_gpio_platform_data结构中定义了值,那么就采用定义的值,否则就采用默认的值。然后是对struct i2c_adapter结构的一些赋值操作,比如指定它的父设备为这里的平台设备,前面在平台设备中定义了一个id,这里用到了,赋给了struct i2c_adapter中的nr成员,这个值表示总线号,这里的总线号和硬件无关,只是在软件上的区分。然后到了最后的主角i2c_bit_add_numbered_bus,这个函数定义在drivers/i2c/algos/i2c-algo-bit.c中

[html] view plaincopyprint?

  1. 1. int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)    
  2. 2. {    
  3. 3.     int err;    
  4. 4.     
  5. 5.     err = i2c_bit_prepare_bus(adap);    
  6. 6.     if (err)    
  7. 7.         return err;    
  8. 8.     
  9. 9.     return i2c_add_numbered_adapter(adap);    
  10. 0. }    

先看i2c_bit_prepare_bus函数

 

[html] view plaincopyprint?

  1.  1. static int i2c_bit_prepare_bus(struct i2c_adapter *adap)    
  2.  2. {    
  3.  3.     struct i2c_algo_bit_data *bit_adap = adap->algo_data;    
  4.  4.     
  5.  5.     if (bit_test) {    
  6.  6.         int ret = test_bus(bit_adap, adap->name);    
  7.  7.         if (ret < 0)    
  8.  8.             return -ENODEV;    
  9.  9.     }    
  10. 10.     
  11. 11.     /* register new adapter to i2c module... */    
  12. 12.     adap->algo = &i2c_bit_algo;    
  13. 13.     adap->retries = 3;    
  14. 14.     
  15. 15.     return 0;    
  16. 16. }    

 

 

bit_test为模块参数,这里不管它,看这样一句adap->algo= &i2c_bit_algo;

来看这个结构定义

[html] view plaincopyprint?

  1. 1. static const struct i2c_algorithm i2c_bit_algo = {    
  2. 2.     .master_xfer    = bit_xfer,    
  3. 3.     .functionality  = bit_func,    
  4. 4. };    

先看这个结构类型在哪里定义的include/linux/i2c.h

 

[html] view plaincopyprint?

  1.  1. struct i2c_algorithm {    
  2.  2.     /* If an adapter algorithm can't do I2C-level access, set master_xfer   
  3.  3.        to NULL. If an adapter algorithm can do SMBus access, set   
  4.  4.        smbus_xfer. If set to NULL, the SMBus protocol is simulated   
  5.  5.        using common I2C messages */    
  6.  6.     /* master_xfer should return the number of messages successfully    
  7.  7.        processed, or a negative value on error */    
  8.  8.     int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,    
  9.  9.                int num);    
  10. 10.     int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,    
  11. 11.                unsigned short flags, char read_write,    
  12. 12.                u8 command, int size, union i2c_smbus_data *data);    
  13. 13.     
  14. 14.     /* To determine what the adapter supports */    
  15. 15.     u32 (*functionality) (struct i2c_adapter *);    
  16. 16. };    

 

其实也没什么,就三个函数指针外加一长串注释

这个结构的master_xfer指针为主机的数据传输,具体来看bit_xfer这个函数,这个函数和I2C协议相关,I2C协议规定要先发送起始信号,才能开始进行数据的传输,最后数据传输完成后发送停止信号,看接下来代码对I2C协议要熟悉,所以这里的关键点是I2C协议。

  1. static int bit_xfer(struct i2c_adapter *i2c_adap,  
  2.             struct i2c_msg msgs[], int num)  
  3. {  
  4.     struct i2c_msg *pmsg;  
  5.     struct i2c_algo_bit_data *adap = i2c_adap->algo_data;  
  6.     int i, ret;  
  7.     unsigned short nak_ok;  
  8.   
  9.     bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");  
  10.     /*发送起始信号*/  
  11.     i2c_start(adap);  
  12.     for (i = 0; i < num; i++) {  
  13.         pmsg = &msgs[i];  
  14.         nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;  
  15.         if (!(pmsg->flags & I2C_M_NOSTART)) {  
  16.             if (i) {  
  17.                 bit_dbg(3, &i2c_adap->dev, "emitting "  
  18.                     "repeated start condition\n");  
  19.                 i2c_repstart(adap);  
  20.             }  
  21.             ret = bit_doAddress(i2c_adap, pmsg);  
  22.             if ((ret != 0) && !nak_ok) {  
  23.                 bit_dbg(1, &i2c_adap->dev, "NAK from "  
  24.                     "device addr 0x%02x msg #%d\n",  
  25.                     msgs[i].addr, i);  
  26.                 goto bailout;  
  27.             }  
  28.         }  
  29.         if (pmsg->flags & I2C_M_RD) {  
  30.             /* read bytes into buffer*/  
  31.             ret = readbytes(i2c_adap, pmsg);  
  32.             if (ret >= 1)  
  33.                 bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",  
  34.                     ret, ret == 1 ? "" : "s");  
  35.             if (ret < pmsg->len) {  
  36.                 if (ret >= 0)  
  37.                     ret = -EREMOTEIO;  
  38.                 goto bailout;  
  39.             }  
  40.         } else {  
  41.             /* write bytes from buffer */  
  42.             ret = sendbytes(i2c_adap, pmsg);  
  43.             if (ret >= 1)  
  44.                 bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",  
  45.                     ret, ret == 1 ? "" : "s");  
  46.             if (ret < pmsg->len) {  
  47.                 if (ret >= 0)  
  48.                     ret = -EREMOTEIO;  
  49.                 goto bailout;  
  50.             }  
  51.         }  
  52.     }  
  53.     ret = i;  
  54.   
  55. bailout:  
  56.     bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");  
  57.     i2c_stop(adap);  
  58.     return ret;  
  59. }  

1.发送起始信号

i2c_start(adap);

看这个函数前,先看I2C协议怎么定义起始信号的

起始信号就是在SCL为高电平期间,SDA从高到低的跳变,再来看代码是怎么实现的

[html] view plaincopyprint?

  1. 1. static void i2c_start(struct i2c_algo_bit_data *adap)    
  2. 2. {    
  3. 3.     /* assert: scl, sda are high */    
  4. 4.     setsda(adap, 0);    
  5. 5.     udelay(adap->udelay);    
  6. 6.     scllo(adap);    
  7. 7. }    


这些setsda和setscl这些都是使用的总线的函数,在这里是使用的i2c-gpio.c中定义的函数,还记得那一系列判断赋值吗。

 

  1. #define setsda(adap, val)   adap->setsda(adap->data, val)  
  2. #define setscl(adap, val)   adap->setscl(adap->data, val)  
  3. #define getsda(adap)        adap->getsda(adap->data)  
  4. #define getscl(adap)        adap->getscl(adap->data)  

 

2.往下是个大的for循环

到了这里又不得不说这个struct i2c_msg结构,这个结构定义在include/linux/i2c.h中

[html] view plaincopyprint?

  1.  1. struct i2c_msg {    
  2.  2.     __u16 addr; /* slave address            */    
  3.  3.     __u16 flags;    
  4.  4. #define I2C_M_TEN       0x0010  /* this is a ten bit chip address */    
  5.  5. #define I2C_M_RD        0x0001  /* read data, from slave to master */    
  6.  6. #define I2C_M_NOSTART       0x4000  /* if I2C_FUNC_PROTOCOL_MANGLING */    
  7.  7. #define I2C_M_REV_DIR_ADDR  0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */    
  8.  8. #define I2C_M_IGNORE_NAK    0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */    
  9.  9. #define I2C_M_NO_RD_ACK     0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */    
  10. 10. #define I2C_M_RECV_LEN      0x0400  /* length will be first received byte */    
  11. 11.     __u16 len;      /* msg length               */    
  12. 12.     __u8 *buf;      /* pointer to msg data          */    
  13. 13. };   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值