嵌入式软件开发之------浅析linux驱动模型(四)device和driver

Linux代码版本:linux3.0

开发板环境: tiny4412

导读:前面先后分析了kset、kobject、bus和class,其中在bus和class的代码之中已经展示了对kobject和kset的应用,而bus和class中的一些结构体成员并没有涉及,在device和driver的注册过程中,将会展示一些成员的用途。

一、device结构体

linux中有各种各样的设备,不同的设备有不同的属性,但是这些设备又有一些共同点,所以device结构体所谓所有类型设备的基类,然后再根据不同的设备封装不同的结构体。下面将介绍device和platform_device结构体,然后分析一个i2c控制器的注册过程。

struct device {
	struct device		*parent;

	struct device_private	*p;

	struct kobject kobj;
	const char		*init_name; /* initial name of the device */
	const struct device_type *type;

	struct mutex		mutex;	/* mutex to synchronize calls to
					 * its driver.
					 */

	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this
					   device */
	void		*platform_data;	/* Platform specific data, device
					   core doesn't touch it */
	struct dev_pm_info	power;
	struct dev_power_domain	*pwr_domain;

#ifdef CONFIG_NUMA
	int		numa_node;	/* NUMA node this device is close to */
#endif
	u64		*dma_mask;	/* dma mask (if dma'able device) */
	u64		coherent_dma_mask;/* Like dma_mask, but for
					     alloc_coherent mappings as
					     not all hardware supports
					     64 bit addresses for consistent
					     allocations such descriptors. */

	struct device_dma_parameters *dma_parms;

	struct list_head	dma_pools;	/* dma pools (if dma'ble) */

	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
					     override */
#ifdef CONFIG_DMA_CMA
	struct cma	*cma_area;	/* contiguous memory area for dma
						allocation */
#endif
	/* arch specific additions */
	struct dev_archdata	archdata;

	struct device_node	*of_node; /* associated device tree node */

	dev_t			devt;	/* dev_t, creates the sysfs "dev" */

	spinlock_t		devres_lock;
	struct list_head	devres_head;

	struct klist_node	knode_class;
	struct class		*class;
	const struct attribute_group **groups;	/* optional groups */

	void	(*release)(struct device *dev);
};

struct device *parent;
device的父设备
struct device_private *p;
device的私有结构体
struct kobject kobj;
device封装的kobj,bus,kset和class最终也都封装了kobject
const char *init_name; /* initial name of the device */
device初始化的名字
const struct device_type *type;
device的类型如partitions、disks和mouse等
struct mutex mutex; /* mutex to synchronize calls to * its driver. */
信号量,操作结构体成员时使用
struct bus_type *bus; /* type of bus device is on */
挂接的bus类型
struct device_driver *driver; /* which driver has allocated thisdevice */
该device对应的driver
void *platform_data; /* Platform specific data, device core doesn't touch it */
platform使用的特殊数据
struct dev_pm_info power;
电源管理相关
struct dev_power_domain *pwr_domain;
电源管理相关
struct device_node *of_node; /* associated device tree node */
device tree相关的node
dev_t   devt; /* dev_t, creates the sysfs "dev" */
设备号
struct klist_node knode_class;
用于挂接在class的链表
struct class *class;
device所属的class
const struct attribute_group **groups; /* optional groups */
属性组,用于创建属性属性文件
void (*release)(struct device *dev);
释放device结构体的时候使用

 

struct platform_device {
	const char    * name;
	int    id;
	struct device	dev;
	u32    num_resources;
	struct resource	* resource;

	const struct platform_device_id	*id_entry;

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

 

const char * name:

设备名字

int id:

设备id号,只有一个此类设备的话设置-1,多个有同类设备在创建设备目录的时候会带上此id号

struct device dev:

封装的device结构体;

u32 num_resources;

所占用的resources的个数

struct resource * resource:

所占用的resource,如IORESOURCE_MEM和IORESOURCE_IRQ等

const struct platform_device_id *id_entry:

和驱动中的id_table相关,当通过驱动 id_table 匹配上时,将匹配到的id_table赋值给id_entry,暂时不知道实际用途

遇到的时候再分析

二、platform_device实例

虽然i2c本身也是一种总线,但是其也挂接在platform总线上。因为重点是platform_device的注册过程,所以对涉及i2c的一些细节不再分析(如硬件资源)。下面的代码还是原始在plat和mach中声明platform_device形式,device tree的形式等分析device tree的时候再详细看。

struct platform_device s3c_device_i2c3 = {
	.name		  = "s3c2440-i2c",
	.id		  = 3,
	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
	.resource	  = s3c_i2c_resource,
};
static struct platform_device *torbreck_devices[] __initdata = {
	&s5pv210_device_iis0,
	&s3c_device_cfcon,
	&s3c_device_hsmmc0,
	&s3c_device_hsmmc1,
	&s3c_device_hsmmc2,
	&s3c_device_hsmmc3,
	&s3c_device_i2c0,
	&s3c_device_i2c3,
	&s3c_device_i2c4,
	&s3c_device_rtc,
	&s3c_device_wdt,
};&s3c_device_i2c3,
	&s3c_device_i2c4,
	&s3c_device_rtc,
	&s3c_device_wdt,
};
static void __init torbreck_machine_init(void)
{
        .......
	platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices));
}	platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices));
}

 

将上面的过程简化 就是

 

 

