查看sys文件系统
ls /sys/bus/i2c/devices/
1-0068 i2c-0 i2c-1
cat 1-0068/name
m41t80
cat i2c-0/name
MPC adpter
ls /sys/devices/fe000,0000.soc85xx/fe000,3100.i2c/i2c-1/1-0068/rtc/rtc0
ls /sys/class/rtc -l
rtc0->../../devices/fe000,0000.soc85xx/fe000,3100.i2c/i2c-1/1-0068/rtc/rtc0
I2C初始化
static int __init i2c_init(void)
retval = bus_register(&i2c_bus_type);
/\
||
\/
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.suspend = i2c_device_suspend,
.resume = i2c_device_resume,
.pm = &i2c_device_pm_ops,
};
=>static int i2c_device_probe(struct device *dev)
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver = to_i2c_driver(dev->driver);
client->driver = driver;
status = driver->probe(client, i2c_match_id(driver->id_table, client));
I2C设备树描述
i2c@3100 {
#address-cells = <1>;
#size-cells = <0>;
cell-index = <1>;
compatible = "fsl-i2c";
reg = <0x118100 0x100>;
interrupts = <38 2>;
interrupt-parent = <&mpic>;
dfsrr;
eeprom@51 {
compatible = "at24,24c256";
reg = <0x51>;
};
eeprom@52 {
compatible = "at24,24c256";
reg = <0x52>;
};
rtc@68 {
compatible = "rstm,m41t80";
reg = <0x68>;
};
};
I2C控制器初始化
static int __init fsl_i2c_init(void)
rv = of_register_platform_driver(&mpc_i2c_driver);
/\
||
\/
/* Structure for a device driver */
static struct of_platform_driver mpc_i2c_driver = {
.match_table = mpc_i2c_of_match,
.probe = fsl_i2c_probe,
.remove = __devexit_p(fsl_i2c_remove),
.driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
},
};
=>static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_id *match)
struct mpc_i2c *i2c= kzalloc(sizeof(*i2c), GFP_KERNEL);
i2c->dev = &op->dev; /* for debug and error output */
i2c->base = of_iomap(op->node, 0);
i2c->irq = irq_of_parse_and_map(op->node, 0);
result = request_irq(i2c->irq, mpc_i2c_isr, IRQF_SHARED, "i2c-mpc", i2c);
dev_set_drvdata(&op->dev, i2c);
i2c->adap = mpc_ops;
i2c_set_adapdata(&i2c->adap, i2c);
/* i2c->adap.dev为i2c-1,op->dev为fe000,3100.i2c */
i2c->adap.dev.parent = &op->dev;
result = i2c_add_adapter(&i2c->adap);
=>int i2c_add_adapter(struct i2c_adapter *adapter)
res = idr_get_new_above(&i2c_adapter_idr, adapter, __i2c_first_dynamic_bus_num, &id);
adapter->nr = id;
return i2c_register_adapter(adapter);//控制器作为i2c设备注册
=>static int i2c_register_adapter(struct i2c_adapter *adap)
/* adap->dev为i2c-1 */
dev_set_name(&adap->dev, "i2c-%d", adap->nr);
adap->dev.bus = &i2c_bus_type;
adap->dev.type = &i2c_adapter_type;
/* adap->dev也就是i2c-1注册在了/sys/bus/i2c/devices/下 */
res = device_register(&adap->dev);
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
of_register_i2c_devices(&i2c->adap, op->node);//注册控制器下的设备
=>void of_register_i2c_devices(struct i2c_adapter *adap, struct device_node *adap_node)
for_each_child_of_node(adap_node, node)
addr = of_get_property(node, "reg", &len);
info.irq = irq_of_parse_and_map(node, 0);
info.addr = be32_to_cpup(addr);
dev_archdata_set_node(&dev_ad, node);
info.archdata = &dev_ad;
result = i2c_new_device(adap, &info);
=>struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
client->addr);
status = device_register(&client->dev);
=>int device_register(struct device *dev)
return device_add(dev);
=>int device_add(struct device *dev)
parent = get_device(dev->parent);
setup_parent(dev, parent);
/* dev是rtc0,parent是1-0068,而dev->kobj.parent是rtc */
=>void setup_parent(struct device *dev, struct device *parent)
struct kobject *kobj;
kobj = get_device_parent(dev, parent);
=>struct kobject *get_device_parent(struct device *dev, struct device *parent)
if (dev->class)
if (parent == NULL)
parent_kobj = virtual_device_parent(dev);
else if (parent->class)
return &parent->kobj;
else
parent_kobj = &parent->kobj;
/* or create a new class-directory at the parent device */
k = kobject_create();
k->kset = &dev->class->p->class_dirs;
/* k就是rtc,创建rtc目录 */
retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
if (kobj)
dev->kobj.parent = kobj;
/* 与setup_parent并列,创建rtc0,dev->kobj是rtc0,而dev->kobj.parent是rtc */
error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
I2C设备初始化
static int __init m41t80_rtc_init(void)
return i2c_add_driver(&m41t80_driver);
/\
||
\/
static struct i2c_driver m41t80_driver = {
.driver = {
.name = "rtc-m41t80",
},
.probe = m41t80_probe,
.remove = m41t80_remove,
.id_table = m41t80_id,
};
=>static inline int i2c_add_driver(struct i2c_driver *driver)
return i2c_register_driver(THIS_MODULE, driver);
=>int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
res = driver_register(&driver->driver);
INIT_LIST_HEAD(&driver->clients);
RTC初始化
static int m41t80_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct m41t80_data *clientdata = = kzalloc(sizeof(*clientdata), GFP_KERNEL);
struct rtc_device *rtc = rtc_device_register(client->name, &client->dev, &m41t80_rtc_ops, THIS_MODULE);
/\
||
\/
static struct rtc_class_ops m41t80_rtc_ops = {
.read_time = m41t80_rtc_read_time,
.set_time = m41t80_rtc_set_time,
.read_alarm = m41t80_rtc_read_alarm,
.set_alarm = m41t80_rtc_set_alarm,
.proc = m41t80_rtc_proc,
.ioctl = m41t80_rtc_ioctl,
};
=>struct rtc_device *rtc_device_register(const char *name, struct device *dev,
const struct rtc_class_ops *ops,
struct module *owner)
struct rtc_device *rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
rtc->id = id;
rtc->ops = ops;
rtc->owner = owner;
rtc->max_user_freq = 64;
/* rtc->dev是rtc0,dev是rtc,dev的parent是i2c-1 */
rtc->dev.parent = dev;
rtc->dev.class = rtc_class;
rtc->dev.release = rtc_device_release;
strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
dev_set_name(&rtc->dev, "rtc%d", id);
rtc_dev_prepare(rtc);
err = device_register(&rtc->dev);
rtc_dev_add_device(rtc);
rtc_sysfs_add_device(rtc);
rtc_proc_add_device(rtc);
rc = m41t80_sysfs_register(&client->dev);
一文看懂I2C协议
https://zhuanlan.zhihu.com/p/362287272
一文搞懂I2C通信
https://zhuanlan.zhihu.com/p/282949543