📄 s3c2410ps.c
字号:
/************************************************************************************************* * Copyright (C) EVOC Co., LTD. 2007 * * File name: s3c2410ps.c * Description: * * Revision history * 2007.11.05 Bing yu liu start. * ************************************************************************************************//* Include files--------------------------------------------------------------*/#include <linux/version.h>#include <linux/kernel.h> /* We're doing kernel work */#include <linux/module.h> /* Specifically, a module */ #include <linux/interrupt.h> /* We want interrupts */#include <linux/miscdevice.h> /* for misc_register() and misc_deregister() */#include <linux/fs.h> /* for struct 'file_operations' */#include <linux/timer.h> /* for timeout interrupts */#include <linux/param.h> /* for HZ. HZ = 100 and the timer step is 1/100 */#include <linux/sched.h> /* for jiffies definition. jiffies is incremented * once for each clock tick; thus it's incremented*/#include <linux/mm.h> /* for verify_area */#include <linux/types.h>#include <linux/slab.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/poll.h>#include <asm/irq.h> /* For IRQ_MACHSPEC */#include <asm/io.h>#include <asm/uaccess.h>#include <asm/arch/irqs.h>#include <asm/arch/hardware.h> /* For IRQ_MACHSPEC */static const char* __file__ = __FILE__;#define PS2_MINOR 0#define DEVICE_NAME "s3c2410ps"#define FSRTC_MINOR 0#define IRQ_PS2 IRQ_EINT10 // GPB4 GPG2 // DATA CLK #define PS2_DATA_CLR (GPBDAT &= ~(1<<4))#define PS2_DATA_SET (GPBDAT |= (1<<4))#define PS2_REVBUFFER_SIZE 0x8#define PSSTATUS_WAITREV 0 //wait receive#define PSSTATUS_REVING 1 //receive data#define PSSTATUS_REVPARITY 2 //receive parity#define PSSTATUS_REVSTOP 3 //receive stop#define PSSTATUS_SendPDCLK 4 //when request send, Then down clk#define PSSTATUS_SendWTCLK 5 //When request send, Then wait change of clk#define PSSTATUS_SendDATA 6 //Send data#define PSSTATUS_SendPARITY 7 //Send Parity#define PSSTATUS_SendSTOP 8 //Send stop#define PSSTATUS_SendWTACK 9 //Wait ack while send#define PS2_SEND_OK 0 //PS/2 send ok#define PS2_SEND_FAILED 0xff //PS/2 send failed#define GETPS0Data() (GPBDAT & (0x1<<4))//PS/2 status regstatic char ps0status = PSSTATUS_WAITREV;//, sendps2 = 0;static struct timer_list key_timer;//PS/2 data buffer manage#define PS2_BUFCNT_INC(inc) do{inc++;inc & = (PS2_REBUFFER_SIZE - 1);}while(0)#define Stop_Time1() do{del_timer(&key_timer);}while(0)static int DbPs2Major = 0;static int device_open = 0;static unsigned char PS0revdata;volatile char count = 0,paritysum = 0;#ifdef CONFIG_DEVFS_FS static devfs_handle_t devfs_PS2_dir,devfs_PS2raw;#endif//static unsigned char ps2_data_buff[PS2_REVBUFFER_SIZE];static unsigned char ps2_senddata0,//ps2_data_Revcnt0 = 0,ps2_data_Readcnt0 = 0, lastps2sendstatus0 = PS2_SEND_OK; #define PS2_BUF_SIZE 32 typedef struct S3C2410fcrps2 { unsigned long head; unsigned long tail; wait_queue_head_t proc_list; struct fasync_struct *fasync_queue; unsigned char buf[PS2_BUF_SIZE];} S3C2410fcrps2; wait_queue_head_t proc_list_w;static int new_ps2_state = 0;//static int device_open = 0;static S3C2410fcrps2 * s3c2410fcrps2_device; volatile u8 place = 0;;void set_timer_irq(struct timer_list *timer,int delay);static inline void Release_PS2CLK0(void){ unsigned long flagst; save_flags(flagst); cli(); GPGDAT |= (1<<2); GPGCON &= ~(0x03<<4); GPGCON |= (0x02<<4); restore_flags(flagst); enable_irq(IRQ_PS2);} static inline void PULLDOWN_PS2CLK0(void){ GPGCON &= ~(0x03<<4); GPGCON |= (0x01<<4); GPGDAT &= ~(1<<2); disable_irq(IRQ_PS2);} static inline void PS2_DATA_OUT(void){ GPBCON &= ~(0x03<<8); GPBCON |= (0x01<<8); GPBUP |= (0x01<<4);} static inline void ReleasePS20Data(void){ GPBCON &= ~(0x03<<8); GPBUP &= ~(0x01<<4);} /************************************************************************* 功能: 参数: 返回值:-1: error 0: OK **************************************************************************/static unsigned char get_char_from_queue(void) {/* used for getting data from driver buffer*/ unsigned char ch; ch = s3c2410fcrps2_device->buf[s3c2410fcrps2_device->tail]; s3c2410fcrps2_device->tail = (s3c2410fcrps2_device->tail + 1) & (PS2_BUF_SIZE - 1); return ch;}/* get_char_from_queue *//************************************************************************* 功能: 参数: 返回值:-1: error 0: OK **************************************************************************/static void put_in_queue(unsigned char *in, int len) {/*used for putting data into driver buffer*/ unsigned long head = s3c2410fcrps2_device->head; unsigned long maxhead = (s3c2410fcrps2_device->tail - len) & (PS2_BUF_SIZE - 1); int i; if (head != maxhead) for (i = 0;i < len;i++) { s3c2410fcrps2_device->buf[head] = in[i]; head++; head &= (PS2_BUF_SIZE - 1); } else printk("the s3c2410fcrps2_device->buf is full\n"); s3c2410fcrps2_device->head = head;}/* put_in_queue *//************************************************************************* 功能: 参数: 返回值:-1: error 0: OK **************************************************************************/static int queue_empty(void) { return s3c2410fcrps2_device->head == s3c2410fcrps2_device->tail ;}/* queue_empty*/ /************************************************************************* 功能:delay 参数: 返回值:-1: error 0: OK **************************************************************************/static void delay(int i) //Delay for 10 CPU Cycles //OK{ for( ;i > 0; i-- ) { asm("nop"); }}/****************************************************************************XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ps/2 send & receive XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX *****************************************************************************//************************************************************************* 功能:EXINT10 interrupt handle 参数: 返回值:lcd status **************************************************************************/static void s3c2410_exint_isr_PS2(int irq,void *dev_id,struct pt_regs *reg){ //static unsigned char PS0revdata; //static char count = 0,paritysum = 0; unsigned char data, revd; unsigned long flags; //printk("input exint10 init!\n"); save_flags(flags); cli(); switch(ps0status){ case PSSTATUS_WAITREV: //ps/2 start receive data //place = 0; data = GETPS0Data(); if(data == 0) { PS0revdata = 0; ps0status = PSSTATUS_REVING; count = 0; paritysum = 0; } break; case PSSTATUS_REVING: //printk("PSSTATUS_REVING\n"); data = GETPS0Data(); PS0revdata >>= 1; if(data)revd = 1; else revd = 0; PS0revdata |= (revd << 7); count++; paritysum += revd; if(count == 8) ps0status = PSSTATUS_REVPARITY; break; case PSSTATUS_REVPARITY: //printk("PSSTATUS_REVPARITY\n"); data = GETPS0Data(); if(data) revd = 1; else revd = 0; paritysum += revd; if((paritysum & 0x01) == 1) //parity ok { ps0status = PSSTATUS_REVSTOP; } else { ps0status = PSSTATUS_WAITREV; } break; case PSSTATUS_REVSTOP: //printk("PSSTATUS_REVSTOP\n"); data = GETPS0Data(); if(data) revd = 1; else revd = 0; if(revd == 1) //receive stop ok { //PS2_data_buff[ps2_data_Revcnt0] = ps0revdata; //ps2_bUFCNT_INC(ps2_data_Revcnt0); //data = PS2_data_Revcnt0; //PS2_BUFCNT_INC(data); put_in_queue((unsigned char *)&PS0revdata ,1); new_ps2_state = 1; if (&s3c2410fcrps2_device->fasync_queue) kill_fasync(&s3c2410fcrps2_device->fasync_queue,SIGIO,POLL_IN); wake_up_interruptible(&s3c2410fcrps2_device->proc_list); //if(data == ps2data_Readcnt0) // PULLDOWN_PS2CLK0(); } ps0status = PSSTATUS_WAITREV; break; case PSSTATUS_SendWTCLK: //send of clk change //printk("PSSTATUS_SendWTCLK\n"); data = (ps2_senddata0 & 0x1); if(data == 1) PS2_DATA_SET; else PS2_DATA_CLR; Stop_Time1(); //stop timeout time count = 1; paritysum = data; ps2_senddata0 >>= 1; ps0status = PSSTATUS_SendDATA; //count = 0; break; case PSSTATUS_SendDATA: //send data //printk("PSSTATUS_SendDATA\n"); data = (ps2_senddata0 & 0x01); if(data == 1) PS2_DATA_SET; else PS2_DATA_CLR; paritysum ^= data; if(count == 7) { ps0status = PSSTATUS_SendPARITY; } count++; ps2_senddata0 >>= 1; break; case PSSTATUS_SendPARITY: //send parity //printk("PSSTATUS_SendPARITY\n"); if(paritysum == 1) PS2_DATA_CLR; else PS2_DATA_SET; ps0status = PSSTATUS_SendSTOP; break; case PSSTATUS_SendSTOP: //send Stop //printk("PSSTATUS_SendTOP\n"); PS2_DATA_SET; ps0status = PSSTATUS_SendWTACK; break; case PSSTATUS_SendWTACK: //wait dev ack //printk("PSSTATUS_SendWTACK\n"); ReleasePS20Data(); data = GETPS0Data(); if(data == 0) { lastps2sendstatus0 = PS2_SEND_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -