阅读platformdriver的代码时,发现在probe函数直接调用platform_get_resource从pdev中获取io内存,但却没有判断传给probe的pdev是否属于这个驱动 !

后来发现原来在arch目录下的对应目录里面有个devs.c文件(这个文件可能因不同的架构而不一样),这个文件里面声明了一个platform设备的资源数组foo_devices,原型如下:

static struct platform_device* foo_devices[] __initdata;

这个数组里面包含了所有platform设备的资源信息。例如:一个设备的资源声明如下:

static struct resource foo_resource[] =
{
[0] =
{
.start = (FOO_BASE_PA),
.end = (FOO_BASE_PA) + (0x0008000),
.flags = IORESOURCE_MEM,
},
[1] =
{
.start = (IRQ_FOO),
.end = (IRQ_FOO),
.flags = IORESOURCE_IRQ,
},
};

static struct platform_device device_foo =
{
.name = "device_foo",
.id = 0,
.resource = foo_resource,
.num_resources = ARRAY_SIZE(foo_resource),
.dev =
{
//根据源代码,这两个成员置成0表示不起作用
.dma_mask = 0x0,
.coherent_dma_mask = 0x0,
},
};

那么将这个device_foo加入foo_devices数组,就能直接在probe函数中用platform_get_resource获取资源了,但是要注意驱动的name成员必须和platform_device结构中的name成员完全相同。

那为什么加入foo_devices数组后就能直接访问了呢?
在 相关体系的machine_desc结构体中(对于每个特定平台都有一个MACHINE_START宏用来定义machine_desc结构体),有一个 接口init_machine,这个接口中会调用platform_add_devices添加foo_devices。例如:

platform_add_devices(foo_devices);

platform_get_resource函数源码如下:

struct resource *platform_get_resource(struct platform_device *dev,

unsigned int type, unsigned int num)

{

int i;

for (i = 0; i < dev->num_resources; i++) {

struct resource *r = &dev->resource[i];

if (type == resource_type(r) && num-- == 0)

return r;

}

return NULL;

}

函数分析:

struct resource *r = &dev->resource[i];

这行代码使得不管你是想获取哪一份资源都从第一份资源开始搜索。

if (type == resource_type(r) && num-- == 0)

这行代码首先通过type == resource_type(r)判断当前这份资源的类型是否匹配,如果匹配则再通过num-- == 0判断是否是你要的,如果不匹配重新提取下一份资源而不会执行num-- == 0这一句代码。

通过以上两步就能定位到你要找的资源了,接着把资源返回即可。如果都不匹配就返回NULL。

实例分析:

下面通过一个例子来看看它是如何拿到设备资源的。

设备资源如下:

static struct resource s3c_buttons_resource[] = {

[0]={

.start = S3C24XX_PA_GPIO,

.end   = S3C24XX_PA_GPIO + S3C24XX_SZ_GPIO - 1,

.flags = IORESOURCE_MEM,

},

[1]={

.start = IRQ_EINT8,

.end   = IRQ_EINT8,

.flags = IORESOURCE_IRQ,

},

[2]={

.start = IRQ_EINT11,

.end   = IRQ_EINT11,

.flags = IORESOURCE_IRQ,

},

[3]={

.start = IRQ_EINT13,

.end   = IRQ_EINT13,

.flags = IORESOURCE_IRQ,

},

[4]={

.start = IRQ_EINT14,

.end   = IRQ_EINT14,

.flags = IORESOURCE_IRQ,

},

[5]={

.start = IRQ_EINT15,

.end   = IRQ_EINT15,

.flags = IORESOURCE_IRQ,

},

[6]={

.start = IRQ_EINT19,

.end   = IRQ_EINT19,

.flags = IORESOURCE_IRQ,

}

};

驱动中通过下面代码拿到第一份资源:

struct resource *res;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

函数进入for里面,i=0,num_resources=7,拿出resource[0]资源。resource_type(r)提取出该份资源 的资源类型并与函数传递下来的资源类型进行比较,匹配。Num=0(这里先判断是否等于0再自减1)符合要求,从而返回该资源。

获取剩下资源的代码如下:

for(i=0; i<6; i++){

buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,i);

if(buttons_irq == NULL){

dev_err(dev,"no irq resource specified\n");

ret = -ENOENT;

goto err_map;

}

button_irqs[i] = buttons_irq->start;

}

分析如下:

For第一次循环:

buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,0);

在拿出第一份资源进行resource_type(r)判断资源类型时不符合(此时num-- == 0这句没有执行),进而拿出第二份资源,此时i=1,num_resources=7,num传递下来为0,资源类型判断时候匹配,num也等于0,从而确定资源并返回。

For第二次循环:

buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,1);

拿出第二份资源的时候resource_type(r)资源类型匹配,但是num传递下来时候为1,执行num-- == 0时不符合(但num开始自减1,这导致拿出第三份资源时num==0),只好拿出第三份资源。剩下的以此类推。

总结:

struct resource *platform_get_resource(struct platform_device *dev,

unsigned int type, unsigned int num)

unsigned int type决定资源的类型,unsigned int num决定type类型的第几份资源(从0开始)。即使同类型资源在资源数组中不是连续排放也可以定位得到该资源。

