close

http://chxxxyg.blog.163.com/blog/static/1502811932010636351825/


 


一、關於匹配
i2c_client->dev和i2c_driver->driver的總線類型都是i2c_bus_type。
 i2c_adapter->dev的總線類型並不是i2c_bus_type。
在註冊後設備與驅動匹配,是i2c_client->dev和i2c_driver->driver的匹配。
i2c_client的建立都是依賴於"new style" driversi2c_driver->driver攜帶的地址信息。


i2c_adapter->dev與i2c_driver->driver並沒有匹配關係,而是
i2c_adapter->class與i2c_driver->class的匹配,它們支持的設備類型的匹配。


 


二、兩類i2c_driver的區別


"new style" driver:
     is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect)
 "legacy"driver:
     driver->detach_adapter || driver->detach_client



  這兩類驅動的區別就是他們所擁有的函數不一樣。
  不能出現這兩類驅動的混合體,即兼有這兩類驅動的標誌函數的驅動。


"new style" driver是攜帶地址信息,並將這些地址轉換成具體的設備client註冊


到內核,這些設備client的name在該驅動的id_table中。


函數driver->detect便是填充結構體i2c_board_info,用i2c_board_info去初始化


client,驅動id_table中的name就是i2c_board_info->type帶入​​client的。


該驅動與設備就是根據這個name相匹配的,匹配後調用函數probe執行一些初始化或是設備探測。


當然該驅動也是可以不攜帶地址信息的,而是註冊後與內核中已存在的client匹配執行probe()。


 "legacy"driver是不攜帶地址信息的,它的主要任務是調用函數driver->detach_adapter為新加入


的適配器,或是與之匹配的適配器創建一個可依附的設備節點,或者是做其他初始化工作。


 


 


三、兩個重要函數的區別


當一個新的驅動加入內核時,會在類型為i2c_adapter_class的適配器中找與之匹配的,


並將驅動支持的設備插入適配器。


class_for_each_device(&i2c_adapter_class, NULL, driver,
         __attach_adapter);


當一個新的適配器加入內核時,會在總線類型為i2c_bus_type的驅動中找與之匹配的,


並將驅動支持的設備插入新加入的這個適配器。
bus_for_each_drv(&i2c_bus_type, NULL, adap,
     i2c_do_add_adapter);


函數class_for_each_device和bus_for_each_drv調用了兩個相似的函數,


__attach_adapter和i2c_do_add_adapter。
 這兩函數的對比如下:
 前者是在新的驅動加入內核時調用函數class_for_each_device時調用的函數。
 函數class_for_each_device是在類i2c_adapter_class中找一個適配器設備
 與新驅動匹配。 該函數變化的是設備不變的是加入的新的驅動(void *data)
 
 後者是在新的適配器加入內核時調用函數bus_for_each_drv時調用的函數。
 函數bus_for_each_drv是在總線類型為i2c_bus_type的驅動中找到一個驅動
 與新加入的適配器匹配。 該函數變化的是驅動,不變的是新加入的適配器(void *data)。
 
 相同點都是執行函數i2c_detect和函數driver->attach_adapter。
 其實在bus_for_each_drv和class_for_each_device並不執行匹配的操作。
 只是簡單的取出所有的驅動或是適配器,執行函數i2c_detect和attach_adapter。
 真正的匹配是在函數i2c_detect和attach_adapter中進行的。
 函數i2c_detect中會去判斷驅動支持的設備類和適配器所支持的設備類是否匹配。
 函數driver->attach_adapter中會判斷adapter->nr是不是自己需要處理的
 適配器,或者是是不是該適配器已被處理過了。
 當然函數i2c_detect和函數driver->attach_adapter是絕不會同時執行的。
 因為函數i2c_detect的執行需要用到函數driver->detect而該函數是"new style" drivers


的標誌函數。 而函數driver->attach_adapter是"legacy" drivers的標誌函數。 i2c_driver中是


沒有兼有這兩種驅動的混​​合體驅動的。


 


四、 不同驅動一般不會對同一個適配器兩次執行函數attach_adapter


每一個函數driver->attach_adapter的操作都跟adapter->nr有關,在這些函數
中都會對adapter->nr進行判斷,所以driver->attach_adapter並不是,一個驅動
的函數attach_adapter對每一個適配器都會成功執行。



比如在驅動i2cdev_driver中函數attach_adapter的執行會創建一個設備節點,
但是對同一個適配器兩次執行函數attach_adapter就不會產生兩個設備節點,
因為產生設備節點的次設備號是由adapter->nr來決定的。 內核是不會允許
對同一個設備號註冊兩次的。


 


五、關於地址管理結構體i2c_client_address_data


i2c.h中初始化了一個默認的結構體addr_data :


static const struct i2c_client_address_data addr_data = { \
 .normal_i2c = normal_i2c, \
 .probe = probe, \
 .ignore = ignore, \
 .forces = forces, \
}


這個結構體與地址探測函數


static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)


緊密相關。


forces:


它存儲的地址有如下特點:
跳過適配器支持的設備類和驅動支持的設備類匹配判斷
 if (!(adapter->class & driver->class))
  goto exit_free;
也就是說即使不匹配,這些設備地址只要滿足某些條件也要將其插入適配器。


probe:


probe支持的設備地址不受ignore(忽略某些地址)的影響.


normal_i2c:


normal_i2c[i]中的地址就要受到ignore的影響.


驅動中所支持的地址一般都存於address_data->normal_i2c中。

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 立你斯 的頭像
    立你斯

    立你斯學習記錄

    立你斯 發表在 痞客邦 留言(0) 人氣()