1. 程式人生 > >寧 靜 以 致 遠

寧 靜 以 致 遠

簡單的說,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);
來建立。

以上就是簡要說說,主要還是要看原始碼才能更深的理解這些流程。