- 论坛徽章:
- 0
|
从网上找了则linux下的fpga驱动,有几个地方不懂,请大侠给讲解下:
/*
* FPGA support
*/
MODULE_LICENSE("Dual BSD/GPL" ;
#define FPGA_PHY_START 0xe3000000
#define FPGA_PHY_SIZE (0x01000000)
#define FPGA_MAJOR 211 //主设备号211
#define FPGA_MINOR 0 //从设备号0
unsigned long fpga_vp; //映射的虚拟地址
#define fpga_dma_channel 0
#define DCG_GPIO1_BASE 0xB1900000
#define DCG_GOIO1_MODE 0x002C
#define DMA_DDMA0_BASE 0xB4002000
#define DMA_GLOBAL_BASE 0xB4003000
struct fpga_dma_device{
unsigned int dma_irq;
unsigned int dma_channel;
};
static int fpga_open(struct inode *,struct file*);
static int fpga_release(struct inode *,struct file *);
static ssize_t fpga_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos);
static ssize_t fpga_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos);
static int fpga_mmap( struct file *,struct vm_area_struct *);
static int fpga_ioctl(struct inode *,struct file *);
struct file_operations fpga_fops={
.open=fpga_open,
.release=fpga_release,
.read=fpga_read,
.write=fpga_write,
.ioctl=fpga_ioctl,
.mmap=fpga_mmap,
.owner=THIS_MODULE
};
irqreturn_t fpga_dma_interrupt(int irq, void *dev_id)
{
struct motion_key_dev * motiondev = (struct motion_key_dev *)dev_id;
//u32 reg_value = 0;
(motion_key_device->count)++;
motion_key_device->int_come = 1;
printk(KERN_WARNING "Enter motion_key_interrup %d \n", motion_key_device->count);
printk(KERN_WARNING "reg value = 0x%x \n", __raw_readl(S3C24XX_EXTINT2));
wake_up_interruptible(&motiondev->key_queue);
printk(KERN_INFO "fpga_dma_interrupt \n" ;
return IRQ_HANDLED;
}
static int fpga_open(struct inode *ip,struct file *fp)
{
struct fpga_dma_device *fpga_device;
int error = 0;
if((error=request_irq(fpga_device->dma_irq, fpga_dma_interrupt, IRQF_DISABLED, "fpga", NULL)))
return error;
if((error=request_dma(fpga_device.dma_channel,"fpga" )){
free_irq(fpga_device.dma_irq,NULL);
return error;
}
fp->f_op=&fpga_fops;
fpga_vp=(unsigned long)ioremap(FPGA_PHY_START,FPGA_PHY_SIZE);
if(!fpga_vp){
printk("ioremap fpga failed\n" ;
return -EINVAL;
}
printk(KERN_INFO"fpga_vp is 0x%.8x \n",fpga_vp);
return(0);
}
static int fpga_release(struct inode *ip,struct file *fp)
{
if(fpga_vp)
iounmap(fpga_vp);
struct fpga_dma_device *fpga_device;
free_dma(fpga_dma_device->dma_channel);
free_irq(fpga_device->dma_irq,NULL);
return(0);
}
static ssize_t fpga_read(struct file *filp, char __user *buf, size_t count,loff_t *f_pos)
{
unsigned char *p = (unsigned char *)fpga_vp;
ssize_t retval = 0;
if(copy_to_user(buf, p, count))
{
retval = -EFAULT;
goto out;
}
retval = count;
out:
return retval;
}
static ssize_t fpga_write(struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)
{
//unsigned char *p = (unsigned char *)fpga_vp;
ssize_t retval = 0;
//printk("Enter write\n" ;
if(copy_from_user(fpga_vp, buf, count))
{
retval = -EFAULT;
printk("Write error\n" ;
goto out;
}
retval = count;
out:
return retval;
}
void fpga_vma_open(struct vm_area_struct *vma)
{ return; }
void fpga_vma_close(struct vm_area_struct *vma)
{ return; }
static struct vm_operations_struct fpga_remap_vm_ops = {
.open = fpga_vma_open,
.close = fpga_vma_close,
};
static int fpga_mmap( struct file *filp,struct vm_area_struct *vma)
{
unsigned int len;
unsigned long start=0, off;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
{
printk(" Error vma->vm_pgoff > !OUL PAGE_SHIFT \n" ;
return -EINVAL;
}
start = FPGA_PHY_START;
len = FPGA_PHY_SIZE;
off = vma->vm_pgoff << PAGE_SHIFT;
if ((vma->vm_end - vma->vm_start + off) > len)
{
printk(" Error vma->vm_end-vma->vm_start\n" ;
return -EINVAL;
}
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
pgprot_val(vma->vm_page_prot) |= PAGE_CACHABLE_DEFAULT;
vma->vm_flags |= VM_IO;
if (remap_pfn_range(vma,vma->vm_start, off,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
{
return -EAGAIN;
}
}
static int fpga_ioctl(struct inode *ip,struct file *fp)
{
printk("use fpga_ioctl\n" ;
return 0;
}
void fpga_dma_init(void)
{
unsigned int gpio1_mode=0x00000010;
au_writel( gpio1_mode , DCG_GPIO1_BASE + 0x0100 );//sys_triout--->GPIO4
gpio1_mode=au_readl(DCG_GPIO1_BASE + 0x0100);
printk(KERN_ALERT "sys_triout--->GPIO4 : %.8x \n",gpio1_mode);
unsigned int dma_val=au_readl(DMA_GLOBAL_BASE+0x0000);//ddma_config
dma_val |=0x00000000;
au_writel(dma_val,DMA_GLOBAL_BASE+0x0000);
dma_val=au_readl(DMA_GLOBAL_BASE+0x000 ;//ddma_throttle
dma_val |= 0x80000000;
au_writel(dma_val,DMA_GLOBAL_BASE+0x000 ;
dma_val=au_readl(DMA_GLOBAL_BASE+0x000c);//ddma_inten
dma_val |= 0x00000001;
au_writel(dma_val,DMA_GLOBAL_BASE+0x000c);
}
static int __init fpga_init(void)
{
int fpga_base;
int fpgamajor;
unsigned int mac0_phy;
printk(KERN_INFO "-----fpga----\n" ;
fpga_dma_init();
fpgamajor=register_chrdev(FPGA_MAJOR,"fpga",&fpga_fops);
if(fpgamajor < 0)
{
printk(KERN_ERR "register_chrdev fault! \n");
return 0;
}
printk(KERN_INFO "fpga:fpgamajor=0x%x or %d\n",fpgamajor,fpgamajor);
printk(KERN_INFO "fpga:init_module() OUT \n");
return 0;
}
static void __exit fpga_exit(void)
{
unregister_chrdev(FPGA_MAJOR,"fpga");
printk(KERN_INFO "fpga cleanup_module OUT \n");
}
module_init(fpga_init);
module_exit(fpga_exit);
/*
* END FPGA support
*/
上面这段代码中有一下几个问题不懂
1 fpga_dma_init函数起什么作用?fpga驱动需要用到dma?
2 那个fpga_mmap函数不懂,PAGE_SHIFT ,_CACHE_MASK ,PAGE_CACHABLE_DEFAULT这几个参数什么意思?
3 注册中断究竟要怎么用?先在kernel中request_irq再在应用程序中使用Request_irq?
|
|