rockchip rk30系列的i2c驱动分析——注意和三星写法有较大不同

来源:互联网 发布:网络不好 英文 编辑:程序博客网 时间:2024/05/21 08:03

Linux下面有很多设备都使用到了i2c,所以看了一下i2c的驱动,虽然现在理解的也可能还是人力物力的,但至少还是有了一些基本的概念

参考:

http://blog.csdn.net/ylyuanlu/article/details/6705942

http://blog.csdn.net/hongjiujing/article/details/4098547


看下i2c初始化过程:


[cpp] view plaincopyprint?
  1. static int __init i2c_init(void)  
  2. {  
  3.     int retval;  
  4.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_ENTER  
  5.     retval = bus_register(&i2c_bus_type);  
  6.     if (retval)  
  7.         return retval;  
  8. #ifdef CONFIG_I2C_COMPAT  
  9.     i2c_adapter_compat_class = class_compat_register("i2c-adapter");  
  10.     if (!i2c_adapter_compat_class) {  
  11.         retval = -ENOMEM;  
  12.         goto bus_err;  
  13.     }  
  14. #endif  
  15.     printk("leaves before i2c_add_driver\n");  
  16.     retval = i2c_add_driver(&dummy_driver);  
  17.     printk("leaves after i2c_add_driver\n");  
  18.     if (retval)  
  19.         goto class_err;  
  20. #ifdef CONFIG_I2C_DEV_RK29  
  21.         init_completion(&i2c_dev_complete);  
  22. #endif  
  23.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_EXIT  
  24.     return 0;  
  25.   
  26. class_err:  
  27. #ifdef CONFIG_I2C_COMPAT  
  28.     class_compat_unregister(i2c_adapter_compat_class);  
  29. bus_err:  
  30. #endif  
  31.     bus_unregister(&i2c_bus_type);  
  32.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_EXIT  
  33.     return retval;  
  34. }  

这个函数主要就是注册了一下i2c的bus

2、


这个是针对RockChip芯片3066一款板子的初始化,注册了5个i2c设备

[cpp] view plaincopyprint?
  1. static void __init rk30_init_i2c(void)  
  2. {  
  3.     printk("leaves Enter %s.\n", __FUNCTION__);  
  4. #ifdef CONFIG_I2C0_RK30  
  5.     platform_device_register(&device_i2c0);  
  6. #endif  
  7. #ifdef CONFIG_I2C1_RK30  
  8.     platform_device_register(&device_i2c1);  
  9. #endif  
  10. #ifdef CONFIG_I2C2_RK30  
  11.     platform_device_register(&device_i2c2);  
  12. #endif  
  13. #ifdef CONFIG_I2C3_RK30  
  14.     platform_device_register(&device_i2c3);  
  15. #endif  
  16. #ifdef CONFIG_I2C4_RK30  
  17.     platform_device_register(&device_i2c4);  
  18. #endif  
  19. #ifdef CONFIG_I2C_GPIO_RK30  
  20.     platform_device_register(&device_i2c_gpio);  
  21. #endif  
  22.     printk("leaves Exit %s.\n", __FUNCTION__);  
  23. }  

3、


这里注册 i2c的驱动

会匹配到上面注册的i2c设备,然后调用rk30_i2c_probe

[cpp] view plaincopyprint?
  1. static struct platform_driver rk30_i2c_driver = {  
  2.     .probe      = rk30_i2c_probe,  
  3.     .remove     = rk30_i2c_remove,  
  4.     .driver     = {  
  5.         .owner  = THIS_MODULE,  
  6.         .name   = "rk30_i2c",  
  7.         .pm = rk30_DEV_PM_OPS,  
  8.     },  
  9. };  
  10. static int __init i2c_adap_init(void)  
  11. {  
  12.     int ret = -1;  
  13.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_RK30_FUNCTION_ENTER  
  14.     ret =  platform_driver_register(&rk30_i2c_driver);  
  15.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_RK30_FUNCTION_EXIT  
  16.     return ret;  
  17. }  

4、



rk30_i2c_probe的流程有点小复杂,我们一步步来看

