Linux启动过程分析(十一)-----i2c_init

按照之前的初始化流程可以得到在该系统下I2C子系统的初始化顺序为:

  1. (drivers\i2c):postcore_initcall(i2c_init);
  2. Setup.c
    (arch\arm\kernel):arch_initcall(customize_machine)对应的da850_evm_init中
  • davinci_cfg_reg_list(da850_i2c0_pins);

  • da8xx_register_i2c(0, &da850_evm_i2c_pdata);

  1. i2c_register_board_info(1, da850_evm_i2c_devices,
    ARRAY_SIZE(da850_evm_i2c_devices));
  2. I2c-davinci.c(drivers\i2c\busses):subsys_initcall(davinci_i2c_init_driver);
  3. I2c-gpio.c (drivers\i2c\busses):subsys_initcall(i2c_gpio_init);

I2c-dev.c (drivers\i2c):module_init(i2c_dev_init);
下面按照这个顺序,先来分析i2c_init


static int __init i2c_init(void)
{
	int retval;
	/*注册I2C总线*/
	retval = bus_register(&i2c_bus_type);
	if (retval)
		return retval;
#ifdef CONFIG_I2C_COMPAT
	i2c_adapter_compat_class = class_compat_register("i2c-adapter");
	if (!i2c_adapter_compat_class) {
		retval = -ENOMEM;
		goto bus_err;
	}
#endif
	retval = i2c_add_driver(&dummy_driver);
	if (retval)
		goto class_err;
	return 0;

class_err:
#ifdef CONFIG_I2C_COMPAT
	class_compat_unregister(i2c_adapter_compat_class);
bus_err:
#endif
	bus_unregister(&i2c_bus_type);
	return retval;
}

第一步先注册I2C总线:
retval = bus_register(&i2c_bus_type);
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,//与电源管理有关
};

重点分析一下:i2c_device_match和I2c_device_probe函数;
match用来进行device和driver的匹配


static int i2c_device_match(struct device *dev, struct device_driver *drv)
{	
	/*返回i2c_client的具体参数,它可以防止把一些不是i2c的设备当作是i2c_client*/
	struct i2c_client	*client = i2c_verify_client(dev);
	struct i2c_driver	*driver;
	/*i2c_verify_client返回NULL,表示这个设备不是i2c的设备*/
	if (!client)
		return 0;

	/* 尝试OF风格的匹配 */
	if (of_driver_match_device(dev, drv))
		return 1;

	driver = to_i2c_driver(drv);//通过device->driver指针获取到对应的i2c_driver指针
	/* match on an id table if there is one */
	if (driver->id_table)
		/*如果i2c驱动的id_table存在的话,使用该函数进行匹配,匹配的方法是拿driver-id_table中的
		每一项与client进行匹配,如果相同则匹配成功*/
		return i2c_match_id(driver->id_table, client) != NULL;

	return 0;
}

probe用于在完成设备和驱动的配对之后调用执行。

static int i2c_device_probe(struct device *dev)
{
	struct i2c_client	*client = i2c_verify_client(dev);//通过device指针获取到对应的i2c_client指针
	struct i2c_driver	*driver;
	int status;

	if (!client)
		return 0;

	driver = to_i2c_driver(dev->driver);//通过device->driver指针获取到对应的i2c_driver指针
	if (!driver->probe || !driver->id_table)
		return -ENODEV;
	client->driver = driver;//i2c设备通过i2c_client->driver指针去指向与他匹配成功的设备驱动i2c_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));调用设备驱动层的probe函数
	if (status) {
		client->driver = NULL;
		i2c_set_clientdata(client, NULL);
	}
	return status;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值