📄 bts3c2410_c54xhpi.c
字号:
/*
* 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 + -