平台总线驱动

Linux提出了platform bus(平台总线)的概念,即使用虚拟总线将设备信息和驱动程序进行分离,设备树的提出就是进一步深化这种思想,将设备信息进行更好的整理。
设备被注册到总线上,总线会根据其名字搜索对应的驱动,如果找到将设备信息导入驱动程序并执行驱动;当一个驱动被注册到平台总线的时候,总线也会搜索设备。

//linux-3.4\include\linux\device.h
struct but_type{
  const char      *name;
  const char      *dev_name;
  struct device     *dev_root;
  ...
  int (*match)(struct device *dev, struct device_driver *drv);
  int (*probe)(struct device *dev);
  int (*remove)(struct device *dev);
  void (*shutdown)(struct device *dev);
  ...
  const struct dev_pm_ops *pm;

}

//linux-3.4\drivers\base\platform.c
struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_attrs	= platform_dev_attrs,
	.match		= platform_match,
	.uevent		= platform_uevent,
	.pm		= &platform_dev_pm_ops,
};

/**
 * platform_driver_register - register a driver for platform-level devices
 * @drv: platform driver structure
 */
int platform_driver_register(struct platform_driver *drv)
{
	drv->driver.bus = &platform_bus_type;
	if (drv->probe)
		drv->driver.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 resource
    软件:网卡设备中的MAC地址等,这些信息需要私有数据的形式封装设备对象(一个设备的设备信息是一个对象,一个设备的驱动方法也是一个对象),需要我们自定义结构进行封装。
    
struct platform_device
 id  表示这个platform_device对象表征了几个设备,当多个设备有共用资源的时候(MFD),里面填充相应的设备数量,如果只是一个,填-1
 dev 父类对象,我们通常关心里面的platform_data和release,前者是用来存储私有设备信息的,后者是供当这个设备的最后引用被删除时被内核回调


定义好了platform_device 结构体后就可以调用函数 platform_add_devices 或platform_device_register向系统中注册设备,前者可以一次性注册多个平台设备。要注意的是,这里的 platform_device 设备的注册过程必须在相应设备驱动加载之前被调用,即执行注册之前。因为驱动注册时需要匹配内核中所以已注册的设备名。


在内核初始化时do_basic_setup()->driver_init()->platform_bus_init()初始化platform bus(虚拟总线),设备注册的时候platform_device_register()->platform_device_add()内核把设备挂在虚拟的platform bus下,驱动注册的时候 platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev() 对每个挂在虚拟的platform bus的设备作 __driver_attach()->driver_match_device()

{return drv->bus->match ? drv->bus->match(dev, drv) : 1;}

driver_probe_device()->really_probe(),如果相符就调用ret = drv->probe(dev);,如果probe成功则绑定该设备到该驱动。


platform_device.h
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;
};


ioport.h
struct resource {
	resource_size_t start;
	resource_size_t end;
	const char *name;
	unsigned long flags;
	struct resource *parent, *sibling, *child;
};


device.h
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_pm_domain	*pm_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 */
	/* 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" */
	u32			id;	/* device instance */

	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);
};

platform_device.h
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;
};

device.h
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;
};


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值