1.platform_device结构体

struct platform_device {
const char * name;/* 设备名 */
u32 id;
struct device dev;
u32 num_resources;/* 设备所使用各类资源数量 */
struct resource * resource;/* 资源 */
};
设备的分配:
struct platform_device *platform_device_alloc(const char *name, int id); //name:设备名,id:设备
id,一般为-1 
设备的注册:
int platform_device_add(struct platform_device *pdev); 
对platform_device的定义通常在BSP的板文件中实现,在板文件中,将platform_device归纳
为一个数组:
static struct platform_device *smdk2410_devices[] __initdata = { 
&s3c_device_usb, 
&s3c_device_lcd, 
&s3c_device_wdt, 
&s3c_device_i2c0, 
&s3c_device_iis, 
}; 
最终通过 platform_add_devices()函数统一注册:
static void __init smdk2410_init(void) 

s3c_i2c0_set_platdata(NULL); 
platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices)); 
smdk_machine_init(); 

platform_add_devices()函数可以将平台设备添加到系统中,这个函数的 原型为:
int platform_add_devices(struct platform_device **devs, int num);
该函数的第一个参数为平台设备数组的指针,第二个参数为平台设备的数量,它内部调用了
platform_device_register()函 数用于注册单个的平台设备。
2.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;
};
看看驱动是怎么注册进去的:
int platform_driver_register(struct platform_driver *drv) 

。。。 
return driver_register(&drv->driver); 

int driver_register(struct device_driver *drv) 

。。。。 
ret = bus_add_driver(drv); 
。。。 

int bus_add_driver(struct device_driver *drv) 

。。。 
if (drv->bus->p->drivers_autoprobe) { 
error = driver_attach(drv); 
if (error) 
goto out_unregister; 

。。。 

int driver_attach(struct device_driver *drv) 

return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); 

来看__driver_attach这个函数,其中分别调用了driver_match_device,driver_probe_device函数。
static int __driver_attach(struct device *dev, void *data) 

struct device_driver *drv = data; 
if (!driver_match_device(drv, dev)) 
return 0; 
if (dev->parent) 
down(&dev->parent->sem); 
down(&dev->sem); 
if (!dev->driver) 
driver_probe_device(drv, dev)
up(&dev->sem); 
if (dev->parent) 
up(&dev->parent->sem);

return 0; 
}
匹配的时候调用的bus的match函数。匹配成功后调用驱动的probe函数。
int driver_probe_device(struct device_driver *drv, struct device *dev) 

。。。 
ret = really_probe(dev, drv); 
。。。 

static int really_probe(struct device *dev, struct device_driver *drv) 

。。。 
int driver_probe_device(struct device_driver *drv, struct device *dev) 

。。。 
ret = really_probe(dev, drv); 
。。。 

static int really_probe(struct device *dev, struct device_driver *drv) 

。。。 
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; 

。。。 

由relly_probe函数可以看出,如果bus定义了probe函数,则调用bus的probe
函数;如果bus,没有定义而driver定义了probe函数,则调用driver的probe
函数。

3.bus_type类型的platform_bus_type
(1)基本结构
struct bus_type platform_bus_type = {
name = “platform”,
dev_attrs = platform_dev_attrs,
match = platform_match,
uevent = platform_uevent,
pm = PLATFORM_PM_OPS_PTR,
};
EXPORT_SYMBOL_GPL(platform_bus_type);
(2)match()表明了platform_device和platform_driver之间如何匹配
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev; 
pdev = container_of(dev, struct platform_device, dev); 
return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); 
}
匹配platform_device和platform_driver主要看二者的name字段是否相同
(3)总线初始化
platform_bus_type是在系统初始化的时候初始化的,不用我们做什么工作:
.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); 
if (error) 
device_unregister(&platform_bus); 
return error; 

4.设备中的资源
flags可以为IORESOURCE_IO、 IORESOURCE_MEM、IORESOURCE_IRQ、IORESOURCE_DMA等
static struct resource ldd6410_dm9000_resource[] = {
[0] = {
.start = 0×18000000,
.end = 0×18000000 + 3,
.flags = IORESOURCE_MEM
},
[1] = {
.start = IRQ_EINT(7),
.end = IRQ_EINT(7),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
}
};
获取资源:
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
5.plat_data
对设备的硬件描述除了中断、内存、DMA通道以外,可能还会有一些配置信 
息,而 这些配置信息也依赖于板,不适宜直接放置在设备驱动本身,因此,
platform也提供了platform_data的支持。例如:
static struct dm9000_plat_data ldd6410_dm9000_platdata = {
.flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
.dev_addr = { 0×0, 0×16, 0xd4, 0×9f, 0xed, 0xa4 },
};
static struct platform_device ldd6410_dm9000 = {
.name = “dm9000″,
.id = 0,
.num_resources = ARRAY_SIZE(ldd6410_dm9000_resource),
.resource = ldd6410_dm9000_resource,
.dev = {
.platform_data = &ldd6410_dm9000_platdata,
}
};
获取plat_data:
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
其中,pdev为platform_device的指针。