int platform_device_register(struct platform_device *pdev)
{
	device_initialize(&pdev->dev);
    {
    	/**初始化 s3c_device_i2c3->dev->kobj.kset = devices_kset,还记得sys下的deivces目录吗
        devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);*/
        dev->kobj.kset = devices_kset;
        /*初始化 s3c_device_i2c3->dev->kobj->ktype = &device_ktype,device设备kobj类型为device_ktype,
        还记得 device_uevent_ops 中的filter 函数过判断此类型吗*/
        kobject_init(&dev->kobj, &device_ktype);
        INIT_LIST_HEAD(&dev->dma_pools);
        mutex_init(&dev->mutex);
        lockdep_set_novalidate_class(&dev->mutex);
        spin_lock_init(&dev->devres_lock);
        INIT_LIST_HEAD(&dev->devres_head);
        device_pm_init(dev);
        set_dev_node(dev, -1);
    }
	return platform_device_add(pdev);
           {
            	int i, ret = 0;

            	if (!pdev)
            		return -EINVAL;
                /*初始化s3c_device_i2c3->dev.parent 为 platform_bus,
                意味着device对应的目录会在 sys/devices/platform下*/
            	if (!pdev->dev.parent)
            		pdev->dev.parent = &platform_bus;
                /*挂接在platform总线上*/
            	pdev->dev.bus = &platform_bus_type;
                /*看结构体定义s3c_device_i2c3->id = 3,所以pdev->dev->kobj->name = "s3c2440-i2c.3"
                如果系统里只有一个此类设备,id初始化为 -1就行了*/
            	if (pdev->id != -1)
            		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
            	else
            		dev_set_name(&pdev->dev, "%s", pdev->name);
                /*下面就是将 s3c_device_i2c3.resource插入到 reourse tree,
                插入的时候会做冲突检查*/
            	for (i = 0; i < pdev->num_resources; i++) {
            		struct resource *p, *r = &pdev->resource[i];

            		if (r->name == NULL)
            			r->name = dev_name(&pdev->dev);

            		p = r->parent;
            		if (!p) {
            			if (resource_type(r) == IORESOURCE_MEM)
            				p = &iomem_resource;
            			else if (resource_type(r) == IORESOURCE_IO)
            				p = &ioport_resource;
            		}
                    /*插入到 resource tree的时候如果检查到 recourse 已被插入过,说明resource冲突,
                    一个硬件资源不能同时分给多个设备用,不然会出错*/
            		if (p && insert_resource(p, r)) {
            			printk(KERN_ERR
            			       "%s: failed to claim resource %d\n",
            			       dev_name(&pdev->dev), i);
            			ret = -EBUSY;
            			goto failed;
            		}
            	}

            	pr_debug("Registering platform device '%s'. Parent at %s\n",
            		 dev_name(&pdev->dev), dev_name(pdev->dev.parent));

            	ret = device_add(&pdev->dev);      
                    {
                    	struct device *parent = NULL;
                    	struct class_interface *class_intf;
                    	int error = -EINVAL;
                        /*增加设备引用计数*/
                    	dev = get_device(dev);
                    	if (!dev)
                    		goto done;

                    	if (!dev->p) {
                    		error = device_private_init(dev);
                    		if (error)
                    			goto done;
                    	}

                    	/*
                    	 * for statically allocated devices, which should all be converted
                    	 * some day, we need to initialize the name. We prevent reading back
                    	 * the name, and force the use of dev_name()
                    	 */
                         /*s3c_device_i2c3->dev->init_name未赋值,也就是为NULL*/
                    	if (dev->init_name) {
                    		dev_set_name(dev, "%s", dev->init_name);
                    		dev->init_name = NULL;
                    	}
                        /*s3c_device_i2c3->dev->name 定义时初始化为 "s3c2410-i2c"*/
                    	if (!dev_name(dev)) {
                    		error = -EINVAL;
                    		goto name_error;
                    	}

                    	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
                        /*前面初始化s3c_device_i2c3->dev->parent = &platform_bus*/
                    	parent = get_device(dev->parent);
                        /*device层面的parent已经建立,setup_parent要建立kobject 层面的关系*/
                    	setup_parent(dev, parent);
                        {
                        	struct kobject *kobj;
                            /*执行结果kobj = &parent->kobj*/
                        	kobj = get_device_parent(dev, parent);
                                   {
                                        /*s3c_device_i2c3->dev->class未初始化,所以为NULL,
                                        等后面分析device_creat的时候再详细分析此函数*/
                                    	if (dev->class) {
                                            ......
                                    	}

                                    	if (parent)
                                    		return &parent->kobj;
                                    	return NULL;
                                    }
                            /*赋值结果 s3c_device_i2c3->dev->kobj->parent =  platform_bus->kobj*/
                        	if (kobj)
                        		dev->kobj.parent = kobj;
                        }

                    	/* use parent numa_node */
                    	if (parent)
                    		set_dev_node(dev, dev_to_node(parent));

                    	/* first, register with generic layer. */
                    	/* we require the name to be set before, and pass NULL */
                        /*又看见kobject_add,在sys/devices/platform下创建s3c2440-i2c.3*/
                    	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
                    	if (error)
                    		goto Error;

                    	/* notify platform of device entry */
                        /*暂时不知道具体用途,代码中极少给platform_notify赋值*/
                    	if (platform_notify)
                    		platform_notify(dev);
                        /*在sys/devices/platform/s3c2440-i2c.3创建uevent文件*/
                    	error = device_create_file(dev, &uevent_attr);
                    	if (error)
                    		goto attrError;
                        /*此时s3c_device_i2c3->dev还没有设备号,所以执行不到,等到device_creat的时候再详细分析*/
                    	if (MAJOR(dev->devt)) {
                    		......
                    	}
                        /*在class下创建链接*/
                    	error = device_add_class_symlinks(dev);
                                {
                                	int error;
                                    /*s3c_device_i2c3->dev->class未赋值,也就是为NULL,在此返回*/
                                	if (!dev->class)
                                		return 0;
                                  
                                	......
                                }
                    	if (error)
                    		goto SymlinkError;
                        /*为s3c_device_i2c3->dev穿件属性文件*/
                    	error = device_add_attrs(dev);
                                {
                                	struct class *class = dev->class;
                                	const struct device_type *type = dev->type;
                                	int error;
                                    /*s3c_device_i2c3->dev->class未赋值,也就是为NULL,在此返回*/
                                	if (class) {
                                		......
                                	}
                                    /* s3c_device_i2c3->dev-type 未赋值,所以为NULL*/
                                	if (type) {
                                		......
                                	}
                                    /*s3c_device_i2c3->dev->groups也是未初始化的*/
                                	error = device_add_groups(dev, dev->groups);
                                	if (error)
                                		goto err_remove_type_groups;

                                	return 0;

                                 err_remove_type_groups:
                                	if (type)
                                		device_remove_groups(dev, type->groups);
                                 err_remove_class_bin_attrs:
                                	if (class)
                                		device_remove_bin_attributes(dev, class->dev_bin_attrs);
                                 err_remove_class_attrs:
                                	if (class)
                                		device_remove_attributes(dev, class->dev_attrs);

                                	return error;
                                }
                    	if (error)
                    		goto AttrsError;
                        /*将device挂接到bus上去,并创建一些属性文件*/
                    	error = bus_add_device(dev);
                                {
                                	struct bus_type *bus = bus_get(dev->bus);
                                	int error = 0;

                                	if (bus) {
                                		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                                		error = device_add_attrs(bus, dev);
                                                {
                                                	int error = 0;
                                                	int i;
                                                    /*结构体定义时就初始化为platform_bus_type->dev_attrs = platform_dev_attrs
                                                    platform_dev_attrs.name = "modalias",也就是会在/sys/devices/platform/s3c2440-i2c.3
                                                    创建一个modalias属性文件*/
                                                	if (!bus->dev_attrs)
                                                		return 0;

                                                	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
                                                		error = device_create_file(dev, &bus->dev_attrs[i]);
                                                		if (error) {
                                                			while (--i >= 0)
                                                				device_remove_file(dev, &bus->dev_attrs[i]);
                                                			break;
                                                		}
                                                	}
                                                	return error;
                                                }
                                		if (error)
                                			goto out_put;
                                        /*还记得cd /sys/bus//platform/devices 吗
                                         priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
                                         下面就是要在/sys/bus//platform/devices创建指向 /sys/devices/platform/s3c2440-i2c.3
                                         的链接,名字也为s3c2440-i2c.3*/
                                		error = sysfs_create_link(&bus->p->devices_kset->kobj,
                                						&dev->kobj, dev_name(dev));
                                		if (error)
                                			goto out_id;
                                        /*在/sys/devices/platform/s3c2440-i2c.3创建指向/sys/bus//platform/的链接,
                                        名字为subsystem*/
                                		error = sysfs_create_link(&dev->kobj,
                                				&dev->bus->p->subsys.kobj, "subsystem");
                                		if (error)
                                			goto out_subsys;
                                        /*将s3c_device_i2c3加入到platform_bus_type->p->klist_devices链表中*/
                                		klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
                                	}
                                	return 0;

                                out_subsys:
                                	sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
                                out_id:
                                	device_remove_attrs(bus, dev);
                                out_put:
                                	bus_put(dev->bus);
                                	return error;
                                }
                    	if (error)
                    		goto BusError;
                        /*电源管理相关,后面分析的电源管理机制的时候再详细分析*/
                    	error = dpm_sysfs_add(dev);
                    	if (error)
                    		goto DPMError;
                        /*电源管理相关,后面分析的电源管理机制的时候再详细分析*/
                    	device_pm_add(dev);
                        
                    	/* Notify clients of device addition.  This call must come
                    	 * after dpm_sysf_add() and before kobject_uevent().
                    	 */
                    	if (dev->bus)
                    		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                    					     BUS_NOTIFY_ADD_DEVICE, dev);

                    	kobject_uevent(&dev->kobj, KOBJ_ADD);
                        
                    	bus_probe_device(dev);
                        {
                        	struct bus_type *bus = dev->bus;
                        	int ret;
                            /*还记得赋值platform_bus_type->p->drivers_autoprobe = 1
                            跟/sys/bus/platform下的drivers_autoprobe文件吗,drivers_autoprobe被置1
                            则自动进行驱动匹配*/
                        	if (bus && bus->p->drivers_autoprobe) {
                        		ret = device_attach(dev);
                                    {
                                    	int ret = 0;

                                    	device_lock(dev);
                                        /*现在只是注册s3c_device_i2c3,还没有匹配驱动,所以 s3c_device_i2c3->dev->driver = NULL*/
                                    	if (dev->driver) {
                                    		if (klist_node_attached(&dev->p->knode_driver)) {
                                    			ret = 1;
                                    			goto out_unlock;
                                    		}
                                    		ret = device_bind_driver(dev);
                                                {
                                                	int ret;

                                                	ret = driver_sysfs_add(dev);
                                                	if (!ret)
                                                		driver_bound(dev);
                                                	return ret;
                                                }
                                    		if (ret == 0)
                                    			ret = 1;
                                    		else {
                                    			dev->driver = NULL;
                                    			ret = 0;
                                    		}
                                    	} else {
                                    		pm_runtime_get_noresume(dev);
                                            /*通过__device_attach函数逐个匹配platform_bus_type->p->klist_drivers成员
                                            也说明了device_drivver会挂接在platform_bus_type->p->klist_drivers*/
                                    		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
                                                {
                                                	struct klist_iter i;
                                                	struct device_driver *drv;
                                                	int error = 0;

                                                	if (!bus)
                                                		return -EINVAL;

                                                	klist_iter_init_node(&bus->p->klist_drivers, &i,
                                                			     start ? &start->p->knode_bus : NULL);
                                                	while ((drv = next_driver(&i)) && !error)
                                                		error = fn(drv, data);  //fn就是__device_attach
                                                                {
                                                                    struct device *dev = data;
                                                                    /*这就调用到传说中的match函数了,在此调用到的是platform_match,在此由于还未
                                                                    注册驱动,所以是匹配不到的*/
                                                                    if (!driver_match_device(drv, dev))
                                                                        {
                                                                            /*drv->bus->match就是platform_bus_type->match = platform_match*/
                                                                            return drv->bus->match ? drv->bus->match(dev, drv) : 1;
                                                                                   {
                                                                                        struct platform_device *pdev = to_platform_device(dev);
                                                                                        struct platform_driver *pdrv = to_platform_driver(drv);

                                                                                        /* Attempt an OF style match first */
                                                                                        /*先进行device tree风格的匹配,到device tree的时候再详细分析*/
                                                                                        if (of_driver_match_device(dev, drv))
                                                                                            return 1;

                                                                                        /* Then try to match against the id table */
                                                                                        /*再进行id_table形式的匹配,后面device_driver再详细分析id_table*/
                                                                                        if (pdrv->id_table)
                                                                                            return platform_match_id(pdrv->id_table, pdev) != NULL;

                                                                                        /* fall-back to driver name match */
                                                                                        /*这就是最原始的比较device和driver的名字*/
                                                                                        return (strcmp(pdev->name, drv->name) == 0);
                                                                                    }
                                                                        }
                                                                        return 0;
                                                                           /*如果匹配到驱动,最终会调用到注册driver中的probe函数
                                                                           后面注册driver的时候再详细分析*/
                                                                    return driver_probe_device(drv, dev); 
                                                                           
                                                                }
                                                	klist_iter_exit(&i);
                                                	return error;
                                                }
                                    		pm_runtime_put_sync(dev);
                                    	}
                                    out_unlock:
                                    	device_unlock(dev);
                                    	return ret;
                                    }
                        		WARN_ON(ret < 0);
                        	}
                        }
                        
                    	if (parent)
                            /*将s3c_device_i2c3加入platform_bus的子设备链表*/
                    		klist_add_tail(&dev->p->knode_parent,
                    			       &parent->p->klist_children);
                        /*将s3c_device_i2c3加入到class的设备链表中*/
                    	if (dev->class) {
                    		mutex_lock(&dev->class->p->class_mutex);
                    		/* tie the class to the device */
                    		klist_add_tail(&dev->knode_class,
                    			       &dev->class->p->klist_devices);
                            /*暂时还没弄清class_interface的具体用途*/
                    		/* notify any interfaces that the device is here */
                    		list_for_each_entry(class_intf,
                    				    &dev->class->p->class_interfaces, node)
                    			if (class_intf->add_dev)
                    				class_intf->add_dev(dev, class_intf);
                    		mutex_unlock(&dev->class->p->class_mutex);
                    	}
                    done:
                    	put_device(dev);
                    	return error;
                     DPMError:
                    	bus_remove_device(dev);
                     BusError:
                    	device_remove_attrs(dev);
                     AttrsError:
                    	device_remove_class_symlinks(dev);
                     SymlinkError:
                    	if (MAJOR(dev->devt))
                    		devtmpfs_delete_node(dev);
                    	if (MAJOR(dev->devt))
                    		device_remove_sys_dev_entry(dev);
                     devtattrError:
                    	if (MAJOR(dev->devt))
                    		device_remove_file(dev, &devt_attr);
                     ueventattrError:
                    	device_remove_file(dev, &uevent_attr);
                     attrError:
                    	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
                    	kobject_del(&dev->kobj);
                     Error:
                    	cleanup_device_parent(dev);
                    	if (parent)
                    		put_device(parent);
                    name_error:
                    	kfree(dev->p);
                    	dev->p = NULL;
                    	goto done;
                    }
            	if (ret == 0)
            		return ret;

             failed:
            	while (--i >= 0) {
            		struct resource *r = &pdev->resource[i];
            		unsigned long type = resource_type(r);

            		if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
            			release_resource(r);
            	}

            	return ret;
            }
}device_initialize(&pdev->dev);
    {
    	/**初始化 s3c_device_i2c3->dev->kobj.kset = devices_kset,还记得sys下的deivces目录吗
        devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);*/
        dev->kobj.kset = devices_kset;
        /*初始化 s3c_device_i2c3->dev->kobj->ktype = &device_ktype,device设备kobj类型为device_ktype,
        还记得 device_uevent_ops 中的filter 函数过判断此类型吗*/
        kobject_init(&dev->kobj, &device_ktype);
        INIT_LIST_HEAD(&dev->dma_pools);
        mutex_init(&dev->mutex);
        lockdep_set_novalidate_class(&dev->mutex);
        spin_lock_init(&dev->devres_lock);
        INIT_LIST_HEAD(&dev->devres_head);
        device_pm_init(dev);
        set_dev_node(dev, -1);
    }
	return platform_device_add(pdev);
           {
            	int i, ret = 0;

            	if (!pdev)
            		return -EINVAL;
                /*初始化s3c_device_i2c3->dev.parent 为 platform_bus,
                意味着device对应的目录会在 sys/devices/platform下*/
            	if (!pdev->dev.parent)
            		pdev->dev.parent = &platform_bus;
                /*挂接在platform总线上*/
            	pdev->dev.bus = &platform_bus_type;
                /*看结构体定义s3c_device_i2c3->id = 3,所以pdev->dev->kobj->name = "s3c2440-i2c.3"
                如果系统里只有一个此类设备,id初始化为 -1就行了*/
            	if (pdev->id != -1)
            		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
            	else
            		dev_set_name(&pdev->dev, "%s", pdev->name);
                /*下面就是将 s3c_device_i2c3.resource插入到 reourse tree,
                插入的时候会做冲突检查*/
            	for (i = 0; i < pdev->num_resources; i++) {
            		struct resource *p, *r = &pdev->resource[i];

            		if (r->name == NULL)
            			r->name = dev_name(&pdev->dev);

            		p = r->parent;
            		if (!p) {
            			if (resource_type(r) == IORESOURCE_MEM)
            				p = &iomem_resource;
            			else if (resource_type(r) == IORESOURCE_IO)
            				p = &ioport_resource;
            		}
                    /*插入到 resource tree的时候如果检查到 recourse 已被插入过,说明resource冲突,
                    一个硬件资源不能同时分给多个设备用,不然会出错*/
            		if (p && insert_resource(p, r)) {
            			printk(KERN_ERR
            			       "%s: failed to claim resource %d\n",
            			       dev_name(&pdev->dev), i);
            			ret = -EBUSY;
            			goto failed;
            		}
            	}

            	pr_debug("Registering platform device '%s'. Parent at %s\n",
            		 dev_name(&pdev->dev), dev_name(pdev->dev.parent));

            	ret = device_add(&pdev->dev);      
                    {
                    	struct device *parent = NULL;
                    	struct class_interface *class_intf;
                    	int error = -EINVAL;
                        /*增加设备引用计数*/
                    	dev = get_device(dev);
                    	if (!dev)
                    		goto done;

                    	if (!dev->p) {
                    		error = device_private_init(dev);
                    		if (error)
                    			goto done;
                    	}

                    	/*
                    	 * for statically allocated devices, which should all be converted
                    	 * some day, we need to initialize the name. We prevent reading back
                    	 * the name, and force the use of dev_name()
                    	 */
                         /*s3c_device_i2c3->dev->init_name未赋值,也就是为NULL*/
                    	if (dev->init_name) {
                    		dev_set_name(dev, "%s", dev->init_name);
                    		dev->init_name = NULL;
                    	}
                        /*s3c_device_i2c3->dev->name 定义时初始化为 "s3c2410-i2c"*/
                    	if (!dev_name(dev)) {
                    		error = -EINVAL;
                    		goto name_error;
                    	}

                    	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
                        /*前面初始化s3c_device_i2c3->dev->parent = &platform_bus*/
                    	parent = get_device(dev->parent);
                        /*device层面的parent已经建立,setup_parent要建立kobject 层面的关系*/
                    	setup_parent(dev, parent);
                        {
                        	struct kobject *kobj;
                            /*执行结果kobj = &parent->kobj*/
                        	kobj = get_device_parent(dev, parent);
                                   {
                                        /*s3c_device_i2c3->dev->class未初始化,所以为NULL,
                                        等后面分析device_creat的时候再详细分析此函数*/
                                    	if (dev->class) {
                                            ......
                                    	}

                                    	if (parent)
                                    		return &parent->kobj;
                                    	return NULL;
                                    }
                            /*赋值结果 s3c_device_i2c3->dev->kobj->parent =  platform_bus->kobj*/
                        	if (kobj)
                        		dev->kobj.parent = kobj;
                        }

                    	/* use parent numa_node */
                    	if (parent)
                    		set_dev_node(dev, dev_to_node(parent));

                    	/* first, register with generic layer. */
                    	/* we require the name to be set before, and pass NULL */
                        /*又看见kobject_add,在sys/devices/platform下创建s3c2440-i2c.3*/
                    	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
                    	if (error)
                    		goto Error;

                    	/* notify platform of device entry */
                        /*暂时不知道具体用途,代码中极少给platform_notify赋值*/
                    	if (platform_notify)
                    		platform_notify(dev);
                        /*在sys/devices/platform/s3c2440-i2c.3创建uevent文件*/
                    	error = device_create_file(dev, &uevent_attr);
                    	if (error)
                    		goto attrError;
                        /*此时s3c_device_i2c3->dev还没有设备号,所以执行不到,等到device_creat的时候再详细分析*/
                    	if (MAJOR(dev->devt)) {
                    		......
                    	}
                        /*在class下创建链接*/
                    	error = device_add_class_symlinks(dev);
                                {
                                	int error;
                                    /*s3c_device_i2c3->dev->class未赋值,也就是为NULL,在此返回*/
                                	if (!dev->class)
                                		return 0;
                                  
                                	......
                                }
                    	if (error)
                    		goto SymlinkError;
                        /*为s3c_device_i2c3->dev穿件属性文件*/
                    	error = device_add_attrs(dev);
                                {
                                	struct class *class = dev->class;
                                	const struct device_type *type = dev->type;
                                	int error;
                                    /*s3c_device_i2c3->dev->class未赋值,也就是为NULL,在此返回*/
                                	if (class) {
                                		......
                                	}
                                    /* s3c_device_i2c3->dev-type 未赋值,所以为NULL*/
                                	if (type) {
                                		......
                                	}
                                    /*s3c_device_i2c3->dev->groups也是未初始化的*/
                                	error = device_add_groups(dev, dev->groups);
                                	if (error)
                                		goto err_remove_type_groups;

                                	return 0;

                                 err_remove_type_groups:
                                	if (type)
                                		device_remove_groups(dev, type->groups);
                                 err_remove_class_bin_attrs:
                                	if (class)
                                		device_remove_bin_attributes(dev, class->dev_bin_attrs);
                                 err_remove_class_attrs:
                                	if (class)
                                		device_remove_attributes(dev, class->dev_attrs);

                                	return error;
                                }
                    	if (error)
                    		goto AttrsError;
                        /*将device挂接到bus上去,并创建一些属性文件*/
                    	error = bus_add_device(dev);
                                {
                                	struct bus_type *bus = bus_get(dev->bus);
                                	int error = 0;

                                	if (bus) {
                                		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                                		error = device_add_attrs(bus, dev);
                                                {
                                                	int error = 0;
                                                	int i;
                                                    /*结构体定义时就初始化为platform_bus_type->dev_attrs = platform_dev_attrs
                                                    platform_dev_attrs.name = "modalias",也就是会在/sys/devices/platform/s3c2440-i2c.3
                                                    创建一个modalias属性文件*/
                                                	if (!bus->dev_attrs)
                                                		return 0;

                                                	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
                                                		error = device_create_file(dev, &bus->dev_attrs[i]);
                                                		if (error) {
                                                			while (--i >= 0)
                                                				device_remove_file(dev, &bus->dev_attrs[i]);
                                                			break;
                                                		}
                                                	}
                                                	return error;
                                                }
                                		if (error)
                                			goto out_put;
                                        /*还记得cd /sys/bus//platform/devices 吗
                                         priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
                                         下面就是要在/sys/bus//platform/devices创建指向 /sys/devices/platform/s3c2440-i2c.3
                                         的链接,名字也为s3c2440-i2c.3*/
                                		error = sysfs_create_link(&bus->p->devices_kset->kobj,
                                						&dev->kobj, dev_name(dev));
                                		if (error)
                                			goto out_id;
                                        /*在/sys/devices/platform/s3c2440-i2c.3创建指向/sys/bus//platform/的链接,
                                        名字为subsystem*/
                                		error = sysfs_create_link(&dev->kobj,
                                				&dev->bus->p->subsys.kobj, "subsystem");
                                		if (error)
                                			goto out_subsys;
                                        /*将s3c_device_i2c3加入到platform_bus_type->p->klist_devices链表中*/
                                		klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
                                	}
                                	return 0;

                                out_subsys:
                                	sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
                                out_id:
                                	device_remove_attrs(bus, dev);
                                out_put:
                                	bus_put(dev->bus);
                                	return error;
                                }
                    	if (error)
                    		goto BusError;
                        /*电源管理相关,后面分析的电源管理机制的时候再详细分析*/
                    	error = dpm_sysfs_add(dev);
                    	if (error)
                    		goto DPMError;
                        /*电源管理相关,后面分析的电源管理机制的时候再详细分析*/
                    	device_pm_add(dev);
                        
                    	/* Notify clients of device addition.  This call must come
                    	 * after dpm_sysf_add() and before kobject_uevent().
                    	 */
                    	if (dev->bus)
                    		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                    					     BUS_NOTIFY_ADD_DEVICE, dev);

                    	kobject_uevent(&dev->kobj, KOBJ_ADD);
                        
                    	bus_probe_device(dev);
                        {
                        	struct bus_type *bus = dev->bus;
                        	int ret;
                            /*还记得赋值platform_bus_type->p->drivers_autoprobe = 1
                            跟/sys/bus/platform下的drivers_autoprobe文件吗,drivers_autoprobe被置1
                            则自动进行驱动匹配*/
                        	if (bus && bus->p->drivers_autoprobe) {
                        		ret = device_attach(dev);
                                    {
                                    	int ret = 0;

                                    	device_lock(dev);
                                        /*现在只是注册s3c_device_i2c3,还没有匹配驱动,所以 s3c_device_i2c3->dev->driver = NULL*/
                                    	if (dev->driver) {
                                    		if (klist_node_attached(&dev->p->knode_driver)) {
                                    			ret = 1;
                                    			goto out_unlock;
                                    		}
                                    		ret = device_bind_driver(dev);
                                                {
                                                	int ret;

                                                	ret = driver_sysfs_add(dev);
                                                	if (!ret)
                                                		driver_bound(dev);
                                                	return ret;
                                                }
                                    		if (ret == 0)
                                    			ret = 1;
                                    		else {
                                    			dev->driver = NULL;
                                    			ret = 0;
                                    		}
                                    	} else {
                                    		pm_runtime_get_noresume(dev);
                                            /*通过__device_attach函数逐个匹配platform_bus_type->p->klist_drivers成员
                                            也说明了device_drivver会挂接在platform_bus_type->p->klist_drivers*/
                                    		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
                                                {
                                                	struct klist_iter i;
                                                	struct device_driver *drv;
                                                	int error = 0;

                                                	if (!bus)
                                                		return -EINVAL;

                                                	klist_iter_init_node(&bus->p->klist_drivers, &i,
                                                			     start ? &start->p->knode_bus : NULL);
                                                	while ((drv = next_driver(&i)) && !error)
                                                		error = fn(drv, data);  //fn就是__device_attach
                                                                {
                                                                    struct device *dev = data;
                                                                    /*这就调用到传说中的match函数了,在此调用到的是platform_match,在此由于还未
                                                                    注册驱动,所以是匹配不到的*/
                                                                    if (!driver_match_device(drv, dev))
                                                                        {
                                                                            /*drv->bus->match就是platform_bus_type->match = platform_match*/
                                                                            return drv->bus->match ? drv->bus->match(dev, drv) : 1;
                                                                                   {
                                                                                        struct platform_device *pdev = to_platform_device(dev);
                                                                                        struct platform_driver *pdrv = to_platform_driver(drv);

                                                                                        /* Attempt an OF style match first */
                                                                                        /*先进行device tree风格的匹配,到device tree的时候再详细分析*/
                                                                                        if (of_driver_match_device(dev, drv))
                                                                                            return 1;

                                                                                        /* Then try to match against the id table */
                                                                                        /*再进行id_table形式的匹配,后面device_driver再详细分析id_table*/
                                                                                        if (pdrv->id_table)
                                                                                            return platform_match_id(pdrv->id_table, pdev) != NULL;

                                                                                        /* fall-back to driver name match */
                                                                                        /*这就是最原始的比较device和driver的名字*/
                                                                                        return (strcmp(pdev->name, drv->name) == 0);
                                                                                    }
                                                                        }
                                                                        return 0;
                                                                           /*如果匹配到驱动,最终会调用到注册driver中的probe函数
                                                                           后面注册driver的时候再详细分析*/
                                                                    return driver_probe_device(drv, dev); 
                                                                           
                                                                }
                                                	klist_iter_exit(&i);
                                                	return error;
                                                }
                                    		pm_runtime_put_sync(dev);
                                    	}
                                    out_unlock:
                                    	device_unlock(dev);
                                    	return ret;
                                    }
                        		WARN_ON(ret < 0);
                        	}
                        }
                        
                    	if (parent)
                            /*将s3c_device_i2c3加入platform_bus的子设备链表*/
                    		klist_add_tail(&dev->p->knode_parent,
                    			       &parent->p->klist_children);
                        /*将s3c_device_i2c3加入到class的设备链表中*/
                    	if (dev->class) {
                    		mutex_lock(&dev->class->p->class_mutex);
                    		/* tie the class to the device */
                    		klist_add_tail(&dev->knode_class,
                    			       &dev->class->p->klist_devices);
                            /*暂时还没弄清class_interface的具体用途*/
                    		/* notify any interfaces that the device is here */
                    		list_for_each_entry(class_intf,
                    				    &dev->class->p->class_interfaces, node)
                    			if (class_intf->add_dev)
                    				class_intf->add_dev(dev, class_intf);
                    		mutex_unlock(&dev->class->p->class_mutex);
                    	}
                    done:
                    	put_device(dev);
                    	return error;
                     DPMError:
                    	bus_remove_device(dev);
                     BusError:
                    	device_remove_attrs(dev);
                     AttrsError:
                    	device_remove_class_symlinks(dev);
                     SymlinkError:
                    	if (MAJOR(dev->devt))
                    		devtmpfs_delete_node(dev);
                    	if (MAJOR(dev->devt))
                    		device_remove_sys_dev_entry(dev);
                     devtattrError:
                    	if (MAJOR(dev->devt))
                    		device_remove_file(dev, &devt_attr);
                     ueventattrError:
                    	device_remove_file(dev, &uevent_attr);
                     attrError:
                    	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
                    	kobject_del(&dev->kobj);
                     Error:
                    	cleanup_device_parent(dev);
                    	if (parent)
                    		put_device(parent);
                    name_error:
                    	kfree(dev->p);
                    	dev->p = NULL;
                    	goto done;
                    }
            	if (ret == 0)
            		return ret;

             failed:
            	while (--i >= 0) {
            		struct resource *r = &pdev->resource[i];
            		unsigned long type = resource_type(r);

            		if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
            			release_resource(r);
            	}

            	return ret;
            }
}

