Linux Device Driver subsystem-I2C

Source: Internet
Author: User

1. Overview

2. Data Structure

3. Adapter

4. I2C-core

5. Slave Device

 

1. Overview

1.1 Definition

  • I2C inter-Integrated Circuit
  • SMBus System Management bus, the I2C subset

1.2 Characteristics

  • The amount of data exchanged is small.
  • The required data transfer rate is low.

1.3 speed

  • Fast speed 400 kbps
  • Full speed 100 kbps

1.4 Topology

 

 

 

2 Data Structure

Understanding the data structure is very important for understanding the entire driver subsystem. I2C mainly has two data structures: struct i2c_client and struct i2c_adapter.

2.1 i2c_client

Struct i2c_client {
Unsigned short flags;/* Div., see below */
Unsigned short ADDR;/* chip address */
Char name [i2c_name_size];
Struct i2c_adapter * adapter;/* the adapter we sit on */
Struct i2c_driver * driver;/* and our access routines */
Struct device dev;/* The device structure */
Int IRQ;/* IRQ issued by device (or-1 )*/
Char driver_name [kobj_name_len];
Struct list_head list;/* deprecated */
Struct completion released;
};

Struct i2c_client represents an I2C slave device mounted to the I2C bus, the data structure required by the device, including

  • Struct i2c_adapter * Adapter
  • The I2C driver from the device struct i2c_driver * driver
  • It is a member variable commonly used by I2C slave devices, such as ADDR and name.
  • The I2C data exclusive to the device driver is attached to Dev-> driver_data.

2.2 i2c_adapter

Struct i2c_adapter {
Struct module * owner;
Unsigned int ID;
Unsigned int class;
Const struct i2c_algorithm * algo;/* the algorithm to access the bus */
Void * algo_data;

......

};
Struct i2c_adapter represents an I2C master device supported by the master chip, the data structure required by the device,

Struct i2c_algorithm * algo is an algorithm used by the I2C master device to transmit data. It is also a capability for data communication between master and slave devices on the I2C bus.

Struct i2c_algorithm {
INT (* master_xfer) (struct i2c_adapter * ADAP, struct i2c_msg * msgs, int num );
INT (* smbus_xfer) (struct i2c_adapter * ADAP, 2010addr,
Unsigned short flags, char read_write,
U8 command, int size, Union i2c_smbus_data * data );
U32 (* functionality) (struct i2c_adapter *);
};