比如第一份IORESOURCE_IRQ类型资源在resource[2],而第二份在resource[5],那

platform_get_resource(pdev,IORESOURCE_IRQ,0);

可以定位第一份IORESOURCE_IRQ资源;

platform_get_resource(pdev,IORESOURCE_IRQ,1);

可以定位第二份IORESOURCE_IRQ资源。

之所以能定位到资源,在于函数实现中的这一行代码:

if (type == resource_type(r) && num-- == 0)

该行代码,如果没有匹配资源类型,num-- == 0不会执行而重新提取下一份资源,只有资源匹配了才会寻找该类型的第几份资源,即使这些资源排放不连续。

platform_get_resource的分析的更多相关文章

  1. 【linux驱动分析】之dm9000驱动分析(六):dm9000_init和dm9000_probe的实现

    一.dm9000_init 打印出驱动的版本,注冊dm9000_driver驱动,将驱动加入到总线上.运行match,假设匹配,将会运行probe函数. 1 static int __init 2 d ...

  2. 三星framebuffer驱动代码分析

    一.驱动总体概述 本次的驱动代码是Samsung公司为s5pv210这款SoC编写的framebuffer驱动,对应于s5pv210中的内部外设Display Controller (FIMD)模块. ...

  3. imx6 framebuffer 分析

    分析imx6 framebuffer设备和驱动的注册过程. Tony Liu, 2016-8-31, Shenzhen 相关文件: arch/arm/mach-mx6/board-mx6q_sabre ...

  4. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  5. Linux驱动修炼之道-RTC子系统框架与源码分析【转】

    转自:http://helloyesyes.iteye.com/blog/1072433 努力成为linux kernel hacker的人李万鹏原创作品,为梦而战.转载请标明出处 http://bl ...

  6. IIC驱动分析

    IIC设备是一种通过IIC总线连接的设备,由于其简单性,被广泛引用于电子系统中.在现代电子系统中,有很多的IIC设备需要进行相互之间通信 IIC总线是由PHILIPS公司开发的两线式串行总线,用于连接 ...

  7. RM-Linux驱动--Watch Dog Timer(看门狗)驱动分析

    from:http://blog.csdn.net/geekcome/article/details/6595265 硬件平台:FL2440 内核版本:2.6.28 主机平台:Ubuntu 11,04 ...

  8. Linux I2C设备驱动编写(三)-实例分析AM3359

    TI-AM3359 I2C适配器实例分析 I2C Spec简述 特性: 兼容飞利浦I2C 2.1版本规格 支持标准模式(100K bits/s)和快速模式(400K bits/s) 多路接收.发送模式 ...

  9. 【转】Linux I2C设备驱动编写(三)-实例分析AM3359

    原文网址:http://www.cnblogs.com/biglucky/p/4059586.html TI-AM3359 I2C适配器实例分析 I2C Spec简述 特性: 兼容飞利浦I2C 2.1 ...

随机推荐

  1. 自学Aruba5.1-Aruba 基于角色(role)的策略管理(重点)

    点击返回:自学Aruba之路 自学Aruba5.1-Aruba 基于角色(role)的策略管理(重点) 1. 角色Role介绍 在ArubaOS中,用户(User)指的是已经完成连接,并获取到IP地址 ...

  2. 洛谷 P2515 [HAOI2010]软件安装 解题报告

    P2515 [HAOI2010]软件安装 题目描述 现在我们的手头有\(N\)个软件,对于一个软件\(i\),它要占用\(W_i\)的磁盘空间,它的价值为\(V_i\).我们希望从中选择一些软件安装到 ...

  3. Python--Django学习笔记1

    Django:The Web framework for perfectionists with deadlines Django是一个Python语言开发的高级Web框架,采用MVC架构,通过配置可 ...

  4. android广播(内部类)使用

    1.广播定义在一个单独的文件中 源码: public class MessageReceiver extends BroadcastReceiver{ @Override public void on ...

  5. 02-body标签中相关标签

    今日内容: 字体标签: h1~h6.<font>.<u>.<b>.<strong><em>.<sup>.<sub> ...

  6. linux 一些命令(2)

    1.查看centos版本 # lsb_release -a 2.查找大于1000M的文件 find / -type f -size +1000M -print0 | xargs -0 du –h

  7. 超详细从零记录Hadoop2.7.3完全分布式集群部署过程

    超详细从零记录Ubuntu16.04.1 3台服务器上Hadoop2.7.3完全分布式集群部署过程.包含,Ubuntu服务器创建.远程工具连接配置.Ubuntu服务器配置.Hadoop文件配置.Had ...

  8. pycharm git无法使用问题(待解决)

    PyCharm 2017.3.1 (Community Edition)Build #PC-173.3942.36, built on December 14, 2017JRE: 1.8.0_152- ...

  9. idea集成python插件

    idea集成python插件 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在继承安装Python插件时,请确认你是否安装Python解释器(Python官网:https://ww ...

  10. Telnet的三种登录方式

    Telnet的三种登录方式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.华为创建telnet的三种验证方式 首先,我们可以简单的看一个拓扑图,让我们可以在亦庄的路由器上对双桥 ...