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

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 plain copy
  1. static struct platform_device sarac_device = {  
  2.         .name           = "cartesio-sarac",  
  3.         .id             = 1,  
  4.         .dev = {  
  5.                 .init_name = "cartesio-sarac",  
  6.                  //设备中包含的 platform数据   
  7.                 .platform_data = &sarac_platform_data,  
  8.         },  
  9.         .num_resources  = ARRAY_SIZE(sarac_resource),  
  10.          //包含的资源  
  11.         .resource       = sarac_resource,  
  12.   };  

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

platform_device 的定义如下:

[cpp]  view plain copy
  1. struct platform_device {  
  2.         const char      * name;  
  3.         int             id;  
  4.         struct device   dev;  
  5.         u32             num_resources;  
  6.         struct resource * resource;  
  7.           
  8.         const struct platform_device_id *id_entry;  
  9.           
  10.         /* arch specific additions */  
  11.         struct pdev_archdata    archdata;  
  12. };        
他包含了一个设备dev,还有resource. 这些都是platform的优势,可以包含很多信息。

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

[cpp]  view plain copy
  1. static struct sarac_platform_data_container sarac_platform_data = {  
  2.         //这个platform data 其实就是一个DMA slave 的定义  
  3.         .mem2sarac_slave = {  
  4.                 .dma_dev        = &dma0_device.dev,     /* SARAC bound to DMA0 */  
  5.                 .tx_req_line    = DMA0_REQ_SRC_DMA_DRE,  
  6.                 .rx_req_line    = DMA0_REQ_SRC_DMA_DRF,  
  7.                 .nr_descs       = 2048,  
  8.                 .channel        = DMA_CHANNEL_AUTO,  
  9.                 .slave_width    = DMA_TRANSFER_WIDTH_32BIT,  
  10.                 .flow_ctrlr     = DMA_FLOW_CONTROLLER_DMA,  
  11.                 .burst_size     = DMA_BURST_SIZE_1,     /* fifo packet size */  
  12.                 .ahb_master     = DMA_AHB_MASTER_0,  
  13.         },  
  14. };  
[cpp]  view plain copy
  1. static struct resource sarac_resource[] = {  
  2.         //resource 包含了两块,一块是寄存器访问地址, 一块是中断号信息  
  3.         [0] = {  
  4.                 .start  = CARTESIO_SARAC_BASE,  
  5.                 .end    = CARTESIO_SARAC_BASE + SZ_4K - 1,  
  6.                 .name   = "SaRaC registers",  
  7.                 .flags  = IORESOURCE_MEM,  
  8.         },  
  9.         [1] = {  
  10.                 .start  = IRQ_SARAC_DRF,  
  11.                 .end    = IRQ_SARAC_DRF,  
  12.                 .name   = "CartesioPlus SaRaC interrupt",  
  13.                 .flags  = IORESOURCE_IRQ,  
  14.         },  
  15. };        
2.  驱动probe中对platform的使用

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

[cpp]  view plain copy
  1. static int __init cartesio_sarac_init(void)  
  2. {  
  3.         return platform_driver_register(&cartesio_sarac_driver);  
  4. }  
  5. module_init(cartesio_sarac_init);  
cartesio_sarac_driver的定义如下:

[cpp]  view plain copy
  1. static struct platform_driver cartesio_sarac_driver = {  
  2.         .probe          = cartesio_sarac_probe,  
  3.         .remove         = __devexit_p(cartesio_sarac_remove),  
  4.         .driver = {  
  5.                 .name   = DEVICE_NAME,  
  6.                 .owner  = THIS_MODULE,  
  7.         },  
  8. };  
这里的.name 定义必须跟之前platform定义中的.name 一致,这样platform驱动和设备才能匹配上。

[cpp]  view plain copy
  1. /* 
  2.  * Asynchronous SaRaC device name 
  3.  */  
  4. #define DEVICE_NAME     "cartesio-sarac"  
