慢慢欣赏linux I2C驱动

查看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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值