代码学习linux内核驱动(十)

代码学习linux内核驱动(十)

DMA驱动使用

#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/atomic.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <linux/wait.h>
#include <linux/kthread.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/dma-mapping.h>
#include <asm-generic/dma.h>
#include <linux/platform_data/dma-imx.h>


/******************************************************
Linux设备模型:总线、设备、驱动
// request_dma disable_dma set_dma_mode set_dma_count enable_dma 需要使能CONFIG_GENERIC_ISA_DMA
//dma_async_device_register dma_request_slave_channel_reason dma_request_chan dmaengine_slave_config dmaengine_prep_slave_sg


******************************************************/
MODULE_AUTHOR("xyzeng");
MODULE_LICENSE("Dual BSD/GPL");
#define SDMA_BUF_SIZE  1024

struct completion dma_m2m_ok;
struct dma_chan *dma_m2m_chan;
static char *wbuf;
static char *rbuf;
static dma_addr_t wpaddr;
static dma_addr_t rpaddr;


static bool dma_m2m_filter(struct dma_chan *chan, void *param)
{
    if (!imx_dma_is_general_purpose(chan))
        return false;
    chan->private = param;
    return true;
}

static void dma_m2m_callback(void *data)
{
	printk("in %s\n",__func__);
	complete(&dma_m2m_ok);
	return ;
}

static int hello_probe(struct platform_device  *pdev)
{
    printk("[%s,%d] enter!\n",__FUNCTION__,__LINE__);
    dma_addr_t dma_addr ;
    struct imx_dma_data m2m_dma_data = {0};
    m2m_dma_data.peripheral_type = IMX_DMATYPE_MEMORY;
    m2m_dma_data.priority = DMA_PRIO_HIGH;

    dma_cap_mask_t dma_m2m_mask;
    dma_cap_zero(dma_m2m_mask);
    //dma_cap_set(DMA_SLAVE, dma_m2m_mask);
    dma_cap_set(DMA_MEMCPY, dma_m2m_mask);
    //dma_cap_set(DMA_MEMCPY, dma_m2m_mask);
    dma_m2m_chan = dma_request_channel(dma_m2m_mask, dma_m2m_filter, &m2m_dma_data);
    if (!dma_m2m_chan) {
        printk("Error opening the SDMA memory to memory channel\n");
        return -EINVAL;
    }
   
    init_completion(&dma_m2m_ok);

    wbuf = dma_alloc_coherent(NULL, SDMA_BUF_SIZE, &wpaddr, GFP_DMA);
    rbuf = dma_alloc_coherent(NULL, SDMA_BUF_SIZE, &rpaddr, GFP_DMA);
    memset(wbuf,0,SDMA_BUF_SIZE);
    memcpy(wbuf,"hello world",strlen("hello world"));
    
 /*   
    char * vaddr = (char *)dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &dma_addr, GFP_DMA); //以页大小申请 GFP_DMA
    if(vaddr == NULL){
        printk("dma_alloc_coherent null \n");
        return 0;
    }
    printk("dma_alloc_coherent %p:%d \n",vaddr,dma_addr);
    memcpy(vaddr,"hello world",64);
*/

    struct dma_slave_config dma_m2m_config;
    struct dma_async_tx_descriptor *dma_m2m_desc;
    dma_m2m_config.direction = DMA_MEM_TO_MEM;
    dma_m2m_config.dst_addr = rpaddr;
    dma_m2m_config.src_addr = wpaddr;
    dma_m2m_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
    dma_m2m_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
    dma_m2m_config.dst_maxburst = 4;
    dma_m2m_config.src_maxburst = 4;
    dmaengine_slave_config(dma_m2m_chan, &dma_m2m_config);
   // dma_m2m_desc = dma_m2m_chan->device->device_prep_dma_cyclic(dma_m2m_chan, NULL, SDMA_BUF_SIZE, SDMA_BUF_SIZE/2, DMA_MEM_TO_MEM);
    //dma_m2m_desc = dmaengine_prep_dma_cyclic(dma_m2m_chan,rpaddr,SDMA_BUF_SIZE,SDMA_BUF_SIZE/2,DMA_MEM_TO_MEM,1);

    dma_m2m_desc = dmaengine_prep_dma_memcpy(dma_m2m_chan,rpaddr,wpaddr,SDMA_BUF_SIZE,0);
    dma_m2m_desc->callback = dma_m2m_callback;
    dmaengine_submit(dma_m2m_desc);

    dma_async_issue_pending(dma_m2m_chan);
    wait_for_completion(&dma_m2m_ok);
    printk("src:%s\n",wbuf);
    printk("dst:%s\n",rbuf);
    int i=0;
        for (; i<SDMA_BUF_SIZE; i++) {
        printk("src_data_%d = %x\n",i, *(wbuf+i) );
        }
        for (i=0; i<SDMA_BUF_SIZE; i++) {
        printk("dst_data_%d = %x\n",i, *(rbuf+i) );
        }


    //dma_free_coherent(&pdev->dev,64,vaddr,dma_addr);
    dma_free_coherent(NULL,SDMA_BUF_SIZE,wbuf, wpaddr);
    dma_free_coherent(NULL,SDMA_BUF_SIZE,rbuf, rpaddr);
    

    
    return 0;
}

static int hello_remove(struct platform_device  *pdev)
{
    printk("[%s,%d] enter!\n",__FUNCTION__,__LINE__);
    
    return 0;
}

static const struct platform_device_id hello_platform_id[] = {
    {
        .name = "device_hello",//device_hello hello-world  匹配设备名
        .driver_data = 1 ,
    }
};


char * hello_world = "hello world!\n";

static const struct of_device_id hello_dt_ids[] = {
    { .compatible = "hello-world", .data = &hello_world, },
};


static struct platform_driver hello_driver = {
    .probe  = hello_probe,
    .remove = hello_remove,
    .driver= {
        .owner          = THIS_MODULE,
        .of_match_table = hello_dt_ids,  //匹配设备
        .name           = "driver_hello",
    },
    .id_table = hello_platform_id,
};

static int code_case_dma_init(void)
{
    printk("[%s,%d] enter!\n",__FUNCTION__,__LINE__);
    platform_driver_register(&hello_driver);
    return 0;
}
static void code_case_dma_exit(void)
{
     printk("[%s,%d] enter!\n",__FUNCTION__,__LINE__);
     platform_driver_unregister(&hello_driver);
}

module_init(code_case_dma_init);
module_exit(code_case_dma_exit);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值