该驱动被加载时,会自动运行cartesio_sarac_probe 函数:
[cpp]  view plain copy
  1. static int __devinit cartesio_sarac_probe(struct platform_device *pdev)  
  2. {  
  3.         struct sarac_device_data *sarac_device;  
  4.         struct resource *res;  
  5.         struct sarac_platform_data_container *sarac_plat_data=NULL;  
  6.   
  7.         int ret;  
  8.   
  9.         sarac_device = kzalloc(sizeof(struct sarac_device_data), GFP_KERNEL);  
  10.         if (!sarac_device) {  
  11.                 dev_err(&pdev->dev, "not enough memory for driver status\n");  
  12.                 return -ENOMEM;  
  13.         }  
  14.   
  15.         //通过这个函数,就把 platform_device 中的内容,赋给 sarac_device,就可以在这驱动中使用了  
  16.         //这里的pdev 就是指向platform_device的指针。  
  17.         platform_set_drvdata(pdev, sarac_device);  
  18.   
  19.         printk("SARAC probe called\n");  
  20.   
  21.         //该函数用来获取platform中的resource资源  
  22.         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
  23.         if (!res) {  
  24.                 dev_err(&pdev->dev, "register area not defined\n");  
  25.                 ret = -ENODEV;  
  26.                 goto out_free;  
  27.         }  
  28.   
  29.         //把IO空间,赋值给sarac_device  
  30.         sarac_device->base_addr = ioremap(res->start, resource_size(res));  
  31.         if (!sarac_device->base_addr) {  
  32.                 dev_err(&pdev->dev, "unable to remap register area\n");  
  33.                 ret = -ENODEV;  
  34.                 goto out_free;  
  35.         }  
  36.   
  37.         //把platform_device->dev.platform_data 赋值过来  
  38.         sarac_plat_data = pdev->dev.platform_data;  
  39.   
  40.         if (sarac_plat_data->mem2sarac_slave.dma_dev) {  
  41.                 sarac_device->dma_to_sarac_client = &sarac_plat_data->mem2sarac_slave;  
  42.   
  43.                 sarac_device->dma_to_sarac_client->tx_reg = res->start + SARAC_DILR;  
  44.   
  45.                 sarac_device->dma_from_sarac_address = res->start + SARAC_DOLR;  
  46.   
  47.         } else {  
  48.                 dev_err(&pdev->dev, "DMA info not found in platform data\n");  
  49.                 ret = -1;  
  50.                 goto dma_err;  
  51.         }  
  52.   
  53.         //把platform_device 中的IRQ 信息赋值过来  
  54.         sarac_device->irq = platform_get_irq(pdev, 0);  
  55.   
  56.         //注册中断  
  57.         ret = request_irq(sarac_device->irq, cartesio_sarac_irq_handler, 0,  
  58.                                          dev_name(&pdev->dev), &pdev->id);  
  59.         if (ret) {  
  60.                 dev_err(&pdev->dev, "failed to allocate IRQ %d\n", sarac_device->irq);  
  61.                 goto out_unmap;  
  62.         }  
  63.         else {  
  64.                 aab_peripheral_enable(AAB_SARAC, AAB_AC_WRITE | AAB_AC_READ);  
  65.         }  
  66.   
  67.         //在sys中创建信息接口  
  68.         sarac_kobj = kobject_create_and_add("audio_sarac", NULL);  
  69.         if (!sarac_kobj)  
  70.                 return -ENOMEM;  
  71.   
  72.         ret = sysfs_create_group(sarac_kobj, &cartesio_sarac_attr_group);  
  73.         if (ret)  
  74.                 return ret;  
  75.   
  76.         dev_info(&pdev->dev, "Module initialized, version" DRV_VERSION  "\n");  
  77.         return 0;  
  78.   
  79. dma_err:  
  80. out_unmap:  
  81.         iounmap(sarac_device->base_addr);  
  82. out_free:  
  83.         kfree(sarac_device);  
  84.         return ret;  
  85. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值