platform框架相关推荐

  1. platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架

    platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...

  2. xilinx axi dma linux 快速搭建框架

    kernel axi dma 驱动 也是更具数据手册来的, 先把业务简单跑起来,然后在做到内核里,熟悉 dma engine 框架 xilinx 驱动的 整个驱动框架,都是基于 platform bu ...

  3. platform 设备驱动实验

    目录 Linux 驱动的分离与分层 驱动的分隔与分离 驱动的分层 platform 平台驱动模型简介 platform 总线 platform 驱动 platform 设备 硬件原理图分析 试验程序编 ...

  4. Linux设备模型之platform设备

    Linux设备模型之platform设备 1. Platform模块的软件架构 2. Platform设备 2.1 platform_device原型 2.2 注册添加device 2.2.1 pla ...

  5. platfrom设备驱动框架

    前面编写的设备驱动都非常的简单,都是对IO进行最简单的读写操作.像I2C.SPI.LCD 等这些复杂外设的驱动就不能这么去写了,Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的 ...

  6. 驱动程序开发:无设备树和有设备树的platform驱动

    1.Linux 驱动的分离与分层   对与对IO进行最简单的读写操作,无需考虑太多的怎么使它重用性强,而像I2C. SPI.LCD 等这些复杂外设的驱动,Linux 系统要考虑到驱动的可重用性,因此提 ...

  7. Linux platform 设备驱动实验-基于正点原子IMX6ULL开发板

    我们以前的设备驱动都非常的简单,都是对IO进行最简单的读写操作.像I2C. SPI.LCD 这些复杂外设的驱动就不能这么去写了,Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的 ...

  8. ALSA-ASOC音频驱动框架简述

    ##ALSA-ASOC音频驱动框架简述 注意:本文只限于讲解ALSA-ASOC音频驱动框架,不深入到寄存器.时序等配置,文章有不足之处,日后逐渐完善补充 另外多谢两位前辈的博客,学到了很多,多谢. h ...

  9. platform driver注册过程

    platform 总线上的驱动注册一般使用module_platform_driver宏,如goldfish设备的注册 module_platform_driver(goldfish_pipe); 这 ...

最新文章

  1. java基础-值传递
  2. MySQL 性能监控4大指标——第一部分
  3. pwm一个时间单位_RK3308——RGB调色灯三路PWM驱动
  4. Azure Redis Cache (3) 创建和使用P级别的Redis Cache
  5. python实例 81,82
  6. 怎么让Go Modules使用私有依赖模块
  7. python使用curve_fit拟合任意分布
  8. 不一样的设计!20个国外优秀的电子商务网站
  9. 免费在线 Logo生成器
  10. 网络共享计算机设置方法,如何设置网络共享(局域网共享如何设置)
  11. Word文字怎么添加下划线
  12. mysql宠物店java_javajdbc宠物商店-Mysql数据库
  13. iphone 手势编程---值得回忆的API
  14. lib库知识全面讲解(.lib、.dll)
  15. 《新浪微博平台架构》---阅读
  16. 【程序员必备】七夕表白攻略:教你用代码轻松打动她的内心!
  17. 月盈利百万的茶馆是如何通过一套商业模式起家?方案分享!
  18. EXCEL内容很少文件却很大---如何变小
  19. CSS 实现色彩渐变
  20. 实验室装水的容器叫什么_实验室常见水的种类_生命之源水

热门文章

  1. 误分区的删除之DBR的修复
  2. win10无法找到网络解决办法
  3. 如何下载和平区卫星地图高清版大图?
  4. 异步电动机matlab仿真实验报告,异步电机矢量控制MATLAB仿真实验
  5. 【IoT】NFC CPU 卡在实际产品中的应用
  6. Nuclei——一款基于YAML语法模板的快速漏洞扫描工具
  7. 罗杰斯Rogers4003,Rogers4350B标准厚度
  8. HTML标题 段落 样式
  9. 爸爸妈妈,我想你们了
  10. Java版WMS系统奇门云网关(奇门仓储)接口实现