从paltform_device注册可以 看出,实际没有做多少工作,还有好多工作没做,比如因class为NULL部分代码执行不到,以及因没有设备号也有一些工作没做。下面进入设备看下整个过程建立的目录、文件和链接。

1. 在sys/devices/platform下创建s3c2440-i2c.3

[root@FriendlyARM rtc0]# cd /sys/devices/platform/
[root@FriendlyARM platform]# ls
alarm                s3c2440-i2c.3        samsung-audio

        ......s3c2440-i2c.3        samsung-audio

        ......

2. 在sys/devices/platform/s3c2440-i2c.3创建uevent文件

[root@FriendlyARM platform]# cd s3c2440-i2c.3/
[root@FriendlyARM s3c2440-i2c.3]# ls
driver     i2c-3      modalias   power      subsystem  ueventuevent

3. 在/sys/devices/platform/s3c2440-i2c.3创建一个modalias属性文件

 

[root@FriendlyARM platform]# cd s3c2440-i2c.3/
[root@FriendlyARM s3c2440-i2c.3]# ls
driver     i2c-3      modalias   power      subsystem  ueventmodalias   power      subsystem  uevent

4. 在/sys/bus/platform/devices创建指向 /sys/devices/platform/s3c2440-i2c.3 的链接,名字也为s3c2440-i2c.3*/

