⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bts3c2410_c54xhpi.c

📁 ARM和DSP基于HPI口的接口程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
* Filename: s3c2410_c54xHPI.c
* Function: driver for HPI port of DSPC54x on the s3c2410 board
* the host is S3c2410
*
* Modified on: June 19th
* delete lost of notations
* Modified on: June 20th
* optimize dsp_hpi_write() function.
*
 Modified on: June 21th
* devide dsp_hpi_write() and  dsp_hpi_irq() into
* two functions
*
* Modified on: Mar 28th, 2008
* 1)remove some no-use code, comment out for a long time
* 2)fix bug when no call open(), but has irq interrupt
* ----use open-count and move the place of request_irq()
* 3)change buffer malloc schedule,when open,malloc a smallbuffer
* 4)modify the reading len schedule
*/

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

#include <linux/miscdevice.h>
#include <linux/ioport.h>	// for check_region(), etc.
#include <linux/sched.h>
//#include <linux/delay.h>  // for mdelay(), udelay()
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/irq.h>

#include <asm/hardware.h>
#include <asm/io.h>     /* for outb(), inl(),etc. */
#include <asm/irq.h>    /* for IRQ_EINT0 */
#include <asm/signal.h>
#include <asm/arch/S3C2410.h>
//#include <asm/segment.h>
#include "s3c2410_c54xHPI.h"

/* There are something differences between kernel-2.6 and kernel-2.4(MIZI provided) */
/* for kernel-2.4(MIZI) */
#define S3C2410_SRCPND SRCPND
#define S3C2410_INTMSK INTMSK
#define S3C2410_INTMOD INTMOD
#define S3C2410_EXTINT0 EXTINT0

#define HPI_ADDR (0x08000000)	// BANK1
#define BIGBUFFER    0xFF
#define SMALLBUFFER  0xEE
#define CHANGEMODE 0xDD
#define CHANGEMODE1 0xAA
#define RESETL 0xCC
#define RESETH 0xBB
#define BUFFER1 0x55
#define BUFFER2 0x66
#define BUFFERSIZE (2048)
		
#define DEVICE_NAME  "dspHPI"
#define DSP_MAJOR  226
		
#define HPI_DEBUG			// turn on/off to debug message
#undef Jdebug               /* undef it, just in case */
#ifdef HPI_DEBUG
#  ifdef __KERNEL__         /* This one if debugging is on, and kernel space */
#    define Jdebug(fmt, args...) printk( KERN_EMERG "hpi: " fmt, ## args)
#  else       /* This one for user space */
#    define Jdebug(fmt, args...) fprintf(stderr, fmt, ## args)
#  endif
#else
#  define Jdebug(fmt, args...)  /* not debugging: nothing */
#endif

static volatile unsigned char *HPI_BASE;
static volatile unsigned char *WHPIC_L1, *WHPIC_H1,*RHPIC_L1, *RHPIC_H1;
static volatile unsigned char *WHPIA_L1, *WHPIA_H1,*RHPIA_L1, *RHPIA_H1;
static volatile unsigned char *WHPID_L1, *WHPID_H1,*RHPID_L1, *RHPID_H1;
static volatile unsigned char *WHPIDI_L1, *WHPIDI_H1,*RHPIDI_L1, *RHPIDI_H1;
unsigned char *buffer1, *buffer2;
int buffer1_idle = 1, buffer2_idle = 1;    //idle = 1 means buffer is empty.
unsigned char current_buffer;     // BUFFER1 or BUFFER2

static int order = 4;

static int ready = 0;
static int overflow_count = 0;
static int buf_flag = SMALLBUFFER;    // big or small buffer shifting
static int length;
static int open_count = 0;
static int intial=1;
static int add=0;
static int num=0;
static int number=0;
static DECLARE_WAIT_QUEUE_HEAD(dsp_wait);   //declaration
//static wait_queue_head_t dsp_wait; // is also OK. 
static int do_write(const char *,int);
 