Next, to implement the driver of the entire I2C sub-system, we will focus on the two data structures. The main steps can be summarized into the following three steps,

  • Implementation of I2C main Device Driver (Drivers/I2C/bus /*)
  • Register i2c_client for I2C slave device (Drivers/I2C/i2c-core)
  • Implement I2C Slave Device Driver

 3 Adapter

The kernel directory Drivers/I2C contains two folders: algorithm and bus. The bus stores the drivers of the I2C main device, and the driver of the main device completes two major tasks,

  • Provides the ability to complete data communication between the I2C master device and the slave device.
  • Complete the registration of the i2c_adapter and all known i2c_client

Taking i2c-pxa.c as an example,

/* Drivers/I2C/bus/i2c-pxa.c */

Static int _ init i2c_adap_pxa_init (void)
{
Return platform_driver_register (& i2c_pxa_driver );
}

Static struct platform_driver i2c_pxa_driver = {
. Probe = i2c_pxa_probe,
......
. Id_table = i2c_pxa_id_table,
};

Static int i2c_pxa_probe (struct platform_device * Dev)
{
Struct pxa_i2c * I2C;
I2C-> ADAP. Algo = i2c_pxa_algorithm; // provides the ability to complete data communication between the I2C master device and the slave device.

I2c_add_numbered_adapter (& I2C-> ADAP); // call the interface function in the i2c-core.c to complete the registration of the i2c_adapter and i2c_client

......
}

Static const struct i2c_algorithm i2c_pxa_algorithm = {
. Master_xfer = i2c_pxa_xfer, // completes I2C data transmission according to the specific requirements of PXA Chip
. Functionality = i2c_pxa_functionality,
};

 

 4 I2C-core

Kernel Directory Drivers/I2C under the i2c-core.c, as the name suggests, is the kernel for I2C provides a unified system interface.

Let's see what i2c_add_numbered_adapter has done,

Int i2c_add_numbered_adapter (struct i2c_adapter * ADAP)
{
......
Status = i2c_register_adapter (ADAP );
Return status;
}

 

Static int i2c_register_adapter (struct i2c_adapter * ADAP)
{
......
Device_register (& ADAP-> Dev); // registers the adapter of the I2C master device, that is, registering an object and sending a uevent.
I2c_scan_static_board_info (ADAP );

......
}
I2c_scan_static_board_info (ADAP). This function is the core of the entire I2C subsystem. it traverses a bidirectional cyclic linked list consisting of I2C slave devices and registers all I2C slave i2c_clients, the specific process is as follows,

Static void i2c_scan_static_board_info (struct i2c_adapter * adapter)
{
Struct i2c_devinfo * DevInfo; // a list of established I2C slave devices

List_for_each_entry (DevInfo, &__ i2c_board_list, list ){
I2c_new_device (adapter, & DevInfo-> board_info );
......
}
}

Struct i2c_client * i2c_new_device (struct i2c_adapter * ADAP, struct i2c_board_info const * info)
{
......
I2c_attach_client (client );
......

}
Int i2c_attach_client (struct i2c_client * client)
{
......
Device_register (& client-> Dev); // register the I2C client from the device
......
}

So, when is the two-way cyclic linked list composed of devices created by I2C?

Taking a gravity sensor device as an example,

/*/ARCH/ARM/Mach-PXA/starwood_p1.c */

Static void _ init saar_init (void)

{

......

I2c_register_board_info (0, array_and_size (saar_i2c_bma220_info ));

......

}

Static struct i2c_board_info saar_i2c_bma220_info [] = {
{
. Driver_name = "bma220 ",
. ADDR = 0x0b,
. IRQ = irq_gpio (mfp_to_gpio (mfp_pin_gpio15 )),
},
};

/* Drivers/I2C/i2c-boardinfo.c */

Int _ init i2c_register_board_info (INT busnum, struct i2c_board_info const * info, unsigned Len)
{

......

Struct i2c_devinfo * DevInfo;
DevInfo-> board_info = * Info;
List_add_tail (& DevInfo-> list, & __ i2c_board_list); // Add I2C from the device to the linked list
......
}

Therefore, during system initialization, we can use i2c_register_board_info to add the required I2C from the device to a two-way circular linked list named _ i2c_board_list. After the system successfully loads the Adapt of the I2C main device, the i2c_client is registered one by one for all I2C devices in this linked list.

 

  5 slave driver

In terms of hardware, the I2C main device has been integrated into the main chip. In terms of software, Linux also provides us with the corresponding driver, which is located under Drivers/I2C/bus, in this case, I2C is much easier to drive from the device. Since the i2c_adapter and i2c_client have been registered when the system loads the driver of the I2C main device, I2C completes three major tasks from the device,

  • Information of I2C slave device with i2c_board_info structure added during system initialization
  • The i2c_adapter algorithm is used in the I2C device driver to implement I2C communication.
  • Mount the I2C data structure from the device to i2c_client.dev-> driver_data.

Taking the gravity sensor device as an example,

Static int _ init bma220_init (void)
{
Return i2c_add_driver (& bma220_driver );
}

Static struct i2c_driver bma220_driver = {
. Driver = {
. Owner = this_module,
. Name = "bma220 ",
},
. Class = i2c_class_hwmon,
. Probe = bma220_probe,
. Remove = bma220_remove,
};

Static int bma220_probe (struct i2c_client * client, const struct i2c_device_id * ID)
{
Struct bma220_data * data;
I2c_check_functionality (client-> adapter, i2c_func_i2c)

I2c_smbus_read_word_data (client, 0x00); // interface provided by the i2c-core, using i2c_adapter algorithm to achieve I2C communication
I2c_set_clientdata (bma220_client, data); // mount the device's data structure to i2c_client.dev-> driver_data
Misc_register (& bma_device );
Request_irq (client-> IRQ, bma220_irq_handler, ir1__trigger_rising, "bma220", & Data-> bma220 );
Bma220_set_en_tt_xyz (0 );
Bma220_reset_int ();

......
}

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.