[cpp] view plaincopyprint?
  1. /* rk30_i2c_probe 
  2.  * 
  3.  * called by the bus driver when a suitable device is found 
  4. */  
  5.   
  6. static int rk30_i2c_probe(struct platform_device *pdev)  
  7. {  
  8.     struct rk30_i2c *i2c = NULL;  
  9.     struct rk30_i2c_platform_data *pdata = NULL;  
  10.     struct resource *res;  
  11.     int ret;  
  12.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_RK30_FUNCTION_ENTER  
  13.     pdata = pdev->dev.platform_data;  
  14.     if (!pdata) {  
  15.         dev_err(&pdev->dev, "no platform data\n");  
  16.         return -EINVAL;  
  17.     }  
  18.   
  19.   
  20.     i2c = kzalloc(sizeof(struct rk30_i2c), GFP_KERNEL);  
  21.     if (!i2c) {  
  22.         dev_err(&pdev->dev, "no memory for state\n");  
  23.         return -ENOMEM;  
  24.     }  
  25.         i2c->con_base = (void __iomem *)GRF_I2C_CON_BASE;  
  26.         i2c_adap_sel(i2c, pdata->bus_num, pdata->adap_type);  
  27.   
  28.         if(pdata->io_init)  
  29.         pdata->io_init();  
  30.         if(pdata->check_idle){  
  31.                 i2c->check_idle = pdata->check_idle;  
  32.         }  
  33.   
  34.     strlcpy(i2c->adap.name, "rk30_i2c"sizeof(i2c->adap.name));  
  35.     i2c->adap.owner   = THIS_MODULE; //初始化adapter  
  36.     i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;  
  37.     i2c->tx_setup     = TX_SETUP;  
  38.     i2c->adap.retries = 2;  
  39.         i2c->adap.timeout = msecs_to_jiffies(100);  
  40.   
  41.     spin_lock_init(&i2c->lock);  
  42.     init_waitqueue_head(&i2c->wait);  
  43.         mutex_init(&i2c->m_lock);   
  44.   
  45.     /* find the clock and enable it */  
  46.   
  47.     i2c->dev = &pdev->dev;  
  48.     i2c->clk = clk_get(&pdev->dev, "i2c");  
  49.     if (IS_ERR(i2c->clk)) {  
  50.         dev_err(&pdev->dev, "cannot get clock\n");  
  51.         ret = -ENOENT;  
  52.         goto err_noclk;  
  53.     }  
  54.   
  55.     i2c_dbg(&pdev->dev, "clock source %p\n", i2c->clk);  
  56.   
  57.     clk_enable(i2c->clk);  
  58.   
  59.     /* map the registers */  
  60.   
  61.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//获取平台资源(I2C)  
  62.     if (res == NULL) {  
  63.         dev_err(&pdev->dev, "cannot find IO resource\n");  
  64.         ret = -ENOENT;  
  65.         goto err_get_resource;  
  66.     }  
  67.   
  68.     //http://blog.csdn.net/skyflying2012/article/details/8672011  
  69.     i2c->ioarea = request_mem_region(res->start, resource_size(res),  
  70.                      pdev->name);//申请I/O内存  
  71.   
  72.     if (i2c->ioarea == NULL) {  
  73.         dev_err(&pdev->dev, "cannot request IO\n");  
  74.         ret = -ENXIO;  
  75.         goto err_ioarea;  
  76.     }  
  77.   
  78.     //用来将I/O内存资源的物理地址映射到核心虚地址空间。  
  79.     i2c->regs = ioremap(res->start, resource_size(res));  
  80.   
  81.     if (i2c->regs == NULL) {  
  82.         dev_err(&pdev->dev, "cannot map IO\n");  
  83.         ret = -ENXIO;  
  84.         goto err_ioremap;  
  85.     }  
  86.   
  87.     i2c_dbg(&pdev->dev, "registers %p (%p, %p)\n",  
  88.         i2c->regs, i2c->ioarea, res);  
  89.   
  90.     /* setup info block for the i2c core */  
  91.   
  92.     i2c->adap.algo_data = i2c;  
  93.     i2c->adap.dev.parent = &pdev->dev;  
  94.     i2c->adap.nr = pdata->bus_num;  
  95.     printk("pdata->bus_num = %d.\n",pdata->bus_num);  
  96.         if(pdata->adap_type == I2C_RK29_ADAP)  
  97.                 ret = i2c_add_rk29_adapter(&i2c->adap);  
  98.         else // I2C_RK30_ADAP  
  99.                 ret = i2c_add_rk30_adapter(&i2c->adap);//添加i2c adapter  
  100.   
  101.     if (ret < 0) {  
  102.         dev_err(&pdev->dev, "failed to add adapter\n");  
  103.         goto err_add_adapter;  
  104.     }  
  105.   
  106.     /* find the IRQ for this unit (note, this relies on the init call to 
  107.      * ensure no current IRQs pending 
  108.      */  
  109.   
  110.     i2c->irq = ret = platform_get_irq(pdev, 0);//获取中断号  
  111.     if (ret <= 0) {  
  112.         dev_err(&pdev->dev, "cannot find IRQ\n");  
  113.         goto err_get_irq;  
  114.     }  
  115.   
  116.     ret = request_irq(i2c->irq, i2c->i2c_irq, IRQF_DISABLED,  
  117.               dev_name(&pdev->dev), i2c);//注册中断服务函数  
  118.   
  119.     if (ret != 0) {  
  120.         dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);  
  121.         goto err_request_irq;  
  122.     }  
  123.   
  124.     ret = rk30_i2c_register_cpufreq(i2c);  
  125.     if (ret < 0) {  
  126.         dev_err(&pdev->dev, "failed to register cpufreq notifier\n");  
  127.         goto err_register_cpufreq;  
  128.     }  
  129.   
  130.     platform_set_drvdata(pdev, i2c);  
  131.   
  132.         i2c->is_div_from_arm[i2c->adap.nr] = pdata->is_div_from_arm;  
  133.         if(i2c->is_div_from_arm[i2c->adap.nr])  
  134.                 wake_lock_init(&i2c->idlelock[i2c->adap.nr], WAKE_LOCK_IDLE, dev_name(&pdev->dev));  
  135.   
  136.         i2c->i2c_init_hw(i2c, 100 * 1000);  
  137.     dev_info(&pdev->dev, "%s: RK30 I2C adapter\n", dev_name(&i2c->adap.dev));  
  138.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_RK30_FUNCTION_EXIT  
  139.     return 0;  
  140. //err_none:  
  141. //  rk30_i2c_deregister_cpufreq(i2c);  
  142. err_register_cpufreq:  
  143.     free_irq(i2c->irq, i2c);  
  144. err_request_irq:  
  145. err_get_irq:  
  146.     i2c_del_adapter(&i2c->adap);  
  147. err_add_adapter:  
  148.     iounmap(i2c->regs);  
  149. err_ioremap:  
  150.     kfree(i2c->ioarea);  
  151. err_ioarea:  
  152.     release_resource(i2c->ioarea);  
  153. err_get_resource:  
  154.     clk_put(i2c->clk);  
  155. err_noclk:  
  156.     kfree(i2c);  
  157.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_RK30_FUNCTION_EXIT  
  158.     return ret;  
  159. }  

