您的位置:首页 > 其它

驱动中platform resource 和 porbe 之间的关系

2012-12-29 12:13 211 查看
1. platform_device 会包含platform_data 和 resource定义:

一般platform device信息,会定义在 arch/arm/mach-xxx/board-xxx.c 中。

如这里的sarac模块,被定义在arch/arm/mach-cartesio/core-sta2065.c中

[cpp] view
plaincopy

static struct platform_device sarac_device = {

.name = "cartesio-sarac",

.id = 1,

.dev = {

.init_name = "cartesio-sarac",

//设备中包含的 platform数据

.platform_data = &sarac_platform_data,

},

.num_resources = ARRAY_SIZE(sarac_resource),

//包含的资源

.resource = sarac_resource,

};

这里的 .name 很重要,驱动会根据这个名字,在probe的时候进行匹配,如果有名字相同,就会匹配上。

platform_device 的定义如下:

[cpp] view
plaincopy

struct platform_device {

const char * name;

int id;

struct device dev;

u32 num_resources;

struct resource * resource;

const struct platform_device_id *id_entry;

/* arch specific additions */

struct pdev_archdata archdata;

};

他包含了一个设备dev,还有resource. 这些都是platform的优势,可以包含很多信息。

如上面的sarac_device,就包含了sarac_platform_data 和 sarac_resource 两块内容,具体定义如下:

[cpp] view
plaincopy

static struct sarac_platform_data_container sarac_platform_data = {

//这个platform data 其实就是一个DMA slave 的定义

.mem2sarac_slave = {

.dma_dev = &dma0_device.dev, /* SARAC bound to DMA0 */

.tx_req_line = DMA0_REQ_SRC_DMA_DRE,

.rx_req_line = DMA0_REQ_SRC_DMA_DRF,

.nr_descs = 2048,

.channel = DMA_CHANNEL_AUTO,

.slave_width = DMA_TRANSFER_WIDTH_32BIT,

.flow_ctrlr = DMA_FLOW_CONTROLLER_DMA,

.burst_size = DMA_BURST_SIZE_1, /* fifo packet size */

.ahb_master = DMA_AHB_MASTER_0,

},

};

[cpp] view
plaincopy

static struct resource sarac_resource[] = {

//resource 包含了两块,一块是寄存器访问地址, 一块是中断号信息

[0] = {

.start = CARTESIO_SARAC_BASE,

.end = CARTESIO_SARAC_BASE + SZ_4K - 1,

.name = "SaRaC registers",

.flags = IORESOURCE_MEM,

},

[1] = {

.start = IRQ_SARAC_DRF,

.end = IRQ_SARAC_DRF,

.name = "CartesioPlus SaRaC interrupt",

.flags = IORESOURCE_IRQ,

},

};

2. 驱动probe中对platform的使用

模块加载时,会注册platform driver: 也就是 platform_driver_register()函数;

[cpp] view
plaincopy

static int __init cartesio_sarac_init(void)

{

return platform_driver_register(&cartesio_sarac_driver);

}

module_init(cartesio_sarac_init);

cartesio_sarac_driver的定义如下:

[cpp] view
plaincopy

static struct platform_driver cartesio_sarac_driver = {

.probe = cartesio_sarac_probe,

.remove = __devexit_p(cartesio_sarac_remove),

.driver = {

.name = DEVICE_NAME,

.owner = THIS_MODULE,

},

};

这里的.name 定义必须跟之前platform定义中的.name 一致,这样platform驱动和设备才能匹配上。

[cpp] view
plaincopy

/*

* Asynchronous SaRaC device name

*/

#define DEVICE_NAME "cartesio-sarac"

该驱动被加载时,会自动运行cartesio_sarac_probe 函数:

[cpp] view
plaincopy

static int __devinit cartesio_sarac_probe(struct platform_device *pdev)

{

struct sarac_device_data *sarac_device;

struct resource *res;

struct sarac_platform_data_container *sarac_plat_data=NULL;

int ret;

sarac_device = kzalloc(sizeof(struct sarac_device_data), GFP_KERNEL);

if (!sarac_device) {

dev_err(&pdev->dev, "not enough memory for driver status\n");

return -ENOMEM;

}

//通过这个函数,就把 platform_device 中的内容,赋给 sarac_device,就可以在这驱动中使用了

//这里的pdev 就是指向platform_device的指针。

platform_set_drvdata(pdev, sarac_device);

printk("SARAC probe called\n");

//该函数用来获取platform中的resource资源

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

if (!res) {

dev_err(&pdev->dev, "register area not defined\n");

ret = -ENODEV;

goto out_free;

}

//把IO空间,赋值给sarac_device

sarac_device->base_addr = ioremap(res->start, resource_size(res));

if (!sarac_device->base_addr) {

dev_err(&pdev->dev, "unable to remap register area\n");

ret = -ENODEV;

goto out_free;

}

//把platform_device->dev.platform_data 赋值过来

sarac_plat_data = pdev->dev.platform_data;

if (sarac_plat_data->mem2sarac_slave.dma_dev) {

sarac_device->dma_to_sarac_client = &sarac_plat_data->mem2sarac_slave;

sarac_device->dma_to_sarac_client->tx_reg = res->start + SARAC_DILR;

sarac_device->dma_from_sarac_address = res->start + SARAC_DOLR;

} else {

dev_err(&pdev->dev, "DMA info not found in platform data\n");

ret = -1;

goto dma_err;

}

//把platform_device 中的IRQ 信息赋值过来

sarac_device->irq = platform_get_irq(pdev, 0);

//注册中断

ret = request_irq(sarac_device->irq, cartesio_sarac_irq_handler, 0,

dev_name(&pdev->dev), &pdev->id);

if (ret) {

dev_err(&pdev->dev, "failed to allocate IRQ %d\n", sarac_device->irq);

goto out_unmap;

}

else {

aab_peripheral_enable(AAB_SARAC, AAB_AC_WRITE | AAB_AC_READ);

}

//在sys中创建信息接口

sarac_kobj = kobject_create_and_add("audio_sarac", NULL);

if (!sarac_kobj)

return -ENOMEM;

ret = sysfs_create_group(sarac_kobj, &cartesio_sarac_attr_group);

if (ret)

return ret;

dev_info(&pdev->dev, "Module initialized, version" DRV_VERSION "\n");

return 0;

dma_err:

out_unmap:

iounmap(sarac_device->base_addr);

out_free:

kfree(sarac_device);

return ret;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: