Several methods of instantiating i2c devices in the Linux kernel----./Linux-4.9.88/Documentation/i2c/instantiating-devices file translation

Table of contents

How to instantiate an I2C device

Method 1a: Declare I2C device by bus number

Method 1b: Declare the I2C device through the device tree

Method 1c: Declare I2C device via ACPI

Method 2: Explicitly instantiate the device

Method 3: Probe the I2C bus of some devices

Method 4: Instantiate from user space


The following content is from ./Linux-4.9.88/Documentation/i2c/instantiating-devices, just translated into Chinese.

How to instantiate an I2C device

Unlike PCI or USB devices, I2C devices are not enumerated at the hardware level. Instead, software must know which devices are connected to each I2C bus segment and the addresses used by those devices. Therefore, kernel code must explicitly instantiate the I2C device. There are several ways to achieve this, depending on the context and requirements.

Method 1a: Declare I2C device by bus number

This approach is appropriate when the I2C bus is a system bus, as is the case with many embedded systems. On such a system, each I2C bus has a pre-known number. Therefore, I2C devices on this bus can be pre-declared. This is   done by calling i2c_register_board_info() Register an  array of structures.i2c_board_info

Example (from omap2 h4):

static struct i2c_board_info h4_i2c_board_info[] __initdata = {
	{
		I2C_BOARD_INFO("isp1301_omap", 0x2d),
		.irq		= OMAP_GPIO_IRQ(125),
	},
	{	/* EEPROM on mainboard */
		I2C_BOARD_INFO("24c01", 0x52),
		.platform_data	= &m24c01,
	},
	{	/* EEPROM on cpu card */
		I2C_BOARD_INFO("24c01", 0x57),
		.platform_data	= &m24c01,
	},
};

static void __init omap_h4_init(void)
{
	(...)
	i2c_register_board_info(1, h4_i2c_board_info,
			ARRAY_SIZE(h4_i2c_board_info));
	(...)
}

The above code declares 3 devices on I2C bus 1, including their respective addresses and custom data required by the driver. I2C devices will be automatically instantiated by i2c-core when registering the I2C bus.

When the I2C bus they are on disappears (if ever), the devices are automatically unbound and destroyed.

Method 1b: Declare the I2C device through the device tree

This method has the same meaning as method 1a. Declaration of an I2C device is done through the device tree as a child node of the master controller.

Example:

i2c1: i2c@400a0000 {
	/* ... 跳过主属性 ... */
	clock-frequency = <100000>;

	flash@50 {
		compatible = "atmel,24c256";
		reg = <0x50>;
	};

	pca9532: gpio@60 {
		compatible = "nxp,pca9532";
		gpio-controller;
		#gpio-cells = <2>;
		reg = <0x60>;
	};
};

Here, the two devices are connected using a bus speed of 100kHz. For additional properties that may need to be set for a device, see its device tree documentation at Documentation/devicetree/bindings/.

Method 1c: Declare I2C device via ACPI

ACPI can also describe I2C devices. Special documentation on this is currently located at Documentation/acpi/enumeration.txt.

Method 2: Explicitly instantiate the device

This method is appropriate when larger devices use the I2C bus for internal communication. Typically this is a TV adapter. They can have tuners, video decoders, audio decoders, etc. and are usually connected to the main chip via an I2C bus. You won't know the I2C bus number in advance, so you can't use method 1 above. Instead, you instantiate your I2C device explicitly. This is   done by filling i2c_board_info in the structure and calling  .i2c_new_device()

Example (from sfe4001 network driver):

static struct i2c_board_info sfe4001_hwmon_info = {
	I2C_BOARD_INFO("max6647", 0x4e),
};

int sfe4001_init(struct efx_nic *efx)
{
	(...)
	efx->board_info.hwmon_client =
		i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);

	(...)
}

The above code instantiates an I2C device on the I2C bus on the network adapter in question.

When you are not sure if the I2C device is present (for example for optional features that are not present on the cheaper model of the board but you can't tell them apart) or it might have a different address from one board to another (manufacturer changes its design without notice). In this case you can call  i2c_new_probed_device() instead  i2c_new_device().

Example (from nxp OHCI driver):

static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };

