Linux I2C driver analysis

  

I2C is a 2-wire serial bus protocol developed by Phillips. Usually used in embedded systems to allow different components to communicate, PC motherboards can communicate with different sensors through I2C. These sensors typically report fan speed, processor temperature, and information about the entire hardware system. This protocol can also be used on RAM chips to provide DIMM information to the operating system
.

In 2.0, the source code of I2C is not in the kernel. The 2.4 kernel includes a little support for I2C, mainly video driver. In the 2.6 kernel, a lot of I2C code is added to the kernel. Thanks to the efforts of many kernel developers, they make the interface more acceptable to the kernel community. Some drivers are still in the external CVS tree and are not placed in kernel.org, but they are only a matter of time.

I2C's kernel source is divided into several parts: the I2C core, I2C bus drivers, I2C algorithm drivers and I2C chip drivers. We will ignore the I2C core part and focus on how to write a bus and algorithm driver.

I2C Bus Drivers The bus driver I2C bus driver is described by a structure i2c_adapter, which is defined in the file include/linux/i2c.h. The following fields need to be set in the bus driver: struct module *owner; -set to the value (THIS_MODULE) that allows the proper module reference counting.unsigned int class; -the type of I2C class devices that this driver supports. Usually this is set to the value I2C_ADAP_CLASS_SMBUS.struct i2c_algorithm * algo; -a pointer to the struct i2c_algorithm structure that describes the way data is transferred through this I2C bus controller More information on this structure is provided below.char name [I2C_NAME_SIZE];. -set to a descriptive name of the I2C bus driver. This value shows up in the sysfs filename associated with this I2C adapter.

The following code comes from an I2C adapter driver example tiny_i2c_adap.c, which can be found in the Linux Journal FTP site [ftp.ssc.com/pub/lj/listings/issue116/7136.tgz [1]] Obtained. Let's see how struct i2c_adapter is set: static struct i2c_adapter tiny_adapter = {.owner = THIS_MODULE,.class = I2C_ADAP_CLASS_SMBUS,.algo = &tiny_algorithm,.name = "tiny adapter",};

Register the I2C adapter, the driver calls the function i2c_add_adapter, and the argument is the struct i2c_adapter pointer. Retval = i2c_add_adapter(&tiny_adapter);

To unregister an I2C adapter, the driver calls i2c_del_adapter with the argument struct i2c_adapter pointer. Like this: i2c_del_adapter(&tiny_adapter);

I2C Algorithm DriversI2C algorithm is for the dialogue between the I2C bus driver and the I2C bus. Many I2C bus drivers define and use their own algorithms. Because they are closely linked, it is how the bus driver talks to a specific type of hardware. For some I2C bus drivers, many I2C algorithms have been written. Some examples of this: ITE adapters, in the directory drivers/i2c/i2c-algo-ite.c; IBM PPC 405 adapters in the directory drivers/i2c/i2c-algo-ibm_ocp.c;a generic I2C bit shift algorithm in directory drivers/I2c/i2c-algo-bit.c; all of these already written algorithms have their own functions, and the I2C bus driver needs to be registered for use. For more information on this, check out the kernel source directory drivers/i2c/i2c-algo-*.c.

We will create our own I2C algorithm driver. An algorithm driver is defined by the structure i2c_algorithm. The structure is defined in include/linux/i2c.h. The following is a description of common fields: char name[32];: The name of the algorithm.unsigned int id;: description of the type of algorithm this structure defines. These different types are defined in the include/linux/i2c-id.h file and start with the characters I2C_ALGO_.

int (* master_xfer) (struct i2c_adapter * adap, struct i2c_msg msgs [], int num) ;: a function pointer to be set if this algorithm driver can do I2C direct-level accesses. If it is set, this function is called whenever an I2C chip driver wants to communicate with the chip device. If it is set to NULL, the smbus_xfer function is used instead.

int (* smbus_xfer) (struct i2c_adapter * adap, u16 addr, unsigned short flags , char read_write, u8 command, int size, union i2c_smbus_data *data);: a function pointer to be set if this algorithm driver can do SMB bus accesses. Most PCI-bas ed I2C bus drivers are able to do this, and they should set this function pointer. If it is set, this function is called whenever an I2C chip driver wants to communicate with the chip device. If it is set to NULL, the master_xfer function Is used instead.u32 (*functionality) (struct i2c_adapter *);: a function pointer called by the I2C core to determine what kind of reads and writes the I2C adapter driver can do.

in our I2C adapter In the driver, the i2c_adapter structure references the tiny_algorithm variable. The structure is defined as follows: static struct i2c_algorithm tiny_algorithm = {.name = "tiny algorithm",.id = I2C_ALGO_SMBUS,.smbus_xfer = tiny_access,.functionality = tiny_func,}; The function tiny_func is very Simple, tell I2C core what type of I2C messages the algorithm can support. In this driver, we have to support many different I2C messages types: static u32 tiny_func(struct i2c_adapter *adapter){return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA;} All I2C message types are defined in include/linux/i2c.h, starting with I2C_FUNC_.

When the I2C client driver wants to talk to the I2C bus, the function tiny_access will be called. Our example function is very simple, it only records the I2C chip driver request to syslog, and returns success to the caller.

Copyright © Windows knowledge All Rights Reserved