i2c 设备节点的访问和不同方式实现

最近碰到实际应用案例中有通过module_i2c_driver 注册实际i2c 设备驱动,再通过struct i2c_driver的.id_table 成员指向的struct i2c_device_id 对象表格来实现 i2c_client的最终被probe;
还有一类是直接通过 i2c_new_client_device 使用板上信息struct i2c_board_info 实例来创建i2c_client的。
但是这类创建出来的设备再应用层使用的时候,出现通信数据不对的情形。为了更好的梳理这两类访问方法的过程,将源码实现做个具体的解读。

参考
https://blog.csdn.net/m0_59249795/article/details/123902869
https://blog.csdn.net/li_wen01/category_6277839.html

在前面的platform device和platform driver初始化中,我们已经实现了I2C总线驱动(adapter),但是我们的设备驱动还没有实现。如果我们现在要访问I2C设备(比如eeprom),我知道的有三总方法:

(一)i2c-dev操作I2C设备:不用添加设备驱动,用户直接在应用层完成对具体I2C 设备的驱动工作。

(二)sysfs操作I2C设备:需添加设备驱动,通过sys展示出来的文件操作设备(比如/sys/devices/platform/s3c2440-i2c/i2c-0/0-0050/eeprom)

(三)设备节点操作i2C设备:添加设备驱动,为设备驱动创建设备节点,从/dev访问I2C设备(比如/dev/eeprom)

一、
通过创建设备树节点,设备树节点和i2c 设备保持相同的命名。
在module_i2c_driver 注册实际i2c 设备驱动,实现probe的调用实现关系如下

1)module_i2c_driver

950  #define module_i2c_driver(__i2c_driver) \
951  	module_driver(__i2c_driver, **i2c_add_driver, \**
952  			i2c_del_driver)

882  #define i2c_add_driver(driver) \
**883  	i2c_register_driver(THIS_MODULE, driver)**
  1. i2c_register_driver
1846  int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
1847  {
1848  	int res;
1849  
1850  	/* Can't register until after driver model init */
1851  	if (WARN_ON(!is_registered))
1852  		return -EAGAIN;
1853  
1854  	/* add the driver to the list of i2c drivers in the driver core */
1855  	driver->driver.owner = owner;
1856  	driver->driver.bus = &i2c_bus_type;
**1857  	INIT_LIST_HEAD(&driver->clients);**
1858  
1859  	/* When registration returns, the driver core
1860  	 * will have called probe() for all matching-but-unbound devices.
1861  	 */
1862  	res = driver_register(&driver->driver);
1863  	if (res)
1864  		return res;
1865  
1866  	pr_debug("driver [%s] registered\n", driver->driver.name);
1867  
1868  	/* Walk the adapters that are already present */
**1869  	i2c_for_each_dev(driver, __process_new_driver);**
1870  
1871  	return 0;
1872  }
1873  EXPORT_SYMBOL(i2c_register_driver);

初始化总线驱动对应的clients 列表,1869 行 去实现具体的i2c 驱动的枚举加载

  1. i2c_for_each_dev __process_new_driver
1822  int i2c_for_each_dev(void *data, int (*fn)(struct device *dev, void *data))
1823  {
1824  	int res;
1825  
1826  	mutex_lock(&core_lock);
1827  	res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
1828  	mutex_unlock(&core_lock);
1829  
1830  	return res;
1831  }
1832  EXPORT_SYMBOL_GPL(i2c_for_each_dev);
1833  
1834  static int __process_new_driver(struct device *dev, void *data)
1835  {
1836  	if (dev->type != &i2c_adapter_type)
1837  		return 0;
**1838  	return i2c_do_add_adapter(data, to_i2c_adapter(dev));**
1839  }

to_i2c_adapter(dev) 实现常规设备描述对struct i2c_adapter的转换。

  1. i2c_do_add_adapter
1335  static int i2c_do_add_adapter(struct i2c_driver *driver,
1336  			      struct i2c_adapter *adap)
1337  {
1338  	/* Detect supported devices on that bus, and instantiate them */
**1339  	i2c_detect(adap, driver);**
1340  
1341  	return 0;
1342  }
  1. i2c_detect
