zoukankan      html  css  js  c++  java
  • 3.0.35 platform 设备资源和数据

    在结构体 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去获取

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

  • 相关阅读:
    JDBC的初步了解及使用
    HTML+CSS的小实例
    java接口与抽象类
    java类的继承(基础)
    java中求质数(素数)的问题
    对HTML5标签的认识(四)
    对HTML5标签的认识(三)
    对HTML5标签的认识(三)
    SublimeText2 快捷键一览表
    Node开发项目管理工具 Grunt 对比 Gulp
  • 原文地址:https://www.cnblogs.com/aqing1987/p/4355197.html
Copyright © 2011-2022 走看看