first, in the board file Client the instantiation of
Defines the device information in the initialization of the kernel, such as in a board file. The premise of this operation is that when the kernel compiles, it is determined which i²c devices and their addresses , as well as the number of the connected bus .
For example, in the board file/arch/arm/mach-xxx/board_xxx.c can be used similar to the following code to register the I²C device information.
1. Static struct I2c_board_info __initdata uio_i2c_board_info[] = {
2. {
3. I2c_board_info ("DEV_NAME0", 0x2d),
5.},
6. {
7. I2c_board_info ("dev_name1", 0x52),
9.},
10. {
I2c_board_info ("Dev_name2", 0x57),
13.},
14.};
15.
. static void __init uio_init (void)
17. {
18. (...)
I2c_register_board_info (1, Uio_i2c_board_info,
Array_size (Uio_i2c_board_info));
21. (...)
22.}
After registering, I2c_adapter will scan all of the registered I2c_board_info and instantiate a i2c_client for the connected i²c device.
In this way, when i2c_driver registers, I2c_client will be bound to I2c_driver (the registered NAME must be the same ), I2c_driver probe function is called.
Second, Enumerating Devices
Use I2c_new_device () or I2c_new_probed_device () to instantiate the client in the device driver file.
The first method mentioned above has many limitations, and it is necessary to know which i²c devices and their addresses and the bus numbers that speak I²c before compiling the kernel.
But sometimes kernel developers do not know what i²c devices or how many i²c buses they have when porting the system. In this case, i2c_new_device () needs to be used. Its prototype is:
struct I2c_client *
I2c_new_device (struct i2c_adapter *adap, struct i2c_board_info const *info);
This function will use the Info information provided to establish a i2c_client and the first parameter points to the I2c_adapter binding. The returned parameter is a i2c_client pointer.
The driver can communicate with the device directly using the i2c_client pointer. This method is a relatively simple method.
The function to get the I2c_adapter pointer is:
struct i2c_adapter* i2c_get_adapter (int id);//ID is the i²c bus number.
To release after use:
void I2c_put_adapter (struct i2c_adapter *adap);
If the address of the I²C device is in advance and even has different addresses on different boards, an address list can be provided for the system to detect.
The function that should be used at this time is i2c_new_probe_device. Use the following:
2. Static const unsigned short normal_i2c[] = {0x2c, 0x2d, i2c_client_end};
3. static int __devinit uio_probe (struct platform_device *pdev)
4. {
5. (...)
6. struct I2c_adapter *i2c_adap;
7. struct I2c_board_info i2c_info;
8. (...)
9. I2c_adap = I2c_get_adapter (2);
memset (&i2c_info, 0, sizeof (struct i2c_board_info));
strlcpy (I2c_info.name, "Isp1301_pnx", i2c_name_size);
Isp1301_i2c_client = I2c_new_probed_device (I2c_adap, &i2c_info,
NORMAL_I2C);
I2c_put_adapter (I2C_ADAP);
15. (...)
16.}
The prototype of I2c_new_probed_device is:
struct I2c_client *
I2c_new_probed_device (struct I2c_adapter *adap,
struct I2c_board_info *info,
unsigned short const *addr_list);
This function will probe the address in the addr_list on the specified bus and assign the first address with the ACK feedback to the INFO->ADDR,
Then call I2c_new_device using the first two parameters. Its return value is also an available i2c_client pointer.
I2c_unregister_device () can unregister the i2c_client of the I2c_new_device ()/i2c_new_probed_device () request.
Add: How do I know the number of a physical i²c bus?
[Email protected]/]# Cat/sys/class/i2c-dev/i2c-0/name
Pnx4008-i2c0
[Email protected]/]# Cat/sys/class/i2c-dev/i2c-1/name
Pnx4008-i2c1
[Email protected]/]# Cat/sys/class/i2c-dev/i2c-2/name
Usb-i2c
Thirdly, in all I²c detect specific devices on the bus.
The limitations of Method 2 in the kernel documentation and the benefits of Method 3 I don't understand. Say your own understanding, that is, Method 2 although it is possible to probe multiple addresses, it can only be probed on a specified bus, and detects the first available address to stop probing. A third method is required if the number of the bus is not previously determined, or if multiple i²c devices are probed at once.
Implementing a third method requires two conditions:
L Implement detect members of I2c_driver. This member function prototype is:
Int (*detect) (struct i2c_client *, int kind, struct i2c_board_info *);
This function must check whether the addr field of the second parameter is its own supported address, or at least the other members of the Info->type,info can be populated, but the addr should not be modified. Returns 0 if it is, otherwise returns-ENODEV.
L Initialize the Address_list member of I2c_driver. When I2c_driver is registered, I2c_core detects all addresses in address_list on all registered I2c_adapter, and then calls I2c_driver members after the hardware probe is successful. Then build a i2c_client based on the info populated by detect. If there are two devices with the same address on the bus, two i2c_client will be created respectively. If more than one address in the Address_list has a device footprint, multiple i2c_client are established.
In practice, however, the kernel documents do not recommend this approach, but instead prefer methods 1 and 2, perhaps because this approach is too flexible.
Iv. enumeration from user space.
If you do not know the address of the I²C device before writing the driver (even if the address list is not known), then it needs to be entered from the user space after the system is running.
User space uses two SYSFS properties files to create and delete I2c_client:new_device and Delete_device. These two files are all write-only.
The New_device has two parameters: the name (string) and address of the I²C device (16 binary numbers starting with 0x). Delete_device has only one parameter, which is the address of the device.
To illustrate:
# echo Device-name 0x50 >/sys/bus/i2c/devices/i2c-3/new_device
You can see that the bus number has been specified at this time.
(see kernel documentation for more details) O (∩_∩) o
How to instantiate I2c_client (four methods)