platform driver

注册struct platform_driver

platform_driver_register

 driver_register
 	->bus_add_driver // add a driver to a bus;
 	 	-> driver_attach // 查找bus下所有设备,找与其匹配的
  		 	-> bus_for_each_dev(drv->bus,NULL,drv,__driver_attach)
			  	-> __driver_attach // 检测每一个设备
 			  			-> driver_match_device  	// 每个设备都调用此函数,判断是否与当前驱动匹配。
 			  										// 实际上是执行 dev->bus->match
						(匹配成功执行)driver_probe_device
											->really_probe 
												-> drv->probe // 驱动与设备匹配时,执行drive->probe
向总线注册驱动时,会检查当前总线下的所有设备,有没有与此驱动匹配的设备。
若有则执行驱动结构体里面的 probe 成员函数
platform_device_register
device_register
	->device_add
	 	->bus_add_device
	 	  bus_probe_device
	 			->device_attach(dd.c)
	 				->bus_for_each_drv(dev->bus, NULL, dev, __device_attach)
	 					->__device_attach 	// 查找bus下的每一个驱动
	 										// 都执行此函数
	 						->driver_match_device(drv, dev)  	// 判断每一个驱动设备是否匹配
	 															// 实际上内部调用的就是 drv->bus->match
	 						  若匹配则执行driver_probe_match
	 											->really_probe
	 												-> drv->probe 

不管是先注册设备还是先注册驱动,驱动和设备匹配以后,drv->probe就会执行。
此probe由驱动编写人员编写的,以后会将常与此函数打交道。

platform_init()

//platform 总线是 bus_type 的一个具体实例
//定义在文件 drivers/base/platform.c
struct bus_type platform_bus_type = {
	/* 总线名字  /sys/bus/platform */
	.name		= "platform", 
	.dev_groups	= platform_dev_groups,
	/* pdev 和 pdrv 的匹配函数*/
	.match		= platform_match, 
	.uevent		= platform_uevent,
	.pm		= &platform_dev_pm_ops,
};

对于platform平台而言,函数 platform_match 负责匹配 platform驱动platform设备

platform_driver
//此结构体定义在文件 include/linux/platform_device.h 中
struct platform_driver {
	/*pdev 和 pdrv 匹配成功后会执行 pdrv->probe 函数 */
	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;
	bool prevent_deferred_probe;
};
platform_device
struct platform_device {
	/* 用于无设备树的匹配,和 pdrv->drv->name */
	const char	*name; 
	int		id;
	bool		id_auto;
	struct device	dev;
	u32		num_resources;
	/* 相比于 dev 新增加的内容 */
	struct resource	*resource;
	const struct platform_device_id	*id_entry;
	char *driver_override; /* Driver name to force a match */
	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;
	/* arch specific additions */
	struct pdev_archdata	archdata;
};
resources
struct resource 
{
    resource_size_t start;
    resource_size_t end;
    const char *name;
    /* 表示 resource 类型 
     * 定义在 ioport.h
     */
    unsigned long flags;
    struct resource *parent, *sibling, *child;
};

platform_init()

int __init platform_bus_init(void)
{
	int error;
	early_platform_cleanup();
	error = device_register(&platform_bus);//添加设备
	if (error)
		return error;
	error =  bus_register(&platform_bus_type);//注册platform_bus_type
	if (error)
		device_unregister(&platform_bus);
	return error;
}

probe调用流程
在这里插入图片描述

分析platform.c

platform_driver_register
//初始化platform_driver中的probe 接口
static struct platform_driver s3c24xx_led_driver = {
	.probe		= led_probe,
	.remove		= led_remove,
	.driver		= {
		.name		= "platform_led",
		.owner		= THIS_MODULE,
	},
};
int platform_driver_register(struct platform_driver *drv)
{
	drv->driver.bus = &platform_bus_type; //设置platform_drv下的driver.bus = platform_bus
	if (drv->probe)
		drv->driver.probe = platform_drv_probe;//platform_drv_probe,负责调用上层驱动
	if (drv->remove)
		drv->driver.remove = platform_drv_remove;
	if (drv->shutdown)
		drv->driver.shutdown = platform_drv_shutdown;
	return driver_register(&drv->driver);//添加struct device_drive
}

