zoukankan      html  css  js  c++  java
  • Android平台上PMEM的使用及Platform设备注册(二)

    三、注册PMEM设备

    这里我们除了描述PMEM设备,还将注册一个拥有memory空间和IRQ资源的示例设备example_device

    对于example_device,定义如下结构体:

    static struct resource example_resources[] = {

        [0] = {

            .start  = 0xC0000000,

            .end    = 0xC0020000,

            .flags  = IORESOURCE_MEM,

        },

        [1] = {

            .start  = 30,

            .end    = 30,

            .flags  = IORESOURCE_IRQ,

        },

    };

     

    static struct platform_device example_device = {

        .name           = "example",

        .id             = 0,

        .num_resources  = ARRAY_SIZE(example_resources),

        .resource       = example_resources,

    };

        example_device设备拥有IORESOURCE_MEM和IORESOURCE_IRQ两种资源,其IORESOURCE_MEM的起始地址为0xC0000000,结束地址为0xC0020000,IORESOURCE_IRQ的中断号为30。

        对于PMEM设备,我们先要介绍一下结构体android_pmem_platform_data。它被定义在文件/kernel/include/linux/android_pmem.h中。其定义为:

    struct android_pmem_platform_data

    {

        const char* name;

        /* starting physical address of memory region */

        unsigned long start;

        /* size of memory region */

        unsigned long size;

        /* set to indicate the region should not be managed with an allocator */

        unsigned no_allocator;

        /* set to indicate maps of this region should be cached, if a mix of

         * cached and uncached is desired, set this and open the device with

         * O_SYNC to get an uncached region */

        unsigned cached;

        /* The MSM7k has bits to enable a write buffer in the bus controller*/

        unsigned buffered;

    };

        我们为PMEM设备定义如下结构体:

    static struct android_pmem_platform_data android_pmem0_pdata = {

           .name = "pmem0",

           .start = PMEM_0_BASE,

           .size = PMEM_0_SIZE,

           .no_allocator = 0,

           .cached = 1,

    };

    static struct android_pmem_platform_data android_pmem1_pdata = {

           .name = "pmem1",

           .start = PMEM_1_BASE,

           .size = PMEM_1_SIZE,

           .no_allocator = 0,

           .cached = 1,

    };

     

    struct platform_device android_pmem0_device = {

           .name = "android_pmem",

           .id = 0,

           .dev = { .platform_data = &android_pmem0_pdata },

    };

     

    struct platform_device android_pmem1_device = {

           .name = "android_pmem",

           .id = 1,

           .dev = { .platform_data = &android_pmem1_pdata },

    };

        然后将这几个设备结构体放置到一个platform_device的数组中,

    static struct platform_device *devices[] __initdata = {

        &example_device,

        &android_pmem0_device,

        &android_pmem1_device,

    };

        最后通过调用函数platform_add_devices()向系统中添加这些设备。

    static void __init androidphone_init(void)

    {

        ……

        platform_add_devices(devices, ARRAY_SIZE(devices));

        ……

    }

     

    函数platform_add_devices()内部调用platform_device_register( )进行设备注册。要注意的是,这里的platform_device设备的注册过程必须在相应设备驱动加载之前被调用,即执行platform_driver_register()之前,原因是驱动注册时需要匹配内核中所有已注册的设备名。

           函数platform_add_devices()定义在文件/kernel/driver/base/platform.c中,

    /**

     * platform_add_devices - add a numbers of platform devices

     * @devs: array of platform devices to add

     * @num: number of platform devices in array

     */

    int platform_add_devices(struct platform_device **devs, int num)

    {

        int i, ret = 0;

     

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

            ret = platform_device_register(devs[i]);

            if (ret) {

                while (--i >= 0)

                    platform_device_unregister(devs[i]);

                break;

            }

        }

     

        return ret;

    }

    EXPORT_SYMBOL_GPL(platform_add_devices);

    最后,需要说明的结构体是platform_driver,它的原型定义,在

    /kernel/include/linux/platform_device.h中,代码如下:

    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;

        struct platform_device_id *id_table;

    };

    内核提供的platform_driver结构体的注册函数为platform_driver_register(),其原型定义在/kernel/driver/base/platform.c文件中,具体实现代码如下:

    /**

     * platform_driver_register

     * @drv: platform driver structure

     */

    int platform_driver_register(struct platform_driver *drv)

    {

        drv->driver.bus = &platform_bus_type;

        if (drv->probe)

            drv->driver.probe = platform_drv_probe;

        if (drv->remove)

            drv->driver.remove = platform_drv_remove;

        if (drv->shutdown)

            drv->driver.shutdown = platform_drv_shutdown;

     

        return driver_register(&drv->driver);

    }

    EXPORT_SYMBOL_GPL(platform_driver_register);

     

           如果想深入了解Platform机制,可以参考下面的文章:

    Linux Platform驱动程序框架解析

    http://www.linuxidc.com/Linux/2011-01/31291.htm

    Linux内核驱动的的platform机制

    http://intq.blog.163.com/blog/static/671231452010124112546491/

     

    E-mailwxiaozhe@163.com

    QQ1226062415
    Date
    2011/5/14
    Blog
    http://blog.csdn.net/wxzking

    欢迎交流,欢迎转载,转载时请保留以上信息。

  • 相关阅读:
    [转]学习NotesList(Robotium自带的例子)
    [转] Android Test Auto Test Multi Activities
    [转]重新签名Android preinstall APK
    [转]简单介绍如何使用robotium进行自动化测试
    javascript bind函数
    IE中不可遍历的属性
    访问私有变量
    高效地获取XMLhttp对象
    判定IE的各个版本
    CSS Selector の最大の欠点
  • 原文地址:https://www.cnblogs.com/nsnow/p/3831563.html
Copyright © 2011-2022 走看看