The document describes the data structures used to represent I2C buses, devices, drivers, and clients in the Linux kernel. It explains how a new I2C bus instance is recognized, how devices are added to the I2C bus, and how an I2C device driver is added and bound to devices. Key data structures include i2c_adapter, i2c_client, i2c_driver, and the device/driver model links between them.
I2C Subsystem
In
Linux 2.6.24
Author:
Varun Mahajan
<varunmahajan06@gmail.com>
2.
Contents
●
Data structures representing I2C bus, device, driver, etc
●
How to add an I2C device to the kernel
●
What happens when a new instance of I2C bus is recognized by the
kernel
●
How to add an I2C device driver to the kernel
●
Device ↔ Driver binding
Data Structures
i2c_driver_1 i2c_driver_2
i2c_client_1 i2c_client_2
D1 D2
I2C Bus 1 i2c_adapter_1
I2C Bus Driver bus_type
I2C Bus 2 i2c_adapter_2
D3
i2c_driver_3
i2c_client_3
5.
How to addan I2C device to the Kernel
Populate the __i2c_board_list in the board specific initialization code
__i2c_board_list List of struct i2c_devinfo
struct i2c_devinfo
busnum BUS_NO
struct
“KXSD9_driver”
i2c_board_info
driver_name
KXSD9_I2C_ADDR
addr
irq
KXSD9_IRQ
*platform_data
PLATFORM_DATA
6.
When a newI2C Bus instance is recognized by Kernel
1. A structure i2c_adapter is instantiated for the new bus instance
struct i2c_adapter
nr /*bus no*/ BUS_NO
/*algorithm to access the bus*/
*algo
(*client_register) (i2c_client*)
(*client_unregister) (i2c_client*)
/*list of clients*/
list_head clients
struct device
7.
When a newI2C Bus instance is recognized by Kernel
2. For this new adapter, the __i2c_board_list is scanned to check for
devices whose bus nos match with the adapter’s bus no. If there is a
match then a new i2c_client structure is created for that device
struct i2c_client
struct i2c_devinfo
BUS_NO
addr /*device address*/
busnum
*adapter
*driver KXSD9_I2C_ADDR
driver_name struct
irq i2c_board_info
struct device
driver_name
“KXSD9_driver”
*parent addr
*driver
*bus irq
KXSD9_IRQ
/*driver/platform *platform_data
specific*/
*driver_data
*platform_data
PLATFORM_DATA
kobj
knode_bus
knode_driver
8.
When a newI2C Bus instance is recognized by Kernel
3. The Data structures are linked as shown below
struct i2c_client struct i2c_adapter
addr /*device address*/ nr /*bus no*/
*adapter /*algorithm to access the bus*/
*driver KXSD9_I2C_ADDR *algo
driver_name
irq (*client_register) (i2c_client*)
BUS_NO (*client_unregister) (i2c_client*)
struct device
/*list of clients*/
“KXSD9_driver”
list_head clients
*parent
*driver struct device
*bus
KXSD9_IRQ
/*driver/platform
specific*/
*driver_data struct bus_type
*platform_data
kobj *name = “i2c”
knode_bus (*match) (device*,
device_driver*)
knode_driver
(*probe) (device *)
(*remove) (device *)
(*shutdown) (device *)
(*suspend) (device *, mesg)
(*resume) (device *)
klist_devices
klist_drivers
9.
How to addan I2C device driver to the Kernel
Populate the i2c_driver structure and define the relevant functions.
Add this driver to the kernel through i2c_add_driver()
struct i2c_driver
KXSD9_probe ( i2c_client *)
(*probe) (i2c_client *)
KXSD9_remove ( i2c_client *)
(*remove) (i2c_client *)
KXSD9_shutdown ( i2c_client *)
(*shutdown) (i2c_client *)
(*suspend) (i2c_client*, mesg) KXSD9_suspend ( i2c_client *)
(*resume) (i2c_client *)
KXSD9_resume ( i2c_client *)
struct device_driver
*name “I2C_driver”
*bus
kobj
klist_devices
knode_bus
Device ↔ DriverBinding
• For this new i2c_driver the kernel scans the klist_devices of the
i2c_bus_type structure. If an existing device’s i2c_client’s
driver_name matches with the i2c_driver.driver’s name, then it calls
i2c_bus_type.probe() for this matched device. I2c_bus_type.probe()
internally calls the i2c_driver.probe(). If i2c_driver.probe() succeeds,
the i2c_driver.driver is added to the klist_drivers of i2c_bus_type and
the device<->driver are bound
• i2c_driver.probe ( i2c_client * )
– Store a reference to i2c_client* for future use
– Initialize the device