2348  static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
2349  {
2350  	const unsigned short *address_list;
2351  	struct i2c_client *temp_client;
2352  	int i, err = 0;
2353  
2354  	address_list = driver->address_list;
**2355  	if (!driver->detect || !address_list)**
2356  		return 0;
2357  
2358  	/* Warn that the adapter lost class based instantiation */
2359  	if (adapter->class == I2C_CLASS_DEPRECATED) {
2360  		dev_dbg(&adapter->dev,
2361  			"This adapter dropped support for I2C classes and won't auto-detect %s devices anymore. "
2362  			"If you need it, check 'Documentation/i2c/instantiating-devices.rst' for alternatives.\n",
2363  			driver->driver.name);
2364  		return 0;
2365  	}
2366  
2367  	/* Stop here if the classes do not match */
2368  	if (!(adapter->class & driver->class))
2369  		return 0;
2370  
2371  	/* Set up a temporary client to help detect callback */
2372  	temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
2373  	if (!temp_client)
2374  		return -ENOMEM;
2375  	temp_client->adapter = adapter;
2376  
2377  	for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
2378  		dev_dbg(&adapter->dev,
2379  			"found normal entry for adapter %d, addr 0x%02x\n",
2380  			i2c_adapter_id(adapter), address_list[i]);
2381  		temp_client->addr = address_list[i];
2382  		**err = i2c_detect_address(temp_client, driver);**
2383  		if (unlikely(err))
2384  			break;
2385  	}
2386  
2387  	kfree(temp_client);
2388  	return err;
2389  }

如果驱动的detect 操作有实现,且地址列表不为空。创建一个临时的temp_client,从驱动的address_list[i]取出对应总线设备地址,通过i2c_detect_address去总线确认

  1. i2c_detect_address
2286  static int i2c_detect_address(struct i2c_client *temp_client,
2287  			      struct i2c_driver *driver)
2288  {
2289  	struct i2c_board_info info;
2290  	struct i2c_adapter *adapter = temp_client->adapter;
2291  	int addr = temp_client->addr;
2292  	int err;
2293  
2294  	/* Make sure the address is valid */
2295  	err = i2c_check_7bit_addr_validity_strict(addr);
2296  	if (err) {
2297  		dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
2298  			 addr);
2299  		return err;
2300  	}
2301  
2302  	/* Skip if already in use (7 bit, no need to encode flags) */
2303  	if (i2c_check_addr_busy(adapter, addr))
2304  		return 0;
2305  
2306  	/* Make sure there is something at this address */
2307  	if (!i2c_default_probe(adapter, addr))
2308  		return 0;
2309  
2310  	/* Finally call the custom detection function */
2311  	memset(&info, 0, sizeof(struct i2c_board_info));
2312  	info.addr = addr;
2313  	**err = driver->detect(temp_client, &info);**
2314  	if (err) {
2315  		/* -ENODEV is returned if the detection fails. We catch it
2316  		   here as this isn't an error. */
2317  		return err == -ENODEV ? 0 : err;
2318  	}
2319  
2320  	/* Consistency check */
2321  	if (info.type[0] == '\0') {
2322  		dev_err(&adapter->dev,
2323  			"%s detection function provided no name for 0x%x\n",
2324  			driver->driver.name, addr);
2325  	} else {
2326  		struct i2c_client *client;
2327  
2328  		/* Detection succeeded, instantiate the device */
2329  		if (adapter->class & I2C_CLASS_DEPRECATED)
2330  			dev_warn(&adapter->dev,
2331  				"This adapter will soon drop class based instantiation of devices. "
2332  				"Please make sure client 0x%02x gets instantiated by other means. "
2333  				"Check 'Documentation/i2c/instantiating-devices.rst' for details.\n",
2334  				info.addr);
2335  
2336  		dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
2337  			info.type, info.addr);
**2338  		client = i2c_new_client_device(adapter, &info);**
2339  		if (!IS_ERR(client))
**2340  			list_add_tail(&client->detected, &driver->clients);**
2341  		else
2342  			dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",
2343  				info.type, info.addr);
2344  	}
2345  	return 0;
2346  }

这里去正式的i2c_client确认和添加。

i2c_driver驱动实例中 如果没有实现detect 操作,只能通过总线的i2c_device_match 来扫描加载设备, i2c_device_probe来加载设备,通过driver->probe的传入 clients来最终添加设备。
实现关系如下

677  struct bus_type i2c_bus_type = {
678  	.name		= "i2c",
679  	.match		= i2c_device_match,
680  	.probe		= i2c_device_probe,
681  	.remove		= i2c_device_remove,
682  	.shutdown	= i2c_device_shutdown,
683  };
684  EXPORT_SYMBOL_GPL(i2c_bus_type);

