I2C Subsystem In Linux-2.6.24

13,253 views

Published on

Published in: Education
3 Comments
26 Likes
Statistics
Notes
No Downloads
Views
Total views
13,253
On SlideShare
0
From Embeds
0
Number of Embeds
933
Actions
Shares
0
Downloads
0
Comments
3
Likes
26
Embeds 0
No embeds

No notes for slide

I2C Subsystem In Linux-2.6.24

  1. 1. I2C Subsystem In Linux 2.6.24 Author: Varun Mahajan <varunmahajan06@gmail.com>
  2. 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
  3. 3. Data Structures I2C Bus DeviceDriver Adapter Driver Client struct i2c_adapter struct i2c_driver struct i2c_clientstruct bus_type nr /*bus no*/ (*probe) (i2c_client *) addr /*device address*/ (*remove) (i2c_client *) /*algorithm to access the bus*/ *adapter*name = “i2c” *algo (*shutdown) (i2c_client *) *driver (*suspend) (i2c_client*, mesg) driver_name(*match) (device*, device_driver*) (*client_register) (i2c_client*) (*resume) (i2c_client *) irq (*client_unregister) (i2c_client*)(*probe) (device *)(*remove) (device *) /*list of clients*/ struct device list_head clients struct device_driver(*shutdown) (device *)(*suspend) (device *, mesg)(*resume) (device *) *parent *name *driver struct device *bus *busklist_devicesklist_drivers kobj /*driver/platform specific*/ klist_devices *driver_data knode_bus *platform_data kobj knode_bus knode_driver
  4. 4. 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. 5. How to add an 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. 6. When a new I2C 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. 7. When a new I2C 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. 8. When a new I2C 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. 9. How to add an 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
  10. 10. Code Flow after i2c_add_driver()
  11. 11. Device ↔ Driver Binding • 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
  12. 12. struct i2c_client KXSD9_I2C_ADDRaddr /*device address*/*adapter*driver struct i2c_adapterdriver_nameirq BUS_NO nr /*bus no*/ struct device /*algorithm to access the bus*/ “KXSD9_driver” *algo *parent *driver (*client_register) (i2c_client*) *bus (*client_unregister) (i2c_client*) KXSD9_IRQ /*list of clients*/ /*driver/platform specific*/ list_head clients *driver_data *platform_data struct device kobj knode_bus MATCH knode_driver struct i2c_driver (*probe) (i2c_client *) (*remove) (i2c_client *) struct bus_type (*shutdown) (i2c_client *) (*suspend) (i2c_client*, mesg) *name = “i2c” (*resume) (i2c_client *) (*match) (device*, device_driver*) struct device_driver (*probe) (device *) (*remove) (device *) “KXSD9_driver” *name *bus (*shutdown) (device *) (*suspend) (device *, mesg) kobj (*resume) (device *) klist_devices klist_devices knode_bus klist_drivers
  13. 13. struct i2c_client KXSD9_I2C_ADDRaddr /*device address*/*adapter*driver struct i2c_adapterdriver_nameirq BUS_NO nr /*bus no*/ struct device /*algorithm to access the bus*/ “KXSD9_driver” *algo *parent *driver (*client_register) (i2c_client*) *bus (*client_unregister) (i2c_client*) KXSD9_IRQ /*list of clients*/ /*driver/platform specific*/ list_head clients *driver_data *platform_data struct device kobj knode_bus knode_driver struct i2c_driver (*probe) (i2c_client *) (*remove) (i2c_client *) struct bus_type (*shutdown) (i2c_client *) (*suspend) (i2c_client*, mesg) *name = “i2c” (*resume) (i2c_client *) (*match) (device*, device_driver*) struct device_driver (*probe) (device *) (*remove) (device *) *name “KXSD9_driver” *bus (*shutdown) (device *) (*suspend) (device *, mesg) kobj (*resume) (device *) klist_devices klist_devices knode_bus klist_drivers
  14. 14. References ● Linux Kernel 2.6.24 Source Code ● I2C Bus Specification version 2.1 January 2000
  15. 15. END…

×