[root@FriendlyARM s3c-i2c]# cd /sys/bus/platform/devices/
[root@FriendlyARM devices]# ls -l 

......
lrwxrwxrwx    1 root     root             0 Jan  1 13:18 s3c2440-i2c.3 -> ../../../devices/platform/s3c2440-i2c.3
......s3c2440-i2c.3 -> ../../../devices/platform/s3c2440-i2c.3
......

5. 在/sys/devices/platform/s3c2440-i2c.3创建指向/sys/bus/platform/的链接,名字为subsystem

[root@FriendlyARM s3c2440-i2c.3]# cd /sys/devices/platform/s3c2440-i2c.3
[root@FriendlyARM s3c2440-i2c.3]# ls
driver     i2c-3      modalias   power      subsystem  ueventsubsystem  uevent

对于uevent和modalias属性文件,可以通过其store和show函数看其功能,下面只展示一下modalias属性的定义

static struct device_attribute platform_dev_attrs[] = { 
        .attr = { 
        .name = “modalias”, 
        .mode = 0444
    },
.show = modalias_show,

};

除了一句打印,没有其它作用。

static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
    char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);


return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
}

三、platform_driver实例

上面是platform_device的实例,下面就分析platform_driver实例,看看实际的driver如何和device匹配的,上面是s3c_device_i2c3的注册,下面就分析其对应的s3c24xx_i2c_driver为例。

