📄 hpi.c
字号:
frame_length=readb(HPD_READ_HIGH+phys_address); frame_length=((frame_length<<8)&0xff00)|tempt; // printk(KERN_INFO"frame length=0x%x\n",frame_length); if(frame_length>1024) return -EINVAL; /* Invalid argument */ //allocate memory if(count<frame_length*2) frame_length=count/2; kbuf=kmalloc(frame_length*2+1,GFP_KERNEL); if(!kbuf) return -ENOMEM; /* Out of memory */ spin_lock_irqsave(&hpi_lock,flags); wmb(); writeb(0x04+HPI_READ_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); wmb(); writeb(HPI_READ_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); for(i=0;i<frame_length;i++) { rmb(); *(kbuf+2*i)=readb(HPD_READ_LOW+phys_address); // udelay(5); rmb(); *(kbuf+2*i+1)=readb(HPD_READ_HIGH+phys_address); // udelay(5); } spin_unlock_irqrestore(&hpi_lock,flags); copy_to_user(buffer,kbuf,frame_length*2); spin_lock_irqsave(&hpi_lock,flags); //RESET FRME INACTIVE wmb(); writeb(0x00+HPI_READ_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); wmb(); writeb(0x00+HPI_READ_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); writeb(dsp_ready,HPD_WRITE_LOW+phys_address); //udelay(5); rmb(); writeb(0x00,HPD_WRITE_HIGH+phys_address); //set arm read interrupt flag //udelay(5); wmb(); writeb(0x02+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); //udelay(5); wmb(); writeb(0x55,HPD_WRITE_LOW+phys_address); //udelay(5); writeb(0x00,HPD_WRITE_HIGH+phys_address); //trigger dspint interrupt writeb(0x0d,HPC_WRITE_LOW+phys_address); // udelay(5); writeb(0x0d,HPC_WRITE_HIGH+phys_address); // udelay(5); spin_unlock_irqrestore(&hpi_lock,flags); //Free Memory kfree(kbuf); read_event=0; return frame_length*2; /* success */ } //hpi write ssize_t hpi_write(struct file *file,const char *buffer,size_t count ,loff_t *ppos) { unsigned char *kbuf ; unsigned char dsp_ready=0; unsigned char frame_active=0x55; size_t frame_length=0; unsigned char tempt; int i; frame_length=count+1; printk(KERN_INFO "COUNT=0X%x\n" ,count); //read dsp ready flag; spin_lock_irqsave(&hpi_lock,flags); writeb(0x01+HPI_READ_BASE_LOW,HPA_WRITE_LOW+phys_address); //udelay(5); writeb(0x00+HPI_READ_BASE_HIGH,HPA_WRITE_HIGH+phys_address); //udelay(5); dsp_ready=readb(HPD_READ_LOW+phys_address); //udelay(5); //READ if data have been taken wmb(); writeb(0x01+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); readb(HPD_WRITE_LOW+phys_address); // udelay(5); frame_active=readb(HPD_WRITE_HIGH+phys_address); spin_unlock_irqrestore(&hpi_lock,flags); if(dsp_ready!=0x55) { //DSP NOT READY printk(KERN_INFO "HPI:DSP not ready"); return -EINVAL; } //If frame has not been read or reading ,loop if(frame_active==0x55) { //FRAME inactive if(file->f_flags&O_NONBLOCK) {printk(KERN_INFO "Write Frame inactive\n"); return 0; /* success */ } write_event=1; while(frame_active==0x55) { interruptible_sleep_on(&hpi_write_queue); if(signal_pending(current)) return -ERESTARTSYS; spin_lock_irqsave(&hpi_lock,flags); // udelay(5); wmb(); writeb(0x01+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); rmb(); frame_active=readb(HPD_READ_HIGH+phys_address); spin_unlock_irqrestore(&hpi_lock,flags); } } if(count>2048) return -EINVAL; //allocate memory kbuf=kmalloc(frame_length,GFP_KERNEL); if(!kbuf) return -ENOMEM; copy_from_user(kbuf,buffer,count); //write data into frame spin_lock_irqsave(&hpi_lock,flags); writeb(0x03+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); for( i=0;i<count/2;i++) {// udelay(5); wmb(); writeb(*(kbuf++),HPD_WRITE_LOW+phys_address); // udelay(5); writeb(*(kbuf++),HPD_WRITE_HIGH+phys_address); } // udelay(5); //set write frame active writeb(0x00+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); writeb(0x55,HPD_WRITE_LOW+phys_address); // udelay(5); writeb(0x55,HPD_WRITE_HIGH+phys_address); //calculate frame length tempt=(unsigned char)(count&0xff); // udelay(5); writeb(tempt,HPD_WRITE_LOW+phys_address); tempt=(unsigned char )((count>>8)&0xff); // udelay(5); writeb(tempt,HPD_WRITE_HIGH+phys_address); //set write interrupt flag // udelay(5); writeb(0x00,HPD_WRITE_LOW+phys_address); // udelay(5); writeb(0x55,HPD_WRITE_HIGH+phys_address); //trigger dspint interrupt writeb(0x0d,HPC_WRITE_LOW+phys_address); // udelay(5); writeb(0x0d,HPC_WRITE_HIGH+phys_address); spin_unlock_irqrestore(&hpi_lock,flags); //free memory kfree(kbuf); write_event=0; return count; /* success */ } unsigned int hpi_poll(struct file *file, poll_table *wait) { poll_wait(file,&hpi_read_queue,wait); poll_wait(file,&hpi_write_queue,wait); if(read_event==0) if(write_event==0) return POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM; /* read and write */ else return POLLIN|POLLRDNORM; /* read */ else if(write_event==0) return POLLOUT|POLLWRNORM; /* write */ return 0; } static void hpi_interrupt(int irq ,void *dev_id, struct pt_regs *regs) { unsigned char read_flag,write_flag; // clear interrrupt; writel(0xffffffff,rINTMSK+int_base_address); // udelay(5); writeb(0x03+HPI_READ_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); writeb(0x00+HPI_READ_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); read_flag=readb(HPD_READ_LOW+phys_address); // udelay(5); write_flag=readb(HPD_READ_HIGH+phys_address); if(read_flag==0x55) wake_up_interruptible(&hpi_write_queue); if(write_flag==0x55) wake_up_interruptible(&hpi_read_queue); writeb(0x09,HPC_WRITE_LOW+phys_address); // udelay(5); writeb(0x09,HPC_WRITE_HIGH+phys_address); // resume interrupt writel(0xfffffff7,rINTMSK+int_base_address); return ; } //file struction struct file_operations hpi_fops={ owner:THIS_MODULE, read: hpi_read, write: hpi_write, poll : hpi_poll, open: hpi_open, release: hpi_release, }; /*module init * */ int hpi_init(void) { int result; phys_address=HPI_BASE; //allocate i/o and interrupt region printk(KERN_INFO"\n\n\n"); printk(KERN_INFO"******************************************************************\n"); printk(KERN_INFO" Welcome to use our system!!\n"); printk(KERN_INFO"This HPI driver is used for connecting ARM:S3c2410 and DSP:TMS54x \n"); printk(KERN_INFO" Written by wangpingan HuNan Normal University !\n"); printk(KERN_INFO" Email:wang8y8y@163.com \n"); printk(KERN_INFO"******************************************************************\n"); if(! (io_base_address=(u32)ioremap(GPIO_BASE,IO_SIZE))) { printk(KERN_INFO"HPI:can't get GPIOG setting configure register address:0x%lx\n",(long unsigned int)GPIO_BASE); return -EIO; /* I/O error */ } printk(KERN_INFO"GPIOG register Mapped io memory :0x%lx\n",(long unsigned int)io_base_address); if(! (int_base_address=(u32)ioremap(INT_BASE,INT_SIZE))) { printk(KERN_INFO"HPI:can't get interrupt setting configure register address:0x%lx\n",(long unsigned int)INT_BASE); return -EIO; } printk(KERN_INFO"interrupt register Mapped io memory :0x%lx\n",(long unsigned int)int_base_address); io_port_configure(); //allocate memory i/o if(! (phys_address=(u32)ioremap(HPI_BASE,HPI_LENGTH))) { printk(KERN_INFO"HPI:can't get HPI setting I/O port address:0x%lx\n",(long unsigned int)HPI_BASE); return -EIO; /* I/O error */ } printk("HPI:HPI setting I/O port Mapped io memory:0x%lx\n",(long unsigned int)phys_address); if(NULL==request_region((long unsigned int)phys_address,HPI_LENGTH,"HPI")) { printk(KERN_INFO"HPI:HPI request_region failed!\n"); return -EIO; /* Failure */ } printk(KERN_INFO"HPI:HPI request_region success!\n"); //Register device result=register_chrdev(HPI_MAJOR,"HPI",&hpi_fops); if(result<0) { printk(KERN_INFO "HPI:can't get major number \n"); release_region((long unsigned int)phys_address,HPI_LENGTH); iounmap ((void *)phys_address); iounmap ((void *)io_base_address); iounmap ((void *)int_base_address); return result; /* Failure */ } major=result; printk(KERN_INFO "HPI: get major number is:%d\n",(unsigned int )result); //set lowlevle trigger set_external_irq(IRQ_NUM,EXT_LOWLEVEL,GPIO_PULLUP_DIS); //requset irq result=request_irq(IRQ_NUM,hpi_interrupt,SA_INTERRUPT,"HPI",NULL); if(result) { printk(KERN_INFO "HPI:can't get assigned irq\n"); release_region((long unsigned int)phys_address,HPI_LENGTH); iounmap ((void *)phys_address); iounmap ((void *)io_base_address); iounmap ((void *)int_base_address); return -EBUSY; /* Device or resource busy */ } else { printk(KERN_INFO"Irq application ok !!!!\n"); //clear dsp interrupt //while(1) writeb(0x09,HPC_WRITE_LOW+phys_address); udelay(5); writeb(0x09,HPC_WRITE_HIGH+phys_address); udelay(5); set_arm_ready(); } return 0; } //unload modlue void hpi_cleanup(void) { writel(0xffffff,rEINTMASK+io_base_address); udelay(2); set_arm_not_ready(); //free irq free_irq(IRQ_NUM,NULL); //unregister device unregister_chrdev(major,"HPI"); release_region((long unsigned int)phys_address,HPI_LENGTH); iounmap ((void *)phys_address); iounmap ((void *)io_base_address); iounmap ((void *)int_base_address); printk(KERN_INFO"HPI:successfully unload ! See you!\n"); } module_init(hpi_init); module_exit(hpi_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -