i2c子系统之i2c bus初始化——i2c_init()

根据前文的分析,在linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的

i2c_init()函数。下面具体此函数具体做了那些预备工作。


1.i2c总线的注册

i2c_init()的函数实现如下:

static int __init i2c_init(void)  
{  
        ... ...  
    retval = bus_register(&i2c_bus_type);  
        ... ...  
}  
可以发现i2c_inti的函数主要功能就是注册i2c总线。下面重点分析下这个i2c_bus_type这个表示总线的结构体。


2.i2c_bus_type总线

struct bus_type i2c_bus_type = {
	.name		= "i2c",
	.match		= i2c_device_match,
	.probe		= i2c_device_probe,
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
	.pm		= &i2c_device_pm_ops,
};

总线提供了match和probe方法:match方法的用来进行client device和client driver的配对。

在向总线i2c_bus_type注册设备或者驱动时会调用此方法。

2.6.37.1中的at24c02采用的是i2c_match_id这种方法,本质上还是通过name来配对。

static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
	struct i2c_client	*client = i2c_verify_client(dev);
	struct i2c_driver	*driver;

	if (!client)                              //判断当前的dev是否是client类型,假如不是立即返回
		return 0;

	/* Attempt an OF style match */
	if (of_driver_match_device(dev, drv))    //条件drv->of_match_table,对at24来说是at24_driver->drv->of_match_table
		return 1;

	driver = to_i2c_driver(drv);
	/* match on an id table if there is one */
	if (driver->id_table)
		return i2c_match_id(driver->id_table, client) != NULL;

	return 0;
}

probe方法在完成设备和驱动的配对后调用执行,i2c_bus_type的probe方法是通过传递进来的drv找到

包含此drv的i2c_driver驱动,然后再去调用i2c_driver的probe方法,此处就是at24_probe。为什么要这

样呢?因为driver_register后,注册的是i2_driver->drv,而drv中的probe未初始化,我们需要调用的是

i2c-driver的probe方法。

static int i2c_device_probe(struct device *dev)
{
	struct i2c_client	*client = i2c_verify_client(dev);
	struct i2c_driver	*driver;
	int status;

	if (!client)
		return 0;

	driver = to_i2c_driver(dev->driver);
	if (!driver->probe || !driver->id_table)
		return -ENODEV;
	client->driver = driver;
	if (!device_can_wakeup(&client->dev))
		device_init_wakeup(&client->dev,
					client->flags & I2C_CLIENT_WAKE);
	dev_dbg(dev, "probe\n");

	status = driver->probe(client, i2c_match_id(driver->id_table, client));
	if (status) {
		client->driver = NULL;
		i2c_set_clientdata(client, NULL);
	}
	return status;
}


你可能感兴趣的:(c,struct,table,null)