linux i2c子系统入口,I2C子系统1 - ARM_Linuxx的个人空间 - OSCHINA - 中文开源技术交流社区...
I2C子系統(tǒng)
核心 i2c_driver 結(jié)構(gòu)體
分配、設(shè)置、注冊(cè)一個(gè)i2c_driver結(jié)構(gòu)體
static struct i2c_driver i2c_example_driver = {
.driver = {
.name = "example",
.of_match_table = of_match_ids_example,
},
.probe = i2c_example_driver_probe,
.remove = i2c_example_driver_remove,
.id_table = example_ids,
};
出入口函數(shù)
/*入口函數(shù) 注冊(cè)一個(gè)i2c_drvier */
static int __init i2c_driver_init(void)
{
return i2c_add_driver(&i2c_example_driver);
}
module_init(i2c_driver_init);
/**出口函數(shù) del一個(gè)i2c_drvier */
static void __exit i2c_driver_exit(void)
{
i2c_del_driver(&i2c_example_driver);
}
i2c_driver表明能支持哪些設(shè)備
i2c_driver表明能支持哪些設(shè)備:
使用of_match_table來判斷
設(shè)備樹中,某個(gè)I2C控制器節(jié)點(diǎn)下可以創(chuàng)建I2C設(shè)備的節(jié)點(diǎn)
如果I2C設(shè)備節(jié)點(diǎn)的compatible屬性跟of_match_table的某項(xiàng)兼容,則匹配成功
i2c_client.name跟某個(gè)of_match_table[i].compatible值相同,則匹配成功 static const struct of_device_id of_match_ids_example[] = {
{ .compatible = "com_name,chip_name", .data = NULL},
{ /* END OF LIST */ } /*最后空一項(xiàng)為必須,空閑為end 判斷條件*/
};
// of_ 開頭一般與設(shè)備樹關(guān)聯(lián)
使用id_table來判斷
i2c_client.name跟某個(gè)id_table[i].name值相同,則匹配成功 static const struct i2c_device_id example_ids[] = {
{ "chip_name", (kernel_ulong_t)NULL },
{ /* END OF LIST */ }
};
i2c_driver跟i2c_client匹配成功后,就調(diào)用i2c_driver.probe函數(shù)。
i2c_client
參考資料 Linux內(nèi)核文檔: 5.0版本內(nèi)核
Documentation\i2c\instantiating-devices.rst
Documentation\i2c\writing-clients.rst
i2c_client表示一個(gè)I2C設(shè)備,創(chuàng)建i2c_client的方法有4種:
方法1
通過I2C bus number來創(chuàng)建 int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len);
通過設(shè)備樹結(jié)點(diǎn) /* 在某個(gè)I2C控制器的節(jié)點(diǎn)下,添加如下代碼: */
ap3216c@1e {
compatible = "lite-on,ap3216c";
reg = <0x1e>;
};
方法2
有時(shí)候無法知道該設(shè)備掛載哪個(gè)I2C bus下,無法知道它對(duì)應(yīng)的I2C bus number。 但是可以通過其他方法知道對(duì)應(yīng)的i2c_adapter結(jié)構(gòu)體。 可以使用下面兩個(gè)函數(shù)來創(chuàng)建i2c_client:
i2c_new_device static struct i2c_client *ap3216c_client;
static int __init i2c_client_ap3216c_init(void)
{
struct i2c_adapter *adapter;
struct i2c_board_info board_info = {
I2C_BOARD_INFO("ap3216c", 0x1e),
};
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
/* register I2C device */
adapter = i2c_get_adapter(0);
ap3216c_client = i2c_new_device(adapter, &board_info);
i2c_put_adapter(adapter);
return 0;
}
i2c_new_probed_device static struct i2c_client *ap3216c_client;
/* 羅列出所有可能的地址,這里只有一個(gè)*/
static const unsigned short normal_i2c[] = { 0x1e, I2C_CLIENT_END };
static int __init i2c_client_ap3216c_init(void)
{
struct i2c_adapter *adapter;
struct i2c_board_info i2c_info;
/* 將名字信息寫入i2c_info,先清0 */
memset(&i2c_info, 0, sizeof(struct i2c_board_info));
strscpy(i2c_info.type, "ap3216c", sizeof(i2c_info.type));
adapter = i2c_get_adapter(0); /* 第0根i2c總線 */
ap3216c_client = i2c_new_probed_device(adapter, &i2c_info,
normal_i2c, NULL);
i2c_put_adapter(adapter);
return 0;
}
差別
i2c_new_device:
會(huì)創(chuàng)建i2c_client,即使該設(shè)備并不存在
i2c_new_probed_device:
它成功的話,會(huì)創(chuàng)建i2c_client,并且表示這個(gè)設(shè)備肯定存在
I2C設(shè)備的地址可能發(fā)生變化,比如AT24C02的引腳A2A1A0電平不一樣時(shí),設(shè)備地址就不一樣
可以羅列出可能的地址
i2c_new_probed_device使用這些地址判斷設(shè)備是否存在
方法3 (不推薦):由i2c_driver.detect函數(shù)來判斷是否有對(duì)應(yīng)的I2C設(shè)備并生成i2c_client
方法4 : 通過用戶空間(user-space)生成
調(diào)試時(shí)、或者不方便通過代碼明確地生成i2c_client時(shí),可以通過用戶空間來生成。 // 創(chuàng)建一個(gè)i2c_client, .name = "eeprom", .addr=0x50, .adapter是i2c-3
# echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device
// 刪除一個(gè)i2c_client
# echo 0x50 > /sys/bus/i2c/devices/i2c-3/delete_device
總結(jié)
以上是生活随笔為你收集整理的linux i2c子系统入口,I2C子系统1 - ARM_Linuxx的个人空间 - OSCHINA - 中文开源技术交流社区...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux替换每个英文字开头为大写,sh
- 下一篇: 在linux下创立bash文件,Linu