I2C设备驱动框架
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/of_device.h>
struct foobar_i2c_device_data {
struct i2c_client *client;
struct i2c_adapter *adap;
};
static int foobar_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct i2c_adapter *adap = client->adapter;
struct foobar_i2c_device_data *device;
dev_info(&client->dev, "probe\n");
device = devm_kzalloc(&client->dev, sizeof(*device), GFP_KERNEL);
if (!device)
return -ENOMEM;
device->client = client;
device->adap = adap;
dev_info(&client->dev, "addr:%x\n", client->addr);
i2c_set_clientdata(client, device);
return 0;
}
static int foobar_i2c_remove(struct i2c_client *client)
{
struct foobar_i2c_device_data *device = i2c_get_clientdata(client);
return 0;
}
static const struct of_device_id foobar_of_match[] = {
{
.compatible ="dummy,foobar-device"
},
{
}
};
MODULE_DEVICE_TABLE(of, foobar_of_match);
const struct i2c_device_id foobar_id[] = {
{
.name = "foobar",
},
{
}
};
static struct i2c_driver foobar_driver = {
.driver = {
.name = "foobar",
.of_match_table = of_match_ptr(foobar_of_match),
},
.probe = foobar_i2c_probe,
.remove = foobar_i2c_remove,
.id_table = foobar_id,
};
module_i2c_driver(foobar_driver);
MODULE_LICENSE("GPL");
I2C设备驱动框架本身比较简单,重要的是相对的子系统驱动
I2C设备的设备树有点特别的地方,在probe的参数里的client里的addr在设备树里设置reg属性,
设置了REG属性之后,在ADAPTER驱动PROBE的时候会自动填充client,如下图:
i2c3:i2c@e1800000 {
compatible = "s5pv210,i2c-adapter";
#address-cells = <1>;
#size-cells = <1>;
mode = "i2c";
reg = <0xe1800000 0x10>;
foobar@0x46 {
compatible = "dummy,foobar-device";
reg = <0x46>;
};
};