static int usb_hcd_nxp_probe(struct platform_device *pdev)
{
	(...)
	struct i2c_adapter *i2c_adap;
	struct i2c_board_info i2c_info;

	(...)
	i2c_adap = i2c_get_adapter(2);
	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
	strlcpy(i2c_info.type, "isp1301_nxp", I2C_NAME_SIZE);
	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
						   normal_i2c, NULL);
	i2c_put_adapter(i2c_adap);
	(...)
}

The above code instantiates up to 1 I2C device on the I2C bus on the OHCI adapter. It first tries address 0x2c, if it doesn't find anything there, then it tries address 0x2d, and if it still doesn't find anything, it simply gives up.

The driver that instantiates the I2C device is responsible for destroying it during cleanup. This is done by calling on the pointer previously   returned  by i2c_new_device() or  .i2c_new_probed_device()i2c_unregister_device()

Method 3: Probe the I2C bus of some devices

Sometimes you don't know enough about the I2C device to even call it  i2c_new_probed_device(). The typical case is the hardware monitoring chip on the PC motherboard. There are dozens of models available, available at 25 different addresses. Given the vast number of motherboards out there, it's nearly impossible to build an exhaustive list of hardware monitoring chips in use. Fortunately, most of these chips have manufacturer and device ID registers so they can be identified by probing.

In this case, the I2C device is neither declared nor explicitly instantiated. Instead, once the driver is loaded, i2c-core will detect these devices and if any are found, the I2C device will be instantiated automatically. To prevent any inappropriate behavior of this mechanism, the following restrictions apply:

  • I2C device drivers must implement  detect() methods that identify supported devices by reading from any register.
  • Only buses that may have supporting devices that agree to be probed will be probed. This avoids probing hardware monitoring chips on TV adapters, for example.

Example: See lm90_driver and lm90_detect() in drivers/hwmon/lm90.c

I2C devices instantiated as a result of successful detection will be automatically destroyed when their driver is detected to be removed or when the underlying I2C bus itself is destroyed, whichever occurs first.

Those familiar with the i2c subsystem in the 2.4 kernel and earlier 2.6 kernels will find that this approach 3 is essentially similar to what was being done at the time. Two significant differences are:

  • Probing is now just a way to instantiate an I2C device, but at the time it was the only way. Where possible, methods 1 and 2 should be preferred. Method 3 should only be used if no other method is available, as it may have unwanted side effects.
  • I2C buses must now explicitly specify which I2C driver classes can probe them (via the class bit field), when all I2C buses are probed by default. Defaults to an empty category, which means no probing occurs. The purpose of the category bit field is to limit the undesirable side effects mentioned above.

Again, method 3 should be avoided whenever possible. Explicit device instantiation (methods 1 and 2) is preferred because it is safer and faster.

Method 4: Instantiate from user space

Normally, the kernel should know which I2C devices are connected and the addresses at which they are located. However, in some cases it does not know, so a sysfs interface was added to let the user provide the information. The interface consists of two properties files, both created in each I2C bus directory: new_device and delete_device. Both files are write-only and you must write the correct parameters to them to properly instantiate or delete the I2C device.

The file new_device requires 2 parameters: the name of the I2C device (a string) and the address of the I2C device (a number, usually represented in hexadecimal starting with 0x, but can also be represented in decimal).

The file delete_device requires one parameter: the address of the I2C device. Since no two devices can be at the same address on a given I2C segment, the address is sufficient to uniquely identify the device to be removed.

Example:

echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device

Although this interface is only used when kernel device declaration cannot be completed, it may be helpful in several situations:

  • The I2C driver normally detects the device (method 3 above), but the bus segment your device is on does not have the correct class bit set, so the detection does not trigger.
  • The I2C driver normally detects the device, but your device is at an unexpected address.
  • I2C drivers often detect devices, but your device is not detected, either because the detection routine is too strict, or because your device is not officially supported yet, but you know it is compatible.
  • You are developing the driver on a test board where you have soldered the I2C device yourself.

This interface is a replacement for the force_* module parameters implemented by some I2C drivers. Since it is implemented in i2c-core rather than in each device driver individually, it is more efficient and has the advantage of not having to reload the driver when changing settings. You can also instantiate the device before the driver is loaded or even available, and you don't need to know what driver the device requires.

Guess you like

Origin blog.csdn.net/u013171226/article/details/132016973