At present, the hardware description of SoC development board under arm adopts devicetree file. After DTS is compiled into DTB by using the DTC program provided by Linux, the DTB is imported into the Linux kernel by u-boot. The Linux kernel reads the DTB, and then registers the resource of the device. The Linux kernel uses of_ The serial function API reads hardware resources. The specific instructions can be seen as follows:. DTS file is compiled to generate. DTB file according to the specific hardware configuration.Then you need to select the driver for the hardware in menuconfig kernel configuration. The probe function of the driver can be triggered only when the hardware driver matches the hardware name in DTSThe drivers of rtc-8564 and PCF8563 are compatible, both of which are PCF8563 drivers.Note: the following analysis is based on the 3.12.0 Linux kernel. Personal analysis inevitably has mistakes, please correct.struct i2c_ adapter struct module *owner;unsigned int class; /* classes to allow probing for */const struct i2c_algorithm *algo; /* the algorithm to access the bus */void *algo_data;/* data fields that are valid for all devices */struct rt_mutex bus_lock;int TImeout; /* in jiffies */int retries;struct device dev; /* the adapter device */int nr;char name[48];struct compleTIon dev_released;struct mutex userspace_clients_lock;struct list_head userspace_clients;struct i2c_bus_recovery_info *bus_recovery_info;;I2C bus controller data is attached to algo_ Data, such as xi2cps, S3C24XX_ i2cstruct device dev; Member indicates I2C_ Adapter is a hardware, corresponding to I2C controller on SOC. And I2C_ Algorithm is the underlying driver of the I2C controller.Similarly:struct i2c_ client unsigned short flags; /* div., see below */unsigned short addr; /* chip address - NOTE: 7bit *//* addresses are stored in the *//* _LOWER_ 7 bits */char name[I2C_NAME_SIZE];struct i2c_adapter *adapter; /* the adapter we sit on */struct i2c_driver *driver; /* and our access rouTInes */struct device dev; /* the device structure */int irq; /* irq issued by device */struct list_head detected;;struct i2c_ Client represents an I2C slave device mounted on the I2C bus. The data structure required by the device includesThe I2C master device struct I2C to which the I2C slave device is attached_ adapter *adapterThe I2C slave device driver struct I2C_ driver *driverAs a member variable commonly used by I2C slave devices, such as addr, name, etcThe I2C slave device driver's unique data is attached to dev - > driver_ Data, in I2C_ Set this struct member in the probe function in the driver. For example, EEPROM of EEPROM_ dataBidirectional linked list composed of all I2C slave devices: detectedStruct device dev indicates struct I2C_ Client represents a hardware, such as EEPROM chip or RTC chip, which is connected to I2C through I2C bus_ Adapter hardware.And I2C_ Driver is this I2C_ Client chip hardware driver.We usually define a private information structure for each I2C character device, and I2C_ The client is generally contained in this private information structure. Hackers who have seen ldr3 source code should be more clear.i2c_ Client attached to I2C_ Adapter, that is, the corresponding relationship between I2C device and I2C bus controller, an I2C_ The adapter can attach multiple I2C_ clienti2c_ Struct list of adapter_ head userspace_ clients; Structure members are linked lists of all clients.The latest version of Linux basically supports all current I2C adapter hardware and I2C slave devices, but engineers may face various situations: I2C_ Adapter and I2C_ Client writes the driver.The I2C core source code is located in drivers / I2C / I2C core. C. It does not depend on the interface function of the hardware platform. It is the link between I2C bus driver and device driver.Add / remove I2C_ adapterint i2c_ add_ adapter(struct i2c_adapter *adapter)//Call I2C_ register_ adapter()int i2c_ del_ adapter(struct i2c_adapter *adapter)Add / remove I2C_ driverint i2c_ register_ driver(struct module *owner, struct i2c_driver *driver)int i2c_ add_ driver(struct i2c_driver *driver)//Call I2C_ register_ drivervoid i2c_ del_ driver(struct i2c_driver *driver)Add / remove I2C_ clientstruct i2c_ client *i2c_ new_ device(struct i2c_adapter *adap, struct i2c_board_info const *info)void i2c_ unregister_ device(struct i2c_client *client)Note: I2C was used before version 2.6.30_ attach_ Client () and I2C_ detach_ Client() function. Then the attach is merged to I2C_ new_ Device, and detach is directly replaced by unregister. In fact, both functions call device internally_ Register () and device_ unregister()I2C transmission, transmission and receptionint i2c_ transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)int i2c_ master_ send(struct i2c_client *client,const char *buf ,int count)int i2c_ master_ recv(struct i2c_client *client, char *buf ,int count)i2c_ The transfer() function is used to exchange a set of messages between the I2C adapter and the I2C device_ master_ Send() function and I2C_ master_ I2C is called internally in the recv() function_ The transfer () function completes a write message and a read message respectively.i2c_ Transfer () itself cannot complete message interaction with hardware. It looks for I2C_ I2C corresponding to adapter_ Algorithm, to realize data transmission, I2C must be realized_ Master of algorithm_ Xfer(), which is related to the specific hardware, is completed by the manufacturer most of the time.i2c_ Transfer() by calling__ i2c_ Transfer() completes I2C communication:int __ i2c_ transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)unsigned long orig_jiffies;int ret, try;/* Retry automaTIcally on arbitration loss */orig_jiffies = jiffies;for (ret = 0, try = 0; try retries; try) ret = adap->algo->master_xfer(adap, msgs, num);if (ret != -EAGAIN)break;if (time_after(jiffies, orig_jiffies adap->timeout))break;return ret;It can be seen that retries is the number of retransmission attempts and timeout is the timeout.1. Loading and unloading of I2C adapterLoad: apply for hardware resources, such as IO address, interrupt number, and call I2C_ add_ Adapter load adapteri2c_ add_ I2C is called in the adapter_ register_ Adapter functionstatic int i2c_ register_ adapter(struct i2c_adapter *adap)... ...device_register(&adap->dev);//Complete the registration of the I2C master device adapter, that is, register the object and send ueventi2c_scan_static_board_info(adap);//Register i2c_client... ...static void i2c_ scan_ static_ board_ info(struct i2c_adapter *adapter)struct i2c_devinfo *devinfo;down_read(&__i2c_board_lock);list_for_each_entry(devinfo, &__i2c_board_list, list) if (devinfo->busnum == adapter->nr&& !i2c_new_device(adapter,&devinfo->board_info))dev_err(&adapter->dev,"Can't create device at 0x%02x",devinfo->board_info.addr);up_read(&__i2c_board_lock);i2c_ new_ Device calls device_ Register registers I2C slave devices.Then, when and how was the bi-directional circular linked list composed of I2C slave devices established?Take / arch / arm / Mach PXA / Saar. C as an examplestatic void __ init saar_ init(void)... ...saar_init_i2c();........static void __ init saar_ init_ i2c(void)pxa_set_i2c_info(NULL);i2c_register_board_info(0, ARRAY_AND_SIZE(saar_i2c_info));static struct i2c_ board_ info saar_ i2c_ info[] = [0] = .type = "da9034",.addr = 0x34,.platform_data = & saar_da9034_info,.irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)),,;/* drivers/i2c/i2c-boardinfo.c */int __ init i2c_ register_ board_ info(int busnum, structi2c_board_info const *info, unsigned len)... ...struct i2c_devinfo *devinfo;devinfo->board_info = *info;List_add_tail (& DEVINFO - > list, &_i2c_board_list); / / add I2C slave device to the linked list... ...Therefore, in the process of system initialization, we can use I2C_ register_ board_ Info, add the required I2C slave device to a device named__ i2c_ board_ List two-way circular linked list. After successfully loading the I2C master device adapt, the system will complete I2C for all I2C slave devices in this linked list one by one_ Registration of client.That is, I2C_ Client and I2C_ All adapters are made by I2C_ Core to maintain.In Xilinx Linux, the I2C slave device is passed to the kernel through DTS files, and the kernel is passed through zynq_ init_ The machine function registers all I2C slave devices, I2C_ client.In the device and driver management system of Linux, all non hot swappable devices are in init by default_ The machine function member is added to the bidirectional linked list of the corresponding maintenance equipment, including platform_ Device and other devices. When a specific device is driven through the driver_ When register is added to the corresponding bus, it goes back to traverse the bidirectional linked list of devices under the corresponding bus. When the driver matches the device, the probe function of the driver will be triggered.DT_ MACHINE_ START(XILINX_EP107, "Xilinx Zynq Platform").smp = smp_ ops(zynq_smp_ops),.map_ io = zynq_ map_ io,.init_ irq = zynq_ irq_ init,.init_ machine = zynq_ init_ machine,.init_ late = zynq_ init_ late,.init_ time = zynq_ timer_ init,.dt_ compat = zynq_ dt_ match,.reserve = zynq_ memory_ init,.restart = zynq_ system_ reset,MACHINE_ ENDYou can refer to the board initialization code of Mach zynqDismount: release hardware resources and call I2C_ del_ Adapter uninstall I2C adaptervoid i2c_ del_ adapter(struct i2c_adapter *adap)..........list_for_each_entry_safe(client, next, &adap->userspace_clients,detected) dev_dbg(&adap->dev, "Removing %s at 0x%x", client->name,client->addr);list_del(&client->detected);i2c_unregister_device(client);Uninstall all slave I2C devices..............device_unregister(&adap->dev);Uninstall the I2C adapter..............2. Write I2C bus communication method algorithmint (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);/* To determine what the adapter supports */u32 (*functionality) (struct i2c_adapter *);It mainly implements the above two functions.Most of the time, we need to define a XXX_ I2C structure, such as struct S3C24XX in drivers / I2C / busses / i2c-s3c2410. C_ i2cXXX_ The I2C structure contains struct I2C_ msg *msg; struct i2c_ adapter adap; void __ iomem *regs; etc.struct i2c_ MSG * MSG receives data from the user layer, sends it to the I2C bus, or reads data from the I2C bus to the user layer.In the probe function of the adapter:struct xi2cps *id;platform_ set_ drvdata(pdev, id);id->adap.dev.of_ node = pdev->dev.of_ node;id->adap.algo = (struct i2c_algorithm *) &xi2cps_ algo;id->adap.timeout = 0x1F;/* Default timeout value */id->adap.retries = 3;/* Default retry value. */id->adap.algo_ data = id;id->adap.dev.parent = &pdev->dev;In terms of hardware, the I2C main device has been integrated into the main chip. In terms of software, Linux also provides us with corresponding drivers, located in