0
点赞
收藏
分享

微信扫一扫

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/

举报

相关推荐

0 条评论