先看 platform_driver 结构体

struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
}; 

platform_driver比较简单,看名字也比较好理解,只关注
const struct platform_device_id *id_table;

驱动兼容的 device 列表,表明此驱动都可用于哪些device,总线的match会用到这个进行匹配

再看

struct device_driver {
	const char		*name;
	struct bus_type		*bus;

	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */

	const struct of_device_id	*of_match_table;

	int (*probe) (struct device *dev);
	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev, pm_message_t state);
	int (*resume) (struct device *dev);
	const struct attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};


const char *name;
驱动的name
struct bus_type *bus;
指向的bus
struct module *owner;
所属的模块,绝大多数情况为 THIS_MODULE,如果不将此驱动编译成模块则为NULL
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */

决定是否在/sys/bus/platform/drivers/s3c-i2c下生成 bind 和 ubind 文件
const struct of_device_id *of_match_table;
在总线的 match 函数中用于device tree形式的匹配
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct dev_pm_ops *pm;

电源管理相关
struct driver_private *p;

 

封装的私有结构体。还记得devce、class和bus_type中都有封装私有结构体吗

 

s3c24xx_i2c_driver实例

 
static struct platform_driver s3c24xx_i2c_driver = {
	.probe		= s3c24xx_i2c_probe,
	.remove		= s3c24xx_i2c_remove,
	.id_table	= s3c24xx_driver_ids,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= "s3c-i2c",
		.pm	= S3C24XX_DEV_PM_OPS,
	},
};

看兼容的设备列表

static struct platform_device_id s3c24xx_driver_ids[] = {
	{
		.name		= "s3c2410-i2c",
		.driver_data	= TYPE_S3C2410,
	}, {
		.name		= "s3c2440-i2c",
		.driver_data	= TYPE_S3C2440,
	}, {
		.name		= "s3c2440-hdmiphy-i2c",
		.driver_data	= TYPE_S3C2440_HDMIPHY,
	}, { },
};

下面看注册过程:

