回顾——华清平台总线驱动210514

回顾——华清平台总线驱动210514

一,

struct bus_type:总线对象,描述一个总线,管理device和driver,完成匹配
struct bus_type{
	const char *name;
	int (*match)(struct device *dev, struct device_driver *drv);
}
注册和注销
int bus_register(struct bus_type *bus)
void bus_unregister(struct bus_type *bus)
device对象:设备对象,描述设备信息,包括地址,中断号,甚至其他自定义的数据
struct device{
	struct kobject kobj; //所有对象的父类
	const char *init_name; //在总线中会有一个名字,由于做匹配,在/sys/bus/mybus/devices/名字
	struct bus_type *bus; //指向该device对象依附于总线的对象
	void *platform_data; //自定义的数据,指向任何类型数据
}
注册和销毁的方法:
int device_register(struct device *dev)
void device_unregister(struct device *dev)
driver对象:描述设备驱动的方法(代码逻辑)
struct device_driver{
//在总线中会有一个名字,用于做匹配,在/sys/bus/mybus/drivers/名字
	const char *name;
//指向该driver对象依附于总线的对象
	struct bus_type *bus;
//如果device和driver匹配之后,driver要做的事情
	int (*probe) (struct device *dev);
//如果device和driver从总线移除之后,driver要做的事情
	int (*remove) (struct device *dev);
}
注册和注销:
int driver_register(struct device_driver *drv)
void driver_unregister(struct device_driver *drv)
如何实现总线匹配,匹配成功之后会自动调用driver的probe方法:
1,实现bus对象中match方法
2,保证driver和device中名字要一样

二,平台总线模型
(一)为什么会有平台总线:
用于平台升级:三星:2410,2440,6410,s5pc100,s5pv210,4412
硬件平台升级的时候,部分的模块的控制方式,基本上十类似的
但是模块的地址是不一样
gpio控制逻辑:1,配置gpio的输入输出功能:gpxxconf
2,给gpio的数据寄存器设置高低电平:gpxxdata
逻辑操作基本上是一样的,但是地址不一样
uart控制:1,设置8n1,115200,no AFC
2,UCON,ULCON,UMODOEN,UDIV
逻辑基本上是一样的,但是地址不一样
问题:当soc升级的时候,对于相似的设备驱动,需要编写很多次(如果不用平台总线),但是会有大部分重复代码
解决:引入平台总线
device(中断/地址)和driver(操作逻辑)分离
在升级的时候,只需要修改device中信息即可(中断/地址)
实现一个driver代码能够驱动多个平台相似的模块,并且修改的代码量很少
(二)平台总线中的三要素:

1,bus
	  platform_bus:不需要自己创建,开机的时候自动创建
	  struct bus_type platform_bus_type = {
	  		.name = "platform",
	  		.dev_grounps = platform_dev_groups,
	  		.match = platform_match,
	  		.uevent = platform_uevent,
	  		.pm = &platform_dev_pm_ops,
	  }
匹配方法:
(1)优先匹配pdriver中的id_table,里面包含了支持不同的平台的名字
(2)直接匹配driver中名字和device中名字

```bash
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
if(pdrv->id_table) //如果pdrv中有idtable,平台列表名字和pdev中的名字
	return platform_match_id(pdrv->id_table, pdev) != NULL;
/*fall-back to driver name match*/
return (strcmp(pdev->name, drv->name) == 0);
2,device对象
struct platform_device{
	const char *name; //用于做匹配
	int id; //一般都是直接给-1
	struct device dev; //继承了device父类
	u32 num_resources; //资源的个数
	struct resource *resource; //资源:包括了一个设备的地址和中断
}
注册和注销
int platform_device_register(struct platform_device *pdev);
void platform_device_unregister(struct platform_device *pdev);
3,driver对象
struct platform_driver {
	int (*probe) (struct platform_device *); //匹配成功之后被调用的函数
	int (*remove) (struct platform_device *); //device移除的时候调用的函数
	struct device_driver driver; //继承了driver父类
	const struct platform_device_id *id_table; //如果driver支持多个平台,在列表中写出来
}
注册和注销
int platform_driver_register(struct platform_driver *drv);
void platform_driver_unregister(struct platform_driver *drv);

(三)编写代码:编写一个能在多个平台下使用的led驱动

1,注册一个platform_device,定义资源:地址和中断
struct resource{
	resource_size_t start; //开始
	resource_size_t end; //结束
	const char *name; //描述,自定义
	unsigned long flags; //区分当前资源描述的是中断(IORESOURCE_IRQ)还是内存(IORESOURCE_MEM)
	struct resource *parent, *sibling, *child;
};
2,注册一个platform_driver,实现操作设备的代码
注册完毕,同时如果和pdev匹配成功,自动调用probe方法:
probe方法:对硬件进行操作
(1)注册设备号,并且注册fops--为用户提供一个设备标示,同时提供文件操作io接口
(2)创建设备节点
(3)初始化硬件
ioremap(地址); //地址从pdev需要获取
readl/writel();
(4)实现各种io接口:xxx_open,xxx_read,...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值