platform平台设备学习

 平台设备驱动的使用

1、声明平台设备 struct platform_device  p_dev;

2、注册平台设备   platform_device_add(&p_dev)

3、注销平台设备 platform_device_unregister(&p_dev);

	1、平台设备,通过struct platform_device 来进行描述。
	struct platform_device {
		const char	* name; //平台设备的名称
		int	id;//设备的ID,当ID=-1的时候,表示设备名称只有一个,否则表示设备编号
		struct device	dev;
		u32		num_resources;
		struct resource	* resource;
		struct platform_device_id	*id_entry;
	};
	2、其中platform_device内包含两个重要的结构体,一个是struct device 该结构体描述设备相关的信息设备之间的层次关系以及设备与总线驱动的关系。
	struct device {
		struct device		*parent;//指向父设备节点
	
		struct device_private	*p;//描述的是klist,struct klist是对struct list_head的扩展,在此它的作用是连接设备列表中的孩子列表。Struct klist_node表示它的兄弟节点。
	
		struct kobject kobj;
		const char		*init_name; /* initial name of the device */
		struct device_type	*type; /*device_type结构表示设备的类型。一个设备类或者总线可以包含不同类型的设备,例如“分区”和“磁盘” , “鼠标”和“事件” 。device_type就可以标识某个设备类型和该设备的特有信息,它就等同于kobject结构中的kobj_type一样。如果name数据成员被指定,那么uevent成员函数就会把它包含在DEVTYPE变量中。*/
	
		struct semaphore	sem;	/* 该信号量用于同步其驱动 */
	
		struct bus_type	*bus;	/*设备所在的总线,指向所连接的总线 */
		struct device_driver *driver;	/* 管理该设备的驱动 */
		void		*driver_data;	/* 设备的私有数据指针*/
		void		*platform_data;	/* Platform specific data, device
						   core doesn't touch it */
		struct dev_pm_info	power;
	
	#ifdef CONFIG_NUMA
		int		numa_node;	/* NUMA node this device is close to */
	#endif
		u64		*dma_mask;	/*指向设备DMA屏蔽字。*/
		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)聚集的DMA缓冲池 */
	
		struct dma_coherent_mem	*dma_mem; /* 设备一致性DMA的屏蔽字
						     override */
		/* arch specific additions */
		struct dev_archdata	archdata;
	
		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;
		struct attribute_group	**groups;	/* optional groups */
	
		void	(*release)(struct device *dev);释放设备描述符的回调函数。
	};

3、通过struct resource结构体来描述
	struct resource {
		resource_size_t start;
		resource_size_t end ;//资源起始的和结束的物理地址
		const char *name;//资源的名称
		unsigned long flags;;//资源的类型,比如MEM,IO,IRQ类型
		struct resource *parent, *sibling, *child;;//资源链表的指针
	};
	
4、platform_device的使用
	1)声明该结构体struct platform_device *my_buttons_dev;
	//给该结构体分配空间和初始化。传入的参数为设备名字和设备ID,当ID=-1的时候表明该设备名称唯一
	my_buttons_dev = platform_device_alloc("my_buttons", -1);
	声明平台设备的资源struct resource
	static struct resource key_resource[]=
	{ 	
		[0] = {
			.start = IRQ_EINT1,
			.end = IRQ_EINT1,
			.flags = IORESOURCE_IRQ,
		},
		[1] = {
			.start = IRQ_EINT2,
			.end = IRQ_EINT2,
			.flags = IORESOURCE_IRQ,
		},
	};
	//使用下面函数将该资源添加到平台设备里面去,使用该函数,会为 platform_device 中的resource结构体指针分配空间并且赋值
	//参数为 (struct platform_device *pdev,struct resource *res, unsigned int num)
	platform_device_add_resources(my_buttons_dev,key_resource,6);
	3)//向系统注册该设备
		ret = platform_device_add(my_buttons_dev);
		
		if(ret)
			platform_device_put(my_buttons_dev);
	并且在退出函数里面将该平台设备注销
	void platform_device_unregister(struct platform_device *pdev)


 

平台驱动使用

 

平台设备驱动最重要的是:struct platform_driver 结构体
	1)struct platform_driver {
		//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 (*suspend_late)(struct platform_device *, pm_message_t state);
		int (*resume_early)(struct platform_device *);
		int (*resume)(struct platform_device *);
		struct device_driver driver; //设备驱动,定义在include/linux/device.h中
		struct platform_device_id *id_table;
	};
	2)声明一个struct platform_driver对象然后对其初始化
	struct platform_driver my_buttons_drv = { 
		.probe = my_plat_probe,//对应设备的探测驱动
		.remove = my_plat_remove,
		.driver = { 
			.owner = THIS_MODULE,
			.name = "my_buttons",//与设备的名字一致和platform_device相关联起来 
		},
	};
	向系统注册这个平台驱动
		ret = platform_driver_register(&my_buttons_drv);
	当模块卸载的时候注销该驱动:
	platform_driver_unregister(&my_buttons_drv);
	
	平台设备驱动中探测设备函数,如果探测成功,向系统注册一个字符设备或者混杂设备,向用户空间提供一个操作设备的接口。
	static int my_plat_probe(struct platform_device *dev)
	{
		int ret,i;
		struct resource *plat_resource;
		struct platform_device *pdev = dev;
		
		printk("my platform dirver find my platfrom device.\n");
	
		for(i=0; i<6; i++){
			plat_resource = platform_get_resource(pdev,IORESOURCE_IRQ,i);
			if(plat_resource == NULL)
				return -ENOENT;	
			buttons_irq[i] = plat_resource->start;
		}
	
		ret = misc_register(&misc);
		if(ret)
			return ret;
	
		
		return 0;
	}
	


 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值