i2c_dev
驱动注册
static int __init i2c_dev_init(void){
register_chrdev_region
}
i2cdev_attach_adapter
i2c-dev.c的核心
static const struct file_operations i2cdev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = i2cdev_read,
.write = i2cdev_write,
.unlocked_ioctl = i2cdev_ioctl,
.compat_ioctl = compat_i2cdev_ioctl,
.open = i2cdev_open,
.release = i2cdev_release,
};
i2cdev_open
adap = i2c_get_adapter(minor);//根据次设备号找到i2c_adapter
client = kzalloc(sizeof(*client),GFP_KERNEL);//分配i2c_client
client->adapter = adap;
file-> private_data = client; //client和adapter建立联系,作为文件私有暂存
i2cdev_ioctl
client = file-> private_data;
client->addr = arg;
i2c_ioctl_rdwr();
i2c_transfer();
i2cdev_ioctl_smbus();
i2c_smbus_xfer();
smbus:系统管理总线
master_xfer:i2c传输,传输一个或多个i2c_msg
i2c_adapter核心是i2c_algorithm
i2c_algorithm核心是master_xfer,实现取决于硬件
i2c_smbus_read_byte() //接收
i2c_smbus_write_byte() //发送
i2c_smbus_read_byte_data() //读取
i2c_smbus_write_byte_data() //写
i2c_driver
如果I2C设备节点的compatible属性跟of_match_table的某项兼容,则匹配成功
i2c_client.name跟某个of_match_table[i].compatible值相同,则匹配成功
i2c_driver跟i2c_client匹配成功后,就调用i2c_driver.probe函数。
i2c_client表示一个I2C设备
int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len);
i2c_driver
static struct i2c_driver xxxx_driver =
{
.driver =
{
.owner = THIS_MODULE,
.name = "xxxx",
},
.id_table = xxxx_idtable,
.probe = xxxx_probe,
}
driver_register
int driver_register(struct device_driver *drv)
{
ret = bus_add_driver(drv);//把drv驱动,注册到总线
}
int bus_add_driver(struct device_driver *drv)
{
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
}
driver_attach()
//try to bind driver to devices.
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
probe
static int probe(struct device *dev, struct device_driver *drv)
{
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;
}
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name);
}
参考:
https://blog.csdn.net/lxllinux/article/details/80902071
https://blog.csdn.net/thisway_diy/article/details/119906457
https://blog.csdn.net/thisway_diy/article/details/119906577