3.0.35 platformデバイスリソースとデータ

14308 ワード

構造体platform_デバイスの定義(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の3つのフィールドに関心を持ち、リソースの開始値、終了値、タイプを表します.
タイプフィールドもioport.hに定義があり、IORESOURCEをサポートするIO, IORESOURCE_MEM, IORESOURCE_IRQ, IORESOURCE_DMAなど.
start,endの意味はflagsによって変更され、例えばflagsがIORESOURCE_である場合MEMの場合、start,endはそれぞれそのplatform_を表すデバイスが占めるメモリの
開始アドレスと終了アドレス;flagsがIORESOURCEである場合IRQの場合、start,endはそれぞれそのplatform_を表すデバイスが使用する割り込み番号の開始値と終了値.
resourceの定義は通常BSPのボードファイルで行われ、platform_を介して行われます.device_add_resources()は、リソースファイルをステージデバイスに登録し、具体的な設定
予備駆動でplatform_を通過get_resource()を使用して、次のように定義します.
/**

 * 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.IMx 6開発ボードのボードファイルには、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);

 
IMx 6の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を導入する概念には、少なくとも次の2つの利点があります.
1)設備を一つのバスに接続させ、管理する
2)BSPと駆動を分離した.BSPではplatformデバイスとデバイスが使用するリソース、デバイスの具体的な情報を定義しますが、ドライバでは汎用APIで取得するだけです.
リソースとデータは、ボード関連コードと駆動コードの分離を実現し、より良い拡張性とプラットフォーム間で駆動する必要があります.