static inline void irq_read(unsigned char *pbuff)
{
	unsigned char temp1, temp2;
	unsigned int loop;
	int i;
	
	writeb(0xf3, WHPIA_L1);
  	writeb(0x5f, WHPIA_H1);
// get ready for reading from 0x5ff0
//	Jdebug("irq_read:(HPIA)=0x%02x%02x\n",readb(RHPIA_H1),readb(RHPIA_L1));
	/*read the buffer idle flag*/
	udelay(10);
	temp1 = readb(RHPIDI_L1);
	temp2 = readb(RHPIDI_H1);
   
    //Jdebug("irq_read:dsp buffer flag:0x%x\n", (temp2<<8)+temp1);
/*	if (0 == temp1 && temp2 == 0)
	{
		printk("irq():buffer is idle.\n");
		return;
	}*/
    /*read the length*/
    temp1 = readb(RHPIDI_L1);
    temp2 = readb(RHPIDI_H1);
 
    pbuff[0] = temp1;
    pbuff[1] = temp2;

    length = (temp2 << 8) + temp1;
    //Jdebug("irq_read:dsp buffer length:0x%04x\n", length);

    /* read the data type */
    temp1 = readb(RHPIDI_L1);
    temp2 = readb(RHPIDI_H1);
    pbuff[2] = temp1;
    pbuff[3] = temp2;
    //Jdebug("irq_read:dsp buffer data type:0x%04x\n", (temp2<<8)+temp1);

    if (length % 2)
	    loop = length / 2;
    else
	    loop = (length+1) / 2;
    
  	writeb(0x00, WHPIA_L1);
  	writeb(0x64, WHPIA_H1);
  	for (i = 2; i < loop; i++)
    {
		udelay(1);
      	pbuff[i*2] = readb(RHPIDI_L1);
      	pbuff[i*2+1] = readb(RHPIDI_H1);
    }
// after read the data, set dsp buffer idle
	writeb(0xf3,WHPIA_L1);
	writeb(0x5f,WHPIA_H1);
	udelay(10);	
	writeb(0x00,WHPID_L1);
	writeb(0x00,WHPID_H1);
}

static void hpi_irq(int irq, void *dev_id, struct pt_regs *regs)
{
	/*writeb(0x7e, WHPIA_L1);
	writeb(0x00, WHPIA_H1);
	
	udelay(10);
	writeb(0xe9, WHPIDI_L1);
        writeb(0x20, WHPIDI_H1);*/
	/*int i;
	writeb(0x7d, WHPIA_L1);
	writeb(0x00, WHPIA_H1);
	writeb(0xe9, WHPIDI_L1);
        writeb(0x20, WHPIDI_H1);
	udelay(10);
	writeb(0x00, WHPIDI_L1);
        writeb(0x00, WHPIDI_H1);
	printk("hpi_irq:entering irq processing.\n");
	printk("hpi_irq:entering irq processing.\n");
		writeb(0x8, WHPIA_L1);
		writeb(0x00, WHPIA_H1);
	for( i=0;i<20;i++)
	{
	writeb(0x7e, WHPIA_L1);
		writeb(0x00, WHPIA_H1);
	udelay(10000);	
	Jdebug("A: = 0x%02x%02x\n",readb(RHPIDI_H1),readb(RHPIDI_L1));
	printk("hpi_irq:entering irq processing.\n");
	printk("hpi_irq:entering irq processing.\n");
	}
	
	return;*/
	//printk("hpi_irq:entering irq processing.\n");
	if (!open_count)
		return;
	/*num++;
	if(num==1)
		return;*/
//	printk("hpi_irq:entering irq processing.\n");
  	if (irq != IRQ_EINT0)
  	{
    	//printk("hpi_irq():bad irq %d in dsp.\n",irq);
    	return;
  	}
  	S3C2410_SRCPND = (0x1 << 0); /*need more knowledge of INT to set this value*/

  	writeb(0x09, WHPIC_L1);  //clear the HINT bit
  	writeb(0x09, WHPIC_H1);
  	
  	udelay(10);
	//Jdebug("hpi_irq:(HPIC) = 0x%02x%02x\n",readb(RHPIC_H1),readb(RHPIC_L1));
	while((0x09==readb(RHPIC_H1))&&(0x09==readb(RHPIC_L1)))
	{
		writeb(0x09, WHPIC_L1);  //clear the HINT bit
  	writeb(0x09, WHPIC_H1);
  	udelay(5);
  }

  	if (buffer1_idle == 1)
  	{
    	if(buf_flag == BIGBUFFER)
      		memset(buffer1, 0, PAGE_SIZE << order);
    	else
      		memset(buffer1, 0, BUFFERSIZE);
  	}
  	else if (buffer2_idle == 1)
  	{
    	if(buf_flag == BIGBUFFER)
      		memset(buffer2, 0, PAGE_SIZE << order);
    	else
      		memset(buffer2, 0, BUFFERSIZE);
  	}
  	else
  	{
    	buffer1_idle = 1;
    	overflow_count++; 
    	//printk("dsp_hpi.irq(): buffer over flow! use buffer1\n");
    	if(buf_flag == BIGBUFFER)
      		memset(buffer1, 0, PAGE_SIZE << order);
    	else
      		memset(buffer1, 0, BUFFERSIZE);
  	}

  	if(buffer1_idle == 1)
  	{
  		irq_read(buffer1);
    	buffer1_idle = 0;
    	current_buffer = BUFFER1; 
      
    //	Jdebug("Read data to buffer1!\n");
    	
      
  	}
  	else if(buffer2_idle == 1)
  	{
  		irq_read(buffer2);
    	buffer2_idle = 0;
    	current_buffer = BUFFER2; 
 
    //	Jdebug("Read data to buffer2!\n");
  	}
 
  	ready = 1;
  	//wake_up_interruptible(&dsp_wait); 
  	//Jdebug("handle finish!\n");
  	//writeb(0x05, WHPIC_L1);
    //writeb(0x05, WHPIC_H1);
  //	Jdebug("send INT to dsp.\n");
  	//S3C2410_SRCPND = (0x0 << 0);
  	
}