这里主要的就是i2c_add_rk30_adapter


[cpp] view plaincopyprint?
  1. int i2c_add_rk30_adapter(struct i2c_adapter *adap)  
  2. {  
  3.         int ret = 0;  
  4.         struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data;  
  5.         LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_RK30_ADAPTER_FUNCTION_ENTER  
  6.         adap->algo = &rk30_i2c_algorithm;  
  7.   
  8.         i2c->i2c_init_hw = &rk30_i2c_init_hw;  
  9.         i2c->i2c_set_clk = &rk30_i2c_set_clk;  
  10.         i2c->i2c_irq = &rk30_i2c_irq;  
  11.   
  12.         ret = i2c_add_numbered_adapter(adap);//注册I2C adapter驱动  
  13.         LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_RK30_ADAPTER_FUNCTION_EXIT  
  14.         return ret;  
  15. }  

这里赋值了一下传输算法

再来看一下i2c_register_adapter


[cpp] view plaincopyprint?
  1. static int i2c_register_adapter(struct i2c_adapter *adap)  
  2. {  
  3.     int res = 0;  
  4.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_ENTER  
  5.     /* Can't register until after driver model init */  
  6.     if (unlikely(WARN_ON(!i2c_bus_type.p))) {  
  7.         res = -EAGAIN;  
  8.         goto out_list;  
  9.     }  
  10.   
  11.     /* Sanity checks */  
  12.     if (unlikely(adap->name[0] == '\0')) {  
  13.         pr_err("i2c-core: Attempt to register an adapter with "  
  14.                "no name!\n");  
  15.         return -EINVAL;  
  16.     }  
  17.     if (unlikely(!adap->algo)) {  
  18.         pr_err("i2c-core: Attempt to register adapter '%s' with "  
  19.                "no algo!\n", adap->name);  
  20.         return -EINVAL;  
  21.     }  
  22.   
  23.     rt_mutex_init(&adap->bus_lock);  
  24.     mutex_init(&adap->userspace_clients_lock);  
  25.     INIT_LIST_HEAD(&adap->userspace_clients);  
  26.   
  27.     /* Set default timeout to 1 second if not already set */  
  28.     if (adap->timeout == 0)  
  29.         adap->timeout = HZ;  
  30.   
  31.     dev_set_name(&adap->dev, "i2c-%d", adap->nr);  
  32.     printk("adap->dev.kobj.name = %s.\n", adap->dev.kobj.name);  
  33.     adap->dev.bus = &i2c_bus_type;  
  34.     adap->dev.type = &i2c_adapter_type;  
  35.     printk("before device_register.\n");  
  36.     res = device_register(&adap->dev);  
  37.     printk("after device_register.\n");  
  38.     if (res)  
  39.         goto out_list;  
  40.   
  41.     dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);  
  42.   
  43. #ifdef CONFIG_I2C_COMPAT  
  44.     res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,  
  45.                        adap->dev.parent);  
  46.     if (res)  
  47.         dev_warn(&adap->dev,  
  48.              "Failed to create compatibility class link\n");  
  49. #endif  
  50.     printk("__i2c_first_dynamic_bus_num = %d.\n", __i2c_first_dynamic_bus_num);  
  51.     /* create pre-declared device nodes */  
  52.     if (adap->nr < __i2c_first_dynamic_bus_num)  
  53.         i2c_scan_static_board_info(adap);  
  54.   
  55.     /* Notify drivers */  
  56.     mutex_lock(&core_lock);  
  57.     //遍历该总线上所有的driver,执行一次__process_new_adapter  
  58.     bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);  
  59.     mutex_unlock(&core_lock);  
  60.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_EXIT  
  61.     return 0;  
  62.   
  63. out_list:  
  64.     mutex_lock(&core_lock);  
  65.     idr_remove(&i2c_adapter_idr, adap->nr);  
  66.     mutex_unlock(&core_lock);  
  67.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_EXIT  
  68.     return res;  
  69. }  

