阅读 129

详解linux dma驱动编写

这篇文章主要介绍了详解linux dma驱动编写,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

linux下面的驱动虽然什么样的情形都有,但是dma驱动却并不少见。dma可以有很多的好处,其中最重要的功能就是能够帮助我们将数据搬来搬去,这个时候cpu就由时间去做别的事情了,提高了设备效率。

1、dma驱动在什么地方

1
drivers/dma

2、如何看s3c的dma驱动,先看Kconfig

1
2
3
4
5
6
7
8
9
10
11
config S3C24XX_DMAC
  bool "Samsung S3C24XX DMA support"
  depends on ARCH_S3C24XX || COMPILE_TEST
  select DMA_ENGINE
  select DMA_VIRTUAL_CHANNELS
  help
   Support for the Samsung S3C24XX DMA controller driver. The
   DMA controller is having multiple DMA channels which can be
   configured for different peripherals like audio, UART, SPI.
   The DMA controller can transfer data from memory to peripheral,
   periphal to memory, periphal to periphal and memory to memory.

3、发现s3c只依赖于S3C24XX_DMAC,这样可以接着看Makefile

1
obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o

4、确认驱动文件为s3c24xx-dma.c,了解基本结构

1
2
3
4
5
6
7
8
9
10
static struct platform_driver s3c24xx_dma_driver = {
  .driver   = {
    .name  = "s3c24xx-dma",
  },
  .id_table  = s3c24xx_dma_driver_ids,
  .probe   = s3c24xx_dma_probe,
  .remove   = s3c24xx_dma_remove,
};
  
module_platform_driver(s3c24xx_dma_driver);

5、驱动为基本的platform driver,接着就可以了解probe函数了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Initialize memcpy engine */
dma_cap_set(DMA_MEMCPY, s3cdma->memcpy.cap_mask);
dma_cap_set(DMA_PRIVATE, s3cdma->memcpy.cap_mask);
s3cdma->memcpy.dev = &pdev->dev;
s3cdma->memcpy.device_free_chan_resources =
        s3c24xx_dma_free_chan_resources;
s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy;
s3cdma->memcpy.device_tx_status = s3c24xx_dma_tx_status;
s3cdma->memcpy.device_issue_pending = s3c24xx_dma_issue_pending;
s3cdma->memcpy.device_config = s3c24xx_dma_set_runtime_config;
s3cdma->memcpy.device_terminate_all = s3c24xx_dma_terminate_all;
s3cdma->memcpy.device_synchronize = s3c24xx_dma_synchronize;
  
/* Initialize slave engine for SoC internal dedicated peripherals */
dma_cap_set(DMA_SLAVE, s3cdma->slave.cap_mask);
dma_cap_set(DMA_CYCLIC, s3cdma->slave.cap_mask);
dma_cap_set(DMA_PRIVATE, s3cdma->slave.cap_mask);
s3cdma->slave.dev = &pdev->dev;
s3cdma->slave.device_free_chan_resources =
        s3c24xx_dma_free_chan_resources;
s3cdma->slave.device_tx_status = s3c24xx_dma_tx_status;
s3cdma->slave.device_issue_pending = s3c24xx_dma_issue_pending;
s3cdma->slave.device_prep_slave_sg = s3c24xx_dma_prep_slave_sg;
s3cdma->slave.device_prep_dma_cyclic = s3c24xx_dma_prep_dma_cyclic;
s3cdma->slave.device_config = s3c24xx_dma_set_runtime_config;
s3cdma->slave.device_terminate_all = s3c24xx_dma_terminate_all;
s3cdma->slave.device_synchronize = s3c24xx_dma_synchronize;
s3cdma->slave.filter.map = pdata->slave_map;
s3cdma->slave.filter.mapcnt = pdata->slavecnt;
s3cdma->slave.filter.fn = s3c24xx_dma_filter;

6、通过code获悉,s3cdma有master和slave两个engine,且部分接口共享。

只要完成dma接口的适配,dma就可以正常使用了。当然,前提是,两个engine要进行注册使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ret = dma_async_device_register(&s3cdma->memcpy);
if (ret) {
  dev_warn(&pdev->dev,
    "%s failed to register memcpy as an async device - %d\n",
    __func__, ret);
  goto err_memcpy_reg;
}
  
ret = dma_async_device_register(&s3cdma->slave);
if (ret) {
  dev_warn(&pdev->dev,
    "%s failed to register slave as an async device - %d\n",
    __func__, ret);
  goto err_slave_reg;
}

以上就是本文的全部内容,希望对大家的学习有所帮助



文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