The functions associated with the I²C subsystem that are first executed when the Linux kernel is booted should be the I2c_init () function in the driver/i2c/i2c-core.c file.
1 static int __init i2c_init (void " 2 { 5 retval = Bus_register (&i2c_bus_type); 9 I2c_adapter_compat_class = Class_compat_register ( " i2c-adapter " 15 retval = i2c_add_driver (&dummy_driver);
18 return 0 27 }
1.bus_register (&i2c_bus_type) registered I²c bus
struct bus_type i2c_bus_type = {. Name "i²c",. Match = I2c_device_match,.probe = I2c_device_probe,.remove = i2c_device_remove,.shutdown = I2c_device_ shutdown,.pm = &I2c_device_pm_ops,};
This function will create the I²C subdirectory under the/sys/bus directory and create the devices and drivers two directories under the I²c subdirectory, and the devices and drivers registered to the I²C bus will be placed in both directories.
2.class_compat_register ("I2c-adapter") create I2c-adapter subclass directory in/sys/class/directory
3.i2c_add_driver (&dummy_driver) registers the driver on I2c-bus, which is created in the/sys/bus/i2c/drivers directory after the successful execution of the function. Driver.name = "Dummy" is the name of the directory.
Static struct i2c_driver dummy_driver = { . driver.name "dummy", . Probe = Dummy_probe, . Remove = dummy_remove, . id_table = dummy_id,};
Before analyzing this function, look at the I2c_bus_type bus-device-drive model.
struct i2c_client *i2c_new_device (struct i2c_adapter *adap, struct i2c_board_info const *info) and
The int i2c_add_adapter (struct i2c_adapter *adapter) registers i2c_client and I2c_adapter with I2c_bus_type. Two different devices are differentiated by dev->type,
struct device_type i2c_adapter_type = { . Groups = i2c_adapter_attr_groups, . Release = i2c_adapter_dev_release,}; Static struct device_type i2c_client_type = { . Groups = i2c_dev_attr_groups, . Uevent = i2c_device_uevent, . Release = i2c_client_dev_release,};
The static inline int i2c_add_driver (struct i2c_driver *driver) registers i2c_driver with I2c_bus_type.
i2c_add_driver (&dummy_driver); --> I2c_register_driver (this_module, driver); -->&dummy_driver->driver.bus = &i2c_bus_type; -->res = Driver_register (& (&dummy_driver)->driver); // registers the driver with the I2c_bust_type -->i2c_for_each_dev (& dummy_driver, __process_new_driver); // traverse a device on the I2c_bus_type bus -->bus _for_each_dev (&i2c_bus_type, NULL, &dummy_driver, __process_new_driver); // call dummy_driver for the found device and __process_ New_driver function -->__process_new_driver (dev, &dummy_driver);
The __process_new_driver function is not executed because the device is not registered on the I2c_bus_type bus because I2c_add_driver (&dummy_driver) is executing.
But the following is an analysis of the execution of the __process_new_driver function, the function eventually called the I2c_detect function to detect the existence of the device.
__process_new_driver (dev,&dummy_driver) --if (dev->type! = &i2c_adapter_type ) return0; // determine if a device of type I2c_adapter_type continues execution --I2c_do_add_adapter (&dummy_driver, To_i2c_adapter (dev)) ; -->i2c_detect (ADAP, &dummy_driver); //
Static intI2c_detect (structI2c_adapter *adapter,structI2c_driver *driver)-intadap_id = i2c_adapter_id (adapter);//gets the serial number of the adapter, which is the first of several i²c controllers of the processor-ConstUnsigned Short*address_list = driver->address_list;//get an array of addresses from an i²c device-if(! (adapter->class& driver->class))return 0;//type matches before continuing execution-structI2c_client *temp_client = Kzalloc (sizeof(structi2c_client), Gfp_kernel);//Assigning i2c_client Structures-->temp_client->adapter =adapter; - for(i =0; Address_list[i]! = i2c_client_end; i + =1)//traverse the I²c address in the Address_list-->TEMP_CLIENT->ADDR = Address_list[i];//set from address to i2c_client structure-->i2c_detect_address (temp_client, driver);//detects if the device that corresponds to the slave address exists
Static intI2c_detect_address (structI2c_client *temp_client,structI2c_driver *driver)-intaddr = temp_client->addr; -->i2c_check_addr_validity (addr);//Detecting Address validity-->i2c_check_addr_busy (adapter, addr);//detects if the device is in use and cannot have two identical address devices on the same physical I2cbus-->i2c_default_probe (adapter, addr);//detects if there is a device response on the i²c physical bus-structI2c_board_info info.addr=temp_client->Addr-->driver->detect (Temp_client, &info);//call I2c_driver's detect function to detect the device and assign the value by Info.type-structI2c_client *client = I2c_new_device (adapter, &info);//creating I2c_client devices on the I2b_bus_type bus-->list_add_tail (&client->detected, &driver->clients);//When the device is created, the i2c_client is linked to the I2c_driver list
I²c Drive Frame (ii)