Summary: At least four read and write methods for I2C driven by linux

    Summarize four methods of reading and writing I2C devices in the Linux environment:


One: read and write /dev/i2c-x device node

    The driver file corresponding to the /dev/i2c-x device node is the i2c-dev.c file that comes with the kernel directory drivers/i2c. Read through this file to find its workflow.

 1. Register the character device node through register_chrdev

  2. Create the corresponding class node under sysfs through class_create

  3. Use bus_register_nofifier to add a notification chain to the I2C bus, and call the corresponding processing function when an adapter is added or deleted

  4. Loop through the devices on the I2C bus through the I2C core function i2c_for_each_dev, and execute the i2cdev_attach_adapter function every time a device is found

  5. In the i2cdev_attach_adapter function, it will first determine whether the device is an adapter. If it is, a corresponding node will be generated in the /dev directory through device_create, named i2c-x, where x is the number of adapters

  6. When the user space uses open("/dev/i2c-x", O_RDWR) to operate the corresponding node, an i2c_client will be created for each user who operates this adapter. The i2c_client will pass client->adapter = adapter and file- >private_data = client associates the corresponding adapter and operation file

  7. When the user space operates the device through the read/write function, the driver obtains the adapter structure through struct i2c_client *client = file->private_data;, and then calls the I2C core function i2c_mater_send/i2c_master_recv, and finally calls the specific adapter to send/receive data function

    When operating the I2C device through this method, it should be noted that after opening the device node through open, the device address needs to be set through the ioctl I2C_SLAVE function, and then the device can be operated through the read/write function.


Two: Customize the I2C device and operate through the corresponding node under /dev

    The driver file can be written as follows:

    1. Register the corresponding I2C driver through module_i2c_driver. At this time, the kernel will traverse the devices mounted on the I2C bus, and match the driver and the device through the bus match method. The matching principle can be 1. Based on the of_driver_match_device method of the device tree, corresponding to The structure is whether the defined driver structure contains of_match_table member 2, matching based on id_table, corresponding to whether the driver defines id_table member 3, matching based on name, the matching principle is whether the name of the driver is the same as the name of the device 4, based on ACPI style matches, use less

    2. When the driver and the device match, the probe function of the I2C bus will be called first to do some processing, and then the probe function of the I2C driver defined by us will be called.

    3. Save the client pointer to our custom device structure in the probe function, such as custom:

    struct xxx{

    struct i2c_client client;

    ... 

};

    4. Register character devices through register_chrdev, create /sys/ and /dev/ nodes through class_create and device_create (or manually create through mknod)

    5. In the open function, set the custom drive structure to file->private_data, which is convenient to obtain in the read and write functions

    6. Open the node under our registered /dev/ directory through the open function in user space, and call the corresponding read/write function during read/write. In the read/write function, the custom driver structure will be obtained through file->private_data. , and then get i2c_client, and finally send it through i2c_mater_send/i2c_master_recv or directly build i2c_msg by i2c_transfer


Three: Create read and write files in the corresponding sys device directory through DEVICE_ATTR

    1. First, register the corresponding I2C driver through module_i2c_driver. In the probe function called after finding the device, you only need to create a set of read and write functions through sysfs_create_files or create multiple sets of operation functions through sysfs_create_group

    2. Write a read and write function and declare it through the DEVICE_ATTR macro, organize the function as a struct attribute, and organize multiple groups of struct attributes into a struct attribute_group and use it as the parameter of the sysfs function just now

    3. The user space does not need to pass the open/read/write method, but only needs to read and write the function just defined in the /sys/class/device name directory through echo/cat.


Four: Register the driver as regmap, and use the read and write method of regmap in the corresponding read and write functions

    Regmap is a feature added after kernel 3.1 to reduce repetitive logic on slow I/O drivers, which can reduce the amount of driver code.

    I personally think that the biggest advantage of this method is that those devices that support both I2C and SPI will only use one of these interfaces in actual use, so the read and write functions of the public part are no longer specific to specific buses through i2c_transfer or spi_sync_transfer. The operation function, but through the regmap_read/regmap_write public function provided by regmap, this function will automatically select the operation of I2C or SPI according to the previous registration of the device, so all we need to do is:

    1. Register the device through module_i2c_driver or module_spi_driver, the kernel will automatically perform I2C or SPI probe operation according to i2c_borad_info or spi_board_info or the bus on which the device is mounted in the device tree

    2. Register the device as the corresponding interface of regmap through devm_regmap_init_i2c in the probe function of I2C, and register the device as the corresponding interface of regmap through devm_regmap_init_spi in the probe function of SPI. The second parameter of the function is the regmap_config structure, indicating the register width and data width.

    3. The device can be registered as a character device through the second method above or the corresponding operation function can be created in the /sys directory by the third method

    4. In the implementation of the operation function, it is only necessary to process the data through regmap_read/regmap_write


Additions welcome!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325664080&siteId=291194637