寧 靜 以 致 遠
阿新 • • 發佈:2018-12-22
簡單的說,i2c驅動也就三步吧,註冊i2c裝置,註冊i2c裝置驅動,建立sysfs檔案供上層呼叫。
1. 註冊i2c裝置。
先定義一個i2c_board_info
static struct i2c_board_info __initdata xxxx_i2c_info[] = {
{
I2C_BOARD_INFO("XXXX", 0x1D),
.platform_data = &xxxx_platform_data,
},
};
再註冊,一般會註冊一個client。
i2c_register_board_info()
強烈建議有興趣的可以看看這個函式的原始碼,可以學到很多。
2. 註冊i2c裝置driver
定義再註冊
static struct i2c_driver xxx_i2c_driver = {
.id_table = xxx_i2c_id,
.probe = xxx_i2c_probe,
.remove = __exit_p(xxx_i2c_remove),
.driver = {
.name = "xxx",
},
};
註冊函式
i2c_add_driver(&xxx_i2c_driver);
註冊過程中,主要是呼叫probe函式,如何跑到probe函式裡同樣需要跟程式碼。這裡不詳述。講講probe函式裡主要幹什麼。
static int xxx_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc = 0; printk("%s called!\n", __func__); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { printk("i2c_check_functionality failed\n"); goto probe_failure; } xxx_sensorw = kzalloc(sizeof(struct xxx_work_t), GFP_KERNEL); if (!xxx_sensorw) { printk("kzalloc failed.\n"); rc = -ENOMEM; goto probe_failure; } i2c_set_clientdata(client, xxx_sensorw); xxx_init_client(client); xxx_client = client; msleep(50); printk("%s successed! rc = %d\n", __func__, rc); return 0; probe_failure: printk("%s failed! rc = %d\n", __func__, rc); return rc; }
probe函式主要是獲取client,而後便可以通過client中adapter的方法來傳輸資料:
static int xxx_i2c_txdata(const uint16_t saddr, uint8_t *txdata, const uint16_t length) { struct i2c_msg msg[] = { { .addr = saddr, .flags = 0, .len = length, .buf = txdata, }, }; if (i2c_transfer(xxx_client->adapter, msg, 1) < 0) { printk("xxx_i2c_txdata faild 0x%x\n", saddr); return -EIO; } return 0; }
3. 建立sysfs供上層呼叫
可以通過函式
sysfs_create_group(&(pdev->dev.kobj), &xxx_attribute_group);
來建立。
以上就是簡要說說,主要還是要看原始碼才能更深的理解這些流程。