博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3.0.35 platform 设备资源和数据
阅读量:5071 次
发布时间:2019-06-12

本文共 5847 字,大约阅读时间需要 19 分钟。

在结构体 platform_device 的定义(include/linux/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;};

描述了platform_device 的资源,资源本身由结构体 resource 描述,其定义(include/linux/ioport.h)如下示:

/* * Resources are tree-like, allowing * nesting etc.. */struct resource {    resource_size_t start;    resource_size_t end;    const char *name;    unsigned long flags;    struct resource *parent, *sibling, *child;};

我们通常关心 start, end, flags 这三个字段,分别表示资源的开始值、结束值和类型。

类型字段也在ioport.h中有定义,支持 IORESOURCE_IO, IORESOURCE_MEM, IORESOURCE_IRQ, IORESOURCE_DMA 等。

start, end 的含义随着flags 而变更,如当 flags 为 IORESOURCE_MEM时,start, end 分别表示该 platform_device 占据的内存的

开始地址和结束地址;当flags 为 IORESOURCE_IRQ时,start, end 分别表示该 platform_device 使用的中断号的开始值和结束值。

对 resource 的定义通常在BSP的板文件中进行,并通过platform_device_add_resources()将资源文件注册到台设备中,而在具体的设

备驱动中通过platform_get_resource() 来获取,其定义(drivers/base/platform.c),如下:

/** * platform_get_resource - get a resource for a device * @dev: platform device * @type: resource type * @num: resource index */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;}EXPORT_SYMBOL_GPL(platform_get_resource);

 

例如在 MY.IMx6 开发板的板文件中为 ECSPI 定义(arch/arm/plat-mxc/devices/platform-spi_imx.c)了如下的resource:

struct platform_device *__init imx_add_spi_imx(        const struct imx_spi_imx_data *data,        const struct spi_imx_master *pdata){    struct resource res[] = {        {            .start = data->iobase,            .end = data->iobase + data->iosize - 1,            .flags = IORESOURCE_MEM,        }, {            .start = data->irq,            .end = data->irq,            .flags = IORESOURCE_IRQ,        },    };    return imx_add_platform_device(data->devid, data->id,            res, ARRAY_SIZE(res), pdata, sizeof(*pdata));}

通过 imx_add_platform_device() 将资源文件添加,其定义(arch/arm/plat-mxc/include/mach/devices-common.h)如下:

static inline struct platform_device *imx_add_platform_device(        const char *name, int id,        const struct resource *res, unsigned int num_resources,        const void *data, size_t size_data){    return imx_add_platform_device_dmamask(            name, id, res, num_resources, data, size_data, 0);}

imx_add_platform_device_dmamask() ,其定义(arch/arm/plat-mxc/devices.c)如下:

struct platform_device *__init imx_add_platform_device_dmamask(        const char *name, int id,        const struct resource *res, unsigned int num_resources,        const void *data, size_t size_data, u64 dmamask){    int ret = -ENOMEM;    struct platform_device *pdev;    pdev = platform_device_alloc(name, id);    if (!pdev)        goto err;    if (dmamask) {        /*         * This memory isn't freed when the device is put,         * I don't have a nice idea for that though.  Conceptually         * dma_mask in struct device should not be a pointer.         * See http://thread.gmane.org/gmane.linux.kernel.pci/9081         */        pdev->dev.dma_mask =            kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);        if (!pdev->dev.dma_mask)            /* ret is still -ENOMEM; */            goto err;        *pdev->dev.dma_mask = dmamask;        pdev->dev.coherent_dma_mask = dmamask;    }    if (res) {        ret = platform_device_add_resources(pdev, res, num_resources);        if (ret)            goto err;    }    if (data) {        ret = platform_device_add_data(pdev, data, size_data);        if (ret)            goto err;    }    ret = platform_device_add(pdev);    if (ret) {err:        if (dmamask)            kfree(pdev->dev.dma_mask);        platform_device_put(pdev);        return ERR_PTR(ret);    }    return pdev;}

而最终调用了 platform_device_add_resources() 其定义(drivers/base/platform.c)如下:

/** * platform_device_add_resources - add resources to a platform device * @pdev: platform device allocated by platform_device_alloc to add resources to * @res: set of resources that needs to be allocated for the device * @num: number of resources * * Add a copy of the resources to the platform device.  The memory * associated with the resources will be freed when the platform device is * released. */int platform_device_add_resources(struct platform_device *pdev,                  const struct resource *res, unsigned int num){    struct resource *r = NULL;    if (res) {        r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);        if (!r)            return -ENOMEM;    }    kfree(pdev->resource);    pdev->resource = r;    pdev->num_resources = num;    return 0;}EXPORT_SYMBOL_GPL(platform_device_add_resources);

 

在IMx6 的SPI驱动中则是通过如下方法得到这2份资源:

具体是在 drivers/spi/spi_imx.c 的 spi_imx_probe() 方法中

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);spi_imx->irq = platform_get_irq(pdev, 0);

而 platform_get_irq 的定义如下:

/** * platform_get_irq - get an IRQ for a device * @dev: platform device * @num: IRQ number index */int platform_get_irq(struct platform_device *dev, unsigned int num){    struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);    return r ? r->start : -ENXIO;}EXPORT_SYMBOL_GPL(platform_get_irq);

 

设备除了可以在BSP中定义资源文件外,还可以附加一些数据信息,因为对设备的硬件描述除了中断,内存,DMA外,可能还会有

一些配置信息,而这些配置信息也依赖于板,不适宜直接放置在驱动本身,因此,platform 也提供了 platform_data 的支持。

 

设备驱动中引入platform 的概念至少有如下两个好处:

1)使得设备被挂接到一个总线上,文便管理

2)隔离了BSP和驱动。在BSP中定义platform设备和设备使用的资源,设备的具体信息,而在驱动中,只需要通过通用API去获取

     资源和数据,做到了板相关代码和驱动代码的分离,便得驱动具有更好的可扩展性和跨平台性。

转载于:https://www.cnblogs.com/aqing1987/p/4355197.html

你可能感兴趣的文章
map基本用法
查看>>
爬虫系列1:Requests+Xpath 爬取豆瓣电影TOP
查看>>
String与StringBuffer的区别
查看>>
ASP方法进行301重定向实战演示
查看>>
Apache Beam 模型
查看>>
vue基础5-生命周期
查看>>
字符编码之间的相互转换 UTF8与GBK(转载)
查看>>
关于vs2003调试时提示:试图运行项目时出错:无法启动调试 没有正确安装调试器。请运行安装程序安装...
查看>>
分享:APK高级保护方法解析(三)
查看>>
$().attr()的使用方法 &amp;&amp; $().html()与$().text()的差别
查看>>
宁夏2018年计算机软件水平考试报名时间
查看>>
Java MyBatis 插入数据库返回主键
查看>>
Spring JDBC 【注入JdbcTemplate】
查看>>
矩阵快速幂HDU6030
查看>>
Git的初步学习
查看>>
linux&Mysql
查看>>
考试反思(2019/1/22)
查看>>
电商app开发新趋势!如何突显竞争力?
查看>>
信息系统综合知识概览
查看>>
winform中ComboBox利用AutoComplete属性实现模糊查询(有缺陷)
查看>>