I2C device and driver association

  
 

In LinuxOS
, there are two types of driver loading: automatic loading at kernel startup and manual loading by user; hardware devices can also be added to the system in two ways: in system startup Hot plugging before and during system operation. Below, we take the I2C controller in the at91 processor under the arm architecture as an example to introduce how the hardware devices and related drivers are bound and loosened.

1. Platform driver registration process

1.1 at91_i2c_init() function

In the file drivers/i2c/busses/i2c-at91.c, the structure struct platform_driver is defined. It is initialized and declared by using the module_init() macro, which calls the at91_i2c_init() function when the module is loaded into the kernel. In this function, the platform_driver_register() function is called to complete the registration.


static struct platform_driver at91_i2c_driver = {

.probe = at91_i2c_probe,

.remove = __devexit_p(at91_i2c_remove),

. Suspend = at91_i2c_suspend,

.resume = at91_i2c_resume,

.driver = {

.name = "at91_i2c",

.owner = THIS_MODULE,

},

};


static int __init at91_i2c_init(void)

{

return platform_driver_register (&at91_i2c_driver);

}

1.2 platform_driver_register() function

In the file drivers/base/platform.c, the platform_driver_register() function is implemented and exported. So that functions in other modules can call this function. After completing the simple wrapper, it calls the driver_register() function to complete the transition from the platform implementation to the Linux kernel implementation.

Here, we need to pay attention to the platform_match() and platform_drv_probe() functions. The platform_match() function determines the association of the driver with the device, and the platform_drv_probe() function is called in the function described later.

//Comparing the name in the driver information with the name in the device information

static int platform_match(struct device * dev, struct device_driver * drv)

{

struct platform_device *pdev = container_of(dev, struct platform_device, dev);


return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);

}


struct bus_type platform_bus_type = {

.name = "platform",

.dev_attrs = platform_dev_attrs,

.match = platform_match,

.uevent = platform_uevent,

.suspend = platform_suspend,

.suspend_late = platform_suspend_late,

.resume_early = platform_resume_early,

.resume = platform_resume,

};

EXPORT_SYMBOL_GPL(platform_bus_type);


/**

* platform_driver_register

* @drv: platform driver structure

*/

int platform_driver_register(struct platform_driver *drv)< Br>

{

drv->driver.bus = &platform_bus_type;

//in the really_probe function Callback to the platform_drv_probe function

if (drv->probe)

drv->driver.probe = platform_drv_probe;

if (drv->remove)

drv->driver.remove = platform_drv_remove;

if (drv->shutdown)

drv->driver.shutdown = platform_drv_shutdown;

If (drv->suspend)

drv->driver.suspend = platform_drv_suspend;

if (drv->resume)

drv->driver. Resume = platform_drv_resume;

return driver_register(&drv->driver);

}

EXPORT_SYMBOL_GPL(platform_driver_register);


1.3 driver_register() function

In the file drivers/base/driver.c, the driver_register() function is implemented. In this function, the klist_device and unloaded fields in the structure struct device_driver are initialized. Through the klist_device field, the device linked list supported by the driver can be saved, and the synchronization between the threads is completed through the “completed” interface mechanism. Detailed information on the linked list and the “Complete” interface can be found in [1]. Returns the result of running the bus_add_driver() function.


/**

* driver_register - register driver with bus

* @drv: driver to register

*

* We pass off most of the work to the bus_add_driver() call,

* since most of the things we have to do deal with the bus

* structures.

*

* The one interesting aspect is that we setup @drv->unloaded

* as a completion that gets complete when the driver reference

* Count reaches 0.

*/

int driver_register(struct device_driver * drv)

{

if ((drv->bus-> Probe && drv->probe)

Copyright © Windows knowledge All Rights Reserved