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中。
留言列表