i2c - gpio

处理器只支持3个i2c通道,常常会不够用,最近写了一个gpio模拟i2c的driver,把模拟的i2c通道加入了i2c-core中,作为第 4 通道,调用接口与标准i2c一致,代码如下:

[cpp]  view plain copy
  1. #define DELAY     2  
  2. #define SCL_GPIO  GPIO_I2C_SCL  
  3. #define SDA_GPIO  GPIO_I2C_SDA  
  4.   
  5. static inline void i2c_delay(uint16_t delay)  
  6. {  
  7.     udelay(delay);  
  8. }  
  9.   
  10. static inline void set_scl_low(void)  
  11. {  
  12.     gpio_direction_output(SCL_GPIO, 0);  
  13. }  
  14.   
  15. static inline void set_scl_high(void)  
  16. {  
  17.     gpio_direction_output(SCL_GPIO, 1);  
  18. }  
  19.   
  20. static inline void set_sda_low(void)  
  21. {  
  22.     gpio_direction_output(SDA_GPIO, 0);  
  23. }  
  24.   
  25. static inline void set_sda_high(void)  
  26. {  
  27.     gpio_direction_output(SDA_GPIO, 1);  
  28. }  
  29.   
  30. static inline void set_sda_in(void)  
  31. {  
  32.     gpio_direction_input(SDA_GPIO);  
  33. }  
  34.   
  35. static inline uint8_t get_sda_bit(void)  
  36. {  
  37.     return __gpio_get_value(SDA_GPIO);  
  38. }  
  39.   
  40. int i2c_gpio_init(void)  
  41. {  
  42.     int err;  
  43.     err = gpio_request(SCL_GPIO, NULL);  
  44.     if (err != 0)  
  45.         return err;  
  46.     err = gpio_request(SDA_GPIO, NULL);  
  47.   
  48.     set_sda_high();  
  49.     set_scl_high();  
  50.   
  51.     return err;  
  52. }  
  53.   
  54. void i2c_gpio_free(void)  
  55. {  
  56.     gpio_free(SDA_GPIO);  
  57.     gpio_free(SCL_GPIO);  
  58. }  
  59.   
  60. static inline void i2c_start(void)  
  61. {  
  62.     set_sda_high();  
  63.     i2c_delay(DELAY);  
  64.     set_scl_high();  
  65.     i2c_delay(DELAY);  
  66.   
  67.     set_sda_low();  
  68.     i2c_delay(DELAY);  
  69.     set_scl_low();  
  70.     i2c_delay(DELAY);  
  71. }  
  72.   
  73. static inline void i2c_stop(void)  
  74. {  
  75.     set_sda_low();  
  76.     i2c_delay(DELAY);  
  77.     set_scl_high();  
  78.     i2c_delay(4*DELAY);  
  79.     set_sda_high();  
  80.     i2c_delay(4*DELAY);  
  81. }  
  82.   
  83. /* 
  84.  * return value: 
  85.  *      0 ---  收到ACK 
  86.  *      1 ---  没收到ACK 
  87.  */  
  88. uint8_t i2c_send_byte(uint8_t send_byte)  
  89. {  
  90.     uint8_t rc = 0;  
  91.     uint8_t out_mask = 0x80;  
  92.     uint8_t count = 8;  
  93.     uint8_t value;  
  94.   
  95.     while(count > 0) {  
  96.         set_scl_low();  
  97.         i2c_delay(DELAY);  
  98.         value = ((send_byte & out_mask) ? 1 : 0);  
  99.         if(value == 1) {  
  100.             set_sda_high();  
  101.         } else {  
  102.             set_sda_low();  
  103.         }  
  104.         send_byte <<= 1;  
  105.         i2c_delay(DELAY);  
  106.   
  107.         set_scl_high();  
  108.         i2c_delay(DELAY);  
  109.   
  110.         count--;  
  111.     }  
  112.     set_scl_low();  
  113.     set_sda_in();  
  114.     i2c_delay(4*DELAY);  
  115.     set_scl_high();  
  116.     i2c_delay(DELAY);  
  117.     rc = get_sda_bit();  
  118.     i2c_delay(DELAY);  
  119.     set_scl_low();  
  120.   
  121.     return rc;  
  122. }  
  123.   
  124. /* 
  125.  * ack = 0 发送ACK 
  126.  * ack = 1 发送非ACK停止读取 
  127.  */  
  128. void i2c_read_byte(uint8_t *buffer, uint8_t ack)  
  129. {  
  130.     uint8_t count = 0x08;  
  131.     uint8_t data = 0x00;  
  132.     uint8_t temp = 0;  
  133.   
  134.     while(count > 0) {  
  135.         set_scl_low();  
  136.         i2c_delay(2*DELAY);  
  137.         if(count == 8)  
  138.             set_sda_in();  
  139.         i2c_delay(DELAY);  
  140.         set_scl_high();  
  141.         i2c_delay(2*DELAY);  
  142.         temp = get_sda_bit();  
  143.         data <<= 1;  
  144.         if(temp)  
  145.             data |= 0x01;  
  146.   
  147.         i2c_delay(DELAY);  
  148.         count--;  
  149.     }  
  150.   
  151.     set_scl_low();  
  152.     i2c_delay(2*DELAY);  
  153.     if(ack) {  
  154.         set_sda_high();  
  155.     } else {  
  156.         set_sda_low();  
  157.     }  
  158.     i2c_delay(DELAY);  
  159.     set_scl_high();  
  160.     i2c_delay(2*DELAY);  
  161.   
  162.     *buffer = data;  
  163.     set_scl_low();  
  164. }  
  165.   
  166. struct atxx_i2c_gpio {  
  167.     struct i2c_adapter adap;  
  168.     struct device *dev;  
  169.     struct clk *clk;  
  170.     struct i2c_msg *msg;  
  171.     spinlock_t lock;  
  172. };  
  173.   
  174. static int send_i2c(struct atxx_i2c_gpio *i2c)  
  175. {  
  176.     int i;  
  177.     uint8_t ack;  
  178.   
  179.     spin_lock_irq(&i2c->lock);  
  180.     i2c_start();  
  181.   
  182.     ack = i2c_send_byte((i2c->msg->addr << 1) | 0x00);  
  183.     if(ack){  
  184.         goto out;  
  185.     }  
  186.   
  187.     for(i = 0; i < i2c->msg->len; i++) {  
  188.         ack = i2c_send_byte(i2c->msg->buf[i]);  
  189.         if(ack){  
  190.             goto out;  
  191.         }  
  192.     }  
  193.   
  194. out:  
  195.     i2c_stop();  
  196.     spin_unlock_irq(&i2c->lock);  
  197.     return ack;  
  198. }  
  199.   
  200. static int recv_i2c(struct atxx_i2c_gpio *i2c)  
  201. {  
  202.     int i;  
  203.     uint8_t ack;  
  204.   
  205.     spin_lock_irq(&i2c->lock);  
  206.     i2c_start();  
  207.   
  208.     ack = i2c_send_byte((i2c->msg->addr << 1) | 0x01);  
  209.     if(ack){  
  210.         goto out;  
  211.     }  
  212.   
  213.     for(i = 0; i < i2c->msg->len - 1; i++) {  
  214.         i2c_read_byte(&i2c->msg->buf[i], 0);  
  215.     }  
  216.   
  217.     i2c_read_byte(&i2c->msg->buf[i2c->msg->len - 1], 1);  
  218. out:  
  219.     i2c_stop();  
  220.     spin_unlock_irq(&i2c->lock);  
  221.     return ack;  
  222. }  
  223.   
  224. static int i2c_atxx_gpio_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  
  225. {  
  226.     int i, ret;  
  227.     struct atxx_i2c_gpio *i2c = i2c_get_adapdata(adap);  
  228.   
  229.     for (i = 0; i < num; i++) {  
  230.         i2c->msg        = &msgs[i];  
  231.         i2c->msg->flags = msgs[i].flags;  
  232.   
  233.         if (i2c->msg->flags & I2C_M_RD) {  
  234.             ret = recv_i2c(i2c);  
  235.             if (ret) {  
  236.                 printk("recv_i2c failed. dev_name(%s).addr = 0x%02x\n",  
  237.                      dev_name(i2c->dev), i2c->msg[0].addr);  
  238.                 return -EAGAIN;  
  239.             }  
  240.         } else {  
  241.             ret = send_i2c(i2c);  
  242.             if (ret) {  
  243.                 printk("send_i2c failed. dev_name(%s).addr = 0x%02x\n",  
  244.                      dev_name(i2c->dev), i2c->msg[0].addr);  
  245.                 return -EAGAIN;  
  246.             }  
  247.         }  
  248.     }  
  249.   
  250.     return num;  
  251. }  
  252.   
  253. static uint32_t i2c_atxx_gpio_func(struct i2c_adapter *adap)  
  254. {  
  255.     return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;  
  256. }  
  257.   
  258. static struct i2c_algorithm i2c_atxx_gpio_algo = {  
  259.     .master_xfer   = i2c_atxx_gpio_xfer,  
  260.     .functionality = i2c_atxx_gpio_func,  
  261. };  
  262.   
  263. static int i2c_atxx_gpio_probe(struct platform_device *pdev)  
  264. {  
  265.     int ret;  
  266.     struct atxx_i2c_gpio *i2c;  
  267.   
  268.     ret = i2c_gpio_init();  
  269.     if(ret) {  
  270.         dev_err(&pdev->dev, "couldn't request gpio\n");  
  271.         return ret;  
  272.     }  
  273.   
  274.     i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);  
  275.     if (!i2c) {  
  276.         dev_err(&pdev->dev, "couldn't allocate memory\n");;  
  277.         ret = -ENOMEM;  
  278.         goto err_mem;  
  279.     }  
  280.   
  281.     spin_lock_init(&i2c->lock);  
  282.   
  283.     i2c->dev = &pdev->dev;  
  284.     i2c->adap.owner = THIS_MODULE;  
  285.     i2c->adap.algo  = &i2c_atxx_gpio_algo;  
  286.     i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;  
  287.     i2c->adap.timeout = I2C_ATXX_TIMEOUT;  
  288.     i2c->adap.retries = I2C_ATXX_RETRIES;  
  289.     i2c->adap.algo_data  = i2c;  
  290.     i2c->adap.dev.parent = &pdev->dev;  
  291.     i2c->adap.nr = pdev->id != -1 ? pdev->id : 0;  
  292.   
  293.     sprintf(i2c->adap.name, "ATXX i2c gpio adapter");  
  294.     platform_set_drvdata(pdev, i2c);  
  295.     i2c_set_adapdata(&i2c->adap, i2c);  
  296.   
  297.     ret = i2c_add_numbered_adapter(&i2c->adap);  
  298.     if (ret) {  
  299.         dev_err(i2c->dev, "failure adding adapter\n");  
  300.         goto err_adp;  
  301.     }  
  302.   
  303.     return 0;  
  304.   
  305. err_adp:  
  306.     kfree(i2c);  
  307. err_mem:  
  308.     i2c_gpio_free();  
  309.     return ret;  
  310. }  
  311.   
  312. static int i2c_atxx_gpio_remove(struct platform_device *pdev)  
  313. {  
  314.     struct atxx_i2c_gpio *i2c = platform_get_drvdata(pdev);  
  315.   
  316.     platform_set_drvdata(pdev, NULL);  
  317.     i2c_del_adapter(&i2c->adap);  
  318.     kfree(i2c);  
  319.     i2c_gpio_free();  
  320.   
  321.     return 0;  
  322. }  
  323.   
  324. static int i2c_atxx_gpio_suspend(struct device *dev)  
  325. {  
  326.     return 0;  
  327. }  
  328.   
  329. static int i2c_atxx_gpio_resume(struct device *dev)  
  330. {  
  331.     return 0;  
  332. }  
  333.   
  334. static void i2c_atxx_gpio_shutdown(struct platform_device *pdev)  
  335. {  
  336.     /* TODO: */  
  337. }  
  338.   
  339. const struct dev_pm_ops i2c_atxx_gpio_pm_ops = {  
  340.     .suspend = i2c_atxx_gpio_suspend,  
  341.     .resume  = i2c_atxx_gpio_resume,  
  342. };  
  343.   
  344. static struct platform_driver i2c_atxx_gpio_driver = {  
  345.     .driver = {  
  346.         .name  = "i2c-gpio",  
  347.         .owner = THIS_MODULE,  
  348.         .pm    = &i2c_atxx_gpio_pm_ops,  
  349.     },  
  350.     .probe      = i2c_atxx_gpio_probe,  
  351.     .remove     = i2c_atxx_gpio_remove,  
  352.     .shutdown   = i2c_atxx_gpio_shutdown,  
  353. };  
  354.   
  355. static int __init i2c_adap_atxx_gpio_init(void)  
  356. {  
  357.     return platform_driver_register(&i2c_atxx_gpio_driver);  
  358. }  
  359. static void __exit i2c_adap_atxx_gpio_exit(void)  
  360. {  
  361.     platform_driver_unregister(&i2c_atxx_gpio_driver);  
  362. }  
  363.   
  364. arch_initcall(i2c_adap_atxx_gpio_init);  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值