📄 d11_dma.c
字号:
len += sprintf(buf+len, "LCDCON2=%8x\n", LCDCON2);
len += sprintf(buf+len, "LCDCON3=%8x\n", LCDCON3);
len += sprintf(buf+len, "LCDCON4=%8x\n", LCDCON4);
len += sprintf(buf+len, "LCDCON5=%8x\n", LCDCON5);
len += sprintf(buf+len, "LCDADDR1=%8x\n", LCDADDR1);
len += sprintf(buf+len, "LCDADDR2=%8x\n", LCDADDR2);
len += sprintf(buf+len, "LCDADDR3=%8x\n", LCDADDR3);
return len;
}
static ssize_t d11_dma_proc_write(struct file *filp, const char *buf, unsigned long len, void *data)
{
return 0;
}
static int d11_dma_create_proc(void)
{
d11_dma_proc_entry = create_proc_entry("d11_dma", 0644, NULL);
if(d11_dma_proc_entry == NULL){
printk("d11_dma: Couldn't create proc entry!\n");
return -ENOMEM;
}
d11_dma_proc_entry->read_proc = d11_dma_proc_read;
d11_dma_proc_entry->write_proc = d11_dma_proc_write;
d11_dma_proc_entry->owner = THIS_MODULE;
return 0;
}
static void d11_dma_remove_proc(void)
{
remove_proc_entry("d11_dma", NULL);
}
/**************************************************************************/
static int d11_dma_open(struct inode * inode, struct file * filp)
{
if(d11_dma_ucount){ // restrict one process open this device.
return -EBUSY;
}
d11_dma_ucount++;
MOD_INC_USE_COUNT;
DPRINTK("open\n");
return 0;
}
static int d11_dma_release(struct inode * inode, struct file * filp)
{
d11_dma_ucount--;
MOD_DEC_USE_COUNT;
DPRINTK("release\n");
return 0;
}
static int d11_dma_ioctl(struct inode * inode, struct file * filp, unsigned int command, unsigned long arg)
{
struct image_dma_t image_dma_data;
copy_from_user(&image_dma_data, (struct image_dma_t *)(arg), sizeof(image_dma_data));
switch(command){
case D11_DMA_IOCWRITE:
if(image_review_buf.freeze && (!image_dma_data.freeze)){
flag_unfreeze = 1;
}
image_review_buf.freeze = image_dma_data.freeze;
/********* 请求写入的新回放区小于原回放区大小***************/
if(image_dma_data.nr_mmblks < image_review_buf.nr_mmblks) {
return 0;
}
/*******************************************************************************
请求写入的新回放区大于原回放区大小且
不超过IMG_MAX_NR 定义的最大回放区大小
*******************************************************************************/
else if((image_dma_data.nr_mmblks > image_review_buf.nr_mmblks)
&& (image_dma_data.nr_mmblks <= IMG_MAX_NR)) {
return 0;
}
return 0;
/*********************** 读取回放区数据***********************************/
case D11_DMA_IOCREAD:
copy_to_user((struct image_dma_t *)(arg), &image_review_buf, sizeof(image_review_buf));
return 0;
#ifdef D11_DMA_DEBUG
case D11_DMA_IOCDBGRST:
/*
in debug mode, this can remove module forcely
*/
while(MOD_IN_USE)
MOD_DEC_USE_COUNT;
MOD_INC_USE_COUNT;
return 0;
#endif /* D11_DMA_DEBUG */
default:
return -ENOTTY; // Inappropriate ioctl for device.
}
return -ENOTTY; // can't recognize the command.
}
static struct file_operations d11_dma_fops = {
ioctl: d11_dma_ioctl,
poll: d11_dma_poll,
mmap: d11_dma_mmap,
read: d11_dma_read,
write: d11_dma_write,
open: d11_dma_open,
release: d11_dma_release,
};
#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_d11_dma_dir, devfs_d11_dma;
#endif
static int __init init_xdreq0_dma(void)
{
int ret;
set_external_irq(IRQ_EINT2, EXT_RISING_EDGE, GPIO_PULLUP_EN); // 设置外中断2
ret = request_irq(IRQ_EINT2, handler_isr_eint2, SA_INTERRUPT, DEVICE_NAME, NULL);
if(ret < 0){
printk(" unable to get EINT2 interrupts\n" );
return -EBUSY;
}
ret = request_irq(IRQ_DMA0, handler_Dma0Done, SA_INTERRUPT, DEVICE_NAME, NULL);
if(ret < 0){
printk(" unable to get DMA0 interrupts\n" );
return -EBUSY;
}
set_gpio_ctrl(GPIO_B9 | GPIO_PULLUP_EN | GPIO_MODE_nXDACK); // GPB9=nXDACK0
set_gpio_ctrl(GPIO_B10 | GPIO_PULLUP_EN | GPIO_MODE_nXDREQ); // GPB10=nXDREQ0
//(void *)fpga_dma0_reg = ioremap(FPGA_DMA0, 4); // Can delete.
GPHCON &= (~(0x0f << 18));
GPHCON |= (0x0a << 18); //GPH9、GPH10 set as clkout.
MISCCR=0x10410; // clkout0=48M,clkout1=PCLK
DISRC0 = FPGA_DMA0; // Bank5 0x28000000
DISRCC0 = (0<<1)+(1<<0); // AHB,fixed
DIDST0 = image_review_buf.image_dma_mmphy[0];
DIDSTC0 = (0<<1)+(0<<0); // AHB, inc
DCON0 = (1<<31)+(1<<30)+(1<<29)+(1<<28)+(0<<27)+(0<<24)+(1<<23)+(1<<22)+(2<<20)+IMG_SIZE/16;
//handshake, sync HCLK, TC int, burst tx, single service, nXDREQ0, H/W request, auto-reload off, word, 64hw
DMTRIG0 = (0<<2)+(1<<1)+0; //no-stop, DMA0 channel on, no-sw trigger
DPRINTK("INTMSK=0x%8x\n", INTMSK);
DPRINTK("GPBCON=0x%8x\n", GPBCON);
DPRINTK("MISCCR=0x%8x\n", MISCCR);
DPRINTK("DISRC0=0x%8x\n", DISRC0);
DPRINTK("DISRCC0=0x%8x\n", DISRCC0);
DPRINTK("DIDST0=0x%8x\n", DIDST0);
DPRINTK("DIDSTC0=0x%8x\n", DIDSTC0);
DPRINTK("DCON0=0x%8x\n", DCON0);
DPRINTK("DMTRIG0=0x%8x\n", DMTRIG0);
DPRINTK("dma init finished!\n");
return 0;
}
static int __init image_init_dma(void)
{
int ret;
ret = init_xdreq0_dma();
//s3c2410_request_dma("XDREQ0", DMA_CH0, handler_Dma0Done, NULL);
return ret;
}
static int __init d11_dma_init(void)
{
int ret;
int i;
int d11_dma_size = 0;
unsigned long *d11_dma_buf = (unsigned long *)0;
dma_addr_t d11_dma_phy = 0;
SET_MODULE_OWNER(&d11_dma_fops);
ret = register_chrdev(d11_dma_major, DEVICE_NAME, &d11_dma_fops);
if(ret < 0){
printk("d11_dma:Cant't get major number!\n");
return ret;
}
if (d11_dma_major == 0) d11_dma_major = ret; /* dynamic */
#ifdef CONFIG_DEVFS_FS
devfs_d11_dma_dir = devfs_mk_dir(NULL, "d11_dma", NULL);
if (!devfs_d11_dma_dir) return -EBUSY; /* problem */
devfs_d11_dma = devfs_register(devfs_d11_dma_dir, "0",
DEVFS_FL_DEFAULT, d11_dma_major, DMA_MINOR,
S_IFCHR | S_IRUSR | S_IWUSR, &d11_dma_fops, NULL);
#endif
DPRINTK("Major device no. -> %d\n",d11_dma_major);
//******** alloce image review buffer *************
image_review_buf.head_index = 0;
image_review_buf.tail_index = 0;
image_review_buf.nr_images = 0;
image_review_buf.nr_mmblks = 0;
image_review_buf.freeze = 0;
d11_dma_size = 4*1024*128; //PAGE_ALIGN(IMG_SIZE + PAGE_SIZE);
image_review_buf.image_blksize = d11_dma_size;
for(i=0; i<IMG_MAX_NR; i++){
d11_dma_buf = consistent_alloc(GFP_KERNEL | GFP_DMA, d11_dma_size, &d11_dma_phy);
if(!d11_dma_buf){
printk("Have no enough memory for image review memory allocate!\n");
printk("Image review memory be truncate to %d (max=%d)!\n", i, IMG_MAX_NR);
break;
}
image_review_buf.nr_mmblks++;
image_review_buf.image_dma_mmblk[i] = d11_dma_buf;
image_review_buf.image_dma_mmphy[i] = d11_dma_phy;
//DPRINTK("%d:dma0 dst kerneladdr= 0x%lx\n", i, (unsigned long)d11_dma_buf);
//DPRINTK("%d:d11_dma_phy=0x%lx\n", i, d11_dma_phy);
}
init_waitqueue_head(&d11_dma_queue);
image_init_dma();
//dma_tester();
//********* Configure BANK3 to 32bit width ********************
//BWSCON = BWSCON & (~(0x3 << 12)) | (0x2 << 12);
if(d11_dma_create_proc()){
return -ENOMEM;
}
return 0;
}
static void __exit d11_dma_exit(void)
{
int i;
int d11_dma_size = 0;
unsigned long * d11_dma_buf = 0;
dma_addr_t d11_dma_phy = 0;
d11_dma_remove_proc();
//iounmap((void *)fpga_dma0_reg);
free_irq(IRQ_EINT2, NULL);
//s3c2410_free_dma(DMA_CH0);
free_irq(IRQ_DMA0, NULL);
//d11_dma_size = PAGE_ALIGN(IMG_SIZE + PAGE_SIZE);
d11_dma_size = 4*1024*128; //PAGE_ALIGN(IMG_SIZE + PAGE_SIZE);
DPRINTK("d11_dma_size=0x%8x\n",d11_dma_size);
for(i=0; i<image_review_buf.nr_mmblks; i++){
d11_dma_buf = image_review_buf.image_dma_mmblk[i];
d11_dma_phy = image_review_buf.image_dma_mmphy[i];
if(d11_dma_buf){
consistent_free(d11_dma_buf, d11_dma_size, d11_dma_phy);
DPRINTK("consistent_free: addr=0x%8x\n",d11_dma_phy);
}
}
DPRINTK("image review area memory released!\n");
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_d11_dma);
devfs_unregister(devfs_d11_dma_dir);
#endif
DPRINTK("release!\n");
unregister_chrdev(d11_dma_major, DEVICE_NAME);
}
module_init(d11_dma_init);
module_exit(d11_dma_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LC<lcliu_chao@126.com>");
MODULE_DESCRIPTION("dma driver for emp-d11");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -