博主按:大熱的天,剛剛負重從五道口走到石板房,大約4公里吧。終於讓我找了一個咖啡屋休息一下,繼續寫這篇驅動分析。單身的生活就是這樣無聊啊。 不發牢騷了,活出個樣兒來給自己看!千難萬險腳下踩,啥也難不倒咱!繼續整!~
先說一下,本文中有個疑惑,一直沒有搞懂,寫在這里,望高人指點一二,不勝感激!
#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
這里I2C_FUNC_PROTOCOL_MANGLING 是什么意思?為什么定義這些東東?看了注釋也不太理解。求解釋!
3. I2C總線驅動代碼分析
s3c2440的總線驅動代碼在i2c-s3c2410.c中。照例先從init看起。
在init中只是調用了平台驅動注冊函數注冊了一個i2c的平台驅動s3c24xx_i2c_driver。這個驅動是一個platform_driver的結構體變量。注意這里不是i2c_driver結構體,因為i2c_driver是對設備的驅動,而這里對控制器的驅動要使用platform_driver
同樣的,重要的函數還是那幾個:probe,remove,suspend_late,resume。再加上一個id_table和device_driver結構體變量。
下面逐個分析:
* probe函數
當調用platform_driver_register函數注冊platform_driver結構體時,probe指針指向的s3c24xx_i2c_probe函數將會被調用。這部分詳細解釋參考本博客另一篇文章《S3C2410看門狗驅動分析》。細心的朋友可能會發現,在s3c24xx_i2c_driver中,驅動的名字是"s3c-i2c",而在板文件中可以看到,設備的名字是"s3c2410-i2c",這兩個名字不一樣,那驅動和設備是如何match的呢?答案就在於id_table。這個id_table包含了驅動所支持的設備ID表。在match的時候,判斷這個表中的名字是不是和設備一致,一致則match成功。這也是為什么一個驅動可以同時match成功多個設備的原因。如果只是靠platform_driver-->driver中的名字來匹配的話,那么驅動和設備只能是一對一的關系了。
扯遠了,還是看看probe的代碼吧~
*remove函數
這是和probe相反的一個函數,在i2c_adap_s3c_exit時調用。主要功能是注銷適配器,釋放中斷,釋放內存區域,禁止始終等等。看到上邊代碼中的err_的各個部分了吧? remove是它們的匯總。
*suspend函數和resume函數
把這兩個放一起說吧,掛起和恢復函數。掛起時保存狀態並置標志位,恢復時重新初始化i2c適配器並置標志位。
Algorithm
哎呀我去,終於到這了。憋得我難受啊。這里要重點介紹一下,不僅要知其然,還要知其所以然,這樣我們以后自己寫驅動的時候就有把握了。
這里實現的就是這個s3c24xx_i2c_xfer。這個是控制器能不能動作的關鍵,缺了這個,控制器就是廢銅爛鐵。
完成任務的函數是s3c24xx_i2c_doxfer(),源碼清單如下,
上面代碼可以分成幾個部分來看:
* s3c24xx_i2c_set_master() 這個函數每隔1ms查看一次i2c總線狀態,timeout是400ms,如果在這期間總線狀態不忙,則返回零。否則返回-ETIMEDOUT
* 將要發送的消息和其他信息付給i2c->msg和其他變量,並將狀態設置為STATE_START
* s3c24xx_i2c_enable_irq() 使能中斷
* s3c24xx_i2c_message_start() 重中之重啊。在看代碼之前先來看看2440的datasheet上是怎么說的吧。

代碼清單如下:
(今天沒寫完啊,明天繼續~)