i2c_register_adapter主要做了4件事

1、  继续adap初始化

2、  注册adap设备

3、  遍历I2C设备链表,并创建链表上相应总线的设备

4、  遍历该总线上所有的driver,执行一次__process_new_adapter

我们看一下遍历i2c链表过程

[cpp] view plaincopyprint?
  1. //函数中遍历I2C设备链表__i2c_board_list,设备的总线号和adapter的总线号相等,(属于该总线的)  
  2. //则使用函数i2c_new_device()创建该设备。  
  3. static void i2c_scan_static_board_info(struct i2c_adapter *adapter)//  
  4. {  
  5.     struct i2c_devinfo  *devinfo;  
  6.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_ENTER  
  7.     down_read(&__i2c_board_lock);  
  8.     list_for_each_entry(devinfo, &__i2c_board_list, list) {  
  9.         if (devinfo->busnum == adapter->nr  
  10.                 && !i2c_new_device(adapter,  
  11.                         &devinfo->board_info))  
  12.             dev_err(&adapter->dev,  
  13.                 "Can't create device at 0x%02x\n",  
  14.                 devinfo->board_info.addr);  
  15.     }  
  16.     up_read(&__i2c_board_lock);  
  17.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_EXIT  
  18. }  

这里调用i2c_new_device创建相应的i2c client,一个i2c_client结构相当于i2c总线上的一个设备

