Original article: Documentation/I2C/upgrading-clients
Translator: Guo shaobei
2010/05/10
Update I2C drivers to the new 2.6 Driver Model
========================================================== ==========
Note: the I2C driver here refers to the I2C client driver, for example, RTC, USB
Transceiver driver and so on.
Ben dooks <ben-linux@fluff.org>
Introduction
------------
This document describes how to upgrade the I2C client driver that already exists in Linux 2.6 From the old model to the new
.
Example of the old model driver
------------------------
Struct example_state {
Struct i2c_client client;
....
};
Static struct i2c_driver example_driver;
Static unsigned short ignore [] = {i2c_client_end };
Static unsigned short normal_addr [] = {our_addr, i2c_client_end };
I2c_client_insmod;
Static int example_attach (struct i2c_adapter * ADAP, int ADDR, int kind)
{
Struct example_state * State;
Struct device * Dev = & ADAP-> dev;/* to use for Dev _ reports */
Int ret;
State = kzarloc (sizeof (struct example_state), gfp_kernel );
If (State = NULL ){
Dev_err (Dev, "failed to create our State/N ");
Return-enomem;
}
Example-> client. ADDR = ADDR;
Example-> client. Flags = 0;
Example-> client. Adapter = ADAP;
I2c_set_clientdata (& State-> i2c_client, State );
Strlcpy (client-> i2c_client.name, "example", i2c_name_size );
Ret = i2c_attach_client (& State-> i2c_client );
If (Ret <0 ){
Dev_err (Dev, "failed to attach client/N ");
Kfree (State );
Return ret;
}
Dev = & State-> i2c_client.dev;
/* Rest of the initialisation goes here .*/
Dev_info (Dev, "example client created/N ");
Return 0;
}
Static int _ devexit example_detach (struct i2c_client * client)
{
Struct example_state * State = i2c_get_clientdata (client );
I2c_detach_client (client );
Kfree (State );
Return 0;
}
Static int example_attach_adapter (struct i2c_adapter * ADAP)
{
Return i2c_probe (ADAP, & addr_data, example_attach );
}
Static struct i2c_driver example_driver = {
. Driver = {
. Owner = this_module,
. Name = "example ",
},
. Attach_adapter = example_attach_adapter,
. Detach_client = _ devexit_p (example_detach ),
. Suspend = example_suspend,
. Resume = example_resume,
};
Update Client
-------------------
The new binding model checks the devices supported by its maintained linked list and the addresses of matched devices registered through code.
. This means that the. attach_adapter and. detach_adapter methods and addr_data methods in the driver are not deleted.
Use again, as shown below:
-Static struct i2c_driver example_driver;
-Static unsigned short ignore [] = {i2c_client_end };
-Static unsigned short normal_addr [] = {our_addr, i2c_client_end };
-I2c_client_insmod;
-Static int example_attach_adapter (struct i2c_adapter * ADAP)
-{
-Return i2c_probe (ADAP, & addr_data, example_attach );
-}
Static struct i2c_driver example_driver = {
-. Attach_adapter = example_attach_adapter,
-. Detach_client = _ devexit_p (example_detach ),
}
Add the probe and remove methods in i2c_driver as follows:
Static struct i2c_driver example_driver = {
+. Probe = example_probe,
+. Remove = _ devexit_p (example_remove ),
}
Modify the example_attach method: method name, and accept the new parameter (i2c_client) as follows:
-Static int example_attach (struct i2c_adapter * ADAP, int ADDR, int kind)
+ Static int example_probe (struct i2c_client * client,
+ Const struct i2c_device_id * ID)
Modify example_attach to example_probe. The probe function must be modified because the i2c_client has been
Create and use.
The following client fields has been created before the probe function is called, so the following client creates the code
Can be deleted:
-Example-> client. ADDR = ADDR;
-Example-> client. Flags = 0;
-Example-> client. Adapter = ADAP;
-
-Strlcpy (client-> i2c_client.name, "example", i2c_name_size );
I2c_set_clientdata is now:
-I2c_set_clientdata (& State-> client, State );
+ I2c_set_clientdata (client, State );
The call to i2c_attach_client () is no longer needed. If the probe function returns successfully, the driver will be automatically matched by the i2c-core
Configuration. The probe function is modified as follows:
-Ret = i2c_attach_client (& State-> i2c_client );
-If (Ret <0 ){
-Dev_err (Dev, "failed to attach client/N ");
-Kfree (State );
-Return ret;
-}
Delete the storage of the struct i2c_client domain from struct example_state.
I2c_client access parameters. When needed, we only need to store a pointer to i2c_client.
Struct example_state {
-Struct i2c_client client;
+ Struct i2c_client * client;
The new I2C client is as follows:
-Struct device * Dev = & ADAP-> dev;/* to use for Dev _ reports */
+ Struct device * Dev = & i2c_client-> dev;/* to use for Dev _ reports */
After the client is changed to attach, the driver no longer needs to register a new client data structure to the core
. As follows:
-Dev = & State-> i2c_client.dev;
In the probe function, make sure that the pointer to the client is saved in the new State:
Static int example_probe (struct i2c_client * i2c_client,
Const struct i2c_device_id * ID)
{
Struct example_state * State;
Struct device * Dev = & i2c_client-> dev;
Int ret;
State = kzarloc (sizeof (struct example_state), gfp_kernel );
If (State = NULL ){
Dev_err (Dev, "failed to create our State/N ");
Return-enomem;
}
+ State-> client = i2c_client;
Update the detach method, change example_detach to example_remove, and delete the i2c_detach_client ()
. You can also delete the returned variable because it is no longer required by the i2c-core function.
-Static int _ devexit example_detach (struct i2c_client * client)
+ Static int _ devexit example_remove (struct i2c_client * client)
{
Struct example_state * State = i2c_get_clientdata (client );
-I2c_detach_client (client );
Finally make sure we have a correct ID table for i2c-core and other utilities:
+ Struct i2c_device_id example_idtable [] = {
+ {"Example", 0 },
+ {}
+ };
+
+ Module_device_table (I2C, example_idtable );
Static struct i2c_driver example_driver = {
. Driver = {
. Owner = this_module,
. Name = "example ",
},
+. Id_table = example_ids,
Our driver now looks like this:
Struct example_state {
Struct i2c_client * client;
....
};
Static int example_probe (struct i2c_client * client,
Const struct i2c_device_id * ID)
{
Struct example_state * State;
Struct device * Dev = & client-> dev;
State = kzarloc (sizeof (struct example_state), gfp_kernel );
If (State = NULL ){
Dev_err (Dev, "failed to create our State/N ");
Return-enomem;
}
State-> client = client;
I2c_set_clientdata (client, State );
/* Rest of the initialisation goes here .*/
Dev_info (Dev, "example client created/N ");
Return 0;
}
Static int _ devexit example_remove (struct i2c_client * client)
{
Struct example_state * State = i2c_get_clientdata (client );
Kfree (State );
Return 0;
}
Static struct i2c_device_id example_idtable [] = {
{"Example", 0 },
{}
};
Module_device_table (I2C, example_idtable );
Static struct i2c_driver example_driver = {
. Driver = {
. Owner = this_module,
. Name = "example ",
},
. Id_table = example_idtable,
. Probe = example_probe,
. Remove = _ devexit_p (example_remove ),
. Suspend = example_suspend,
. Resume = example_resume,
};