2.1 Define I2C driver
Before the definition of I2C driver, Define of_device_id and i2c_device_id.Of_device_id is used to call the device information defined in the DTS file in the device drive, which is defined as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | &i2c1 { #address-cells = <1>; #size-cells = <0>; clock-frequency = <400000>; mediatek,use-open-drain ext_disp@1d { compatible = "mediatek,ext_disp"; reg = <0x1d>; status = "okay"; }; }; static const struct of_device_id mt8193_i2c_mhl_id[]= { { .compatible = "mediatek,ext_disp" }, { } }; #define MT8193_DEVICE_NAME "mtk-multibridge" static const struct i2c_device_id mt8193_i2c_id[] = { {MT8193_DEVICE_NAME, 0}, {} }; struct i2c_driver mt8193_i2c_driver = { .probe = mt8193_i2c_probe, .remove = mt8193_i2c_remove, .driver = { .name = MT8193_DEVICE_NAME, .of_match_table = mt8193_i2c_mhl_id, }, .id_table = mt8193_i2c_id, }; |
Note: id_table indicates the device supported by the device drive.
2.2 Registered I2C driver
i2c_add_driver(&mt8193_i2c_driver);
When callIing i2c_add_driver to registered I2C driver,OS will traverse the I2C device.if the I2C driver support the traversal of the device, it will call the probe function of the device driver.
2.3 I2C communication
After registering a good I2C driver, you can exchange data by I2C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | int mt8193_i2c_write(u16 addr, u32 data) { struct i2c_client *client = mt8193_i2c_client; u8 buffer[8]; int ret = 0; struct i2c_msg msg = { /*.addr = client->addr & I2C_MASK_FLAG,*/ .addr = client->addr, .flags = 0, .len = (((addr >> 8) & 0xFF) >= 0x80)?5:6, .buf = buffer, }; if (((addr >> 8) & 0xFF) >= 0x80) { /* 8 bit : fast mode */ buffer[0] = (addr >> 8) & 0xFF; buffer[1] = (data >> 24) & 0xFF; buffer[2] = (data >> 16) & 0xFF; buffer[3] = (data >> 8) & 0xFF; buffer[4] = data & 0xFF; } else { /* 16 bit : noraml mode */ buffer[0] = (addr >> 8) & 0xFF; buffer[1] = addr & 0xFF; buffer[2] = (data >> 24) & 0xFF; buffer[3] = (data >> 16) & 0xFF; buffer[4] = (data >> 8) & 0xFF; buffer[5] = data & 0xFF; } ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) { pr_err("%s: send command error\n", __func__); return -EFAULT; } return 0; } int mt8193_i2c_read(u16 addr, u32 *data) { struct i2c_client *client = mt8193_i2c_client; struct i2c_msg msg[2]; u8 rxBuf[8] = {0}; u8 lens = 0; if (((addr >> 8) & 0xFF) >= 0x80) { /* 8 bit : fast mode */ rxBuf[0] = (addr >> 8) & 0xFF; lens = 1; } else { /* 16 bit : noraml mode */ rxBuf[0] = (addr >> 8) & 0xFF; rxBuf[1] = addr & 0xFF; lens = 2; } msg[0].flags = 0; msg[0].addr = client->addr; msg[0].buf = rxBuf; msg[0].len = lens; msg[1].flags = I2C_M_RD; msg[1].addr = client->addr; msg[1].buf = rxBuf; msg[1].len = 4; i2c_transfer(client->adapter, msg, 2); *data = (rxBuf[3] << 24) | (rxBuf[2] << 16) | (rxBuf[1] << 8) | (rxBuf[0]); /*LSBfisrt*/ return 0; } |
So Host can use the API (mt8193_i2c_read ,mt8193_i2c_write) to communicate with the slave.