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

📄 9200-zlg7289a.c

📁 本程序是在arm9200平台上对zlg7289的驱动程序
💻 C
字号:
/* * */#define __NO_VERSION__#include <linux/module.h>#include <linux/version.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/errno.h>#include <linux/timer.h>#include <linux/delay.h>#include <linux/config.h>#include <linux/mm.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/ioport.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/hardware.h>#include <asm/uaccess.h>#undef  DEBUG_ZLG7289//#define DEBUG_ZLG7289	1#ifdef DEBUG_ZLG7289#define DBG_ZLG7289(fmt, args...) printk(fmt,## args)#else#define DBG_ZLG7289(fmt, args...)#endifstatic int zlg7289_open(struct inode *, struct file *);static int zlg7289_close(struct inode *, struct file *);static int zlg7289_read(struct file *, char *, size_t, loff_t *);static int zlg7289_write(struct file *, const char *, size_t, loff_t *);static void zlg7289_interrupt(int, void *, struct pt_regs *);static void zlg7289_hardware_init(void);static unsigned char zlg7289_transform(unsigned char, unsigned char, int);static void uled_control(int, unsigned char);#define ZLG7289_MAJOR 	252#define TRAN_CMD	1#define TRAN_CMD_DATA	2#define READ_CMD_DATA	3/* User CMD */#define ULED1_CONTROL	1#define ULED2_CONTROL	2#define ULED3_CONTROL	3#define ULED4_CONTROL	4#define ZLG_CMD		5#define ZLG_CMD_DATA	6/* PA0 --> DATA, PA2 --> CLK, PA3 --> CS#, PB29 --> KEY# *//* PC1, PC15, PC13, PC11 for User LED */#define ZLG_CS		AT91C_PIO_PA24#define ZLG_CLK		AT91C_PIO_PA28#define ZLG_DATA	AT91C_PIO_PA29#define ZLG_KEY		AT91C_PIO_PB29#define USER_LED1	AT91C_PIO_PC1#define USER_LED2	AT91C_PIO_PC15#define USER_LED3	AT91C_PIO_PC13#define USER_LED4	AT91C_PIO_PC11static struct file_operations zlg7289_fops = {	open:           zlg7289_open,	read:		zlg7289_read,	write:          zlg7289_write,	release:        zlg7289_close,};static int input_flag = 0;static unsigned char input_data = 0xff;static void zlg7289_hardware_init (void){	DBG_ZLG7289("zlg7289_hardware_init\n");	AT91_SYS->PIOA_PER |= ZLG_CS | ZLG_DATA | ZLG_CLK;	AT91_SYS->PIOB_PER |= ZLG_KEY;	AT91_SYS->PIOC_PER |= USER_LED1 | USER_LED2 | USER_LED3 | USER_LED4;	AT91_SYS->PIOA_OER |= ZLG_CS | ZLG_DATA | ZLG_CLK;	AT91_SYS->PIOA_SODR |= ZLG_CS;		AT91_SYS->PIOB_ODR |= ZLG_KEY;	AT91_SYS->PIOB_IER |= ZLG_KEY;	AT91_SYS->PMC_PCER |= 0x0000001c;	AT91_SYS->PIOC_OER |= USER_LED1 | USER_LED2 | USER_LED3 | USER_LED4;	AT91_SYS->PIOC_SODR |= USER_LED1 | USER_LED2 | USER_LED3 | USER_LED4;	}static void uled_control (int index, unsigned char on_off){	unsigned long led_pin;		DBG_ZLG7289("uled_control index=%d, on_off=%d\n", index, on_off);		switch (index){		case 1:			led_pin = USER_LED1;			break;		case 2:			led_pin = USER_LED2;			break;		case 3:			led_pin = USER_LED3;			break;		case 4:			led_pin = USER_LED4;			break;		default:			return;	}		if(on_off == 1)		AT91_SYS->PIOC_SODR |= led_pin;	else		AT91_SYS->PIOC_CODR |= led_pin;			return;}static unsigned char zlg7289_transform (unsigned char cmd, unsigned char data, int type){	int i;	unsigned char bit, read_data=0;		DBG_ZLG7289("zlg7289_transform cmd=%x, data=%x, type=%x\n", cmd, data, type);	/* CS# Low */	AT91_SYS->PIOA_CODR |= ZLG_CS;	udelay(50);		/* Transform CMD */	for(i=1; i<=8; i++){		/* CMD Output */		bit = ( cmd >> (8-i) ) & 0x01 ;		//DBG_ZLG7289("zlg7289_transform bit %x\n", bit);		if( bit )			AT91_SYS->PIOA_SODR |= ZLG_DATA;	        else			AT91_SYS->PIOA_CODR |= ZLG_DATA;		udelay(50);			/* CLK High */		AT91_SYS->PIOA_SODR |= ZLG_CLK;		udelay(50);		/* CLK Low */		AT91_SYS->PIOA_CODR |= ZLG_CLK;		udelay(50);	}		switch (type) {		case TRAN_CMD:			break;		case TRAN_CMD_DATA:			/* Transform DATA */        		for(i=7; i>=0; i--){			       	/* DATA Output */				bit = ( data >> i ) & 0x01 ;		                if( bit )		     			AT91_SYS->PIOA_SODR |= ZLG_DATA;					else   					AT91_SYS->PIOA_CODR |= ZLG_DATA;				udelay(50);				/* CLK High */				AT91_SYS->PIOA_SODR |= ZLG_CLK;				udelay(50);				/* CLK Low */				AT91_SYS->PIOA_CODR |= ZLG_CLK;				udelay(50);			}		        break;			case READ_CMD_DATA:			/* DATA Input */			AT91_SYS->PIOA_ODR |= ZLG_DATA;			/* Read DATA */			for(i=7; i>=0; i--){				/* CLK High */				AT91_SYS->PIOA_SODR |= ZLG_CLK;				udelay(25);				/**/				if( (AT91_SYS->PIOA_PDSR & ZLG_DATA) != 0 )			      		read_data |= 1 << i;				udelay(25);				/* CLK Low */				AT91_SYS->PIOA_CODR |= ZLG_CLK;				udelay(50);			}			/* DATA Output */			AT91_SYS->PIOA_OER |= ZLG_DATA;			break;		default:			DBG_ZLG7289("zlg7289_transform error type %x\n", type);			break;		}//end switch		/* CS# High */	AT91_SYS->PIOA_SODR |= ZLG_CS;	udelay(50);	DBG_ZLG7289("zlg7289_transform: read_data = %x\n", read_data);	return read_data;}static int zlg7289_open (struct inode *inode, struct file *file){	DBG_ZLG7289("zlg7289_open\n");	MOD_INC_USE_COUNT;	return 0;}static int zlg7289_close (struct inode *inode, struct file *file){	DBG_ZLG7289("zlg7289_close\n");	MOD_DEC_USE_COUNT;		return 0;}static int zlg7289_read (struct file *file, char *buf, size_t count, loff_t *ppos){	unsigned char data;		DBG_ZLG7289("zlg7289_read: input_flag %d\n", input_flag);/*		if(!input_flag){		repeat:		set_current_state(TASK_INTERRUPTIBLE);	       	if (!input_flag && !signal_pending(current)) {			schedule();			goto repeat;							}		current->state = TASK_RUNNING;			}*/	put_user(input_data, buf);//	input_flag = 0;	input_data = 0xff;		return count;}static int zlg7289_write (struct file *file, const char *buf, size_t count, loff_t *ppos){	unsigned char cmd_type, on_off, cmd, data;		DBG_ZLG7289("zlg7289_write: %p\n", buf);	get_user(cmd_type, buf++);		switch (cmd_type) {		case ULED1_CONTROL:			get_user(on_off, buf);			uled_control(1, on_off);			break;		case ULED2_CONTROL:			get_user(on_off, buf);			uled_control(2, on_off);			break;		case ULED3_CONTROL:			get_user(on_off, buf);			uled_control(3, on_off);			break;		case ULED4_CONTROL:			get_user(on_off, buf);			uled_control(4, on_off);			break;		case ZLG_CMD:			get_user(cmd, buf);			zlg7289_transform(cmd, 0, TRAN_CMD);			break;		case ZLG_CMD_DATA:			get_user(cmd, buf++);			get_user(data, buf);			zlg7289_transform(cmd, data, TRAN_CMD_DATA);			break;		default:			DBG_ZLG7289("zlg7289_write: cmd_type = %d error\n", cmd_type);			break;	}//end switch		return count;	}static void zlg7289_interrupt (int irq, void *dev_id, struct pt_regs *regs){	unsigned char data = 0;		//DBG_ZLG7289("zlg7289_interrupt\n");		if(AT91_SYS->PIOB_ISR & ZLG_KEY){		data = zlg7289_transform(0x15, 0, READ_CMD_DATA);	}	printk("zlg7289_interrupt: key = %x\n", data);	if( data != 0xff){		input_flag = 1;		input_data = data;			}		return;	}static void __init zlg7289_init (void){	int ret;		zlg7289_hardware_init();			ret = request_irq(AT91C_ID_PIOB, zlg7289_interrupt, 0,"ZLG7289", NULL);	    	if( ret !=0 ){		printk(KERN_ERR "Request Interrupt %d failed: error = %d\n", AT91C_ID_PIOB, ret);		goto fail_request_irq;	} 	if(register_chrdev(ZLG7289_MAJOR, "zlg7289", &zlg7289_fops)){		DBG_ZLG7289("register_chrdev for zlg7289 error\n");		goto fail_register_chrdev;	}	printk(KERN_INFO __FILE__ ":  Keyboard for AT91RM9200, Using IRQ %d\n", AT91C_ID_PIOB);	return;	fail_register_chrdev:	free_irq(AT91C_ID_PIOB, NULL);fail_request_irq:	return;}static void __exit zlg7289_cleanup (void){	unregister_chrdev(ZLG7289_MAJOR, "zlg7289");		return;	}module_init(zlg7289_init);module_exit(zlg7289_cleanup);

⌨️ 快捷键说明

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