static int dsp_hpi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
	int read_len;
  	if(!ready) //not ready yet ?
    	return 0;
    
  	if(count > (PAGE_SIZE << order))
  	{	
		//printk("dsp_hpi.read():Reading number is exceeding maximent!\n");
  		return -EINVAL;
	}
  //save_flags(flags);
	if (count < length)
		read_len = count;
	else
		read_len = length;
  	switch(current_buffer)
  	{
 	 	case BUFFER1:
    		copy_to_user(buffer, buffer1, read_len);
    		buffer1_idle = 1; /*after move the data from kernel to user, this buffer can be used again.*/
    		break;
  		case BUFFER2:
    		copy_to_user(buffer, buffer2, read_len);
    		buffer2_idle = 1;
    		break;
  		default:
		//	printk("reading buffer error!\n");
    		break;
  	}

  //restore_flags(flags);
  	ready = 0;
  	return read_len;
}

static int dsp_hpi_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
{ 
  switch(cmd)
  {
  case BIGBUFFER:
    buffer1 = (void *)__get_free_pages(GFP_KERNEL, order);
    if(!buffer1)
    {
      printk("failed assigned big mem for buffer1 ! \n");
      return -ENOMEM;
    }
    buffer2 = (void *)__get_free_pages(GFP_KERNEL, order);
    if(!buffer2)
    {
      printk("failed assigned big mem for buffer2 ! \n");
      return -ENOMEM;
    }
    buf_flag = BIGBUFFER;
    printk("dsp_hpi_ioctl: assigned a big mem. \n");
    return buf_flag;
    break;

  case SMALLBUFFER:
	  buffer1 = (unsigned char *)kmalloc(BUFFERSIZE, GFP_KERNEL);
    if(!buffer1)
    {
      printk("failed assigned small mem for buffer1 ! \n");
      return -ENOMEM;
    }
    buffer2 = (unsigned char *)kmalloc(BUFFERSIZE, GFP_KERNEL);
    if(!buffer2)
    {
      printk("failed assigned small mem for buffer2 ! \n");
      return -ENOMEM;
    }
    buf_flag = SMALLBUFFER;
    printk("dsp_hpi_ioctl: assigned a small mem. \n");
    return buf_flag;
    break;
	case CHANGEMODE:
		intial=0;
		add=arg;
		printk("add=%x\n",add);
		printk("change mode success.\n");
		return intial;
		break;
	case CHANGEMODE1:
		intial=1;
		return intial;
	case RESETL:
		intial=2;
		GPGDAT&=(0<<11);
		//writeb(0x00, WHPIC_L1);  //set SAM共享访问模式
  	//writeb(0x02, WHPIC_H1);
		printk("RESET LOW.\n");
		return intial;
		break;
	case RESETH:
		intial=3;
		writeb(0x7f, WHPIA_L1);
		writeb(0x00, WHPIA_H1);
	udelay(10000);
	Jdebug("A: = 0x%02x%02x\n",readb(RHPID_H1),readb(RHPID_L1));
		//GPGDAT|=(1<<11);
		writeb(0x20, RHPID_H1);
		writeb(0xe9, RHPID_L1);
		udelay(10000);
	Jdebug("A: = 0x%02x%02x\n",readb(RHPID_H1),readb(RHPID_L1));
		printk("RESET HIGH.\n");
		return intial;
		break;
  default:
    break;
    return -EINVAL;
  }
  return 0;
}