static int __init i2c_adap_s3c_init(void)
{
	return platform_driver_register(&s3c24xx_i2c_driver);
            {
            	drv->driver.bus = &platform_bus_type;
                /*s3c24xx_i2c_driver->probe = s3c24xx_i2c_probe
                s3c24xx_i2c_driver->remove = s3c24xx_i2c_remove*/
            	if (drv->probe)
            		drv->driver.probe = platform_drv_probe;
                                        {
                                        	struct platform_driver *drv = to_platform_driver(_dev->driver);
                                        	struct platform_device *dev = to_platform_device(_dev);
                                            /*最终还是调用的s3c24xx_i2c_driver->probe = s3c24xx_i2c_probe*/
                                        	return drv->probe(dev);
                                        }   
            	if (drv->remove)
            		drv->driver.remove = platform_drv_remove;
                                        {
                                        	struct platform_driver *drv = to_platform_driver(_dev->driver);
                                        	struct platform_device *dev = to_platform_device(_dev);
                                            /*最终还是调用的s3c24xx_i2c_driver->remove = s3c24xx_i2c_remove*/
                                        	return drv->remove(dev);
                /*s3c24xx_i2c_driver.shutdown = NULL*/                        }
            	if (drv->shutdown)
            		drv->driver.shutdown = platform_drv_shutdown;
                /*注册driver*/
            	return driver_register(&drv->driver);
                        {
                        	int ret;
                        	struct device_driver *other;

                        	BUG_ON(!drv->bus->p);
                            /*platform_bus_type->probe = NULL
                            platform_bus_type->remove = NULL
                            platform_bus_type->shutdown = NULL
                            s3c24xx_i2c_driver->probe = s3c24xx_i2c_probe
                            s3c24xx_i2c_driver->remove = s3c24xx_i2c_remove
                            s3c24xx_i2c_driver.shutdown = NULL*/
                        	if ((drv->bus->probe && drv->probe) ||
                        	    (drv->bus->remove && drv->remove) ||
                        	    (drv->bus->shutdown && drv->shutdown))
                        		printk(KERN_WARNING "Driver '%s' needs updating - please use "
                        			"bus_type methods\n", drv->name);
                            /*通过name查找是否已经注册过此driver*/
                        	other = driver_find(drv->name, drv->bus);
                                    {
                                    	struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
                                    	struct driver_private *priv;

                                    	if (k) {
                                    		priv = to_driver(k);
                                    		return priv->driver;
                                    	}
                                    	return NULL;
                                    }
                            /*如果已经注册过此driver,打印错误信息并返回EBUSY*/
                            if (other) {
                        		put_driver(other);
                        		printk(KERN_ERR "Error: Driver '%s' is already registered, "
                        			"aborting...\n", drv->name);
                        		return -EBUSY;
                        	}

                        	ret = bus_add_driver(drv);
                                 {
                                	struct bus_type *bus;
                                	struct driver_private *priv;
                                	int error = 0;
                            /*前面初始化 s3c24xx_i2c_driver->driver.bus = &platform_bus_type*/
                                	bus = bus_get(drv->bus);
                                	if (!bus)
                                		return -EINVAL;

                                	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

                                    /*为s3c24xx_i2c_driver->driver申请私有结构体*/

                                	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
                                	if (!priv) {
                                		error = -ENOMEM;
                                		goto out_put_bus;
                                	}
                                	klist_init(&priv->klist_devices, NULL, NULL);
                                	priv->driver = drv;
                                	drv->p = priv;
                                    /*s3c24xx_i2c_driver->driver->priv->kobj.kset = platform_bus_type->p->drivers_kset
                                    还记得sys/bus/platform下的drivers目录吗
                                    priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);*/
                                	priv->kobj.kset = bus->p->drivers_kset;
                                    /*在sys/bus/platform/drivers目录下创建s3c-i2c的目录*/
                                	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
                                				     "%s", drv->name);
                                	if (error)
                                		goto out_unregister;
                                    /*又见到了drivers_autoprobe,还记得/sys/bus/platform下的drivers_autoprobe文件吗
                                    platform_bus_type->p->drivers_autoprobe = 1,自动匹配device和driver*/
                                	if (drv->bus->p->drivers_autoprobe) {
                                		error = driver_attach(drv);
                                                {
                                                	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
                                                           {
                                                            	struct klist_iter i;
                                                            	struct device *dev;
                                                            	int error = 0;

                                                            	if (!bus || !bus->p)
                                                            		return -EINVAL;
                                                                /*device注册的时候就是挂接到 platform_bus_type->p->klist_devices
                                                                下面就是遍历platform_bus_type的device链表,然后通过__driver_attach和driver
                                                                做匹配*/

                                                            	klist_iter_init_node(&bus->p->klist_devices, &i,
                                                            			     (start ? &start->p->knode_bus : NULL));
                                                            	while ((dev = next_device(&i)) && !error)
                                                            		error = fn(dev, data);  //fn = __driver_attach
                                                                            {
                                                                            	struct device_driver *drv = data;

                                                                            	/*
                                                                            	 * Lock device and try to bind to it. We drop the error
                                                                            	 * here and always return 0, because we need to keep trying
                                                                            	 * to bind to devices and some drivers will return an error
                                                                            	 * simply if it didn't support the device.
                                                                            	 *
                                                                            	 * driver_probe_device() will spit a warning if there
                                                                            	 * is an error.
                                                                            	 */

                                                                            	if (!driver_match_device(drv, dev))
                                                                                    {   /*drv->bus->match = platform_match,最终还是调用到platform的match函数
                                                                                        最终会匹配到 s3c_device_i2c3*/
                                                                                    	return drv->bus->match ? drv->bus->match(dev, drv) : 1;
                                                                                    }
                                                                            		return 0;
                                                                                /*dev = s3c_device_i2c3->dev
                                                                                  s3c_device_i2c3->dev->parent = &platform_bus */

                                                                            	if (dev->parent)	/* Needed for USB */
                                                                            		device_lock(dev->parent);
                                                                            	device_lock(dev);
                                                                                /*虽然device和driver都找到了,可还未将driver赋值给device呢*/
                                                                            	if (!dev->driver)
                                                                            		driver_probe_device(drv, dev);
                                                                                    {
                                                                                    	int ret = 0;

                                                                                    	if (!device_is_registered(dev))
                                                                                    		return -ENODEV;

                                                                                    	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
                                                                                    		 drv->bus->name, __func__, dev_name(dev), drv->name);

                                                                                    	pm_runtime_get_noresume(dev);
                                                                                    	pm_runtime_barrier(dev);
                                                                                    	ret = really_probe(dev, drv);
                                                                                            {
                                                                                            	int ret = 0;

                                                                                            	atomic_inc(&probe_count);
                                                                                            	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
                                                                                            		 drv->bus->name, __func__, drv->name, dev_name(dev));
                                                                                            	WARN_ON(!list_empty(&dev->devres_head));
                                                                                                /*这里才将driver和device关联起来*/
                                                                                            	dev->driver = drv;
                                                                                            	if (driver_sysfs_add(dev)) {
                                                                                                    {
                                                                                                    	int ret;

                                                                                                    	if (dev->bus)
                                                                                                    		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                                                                                    					     BUS_NOTIFY_BIND_DRIVER, dev);
                                                                                                        /*sys/bus/platform/drivers/s3c-i2c创建指向s3c2440-i2c.3的链接,
                                                                                                        名字仍然为s3c2440-i2c.3*/
                                                                                                    	ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
                                                                                                    			  kobject_name(&dev->kobj));
                                                                                                    	if (ret == 0) {
                                                                                                            /*在sys/bus/platform/device/s3c2440-i2c.3下
                                                                                                            创建指向sys/bus/platform/drivers/s3c-i2c的链接,名字为driver*/
                                                                                                    		ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
                                                                                                    					"driver");
                                                                                                    		if (ret)
                                                                                                    			sysfs_remove_link(&dev->driver->p->kobj,
                                                                                                    					kobject_name(&dev->kobj));
                                                                                                    	}
                                                                                                    	return ret;
                                                                                                    }
                                                                                            		printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
                                                                                            			__func__, dev_name(dev));
                                                                                            		goto probe_failed;
                                                                                            	}
                                                                                                /*platform_bus_type->probe = NULL,所以调用
                                                                                                s3c24xx_i2c_driver->probe也就是 s3c24xx_i2c_probe*/
                                                                                            	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);
                                                                                                {   /*前面s3c_device_i2c3->dev->p->knode_driver未初始化,也就是为NULL*/
                                                                                                	if (klist_node_attached(&dev->p->knode_driver)) {
                                                                                                		printk(KERN_WARNING "%s: device %s already bound\n",
                                                                                                			__func__, kobject_name(&dev->kobj));
                                                                                                		return;
                                                                                                	}

                                                                                                	pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
                                                                                                		 __func__, dev->driver->name);
                                                                                                    /*将device挂接在driver的设备链表中*/
                                                                                                	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);

                                                                                                	if (dev->bus)
                                                                                                		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                                                                                					     BUS_NOTIFY_BOUND_DRIVER, dev);
                                                                                                }
                                                                                            	ret = 1;
                                                                                            	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
                                                                                            		 drv->bus->name, __func__, dev_name(dev), drv->name);
                                                                                            	goto done;

                                                                                            probe_failed:
                                                                                            	devres_release_all(dev);
                                                                                            	driver_sysfs_remove(dev);
                                                                                            	dev->driver = NULL;

                                                                                            	if (ret != -ENODEV && ret != -ENXIO) {
                                                                                            		/* driver matched but the probe failed */
                                                                                            		printk(KERN_WARNING
                                                                                            		       "%s: probe of %s failed with error %d\n",
                                                                                            		       drv->name, dev_name(dev), ret);
                                                                                            	}
                                                                                            	/*
                                                                                            	 * Ignore errors returned by ->probe so that the next driver can try
                                                                                            	 * its luck.
                                                                                            	 */
                                                                                            	ret = 0;
                                                                                            done:
                                                                                            	atomic_dec(&probe_count);
                                                                                            	wake_up(&probe_waitqueue);
                                                                                            	return ret;
                                                                                            }
                                                                                    	pm_runtime_put_sync(dev);

                                                                                    	return ret;
                                                                                    }
                                                                            	device_unlock(dev);
                                                                            	if (dev->parent)
                                                                            		device_unlock(dev->parent);

                                                                            	return 0;
                                                                            }
                                                            	klist_iter_exit(&i);
                                                            	return error;
                                                           }
                                                }
                                		if (error)
                                			goto out_unregister;
                                	}
                                    /*将s3c24xx_i2c_driver挂接在platform的driver链表中*/
                                	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
                                	module_add_driver(drv->owner, drv);
                                    /*在/sys/bus/platform/drivers/s3c-i2c创建uevent文件*/
                                	error = driver_create_file(drv, &driver_attr_uevent);
                                	if (error) {
                                		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
                                			__func__, drv->name);
                                	}
                                    /*为 s3c24xx_i2c_driver 创建默认的属性文件,可是platform_bus_type->drv_attrs = NULL,所以此例中没有
                                    没有创建任何文件*/
                                	error = driver_add_attrs(bus, drv);
                                            {
                                            	int error = 0;
                                            	int i;

                                            	if (bus->drv_attrs) {
                                            		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
                                            			error = driver_create_file(drv, &bus->drv_attrs[i]);
                                            			if (error)
                                            				goto err;
                                            		}
                                            	}
                                            done:
                                            	return error;
                                            err:
                                            	while (--i >= 0)
                                            		driver_remove_file(drv, &bus->drv_attrs[i]);
                                            	goto done;
                                            }
                                	if (error) {
                                		/* How the hell do we get out of this pickle? Give up */
                                		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
                                			__func__, drv->name);
                                	}
                                    /*s3c24xx_i2c_driver->drv->suppress_bind_attrs 未赋值,也就是为0*/
                                	if (!drv->suppress_bind_attrs) {
                                		error = add_bind_files(drv);
                                                {
                                                	int ret;
                                                    /*在/sys/bus/platform/drivers/s3c-i2c目录下创建 ubind 文件*/
                                                	ret = driver_create_file(drv, &driver_attr_unbind);
                                                	if (ret == 0) {
                                                        /*在/sys/bus/platform/drivers/s3c-i2c目录下创建 bind 文件*/
                                                		ret = driver_create_file(drv, &driver_attr_bind);
                                                		if (ret)
                                                			driver_remove_file(drv, &driver_attr_unbind);
                                                	}
                                                	return ret;
                                                }
                                		if (error) {
                                			/* Ditto */
                                			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
                                				__func__, drv->name);
                                		}
                                	}
                                    /*发送 KOBJ_ADD */
                                	kobject_uevent(&priv->kobj, KOBJ_ADD);
                                	return 0;

                                out_unregister:
                                	kobject_put(&priv->kobj);
                                	kfree(drv->p);
                                	drv->p = NULL;
                                out_put_bus:
                                	bus_put(bus);
                                	return error;
                                }
                        	if (ret)
                        		return ret;
                            /*创建属性组及文件,s3c24xx_i2c_driver->drv未初始化,也就是为NULL,不会创建任何文件*/
                        	ret = driver_add_groups(drv, drv->groups);
                                {
                                	int error = 0;
                                	int i;

                                	if (groups) {
                                		for (i = 0; groups[i]; i++) {
                                			error = sysfs_create_group(&drv->p->kobj, groups[i]);
                                			if (error) {
                                				while (--i >= 0)
                                					sysfs_remove_group(&drv->p->kobj,
                                							   groups[i]);
                                				break;
                                			}
                                		}
                                	}
                                	return error;
                                }
                        	if (ret)
                        		bus_remove_driver(drv);
                        	return ret;
                        }
            }
}{
            	drv->driver.bus = &platform_bus_type;
                /*s3c24xx_i2c_driver->probe = s3c24xx_i2c_probe
                s3c24xx_i2c_driver->remove = s3c24xx_i2c_remove*/
            	if (drv->probe)
            		drv->driver.probe = platform_drv_probe;
                                        {
                                        	struct platform_driver *drv = to_platform_driver(_dev->driver);
                                        	struct platform_device *dev = to_platform_device(_dev);
                                            /*最终还是调用的s3c24xx_i2c_driver->probe = s3c24xx_i2c_probe*/
                                        	return drv->probe(dev);
                                        }   
            	if (drv->remove)
            		drv->driver.remove = platform_drv_remove;
                                        {
                                        	struct platform_driver *drv = to_platform_driver(_dev->driver);
                                        	struct platform_device *dev = to_platform_device(_dev);
                                            /*最终还是调用的s3c24xx_i2c_driver->remove = s3c24xx_i2c_remove*/
                                        	return drv->remove(dev);
                /*s3c24xx_i2c_driver.shutdown = NULL*/                        }
            	if (drv->shutdown)
            		drv->driver.shutdown = platform_drv_shutdown;
                /*注册driver*/
            	return driver_register(&drv->driver);
                        {
                        	int ret;
                        	struct device_driver *other;

                        	BUG_ON(!drv->bus->p);
                            /*platform_bus_type->probe = NULL
                            platform_bus_type->remove = NULL
                            platform_bus_type->shutdown = NULL
                            s3c24xx_i2c_driver->probe = s3c24xx_i2c_probe
                            s3c24xx_i2c_driver->remove = s3c24xx_i2c_remove
                            s3c24xx_i2c_driver.shutdown = NULL*/
                        	if ((drv->bus->probe && drv->probe) ||
                        	    (drv->bus->remove && drv->remove) ||
                        	    (drv->bus->shutdown && drv->shutdown))
                        		printk(KERN_WARNING "Driver '%s' needs updating - please use "
                        			"bus_type methods\n", drv->name);
                            /*通过name查找是否已经注册过此driver*/
                        	other = driver_find(drv->name, drv->bus);
                                    {
                                    	struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
                                    	struct driver_private *priv;

                                    	if (k) {
                                    		priv = to_driver(k);
                                    		return priv->driver;
                                    	}
                                    	return NULL;
                                    }
                            /*如果已经注册过此driver,打印错误信息并返回EBUSY*/
                            if (other) {
                        		put_driver(other);
                        		printk(KERN_ERR "Error: Driver '%s' is already registered, "
                        			"aborting...\n", drv->name);
                        		return -EBUSY;
                        	}

                        	ret = bus_add_driver(drv);
                                 {
                                	struct bus_type *bus;
                                	struct driver_private *priv;
                                	int error = 0;
                            /*前面初始化 s3c24xx_i2c_driver->driver.bus = &platform_bus_type*/
                                	bus = bus_get(drv->bus);
                                	if (!bus)
                                		return -EINVAL;

                                	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

                                    /*为s3c24xx_i2c_driver->driver申请私有结构体*/

                                	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
                                	if (!priv) {
                                		error = -ENOMEM;
                                		goto out_put_bus;
                                	}
                                	klist_init(&priv->klist_devices, NULL, NULL);
                                	priv->driver = drv;
                                	drv->p = priv;
                                    /*s3c24xx_i2c_driver->driver->priv->kobj.kset = platform_bus_type->p->drivers_kset
                                    还记得sys/bus/platform下的drivers目录吗
                                    priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);*/
                                	priv->kobj.kset = bus->p->drivers_kset;
                                    /*在sys/bus/platform/drivers目录下创建s3c-i2c的目录*/
                                	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
                                				     "%s", drv->name);
                                	if (error)
                                		goto out_unregister;
                                    /*又见到了drivers_autoprobe,还记得/sys/bus/platform下的drivers_autoprobe文件吗
                                    platform_bus_type->p->drivers_autoprobe = 1,自动匹配device和driver*/
                                	if (drv->bus->p->drivers_autoprobe) {
                                		error = driver_attach(drv);
                                                {
                                                	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
                                                           {
                                                            	struct klist_iter i;
                                                            	struct device *dev;
                                                            	int error = 0;

                                                            	if (!bus || !bus->p)
                                                            		return -EINVAL;
                                                                /*device注册的时候就是挂接到 platform_bus_type->p->klist_devices
                                                                下面就是遍历platform_bus_type的device链表,然后通过__driver_attach和driver
                                                                做匹配*/

                                                            	klist_iter_init_node(&bus->p->klist_devices, &i,
                                                            			     (start ? &start->p->knode_bus : NULL));
                                                            	while ((dev = next_device(&i)) && !error)
                                                            		error = fn(dev, data);  //fn = __driver_attach
                                                                            {
                                                                            	struct device_driver *drv = data;

                                                                            	/*
                                                                            	 * Lock device and try to bind to it. We drop the error
                                                                            	 * here and always return 0, because we need to keep trying
                                                                            	 * to bind to devices and some drivers will return an error
                                                                            	 * simply if it didn't support the device.
                                                                            	 *
                                                                            	 * driver_probe_device() will spit a warning if there
                                                                            	 * is an error.
                                                                            	 */

                                                                            	if (!driver_match_device(drv, dev))
                                                                                    {   /*drv->bus->match = platform_match,最终还是调用到platform的match函数
                                                                                        最终会匹配到 s3c_device_i2c3*/
                                                                                    	return drv->bus->match ? drv->bus->match(dev, drv) : 1;
                                                                                    }
                                                                            		return 0;
                                                                                /*dev = s3c_device_i2c3->dev
                                                                                  s3c_device_i2c3->dev->parent = &platform_bus */

                                                                            	if (dev->parent)	/* Needed for USB */
                                                                            		device_lock(dev->parent);
                                                                            	device_lock(dev);
                                                                                /*虽然device和driver都找到了,可还未将driver赋值给device呢*/
                                                                            	if (!dev->driver)
                                                                            		driver_probe_device(drv, dev);
                                                                                    {
                                                                                    	int ret = 0;

                                                                                    	if (!device_is_registered(dev))
                                                                                    		return -ENODEV;

                                                                                    	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
                                                                                    		 drv->bus->name, __func__, dev_name(dev), drv->name);

                                                                                    	pm_runtime_get_noresume(dev);
                                                                                    	pm_runtime_barrier(dev);
                                                                                    	ret = really_probe(dev, drv);
                                                                                            {
                                                                                            	int ret = 0;

                                                                                            	atomic_inc(&probe_count);
                                                                                            	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
                                                                                            		 drv->bus->name, __func__, drv->name, dev_name(dev));
                                                                                            	WARN_ON(!list_empty(&dev->devres_head));
                                                                                                /*这里才将driver和device关联起来*/
                                                                                            	dev->driver = drv;
                                                                                            	if (driver_sysfs_add(dev)) {
                                                                                                    {
                                                                                                    	int ret;

                                                                                                    	if (dev->bus)
                                                                                                    		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                                                                                    					     BUS_NOTIFY_BIND_DRIVER, dev);
                                                                                                        /*sys/bus/platform/drivers/s3c-i2c创建指向s3c2440-i2c.3的链接,
                                                                                                        名字仍然为s3c2440-i2c.3*/
                                                                                                    	ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
                                                                                                    			  kobject_name(&dev->kobj));
                                                                                                    	if (ret == 0) {
                                                                                                            /*在sys/bus/platform/device/s3c2440-i2c.3下
                                                                                                            创建指向sys/bus/platform/drivers/s3c-i2c的链接,名字为driver*/
                                                                                                    		ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
                                                                                                    					"driver");
                                                                                                    		if (ret)
                                                                                                    			sysfs_remove_link(&dev->driver->p->kobj,
                                                                                                    					kobject_name(&dev->kobj));
                                                                                                    	}
                                                                                                    	return ret;
                                                                                                    }
                                                                                            		printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
                                                                                            			__func__, dev_name(dev));
                                                                                            		goto probe_failed;
                                                                                            	}
                                                                                                /*platform_bus_type->probe = NULL,所以调用
                                                                                                s3c24xx_i2c_driver->probe也就是 s3c24xx_i2c_probe*/
                                                                                            	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);
                                                                                                {   /*前面s3c_device_i2c3->dev->p->knode_driver未初始化,也就是为NULL*/
                                                                                                	if (klist_node_attached(&dev->p->knode_driver)) {
                                                                                                		printk(KERN_WARNING "%s: device %s already bound\n",
                                                                                                			__func__, kobject_name(&dev->kobj));
                                                                                                		return;
                                                                                                	}

                                                                                                	pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
                                                                                                		 __func__, dev->driver->name);
                                                                                                    /*将device挂接在driver的设备链表中*/
                                                                                                	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);

                                                                                                	if (dev->bus)
                                                                                                		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                                                                                					     BUS_NOTIFY_BOUND_DRIVER, dev);
                                                                                                }
                                                                                            	ret = 1;
                                                                                            	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
                                                                                            		 drv->bus->name, __func__, dev_name(dev), drv->name);
                                                                                            	goto done;

                                                                                            probe_failed:
                                                                                            	devres_release_all(dev);
                                                                                            	driver_sysfs_remove(dev);
                                                                                            	dev->driver = NULL;

                                                                                            	if (ret != -ENODEV && ret != -ENXIO) {
                                                                                            		/* driver matched but the probe failed */
                                                                                            		printk(KERN_WARNING
                                                                                            		       "%s: probe of %s failed with error %d\n",
                                                                                            		       drv->name, dev_name(dev), ret);
                                                                                            	}
                                                                                            	/*
                                                                                            	 * Ignore errors returned by ->probe so that the next driver can try
                                                                                            	 * its luck.
                                                                                            	 */
                                                                                            	ret = 0;
                                                                                            done:
                                                                                            	atomic_dec(&probe_count);
                                                                                            	wake_up(&probe_waitqueue);
                                                                                            	return ret;
                                                                                            }
                                                                                    	pm_runtime_put_sync(dev);

                                                                                    	return ret;
                                                                                    }
                                                                            	device_unlock(dev);
                                                                            	if (dev->parent)
                                                                            		device_unlock(dev->parent);

                                                                            	return 0;
                                                                            }
                                                            	klist_iter_exit(&i);
                                                            	return error;
                                                           }
                                                }
                                		if (error)
                                			goto out_unregister;
                                	}
                                    /*将s3c24xx_i2c_driver挂接在platform的driver链表中*/
                                	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
                                	module_add_driver(drv->owner, drv);
                                    /*在/sys/bus/platform/drivers/s3c-i2c创建uevent文件*/
                                	error = driver_create_file(drv, &driver_attr_uevent);
                                	if (error) {
                                		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
                                			__func__, drv->name);
                                	}
                                    /*为 s3c24xx_i2c_driver 创建默认的属性文件,可是platform_bus_type->drv_attrs = NULL,所以此例中没有
                                    没有创建任何文件*/
                                	error = driver_add_attrs(bus, drv);
                                            {
                                            	int error = 0;
                                            	int i;

                                            	if (bus->drv_attrs) {
                                            		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
                                            			error = driver_create_file(drv, &bus->drv_attrs[i]);
                                            			if (error)
                                            				goto err;
                                            		}
                                            	}
                                            done:
                                            	return error;
                                            err:
                                            	while (--i >= 0)
                                            		driver_remove_file(drv, &bus->drv_attrs[i]);
                                            	goto done;
                                            }
                                	if (error) {
                                		/* How the hell do we get out of this pickle? Give up */
                                		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
                                			__func__, drv->name);
                                	}
                                    /*s3c24xx_i2c_driver->drv->suppress_bind_attrs 未赋值,也就是为0*/
                                	if (!drv->suppress_bind_attrs) {
                                		error = add_bind_files(drv);
                                                {
                                                	int ret;
                                                    /*在/sys/bus/platform/drivers/s3c-i2c目录下创建 ubind 文件*/
                                                	ret = driver_create_file(drv, &driver_attr_unbind);
                                                	if (ret == 0) {
                                                        /*在/sys/bus/platform/drivers/s3c-i2c目录下创建 bind 文件*/
                                                		ret = driver_create_file(drv, &driver_attr_bind);
                                                		if (ret)
                                                			driver_remove_file(drv, &driver_attr_unbind);
                                                	}
                                                	return ret;
                                                }
                                		if (error) {
                                			/* Ditto */
                                			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
                                				__func__, drv->name);
                                		}
                                	}
                                    /*发送 KOBJ_ADD */
                                	kobject_uevent(&priv->kobj, KOBJ_ADD);
                                	return 0;

                                out_unregister:
                                	kobject_put(&priv->kobj);
                                	kfree(drv->p);
                                	drv->p = NULL;
                                out_put_bus:
                                	bus_put(bus);
                                	return error;
                                }
                        	if (ret)
                        		return ret;
                            /*创建属性组及文件,s3c24xx_i2c_driver->drv未初始化,也就是为NULL,不会创建任何文件*/
                        	ret = driver_add_groups(drv, drv->groups);
                                {
                                	int error = 0;
                                	int i;

                                	if (groups) {
                                		for (i = 0; groups[i]; i++) {
                                			error = sysfs_create_group(&drv->p->kobj, groups[i]);
                                			if (error) {
                                				while (--i >= 0)
                                					sysfs_remove_group(&drv->p->kobj,
                                							   groups[i]);
                                				break;
                                			}
                                		}
                                	}
                                	return error;
                                }
                        	if (ret)
                        		bus_remove_driver(drv);
                        	return ret;
                        }
            }
}

