代码学习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);
更多推荐
代码学习linux内核驱动(十)
发布评论