copy from:
文章目錄
linux i2c匯流排(一)i2c驅動框架
一、linux i2c驅動的主要物件
1.1 i2c匯流排
1.2 i2c裝置
1.3 i2c驅動
1.4 i2c介面卡
二、linux i2c驅動框架
三、i2c驅動框架原始碼剖析
3.1 註冊i2c裝置
3.2 註冊i2c驅動
3.3 i2c介面卡的構建
3.4 i2c資料傳輸
一、linux i2c驅動的主要物件
1.1 i2c匯流排
i2c匯流排用於管理i2c裝置和i2c驅動,維護乙個裝置鍊錶和驅動鏈表,定義了裝置和驅動的匹配規則,定義了匹配成功後的行為,其在核心中的定義如下
struct bus_type i2c_bus_type = ;
1.2 i2c裝置
i2c裝置描述了i2c裝置的硬體資訊,例如i2c裝置的位址、i2c裝置在接在哪乙個i2c控制器上,其結構體定義如下
struct i2c_client ;
1.3 i2c驅動
i2c驅動是i2c裝置的驅動程式,用於匹配i2c裝置,其結構體定義如下
struct i2c_driver ;
1.4 i2c介面卡
i2c介面卡是soc上的i2c控制器的軟體抽象,可以通過其定義的演算法向硬體裝置傳輸資料,其結構體定義如下
struct i2c_adapter ;
其中的i2c_algorithm表示演算法,用於向硬體裝置傳輸資料,其定義如下
struct i2c_algorithm ;12
3456
78總結一下:i2c驅動的主要物件是i2c匯流排、i2c裝置、i2c驅動、i2c介面卡
i2c匯流排用於管理i2c裝置和i2c驅動
i2c裝置描述了i2c裝置的硬體資訊
i2c驅動是i2c裝置對應的驅動程式
i2c介面卡是soc上的i2c控制器,其定義了演算法,可以向i2c硬體裝置傳輸資料
其中直接面向編寫i2c裝置驅動的開發者的是i2c裝置和i2c驅動,i2c匯流排和i2c介面卡是幕後工作者
二、linux i2c驅動框架
i2c驅動框架可以分為四部分,i2c核心、i2c裝置、i2c驅動、i2c介面卡,其中i2c匯流排位於i2c核心中
可以用下圖來總結
i2c核心維護著一條i2c匯流排,提供了註冊i2c裝置、i2c驅動、i2c介面卡的介面
i2c匯流排維護著一條裝置鍊錶和驅動鏈表,當向i2c核心層註冊裝置時,會將其新增到匯流排的裝置鍊錶中,然後遍歷匯流排上的驅動鏈表,檢視二者是否匹配,如果匹配就呼叫驅動的probe函式
當註冊i2c驅動時,也會將其新增到i2c匯流排的驅動鏈表中,然後遍歷匯流排的裝置鍊錶,檢視二者是否匹配,如果匹配就呼叫驅動的probe函式
在i2c驅動程式中,通過i2c介面卡中的演算法向i2c硬體裝置傳輸資料
三、i2c驅動框架原始碼剖析
3.1 註冊i2c裝置
註冊i2c適配可以通過i2c_new_device,此函式會生成乙個i2c_client,指定對應的匯流排為i2c匯流排,然後向匯流排註冊裝置
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
看一下其中的i2c_bus_type物件,其表示i2c匯流排,定義了裝置和驅動的匹配規則還有匹配成功後的行為
struct bus_type i2c_bus_type = ;
下面再來看看device_register向匯流排註冊裝置過程中會發生什麼
device_register首先會將裝置新增到匯流排的裝置鍊錶中,然後遍歷匯流排的驅動鏈表,判斷裝置和驅動是否匹配,如果匹配就呼叫驅動的probe函式,下面看一看原始碼分析
int device_register(struct device *dev)
int device_add(struct device *dev)
其中bus_add_device函式會將裝置新增到匯流排的裝置鍊錶中,如下
int bus_add_device(struct device *dev)12
34bus_probe_device函式會遍歷匯流排的驅動鏈表,如下
void bus_probe_device(struct device *dev)
1int device_attach(struct device *dev)
bus_for_each_drv(dev->bus, null, dev, __device_attach);會遍歷匯流排的驅動鏈表的每一項,然後呼叫__device_attach
static int __device_attach(struct device_driver *drv, void *data)
driver_match_device函式會判斷裝置和驅動是否匹配,如果匹配就呼叫driver_probe_device
首先來看一看driver_match_device函式的定義
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
發現它呼叫了匯流排的match函式,這裡的匯流排在註冊i2c裝置的時候已經被設定為i2c匯流排了,定義如下
struct bus_type i2c_bus_type = ;
所以這裡會呼叫到i2c_device_match函式,i2c_device_match會通過i2c驅動的id_table中每一的name和i2c裝置的name進行匹配
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
const struct i2c_client *client)
return null;
}static int i2c_device_match(struct device *dev, struct device_driver *drv)
如果匹配成功會呼叫driver_probe_device,下面再來看看driver_probe_device
driver_probe_device函式最終會先呼叫到i2c匯流排的probe函式,然後再呼叫i2c驅動的probe函式
int driver_probe_device(struct device_driver *drv, struct device *dev)
static int really_probe(struct device *dev, struct device_driver *drv)
匯流排的probe函式為i2c_device_probe,此函式會呼叫驅動的probe函式
static int i2c_device_probe(struct device *dev)
3.2 註冊i2c驅動
可以通過i2c_add_driver註冊i2c驅動,該函式會指定驅動對應的匯流排為i2c匯流排,然後向匯流排註冊驅動,
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
i2c_bus_type的定義如下
struct bus_type i2c_bus_type = ;
driver_register函式遍歷匯流排的裝置鍊錶進行操作,然後將驅動新增到匯流排的驅動鏈表中
int driver_register(struct device_driver *drv)
int bus_add_driver(struct device_driver *drv)
int driver_attach(struct device_driver *drv)
下面來看一看__driver_attach函式,此函式會判斷裝置和驅動是否匹配,如果匹配就呼叫驅動的probe函式
static int __driver_attach(struct device *dev, void *data)
這個過程和註冊裝置的過程是一樣的,這裡不再分析
3.3 i2c介面卡的構建
對於i2c介面卡,我們不討論它的註冊細節,我們看它是如何構建的
對於三星平台,在drivers\i2c\busses\i2c-s3c2410.c檔案中構建並註冊了i2c介面卡,這是三星平台i2c控制器的驅動
static const struct i2c_algorithm s3c24xx_i2c_algorithm = ;
static int s3c24xx_i2c_probe(struct platform_device *pdev)
其中的s3c24xx_i2c_algorithm中的s3c24xx_i2c_xfer就是通過操作暫存器來通過i2c控制器傳輸資料
3.4 i2c資料傳輸
上面介紹i2c資料傳輸是通過i2c介面卡完成的,下面來分析一下原始碼
在i2c驅動中,使用i2c_transfer來傳輸i2c資料,此函式肯定是通過i2c介面卡的演算法進行操作的,如下
linux i2c匯流排驅動
技術就是這樣,看一百遍不如做十遍。在對i2c做了乙個簡單的記錄之後發現比單看要理解更深刻,當然在記錄完i2c驅動之後,最希望自己能夠堅持自己實現at24c02的讀寫驅動與測試應用程式。由於是做記錄,少不了借用網路各種優秀資源,下圖是某部落格中找到的i2c框架。1 hardware層,cpu的i2c ...
Linux I2C匯流排框架 學習筆記
i2c框架結構 linux 核心中的 i2c 框架分為 3 部分,分別是 core bus driver devicedriver 其中 core 部分是框架中的框架,會呼叫 bus driver 和 device driver 中的函式和結構體進行 i2c 註冊 資料讀寫。我將其整理成為下面這張框...
i2c匯流排時序
一心想踏入linux device driver的世界,想著i2c匯流排相對於usb等其他匯流排較為簡單,就以i2c作為切入點,希望可以逐步理解ldd的設計思想,並能理解其裝置模型的概念。在此對近期於i2c匯流排及驅動原始碼的理解做備忘,以免徒勞。平台友善之臂s70 tiny6410 cpusams...