[cpp] view plaincopyprint?
  1. struct i2c_client *  
  2. i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  
  3. {  
  4.     struct i2c_client   *client;  
  5.     int         status;  
  6.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_ENTER  
  7.     client = kzalloc(sizeof *client, GFP_KERNEL);  
  8.     if (!client)  
  9.         return NULL;  
  10.   
  11.     client->adapter = adap;  
  12.   
  13.     client->dev.platform_data = info->platform_data;  
  14.   
  15.     if (info->archdata)  
  16.         client->dev.archdata = *info->archdata;  
  17.   
  18.     client->flags = info->flags;  
  19.     client->addr = info->addr; /* 取得I2C器件地址 */  
  20.     client->irq = info->irq;  
  21.     client->udelay = info->udelay;  // add by kfx  
  22.   
  23.     strlcpy(client->name, info->type, sizeof(client->name));  
  24.     /* Check for address validity */  
  25.     status = i2c_check_client_addr_validity(client);  
  26.     if (status) {  
  27.         dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",  
  28.             client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);  
  29.         goto out_err_silent;  
  30.     }  
  31.   
  32.     /* Check for address business */  
  33.     #if 0  
  34.     status = i2c_check_addr_busy(adap, client->addr);  
  35.     if (status)  
  36.         goto out_err;  
  37.     #else  
  38.     /* ddl@rock-chips.com : Devices which have some i2c addr can work in same i2c bus,  
  39.        if devices havn't work at the same time.*/  
  40.     status = i2c_check_addr_ex(adap, client->addr);  
  41.     if (status != 0)  
  42.         dev_err(&adap->dev, "%d i2c clients have been registered at 0x%02x",  
  43.             status, client->addr);     
  44.     #endif  
  45.   
  46.     client->dev.parent = &client->adapter->dev;  
  47.     client->dev.bus = &i2c_bus_type;  
  48.     client->dev.type = &i2c_client_type;  
  49.     client->dev.of_node = info->of_node;  
  50.   
  51.     /* ddl@rock-chips.com : Devices which have some i2c addr can work in same i2c bus,  
  52.       if devices havn't work at the same time.*/  
  53.     #if 0  
  54.     dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),  
  55.                  client->addr);  
  56.     #else  
  57.     if (status == 0)  
  58.         dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),  
  59.                  client->addr);  
  60.     else   
  61.         dev_set_name(&client->dev, "%d-%04x-%01x", i2c_adapter_id(adap),  
  62.                  client->addr,status);  
  63.     #endif  
  64.     printk("device_register before \n");  
  65.     status = device_register(&client->dev);  
  66.     printk("device_register after \n");  
  67.     if (status)  
  68.         goto out_err;  
  69.   
  70.     printk( "client [%s] registered with bus id %s\n",  
  71.         client->name, dev_name(&client->dev));  
  72.     LEAVES_DEBUG_FLAG_DRIVER_I2c_BUSSES_I2c_I2c_CORE_FUNCTION_EXIT  
  73.     return client;  
  74.   
  75. out_err:  
  76.     dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "  
  77.         "(%d)\n", client->name, client->addr, status);  
  78. out_err_silent:  
  79.     kfree(client);  
  80.     return NULL;  
  81. }  

这里调用了device_register注册了相应的i2c设备,如我们后面讲到的陀螺仪在i2c0总线上定义的

[cpp] view plaincopyprint?
  1. static struct i2c_board_info __initdata i2c0_info[] = {   
  2. …  
  3. #if defined (CONFIG_GYRO_L3G4200D)  
  4.     {  
  5.         .type          = "l3g4200d_gryo",  
  6.         .addr          = 0x69,  
  7.         .flags         = 0,  
  8.         .irq           = L3G4200D_INT_PIN,  
  9.         .platform_data = &l3g4200d_info,  
  10.     },  
  11. …  
  12. }  

这里进行了陀螺设备的注册

__process_new_adapter会调用i2c_do_add_adapter,但此时只有一个dummy_driver,而且他没有定义attach_adapter,所以其实什么事也没有做

 

 

这样,i2c设备初始化就已经完成了,就可以等待注册i2c驱动



0 0