下面具體分析如何寫第一部分:
主控芯片的i2c驅動分為2個步驟:
寫總線驅動:
選了個主控芯片,比如:S3C8900(自己瞎編的芯片)
在driver/i2c/busses/i2c-s3c2410.c中沒有找到這個芯片的I2C支持(總線驅動支持)。。。(倒霉了,沒有選好芯片,也可能是最新型號的,linux內核沒跟上)
在此之前先分析i2c-s3c2410.c中完成的工作(總線驅動):
- 設計對應於i2c_adapter_xxx_init()模板的s3c8900的模塊加載函數和對應於i2c_adapter_xxx_exit()函數模板的模塊卸載函數。
- 設計對應於i2c_adapter_xxx_xfer()模板的 s3c8900適配器的通信方法函數,針對 s3c24xx、64xx、s5pc1XX、s5p64xx處理器functionality()函數s3c24xx_i2c-func()只需簡單的返回I2C_FUNC_I2C|I2C_FUNC_SMBUS_EMUL|I2C_FUNC_PROTOCOL_MANGLING表明其支持的功能
話說沒找到總線驅動支持,(這倒霉孩子)那就得編寫個類似的i2c-s3c8900.c的總線驅動支持,嘿嘿,照着上面的功能寫吧,反正是總線驅動。
寫吧,還等啥啊!!~~~~~
- I2C適配器驅動加載與卸載
- 初始化i2c適配器所使用的硬件資源,如申請I/O地址、中斷號等
- 通過i2c_add_adapter添加i2c_adapter數據結構,當然這個數據結構的成員已經被xxx適配器的相應的函數指針所初始化
- i2c總線卸載模塊與裝載相反,是否i2c適配器使用的硬件資源,通過i2c_del_adapter刪除i2c_adapter的數據結構
模板如下:
static int __init i2c_adapter_xxx_init(void)
{
xxx_adapter_hw_init();//初始化硬件資源
i2c_add_adapter(&xxx_adapter);
}
static void __init i2c_adapter_xxx_exit(void)
{
xxx_adapter_hw_free();//釋放硬件資源
i2c_del_adapter(&xxx_adapter);
}
具體CPU具體分析,有的用platform做的,可以參考6410的做法
- I2C總線的通信方法
我們需要為特定的i2c適配器實現其通信方法,主要實現i2c_algorithm的master_xfer()函數和functionality()函數
functionality函數很簡單,用於返回algorithm所支持的通信協議,如:I2C_FUCN-_I2C , I2C_FUNC_10BIT_ADDR,I2C_FUNC_SMBUS_READ_BYTE,I2C_FUNC_SMBUS_write_byte等
master_xfer函數在i2c適配器上完成傳遞給他的i2c_msg數組中的每個i2c消息。
模板如下:
static int i2c_adapter_xxx_xfer(struct i2c_adapter *adap,struct i2c_msg *msgs, int num)
{
......
for(i = 0; i<num ; i++){
i2c_adapter_xxx_start(); //產生開始位
//如果是讀消息
if(msg[i]->falgs &I2C_M_RD){
i2c_adapter_xxx_setaddr((msg->addr<<1)|1); //發送從設備讀地址
i2c_adapter_xxx_wait_ack();//獲取從設備的ack信息
i2c_adapter_xxx_readbytes(msgs[i]->buf,msgs[i]->len);//讀取msg[i]->len長的數據到msg[i]->buf里
} else{ //是寫消息
i2c_adapter_xxx_setaddr((msg->addr<<1)|1); //發送從設備寫地址
i2c_adapter_xxx_wait_ack();//獲取從設備的ack信息
i2c_adapter_xxx_readbytes(msgs[i]->buf,msgs[i]->len);//讀取msg[i]->len長的數據到msg[i]->buf里
}
}
i2c_adapter_xxx_stop(); //產生停止位
}
好啦,完成了裝載和卸載,又完成了通信方法這兩個重要的東東,那么總線驅動結構已經完成啦,累死了!
第三部分准備具體寫個驅動程序看看,呵呵