Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

I2C Subsystem In Linux-2.6.24

16,217 views

Published on

Published in: Education
  • Login to see the comments

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…

×