上面的 s3c24xx_i2c_driver 注册过程,大致就是从platform总线上匹配到 s3c_device_i2c3 ,然后调用 s3c24xx_i2c_probe,同时建立一些目录、链接和属性文件。简单一点描述就是先注册个platform类型的device,在注册一个platform类型的driver,在platform总线的牵引(match)下,device 和driver绑定并调用到driver的初始化函数。到此只是驱动模型框架的作用,真正驱动的是从 s3c24xx_i2c_probe 开始,设置时钟,IO口和中断等等。下面看下s3c24xx_i2c_driver 注册过程中产生的文件。

1. 在sys/bus/platform/drivers目录下创建s3c-i2c的目录

[root@FriendlyARM drivers]# ls
alarm               s3c-i2c             s5p-tmu
......s3c-i2c             s5p-tmu
......

2. 在sys/bus/platform/drivers/s3c-i2c创建指向s3c2440-i2c.3的链接,名字仍然为s3c2440-i2c.3

[root@FriendlyARM s3c-i2c]# cd /sys/bus/platform/drivers/s3c-i2c/
[root@FriendlyARM s3c-i2c]# ls -l
--w-------    1 root     root          4096 Jan  1 12:48 bind
lrwxrwxrwx    1 root     root             0 Jan  1 12:48 s3c2440-i2c.0 -> ../../../../devices/platform/s3c2440-i2c.0
lrwxrwxrwx    1 root     root             0 Jan  1 12:48 s3c2440-i2c.3 -> ../../../../devices/platform/s3c2440-i2c.3
lrwxrwxrwx    1 root     root             0 Jan  1 12:48 s3c2440-i2c.4 -> ../../../../devices/platform/s3c2440-i2c.4s3c2440-i2c.3 -> ../../../../devices/platform/s3c2440-i2c.3
lrwxrwxrwx    1 root     root             0 Jan  1 12:48 s3c2440-i2c.4 -> ../../../../devices/platform/s3c2440-i2c.4

3. 在sys/bus/platform/device/s3c2440-i2c.3下创建指向sys/bus/platform/drivers/s3c-i2c的链接,名字为driver

[root@FriendlyARM s3c-i2c]# cd /sys/bus/platform/devices/s3c2440-i2c.3
[root@FriendlyARM s3c2440-i2c.3]# ls -l
lrwxrwxrwx    1 root     root             0 Jan  1 13:21 driver -> ../../../bus/platform/drivers/s3c-i2c
drwxr-xr-x    9 root     root             0 Jan  1  2016 i2c-3driver -> ../../../bus/platform/drivers/s3c-i2c
drwxr-xr-x    9 root     root             0 Jan  1  2016 i2c-3

4. 在/sys/bus/platform/drivers/s3c-i2c创建uevent文件

[root@FriendlyARM s3c2440-i2c.3]# cd /sys/bus/platform/drivers/s3c-i2c/
[root@FriendlyARM s3c-i2c]# ls
bind           s3c2440-i2c.3  s3c2440-i2c.3  s3c2440-i2c.7  unbind
s3c2440-i2c.0  s3c2440-i2c.2  s3c2440-i2c.4  uevent

5.在/sys/bus/platform/drivers/s3c-i2c目录下创建 ubind 文件

在/sys/bus/platform/drivers/s3c-i2c目录下创建 bind 文件

 

[root@FriendlyARM s3c2440-i2c.3]# cd /sys/bus/platform/drivers/s3c-i2c/
[root@FriendlyARM s3c-i2c]# ls
bind           s3c2440-i2c.3  s3c2440-i2c.3  s3c2440-i2c.7  unbind
s3c2440-i2c.0  s3c2440-i2c.2  s3c2440-i2c.4  ueventbind           s3c2440-i2c.3  s3c2440-i2c.3  s3c2440-i2c.7  unbind
s3c2440-i2c.0  s3c2440-i2c.2  s3c2440-i2c.4  uevent

对于uevent、bind和ubind等属性文件,可以查看store和show函数。下面展开一下ubind和bind属性的定义:

static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);

展开:

struct driver_attribute driver_attr_unbind = 
{
    .attr = {
        .name = "unbind",
        .mode = _mode 
    },	
	.show	= NULL,					
	.store	= driver_bind,
}

store函数:

static ssize_t driver_unbind(struct device_driver *drv,
			     const char *buf, size_t count)
{
	struct bus_type *bus = bus_get(drv->bus);
	struct device *dev;
	int err = -ENODEV;

	dev = bus_find_device_by_name(bus, NULL, buf);
	if (dev && dev->driver == drv) {
		if (dev->parent)	/* Needed for USB */
			device_lock(dev->parent);
		device_release_driver(dev);
        {
        	struct device_driver *drv;

        	drv = dev->driver;
        	if (drv) {
        		pm_runtime_get_sync(dev);

        		driver_sysfs_remove(dev);

        		if (dev->bus)
        			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
        						     BUS_NOTIFY_UNBIND_DRIVER,
        						     dev);

        		pm_runtime_put_sync(dev);

        		if (dev->bus && dev->bus->remove)
        			dev->bus->remove(dev);
        		else if (drv->remove)
        			drv->remove(dev);
        		devres_release_all(dev);
        		dev->driver = NULL;
        		klist_remove(&dev->p->knode_driver);
        		if (dev->bus)
        			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
        						     BUS_NOTIFY_UNBOUND_DRIVER,
        						     dev);

        	}
        }
		if (dev->parent)
			device_unlock(dev->parent);
		err = count;
	}
	put_device(dev);
	bus_put(bus);
	return err;
}

从上面代码可看出,像unbind文件中写入device的name,就会取消device和该driver的绑定。

下面再看bind属性的定义:

static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);

展开;

struct driver_attribute driver_attr_bind = 
{
    .attr = {
        .name = "bind",
        .mode = _mode 
    },	
	.show	= NULL,					
	.store	= driver_bind,
}

store函数:

static ssize_t driver_bind(struct device_driver *drv,
			   const char *buf, size_t count)
{
	struct bus_type *bus = bus_get(drv->bus);
	struct device *dev;
	int err = -ENODEV;

	dev = bus_find_device_by_name(bus, NULL, buf);
	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
		if (dev->parent)	/* Needed for USB */
			device_lock(dev->parent);
		device_lock(dev);
		err = driver_probe_device(drv, dev);
            {
            	int ret = 0;

            	if (!device_is_registered(dev))
            		return -ENODEV;

            	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
            		 drv->bus->name, __func__, dev_name(dev), drv->name);

            	pm_runtime_get_noresume(dev);
            	pm_runtime_barrier(dev);
            	ret = really_probe(dev, drv);
            	pm_runtime_put_sync(dev);

            	return ret;
            }
		device_unlock(dev);
		if (dev->parent)
			device_unlock(dev->parent);

		if (err > 0) {
			/* success */
			err = count;
		} else if (err == 0) {
			/* driver didn't accept device */
			err = -ENODEV;
		}
	}
	put_device(dev);
	bus_put(bus);
	return err;
}

从上面的代码可以看出,向bind文件写入device的name,那么就将搜索device和该driver绑定。

上面的unbind和bing是不是很像/sys/bus/platform/下的drivers_probe文件?

下一节将从 s3c24xx_i2c_probe 分析i2c的驱动框架。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值