driver_register()

int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;
	BUG_ON(!drv->bus->p);
	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);
	other = driver_find(drv->name, drv->bus);//分析见下面,检查是否已经注册过了
	if (other) {
		printk(KERN_ERR "Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EBUSY;
	}
	ret = bus_add_driver(drv);//注册到drv->bus
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret)
		bus_remove_driver(drv);
	return ret;
}

driver_find()

struct kobject {
	const char		*name;
	struct list_head	entry;
	struct kobject		*parent;
	struct kset		*kset; //kset 是嵌入相同类型结构的 kobject 集合,包含很多kobject ,是kobject的顶层容器,把kset 添加到系统中,会在sysfs中创建一个目录,kset中的每个kobject都会在sysfs中表述
	struct kobj_type	*ktype;
	struct sysfs_dirent	*sd;
	struct kref		kref;
	unsigned int state_initialized:1;
	unsigned int state_in_sysfs:1;
	unsigned int state_add_uevent_sent:1;
	unsigned int state_remove_uevent_sent:1;
	unsigned int uevent_suppress:1;
};
struct subsys_private {
	struct kset subsys;
	struct kset *devices_kset;
	struct list_head interfaces;
	struct mutex mutex;
	struct kset *drivers_kset;//driver的kobject集合
	struct klist klist_devices;
	struct klist klist_drivers;
	struct blocking_notifier_head bus_notifier;
	unsigned int drivers_autoprobe:1;
	struct bus_type *bus;
	struct kset glue_dirs;
	struct class *class;
};
struct driver_private {
	struct kobject kobj;
	struct klist klist_devices;
	struct klist_node knode_bus;
	struct module_kobject *mkobj;
	struct device_driver *driver;
};
struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
    //bus_type的p是subsys_private类型,
    //在bus的private 的 kset中找name 的kobject
	struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
	struct driver_private *priv;
	if (k) {
		/* Drop reference added by kset_find_obj() */
		kobject_put(k);
		priv = to_driver(k);//priv = container_of(k, struct driver_private, kobj)
        //driver_private -> kobj 会 添加到 bus_type -> subsys_private -> ksets中
		return priv->driver;//dirver_private -> driver 指向 device_driver
	}
	return NULL;
}

bus_add_driver()

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;
};
struct driver_private {
	struct kobject kobj;
	struct klist klist_devices;
	struct klist_node knode_bus;
	struct module_kobject *mkobj;
	struct device_driver *driver;
};
int bus_add_driver(struct device_driver *drv)
{
	struct bus_type *bus;
	struct driver_private *priv;
	int error = 0;

	bus = bus_get(drv->bus);
	if (!bus)
		return -EINVAL;
	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
	priv = kzalloc(sizeof(*priv), GFP_KERNEL); //申请driver_private 结构体
	if (!priv) {
		error = -ENOMEM;
		goto out_put_bus;
	}
    /*driver 和 device 匹配后 ,会把设备加到driver 的 p -> klist_devices
    klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
    */
	klist_init(&priv->klist_devices, NULL, NULL);
	priv->driver = drv; //private 和 driver 关联
	drv->p = priv;
	priv->kobj.kset = bus->p->drivers_kset; //private的kobj-> kset 指向 bus_type->p->driver_kset
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
				     "%s", drv->name);//设置kobj的name
	if (error)
		goto out_unregister;

	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);//attach device,分析过程,见上图probe
		if (error)
			goto out_unregister;
	}
	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //priv->knode_bus 添加到 bus->p-klist_drivers
	module_add_driver(drv->owner, drv);

	error = driver_create_file(drv, &driver_attr_uevent);
	if (error) {
		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
			__func__, drv->name);
	}
	error = driver_add_attrs(bus, drv);
	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);
	}

	if (!drv->suppress_bind_attrs) {
		error = add_bind_files(drv);
		if (error) {
			/* Ditto */
			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
				__func__, drv->name);
		}
	}

	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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值