I2C协议和驱动框架分析(三)

3、从设备驱动分析

       总线驱动一般由主控芯片厂商(高通海思MTK展讯全志瑞芯微等等)已经做好了,驱动工程师就需要完成 I2C 设备驱动。I2C的设备驱动框架只是一款芯片(I2C接口)驱动的基础,通常还会和其他子系统(比如 camera 的 V4L2、Audio codec 的 ASoc 以及各类 sensor 的 input 子系统等)糅合在一起。所以,不管是实现一款芯片的驱动还是去分析别人的驱动代码,都需要有相关的子系统知识。这里我们以 goodix 的 TP 驱动为例,主要分析 I2C 的设备驱动部分。驱动入口如下:

static const struct i2c_device_id goodix_ts_id[] = {
	{ GTP_I2C_NAME, 0 },
	{ }
};

static struct of_device_id goodix_ts_dt_ids[] = {
	{ .compatible = "goodix,gt9xx" },
	{ }
};

static struct i2c_driver goodix_ts_driver = {
	.probe    = goodix_ts_probe,
	.remove   = goodix_ts_remove,
	.id_table = goodix_ts_id,
	.driver = {
		.name  = GTP_I2C_NAME,
		.owner = THIS_MODULE,
		.of_match_table = of_match_ptr(goodix_ts_dt_ids),
	},
};

static int goodix_ts_init(void)
{
	/*
	 * 工作队列机制,任务推后执行
	 * 创建单内核线程,并返回一个工作队列
	 * 中断里调用queue_work()内核会调度执行该工作队列里的任务
	 */
	goodix_wq = create_singlethread_workqueue("goodix_wq");
	if (!goodix_wq) {
		GTP_ERROR("Failed to create workqueue goodix_wq");
		return -ENOMEM;
	}

	return i2c_add_driver(&goodix_ts_driver);
}

static void goodix_ts_exit(void)
{
	i2c_del_driver(&goodix_ts_driver);

	if (goodix_wq)
		destroy_workqueue(goodix_wq);
}

module_init(goodix_ts_init);
module_exit(goodix_ts_exit);

       关于工作队列,以后有机会单独拿出来分析一波。任何一个 i2c 设备驱动都会调用 i2c_add_driver,我们的分析就从这个函数开始:

#define i2c_add_driver(driver) \
	i2c_register_driver(THIS_MODULE, driver)

i2c_add_driver 是个宏函数,i2c_register_driver(i2c-core.c) 的函数体如下:

/*
 * An i2c_driver is used with one or more i2c_client (device) nodes to access
 * i2c slave chips, on a bus instance associated with some i2c_adapter.
 */
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
	int res;

	/* Can't register until after driver model init */
	if (unlikely(WARN_ON(!i2c_bus_type.p)))
		return -EAGAIN;

	/* add the driver to the list of i2c drivers in the driver core */
	driver->driver.owner = owner;
	/* 设备驱动挂在i2c_bus_type下 */
	driver->driver.bus = &i2c_bus_type;
	INIT_LIST_HEAD(&driver->clients);

	/* When registration returns, the driver core
	 * will have called probe() for all matching-but-unbound devices.
	 */
	res = driver_register(&driver->driver);
	if (res)
		return res;

	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);

	/* Walk the adapters that are already present */
	/* 并没有做什么实质性的工作,由于device_type不匹配就返回了 */
	i2c_for_each_dev(driver, __process_new_driver);

	return 0;
}
EXPORT_SYMBOL(i2c_register_driver);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值