My philosophy: Simple and practical can be, do not engage in a pile of source code out, the results show people do not know how to use, Look at me:
1, in arch/arm/mach-xxx/own platform file to add I2C information, beauty its name Yue: i2c_board_info
For example:
static struct I2c_board_info __initdata xxxi2c_board_info[] = {
{
I2c_board_info ("Abcd1", 0x20),/* string to match the back, 0x20 from the device address * *
. Platform_data = 0,
},
{
I2c_board_info ("Abcd2", 0x21),
. Platform_data = 0,
},
};
Then call I2c_register_board_info (1, Xxxi2c_board_info, Array_size (Xxxi2c_board_info));
The first argument is 0 or 1, and I don't know:-(.
2, in another device driver file, such as you put into the/driver/char under the character device, generally module_init (Func_init ()) Form, then call I2c_add_driver () can, there are several to define:
static const struct I2C_DEVICE_ID xxx_led_id[] = {
{"ABCD1", 0},/* The name must match the Board_info to invoke the probe function * *
{"Abcd2", 0},
{ }
};
Module_device_table (I2C, xxx_led_id);
static struct I2c_driver Xxx_led_driver = {
. Driver = {
. Name = "Yourname", * * This name does not need to be matched with another * *
. Owner = This_module,
},
. Probe = Xxx_led_probe,
. remove = Xxx_remove,
. id_table = xxx_led_id,
};
See, struct i2c_device_id inside the string and i2c_board_info inside the match, Xxx_led_probe will not call.
If you don't want to use the same probe, write a struct i2c_device_id and struct i2c_driver
What do you know about the process and what each structure is for?
-----------------------Legacy Way -------NewStyle Way ----------------------------------- ------------------------
recently saw the Vedon drive video of the I2C part, summed up the relevant knowledge, share to everyone. There are two ways to write the I2C device driver in the kernel, one is the Legacy Way, the other is the NewStyle method. Vedon video and Song Baohua books are all about legacy, but in the new version of the kernel, the legacy I2C device driver has not been compiled because several major kernel functions have ceased to exist, that is, the kernel no longer supports the legacy device driver for the system. Below explains the NewStyle mode of I2C device driver.
< a > define and populate I2c_driver:
staticconst struct i2c_device_id at24c08b_id[] = {{"at24c08b", 0},//The I2c_driver supported i2c_client {}}; Module_device_table (i2c,at24c08b_id); /* Define and populate I2c_driver: *probe device probe function, I2c_add_driver () will be invoked *remove device unload function;/staticstruct i2c_driver at24c08b_driver = { . driver= {. Name= "at24c08b",. Owner = This_module,. probe= at24c08b_probe,. Remove = __devexit_p (At24c08b_remove),. id_table= at24c08b_id,};
< two > Module initialization function
Staticint __init at24c08b_init (void) {returni2c_add_driver (&at24c08b_driver); }
Analysis I2c_add_driver ():
i2c_register_driver () driver-> driver.bus= &i2c_bus_type;//Set the bus type of the I2c_driver driver_ Register ()//The function ends with the call to probe () function &NBSP ; I2c_for_each_dev (driver,__process_new_driver //For each existing i2c_adapter, call __process_new_driver () function & nbsp I2c_do_add_adapter () i2c_detect (Adap,driver); //Our i2c_driver did not set the Address_list and Detect () function, So I came back here. &nbsP; address_list = driver->address_list; if (!driver->detect | |!address_list) return0;
Analysis Driver_register ():
driver_find ()//i2c_driver has been registered bus_add_driver ()//Will i2c_ Driver hook up to I2C bus I2c_bus_type driver_attach () //For every I2C device on the I2C bus i2c_client will invoke __driver_attach, where Dev is i2c_client,drv i2c_driver bus_for_each_dev (Drv->bus,NULL, DRV, __driver_ Attach); driver_match_ Device (Drv,dev) //calls the match function of the I2C bus I2c_bus_type returndrv->bus->match? Drv->bus->match (Dev, DRV): 1; &nbsP; i2c_device_match () //If I2c_client's name and I2C_DEVICE_ID's name are the same, then the match succeeds before calling probe () &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;I2C_MATCH_ID (driver->id_table,client) driver_probe_device ( ) really_probe () //calls the probe function of the I2C bus I2c_bus_type &Nbsp; dev->bus->probe (Dev); i2c_device_probe () //Call to I2c_driver Probe () function & nbsp; driver->probe (client, i2c_match_id (driver- >id_table, client)
The I2C bus i2c_bus_type is defined as follows:
Structbus_type I2c_bus_type = {. Name = "I2C",. Match =i2c_device_match,. Probe =i2c_devic E_probe,. Remove =i2c_device_remove,. Shutdown =i2c_device_shutdown, ...};
< three > registered I2C equipment Related information
For the NewStyle approach, you need to register the I2c_board_info with the I2c_register_board_info () function to provide information about I2C devices to the kernel.
Add the following code to the ARCH/ARM/MACH-S3C2440/MACH-MINI2440.C:
/*I2C Equipment at24c08b Information * * staticstruct i2c_board_info i2c_devices[] __initdata = {{I2c_board_info ("at24c08b", 0x50),}, 0X50 is the at24c08b device address}; Staticvoid __init mini2440_machine_init (void) {... i2c_register_board_info (0,i2c_devices,array_size (i2c_devices)); }
Analysis I2c_register_board_info ():
Structi2c_devinfo *devinfo;//defines a i2c_devinfo devinfo->board_info= *info;//save I2c_board_info//Will I2 C_devinfo hanging on the chain table __i2c_board_list on List_add_tail (&devinfo->list,&__i2c_board_list);
Search __i2c_board_list know:
This function is called in I2c_add_numbered_adapter ()//i2c-s3c2410.c to register a i2c_adapter i2c_add_adapter () i2c_register_adapter () i2c_scan_static_board_info () list_for_each_entry (devinfo,&__i2c_board_list, list) //using I2c_adapter and I2c_board_info constructs i2c_client &NBSP;&N bsp; if (Devinfo->busnum = = Adapter->nr &&!i2c_new_device (Adapter,&devinfo->board _info)) & nbSp; structi2c_client *client; client->adapter= adap;//Set I2c_client adapter client->addr= info->addr;//Set Device address ...//continue to set i2c_client device_register ()//Connect I2C device I2c_client to the I2C bus
Analysis Device_register ():
Device_add () Bus_add_device ()//hook up the device on the bus, and for I2C, the i2c_client is attached to I2c_bus_type Klist_add_ta Il (&dev->p->knode_bus,&bus->p->klist_devices);
PS: This set of analysis is applicable to all drivers that conform to the bus device driver model, such as USB bus, platform bus, PCI bus, I2C bus, etc.
< four >i2c_driver probe () function
Normal registration of a character device, namely:
(1) Distribution equipment Number: Alloc_chrdev_region ()
(2) Structural file_operations
(3) Assigning settings to register Cdev:cdev_init (&cdev,&file_operations); Cdev_add ()
< five >file_operations read () and write () functions
(1) Read:
{/* Check whether the I2c_adapter supports read-byte functionality/* I2c_check_functionality (I2c_func_smbus_read_byte_data) i2c_smbus_read_byte_data ()/ /from EEPROM read a byte of Data copy_to_user ()//Copy to user space}
Not all I2C or SMBus adapters implement all the functionality on the I2C specification, so when you access the I2C adapter,
It is not entirely assumed that the adapter provides the functionality you need. A test adapter is required to provide
The method of the desired function.
For a list of constantly updated I2C adapter feature constants, refer to <linux/i2c.h>
I2C_FUNC_I2C Unformatted I2c-level Command
I2C_FUNC_10BIT_ADDR Processing 10-bit Address Extension
I2c_func_smbus_read_byte processing SMBUS read_byte command
I2c_func_smbus_write_byte processing SMBUS write_byte command
I2c_func_smbus_read_byte_data processing SMBUS read_byte_data command
I2c_func_smbus_write_byte_data processing SMBUS write_byte_data command
I2c_func_smbus_read_word_data processing SMBUS read_word_data command
I2c_func_smbus_write_word_data processing SMBUS write_word_data command
...
Analysis I2c_smbus_read_byte_data (i2c_smbus_byte_data):
I2c_smbus_xfer (I2c_smbus_byte_data) i2c_smbus_xfer_emulated (i2c_smbus_byte_data) Msg[1].len = 1; ...//setting read Data i2c_msg I2c_transfer ()///FINAL call to I2c_adapter//m set in I2C-S3C2410.C Aster_xfer () function Adap->algo->master_xfer ()
(2) Write:
{/* Check whether the I2c_adapter supports read-byte functionality//I2c_check_functionality () Copy_from_user ();//Get user-space data i2c_smbus_write_byte_data ()/ /write data to EEPROM}
Analysis I2c_smbus_write_byte_data (i2c_smbus_byte_data):
I2c_smbus_xfer (I2c_smbus_byte_data) i2c_smbus_xfer_emulated (i2c_smbus_byte_data) Msg[1].len = 2; ...//Set the Master_xfer () function of the i2c_msg i2c_transfer ()///Final call to the I2c_adapter//set in I2C-S3C2410.C when writing data Adap->algo->master_xfer ()
#######################################
In fact, this is not the latest way, the latest is the use of the structure of the device tree ...