After completing the Platform_device addition, the I2C subsystem will perform the Platform_driver registration process.
Platform_driver registration by calling the initialization function I2c_adapter_s3c_init letter
Number to complete.
The I2c_adap_s3c_init () function body is as follows:
static int __init i2c_adap_s3c_init (void)
{return
platform_driver_register (&s3c24xx_i2c_driver);
}
Platform_driver_register (&s3c24xx_i2c_driver), will complete the Platform_bus bus registration Platform_driver type driver
S3c24xx_i2c_driver's work. S3c24xx_i2c_driver is as follows:
static struct Platform_driver S3c24xx_i2c_driver = {
. Probe = S3c24xx_i2c_probe,
. Remove = S3c24xx_ I2c_remove,
. id_table = s3c24xx_driver_ids,
. Driver = {
. Owner = this_module
. Name = "S3C-I2C",
. PM = s3c24xx_dev_pm_ops,
},
};
Id_table is initialized to S3c24xx_driver_ids:
static struct platform_device_id s3c24xx_driver_ids[] = {
. Name = ' S3C2410-I2C ',
. Driver_data = type_s3c2410,
}, {
. Name = ' S3C2440-I2C ',
. Driver_data = type_s3c2440,},
{},
};
Platform_driver will attempt to register the registered Platform_driver in the process of registering to the Platform_bus bus
Paired with all Platform_device that have been registered on the Platform_bus.
The related operations of the Platform_bus bus are as follows:
struct Bus_type platform_bus_type = {
. Name = "Platform",
. Dev_attrs = platform_dev_attrs,
. Match = Platform_match,
. uevent = platform_uevent,
. PM = &platform_dev_pm_ops,
};
The pairing process is implemented by calling the match method of the bus, that is, the Platform_match function. As follows:
static int Platform_match (struct device *dev struct device_driver) {*drv struct platform_device
= *pdev Form_device (dev);
struct Platform_driver *pdrv = To_platform_driver (DRV);
/* Attempt an of style match a
/if (Of_driver_match_device (Dev, DRV)) return
1;
/* Then try to match against the ID table
/if (pdrv->id_table) return
platform_match_id (pdrv->id_table, PD EV)!= NULL;
/* Fall-back to driver name match *
/return (strcmp (pdev->name, drv->name) = = 0);
You can see in the function that there are
if (pdrv->id_table) return
platform_match_id (pdrv->id_table, Pdev)!= NULL;
Related statements.
This is where the pairing is based on the name of Platfor_device and Platform_driver. But Platform_driver has several names.
You can choose to implement the pairing by Id_table. Executed here, previously registered to Platform_bus's Platform_device
-Type device s3c_devicei2c0 and the Platfor_drver drive s3c24xx_i2c_drive that is now just registered to the Platform_bus bus will
Achieve pairing success.
After a successful pairing, an attempt is made to probe
static int really_probe (struct device *dev, struct device_driver)
{
...
if (dev->bus->probe) {
ret = dev->bus->probe (dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe (dev);
if (ret)
goto probe_failed;
}
Have the above code know, successfully paired after the first call is the bus probe, if the bus is not initialized probe method will go
Call the probe in the drive, that is, the Platform_driver.drv->probe, and the Platform_bus itself does not initialize the probe method,
So the driver probe method is invoked here, and the driver probe is initialized during registration.
int Platform_driver_register (struct platform_driver *drv)
{
Drv->driver.bus = &platform_bus_type;
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;
Return Driver_register (&drv->driver);
}
Call function Platform_drv_probe directly, the function is as follows:
static int platform_drv_probe (struct device *_dev) {struct Platform_driver *drv
= To_platform_driver (_dev- >driver);
struct Platform_device *dev = To_platform_device (_dev);
return Drv->probe (dev);
}
The function works very simply by finding the Platform_driver driver that contains it by _dev->driver, and then
Call this driven probe method, the S3c24xx_i2c_probe function.
The functions of the probe function are as follows:
1. First create struct S3C24XX_I2C *i2c.
The initialization of I2C related data originates from S3c2_device_i2c0.dev.platdata.
2. Algo method by I2c->adap.algo = &s3c24xx_i2c_algorithm; initialization.
Called to the S3c24xx_i2c_algorithm function when the write system is called.
3.init_waitqueue_head (&i2c->wait); Initialize a wait queue
4.s3c24xx_i2c_init (I2C) initialization I2C controller, mainly to s3c24xx I2C control
Registers to perform some operations, such as configuring the S3C2440I/O function, setting the address from the machine, and
Set I2C clock frequency and other related operations. setting of clock frequency see Bowen.
5.REQUEST_IRQ (I2C->IRQ, S3C24XX_I2C_IRQ, irqf_disabled,
Dev_name (&pdev->dev), I2C);
Application interrupt, the kernel of the I2C read and write is through the interrupt to implement, specifically later analysis
6.i2c_add_numbered_adapter (&I2C->ADAP); finally registers a I2C with the system adapter
Here you need to focus on the 2nd, 5, 6 points.
The following 6th is analyzed first. 2nd, 5 to wait until the back of the read and write At24c02 time to analyze.