1. platform_device 会包含platform_data 和 resource定义:
一般platform device信息,会定义在 arch/arm/mach-xxx/board-xxx.c 中。
如这里的sarac模块,被定义在arch/arm/mach-cartesio/core-sta2065.c中
- 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 的定义如下:
- 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;
- };
如上面的sarac_device,就包含了sarac_platform_data 和 sarac_resource 两块内容,具体定义如下:
- 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,
- },
- };
- 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,
- },
- };
模块加载时,会注册platform driver: 也就是 platform_driver_register()函数;
- static int __init cartesio_sarac_init(void)
- {
- return platform_driver_register(&cartesio_sarac_driver);
- }
- module_init(cartesio_sarac_init);
- static struct platform_driver cartesio_sarac_driver = {
- .probe = cartesio_sarac_probe,
- .remove = __devexit_p(cartesio_sarac_remove),
- .driver = {
- .name = DEVICE_NAME,
- .owner = THIS_MODULE,
- },
- };
- /*
- * Asynchronous SaRaC device name
- */
- #define DEVICE_NAME "cartesio-sarac"
- 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;
- }