101  const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
102  						const struct i2c_client *client)
103  {
104  	if (!(id && client))
105  		return NULL;
106  
107  	while (id->name[0]) {
108  		if (strcmp(client->name, id->name) == 0)
109  			return id;
110  		id++;
111  	}
112  	return NULL;
113  }
114  EXPORT_SYMBOL_GPL(i2c_match_id);
115  
116  static int i2c_device_match(struct device *dev, struct device_driver *drv)
117  {
118  	struct i2c_client	*client = i2c_verify_client(dev);
119  	struct i2c_driver	*driver;
120  
121  
122  	/* Attempt an OF style match */
123  	if (i2c_of_match_device(drv->of_match_table, client))
124  		return 1;
125  
126  	/* Then ACPI style match */
127  	if (acpi_driver_match_device(dev, drv))
128  		return 1;
129  
130  	driver = to_i2c_driver(drv);
131  
132  	/* Finally an I2C match */
133  	if (i2c_match_id(driver->id_table, client))
134  		return 1;
135  
136  	return 0;
137  }

466  static int i2c_device_probe(struct device *dev)
467  {
468  	struct i2c_client	*client = i2c_verify_client(dev);
469  	struct i2c_driver	*driver;
470  	bool do_power_on;
471  	int status;
472  
473  	if (!client)
474  		return 0;
475  
476  	client->irq = client->init_irq;
477  
478  	if (!client->irq) {
479  		int irq = -ENOENT;
480  
481  		if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
482  			dev_dbg(dev, "Using Host Notify IRQ\n");
483  			/* Keep adapter active when Host Notify is required */
484  			pm_runtime_get_sync(&client->adapter->dev);
485  			irq = i2c_smbus_host_notify_to_irq(client);
486  		} else if (dev->of_node) {
487  			irq = of_irq_get_byname(dev->of_node, "irq");
488  			if (irq == -EINVAL || irq == -ENODATA)
489  				irq = of_irq_get(dev->of_node, 0);
490  		} else if (ACPI_COMPANION(dev)) {
491  			bool wake_capable;
492  
493  			irq = i2c_acpi_get_irq(client, &wake_capable);
494  			if (irq > 0 && wake_capable)
495  				client->flags |= I2C_CLIENT_WAKE;
496  		}
497  		if (irq == -EPROBE_DEFER) {
498  			status = irq;
499  			goto put_sync_adapter;
500  		}
501  
502  		if (irq < 0)
503  			irq = 0;
504  
505  		client->irq = irq;
506  	}
507  
508  	**driver = to_i2c_driver(dev->driver);**
509  
510  	/*
511  	 * An I2C ID table is not mandatory, if and only if, a suitable OF
512  	 * or ACPI ID table is supplied for the probing device.
513  	 */
514  	if (!driver->id_table &&
515  	    !acpi_driver_match_device(dev, dev->driver) &&
516  	    !i2c_of_match_device(dev->driver->of_match_table, client)) {
517  		status = -ENODEV;
518  		goto put_sync_adapter;
519  	}
520  
521  	if (client->flags & I2C_CLIENT_WAKE) {
522  		int wakeirq;
523  
524  		wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
525  		if (wakeirq == -EPROBE_DEFER) {
526  			status = wakeirq;
527  			goto put_sync_adapter;
528  		}
529  
530  		device_init_wakeup(&client->dev, true);
531  
532  		if (wakeirq > 0 && wakeirq != client->irq)
533  			status = dev_pm_set_dedicated_wake_irq(dev, wakeirq);
534  		else if (client->irq > 0)
535  			status = dev_pm_set_wake_irq(dev, client->irq);
536  		else
537  			status = 0;
538  
539  		if (status)
540  			dev_warn(&client->dev, "failed to set up wakeup irq\n");
541  	}
542  
543  	dev_dbg(dev, "probe\n");
544  
545  	status = of_clk_set_defaults(dev->of_node, false);
546  	if (status < 0)
547  		goto err_clear_wakeup_irq;
548  
549  	do_power_on = !i2c_acpi_waive_d0_probe(dev);
550  	status = dev_pm_domain_attach(&client->dev, do_power_on);
551  	if (status)
552  		goto err_clear_wakeup_irq;
553  
554  	client->devres_group_id = devres_open_group(&client->dev, NULL,
555  						    GFP_KERNEL);
556  	if (!client->devres_group_id) {
557  		status = -ENOMEM;
558  		goto err_detach_pm_domain;
559  	}
560  
561  	/*
562  	 * When there are no more users of probe(),
563  	 * rename probe_new to probe.
564  	 */
565  	if (driver->probe_new)
566  		status = driver->probe_new(client);
567  	else if (driver->probe)
**568  		status = driver->probe(client,
569  				       i2c_match_id(driver->id_table, client));**
570  	else
571  		status = -EINVAL;
572  
573  	/*
574  	 * Note that we are not closing the devres group opened above so
575  	 * even resources that were attached to the device after probe is
576  	 * run are released when i2c_device_remove() is executed. This is
577  	 * needed as some drivers would allocate additional resources,
578  	 * for example when updating firmware.
579  	 */
580  
581  	if (status)
582  		goto err_release_driver_resources;
583  
584  	return 0;
585  
586  err_release_driver_resources:
587  	devres_release_group(&client->dev, client->devres_group_id);
588  err_detach_pm_domain:
589  	dev_pm_domain_detach(&client->dev, do_power_on);
590  err_clear_wakeup_irq:
591  	dev_pm_clear_wake_irq(&client->dev);
592  	device_init_wakeup(&client->dev, false);
593  put_sync_adapter:
594  	if (client->flags & I2C_CLIENT_HOST_NOTIFY)
595  		pm_runtime_put_sync(&client->adapter->dev);
596  
597  	return status;
598  }

设备树创建和调用设备驱动的过程如下

static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
struct device_node *node)
{
struct i2c_client *client;
struct i2c_board_info info;
int ret;

dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);

ret = of_i2c_get_board_info(&adap->dev, node, &info);
if (ret)
	return ERR_PTR(ret);

client = i2c_new_client_device(adap, &info);
if (IS_ERR(client))
	dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);

return client;

}

在of_i2c_register_device 函数中也是调用了i2c_new_client_device,实现板上信息对应的i2c_client创建, 而这个板上信息使用of_i2c_get_board_info(&adap->dev, node, &info); 从设备树的节点上获取。

void of_i2c_register_devices(struct i2c_adapter *adap)
{
	struct device_node *bus, *node;
	struct i2c_client *client;

	/* Only register child devices if the adapter has a node pointer set */
	if (!adap->dev.of_node)
		return;

	dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");

	bus = of_get_child_by_name(adap->dev.of_node, "i2c-bus");
	if (!bus)
		bus = of_node_get(adap->dev.of_node);

	for_each_available_child_of_node(bus, node) {
		if (of_node_test_and_set_flag(node, OF_POPULATED))
			continue;

		client = of_i2c_register_device(adap, node);
		if (IS_ERR(client)) {
			dev_err(&adap->dev,
				 "Failed to create I2C device for %pOF\n",
				 node);
			of_node_clear_flag(node, OF_POPULATED);
		}
	}

	of_node_put(bus);
}

of_i2c_register_device 被i2c_register_adapter调用,i2c_register_adapter 被 __i2c_add_numbered_adapter调用,最终实现了i2c_add_adapter 和i2c_add_numbered_adapter 这类master 设备的接口。

二、 i2c_new_client_device 过程

i2c_new_client_device 会创建struct i2c_client对象,同时会通过device_register 创建一个sysfs 设备树上的一个节点。而且是对应的adaptor 目录下面。
这个client 和 ”(一)i2c-dev操作I2C设备:不用添加设备驱动,用户直接在应用层完成对具体I2C 设备的驱动工作“ 生成的client 是不同的。

struct i2c_client *
i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
	struct i2c_client	*client;
	int			status;

	client = kzalloc(sizeof *client, GFP_KERNEL);
	if (!client)
		return ERR_PTR(-ENOMEM);

	client->adapter = adap;

	client->dev.platform_data = info->platform_data;
	client->flags = info->flags;
	client->addr = info->addr;

	client->init_irq = info->irq;
	if (!client->init_irq)
		client->init_irq = i2c_dev_irq_from_resources(info->resources,
							 info->num_resources);

	strscpy(client->name, info->type, sizeof(client->name));

	status = i2c_check_addr_validity(client->addr, client->flags);
	if (status) {
		dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",
			client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
		goto out_err_silent;
	}

	/* Check for address business */
	status = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client));
	if (status)
		goto out_err;

	client->dev.parent = &client->adapter->dev;
	client->dev.bus = &i2c_bus_type;
	client->dev.type = &i2c_client_type;
	client->dev.of_node = of_node_get(info->of_node);
	client->dev.fwnode = info->fwnode;

	device_enable_async_suspend(&client->dev);
	i2c_dev_set_name(adap, client, info);

	if (info->swnode) {
		status = device_add_software_node(&client->dev, info->swnode);
		if (status) {
			dev_err(&adap->dev,
				"Failed to add software node to client %s: %d\n",
				client->name, status);
			goto out_err_put_of_node;
		}
	}

	status = device_register(&client->dev);
	if (status)
		goto out_remove_swnode;

	dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
		client->name, dev_name(&client->dev));

	return client;

out_remove_swnode:
	device_remove_software_node(&client->dev);
out_err_put_of_node:
	of_node_put(info->of_node);
out_err:
	dev_err(&adap->dev,
		"Failed to register i2c client %s at 0x%02x (%d)\n",
		client->name, client->addr, status);
out_err_silent:
	kfree(client);
	return ERR_PTR(status);
}
EXPORT_SYMBOL_GPL(i2c_new_client_device);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值