static int do_write(const char *pbuff, int count)
{
    unsigned char temp1, temp2;
    unsigned char temp3, temp4;
    unsigned char temp5, temp6,temp7;
    unsigned int len, loop;
    int i;
    int addtemp;
    char bt1,bt2;
    if(intial==1)
    {
    	writeb(0xf0, WHPIA_L1);
    	writeb(0x5f, WHPIA_H1);
			/*get ready to write 0x5ff1, length*/
    	temp1 = pbuff[0];
    	writeb(temp1, WHPIDI_L1);

    	temp2 = pbuff[1];
    	writeb(temp2, WHPIDI_H1);
    	/*So, (0x5ff1) = buffer1[1]+buffer1[0]*/
    	len = (temp2 << 8) + temp1;
    	//Jdebug("dsp_hpi:data length:%d \n", len);
			if(len>2048)
			{
			//	Jdebug("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!!\n");
				while(1);
			}
    	if (len != count)
			{
				//printk("Data length does mot match with writint count!\n");    
  			return -EINVAL;
			}

			/* write data type to 0x5ff2*/
    	temp1 = pbuff[2];
    	writeb(temp1, WHPIDI_L1);
    	temp2 = pbuff[3];
    	writeb(temp2, WHPIDI_H1);
    	//Jdebug("dsp_hpi:data type:0x%4x\n", (temp2<<8)+temp1);

    	if (len == 4)
    	{/* len = 4, maybe means no data.*/
				/*      temp1 = buffer1[4];
      	outb(temp1, WHPIDI_L);
      	temp2 = buffer1[5];
      	outb(temp2, WHPIDI_H);
				*/
      	//Jdebug("dsp_hpi.write(): send an interruption.\n");
      	temp1 = readb(RHPIC_L1);
      	temp2 = readb(RHPIC_H1);
      	temp1 = temp1 | (0x1<<2);
      	temp2 = temp2 | (0x1<<2);
      	writeb(temp1, WHPIC_L1);
      	writeb(temp2, WHPIC_H1);

      	return (len);
    	}
    	else  /*data processing*/
    	{
				udelay(20);
      	writeb(0xf0, WHPIA_L1);
      	writeb(0x5f, WHPIA_H1);
				udelay(20);
      	writeb(0xFF, WHPID_L1);
      	writeb(0xFF, WHPID_H1);
      	while((0xff!=readb(RHPID_H1))&&(0xff!=readb(RHPID_L1)))
	    {
		    writeb(0xFF, WHPID_L1);
      	writeb(0xFF, WHPID_H1);
  	    udelay(5);
      }
      	
  /* (0x5ff0) = 0xFFFF, meaning that data buffer is busy.*/

      	if (len%2)
        	loop = len / 2;
      	else
        	loop = (len+1) / 2; 

      	writeb(0xff, WHPIA_L1);
      	writeb(0x5f, WHPIA_H1);
        /*get ready to write data from 0x6000*/
      	for(i=2; i<loop; i++)
      	{
        	udelay(10);
        	writeb(pbuff[2*i], WHPIDI_L1);
        	writeb(pbuff[2*i+1], WHPIDI_H1);
      	}
			
			writeb(0x05, WHPIC_L1);  
  		writeb(0x05, WHPIC_H1);
     // Jdebug("dsp_hpi.write():send a INT to dsp.\n");
      /*writeb(0xf5, WHPIA_L1);
      writeb(0x5f, WHPIA_H1);
				udelay(20);
      while((0xff==readb(RHPID_H1))&&(0xff==readb(RHPID_L1)))
		{
			writeb(0x05, WHPIC_L1);  
  		writeb(0x05, WHPIC_H1);
  		udelay(1000);
  	}
	    Jdebug("(HPIC) = 0x%02x%02x\n",readb(RHPIC_H1),readb(RHPIC_L1));
	writeb(0xf5, WHPIA_L1);
      	writeb(0x5f, WHPIA_H1);
				udelay(20);
      	writeb(0xFF, WHPID_L1);
      	writeb(0xFF, WHPID_H1);
     while((0xff!=readb(RHPID_H1))&&(0xff!=readb(RHPID_L1)))
	{
		writeb(0xFF, WHPID_L1);
      	writeb(0xFF, WHPID_H1);
  	udelay(5);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -