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

📄 cf.c

📁 基于ARM9200的CF卡驱动程序
💻 C
字号:
/*  * 8255a GPIO interface for Linux on Atmel AT91RM9200 * Copyright (c) 2006 Ligang Wang * wangzitan@163.com *//* include some file */ #include <linux/module.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/string.h>#include <linux/poll.h>#include <linux/init.h>#include <asm/io.h>#include <asm/system.h>#include <asm/arch/hardware.h>#include <asm/segment.h>#include "cf.h"AT91PS_SYS AT91_SYS1 = (AT91PS_SYS) AT91C_VA_BASE_SYS;static cf_information card_info;/* * Read funcation for vfs */ssize_t at91_cf_read(struct file * file, char *buf, size_t count, loff_t * ppos){	char temp;
	int i,retval;	unsigned short tmp_data[256];
	temp = 0;
	*((char *)(card_info.cf_addr_io_base + 2)) = 1;
	*((char *)(card_info.cf_addr_io_base + 3)) = 0;
	*((char *)(card_info.cf_addr_io_base + 4)) = 0;
	*((char *)(card_info.cf_addr_io_base + 5)) = 0;
	*((char *)(card_info.cf_addr_io_base + 6)) = 0xe0;
	*((char *)(card_info.cf_addr_io_base + 7)) = 0x20;

	 while(temp != 0x58)//(((temp>>8)&0xff) != 0x58)
	 {
	 	temp = *((char *)(card_info.cf_addr_io_base + 7));	 	printk("Read data %04x\n", temp);
	 }

	 for(i=0;i<256;i++)
	 {
	 	tmp_data[i] =  *((unsigned short  *)(card_info.cf_addr_io_base+8));	 	
	 }
	retval = copy_to_user(buf,(char *)tmp_data,sizeof(unsigned char)*512);	if (!retval)		retval = sizeof(unsigned char)*512;	return retval;	return -1;}/* * Write funcation for vfs */ssize_t at91_cf_write(struct file * file, const char * buf, size_t count, loff_t * ppos){	char temp;
	int i;	unsigned short tmp_data[256];
	int retval = 0;	retval = copy_from_user((char *)tmp_data,buf,sizeof(unsigned char)*512);	if (retval)		return retval;	temp = 0;
	*((char *)(card_info.cf_addr_io_base + 2)) = 64;
	*((char *)(card_info.cf_addr_io_base + 3)) = 0;
	*((char *)(card_info.cf_addr_io_base + 4)) = 0;
	*((char *)(card_info.cf_addr_io_base + 5)) = 0;
	*((char *)(card_info.cf_addr_io_base + 6)) = 0xe0;
	*((char *)(card_info.cf_addr_io_base + 7)) = 0x30;

	 while(temp != 0x58)//(((temp>>8)&0xff) != 0x58)
	 {
	 	temp = *((char *)(card_info.cf_addr_io_base + 7));	 	//printk("write status data %04x\n", temp);
	 }

	 for(i=0;i<256;i++)
	 {
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 	
	 	*((unsigned short  *)(card_info.cf_addr_io_base+8)) = tmp_data[i] ;	 		}
	return 512;}		/* open a device */static int at91_cf_open(struct inode* inode,struct file* file){	MOD_INC_USE_COUNT;
	return 0;	}/* * Handle commands from user-space. */static int at91_cf_ioctl(struct inode *inode, struct file *file,		unsigned int cmd, unsigned long arg){		return 0;		}static void at91_cf_setiomode(){	char data;
	data = *(unsigned char *)(card_info.cf_addr_attrib_base + (1<<9));
	printk("data0 = %x\n",data);
	data &= 0xc0;
	data ++;
	*(unsigned char *)(card_info.cf_addr_attrib_base + (1<<9)) = data;
	data = *(unsigned char *)(card_info.cf_addr_attrib_base + (1<<9));
	printk("data1 = %x\n",data);	}/* * setup cf hardware */	static void at91_cf_setup(void){	/*Enable clock and power of PIOC and PIOB. */	AT91_SYS1->PMC_PCER = ((1<<AT91C_ID_PIOC)|(1<<AT91C_ID_PIOB)); 		/*Configure PIO as CF card periph*/	AT91_SYS1->PIOC_PDR = AT91C_PC6_NWAIT | AT91C_PC7_A23 | AT91C_PC9_A25_CFRNW |     	AT91C_PC10_NCS4_CFCS | AT91C_PC11_NCS5_CFCE1 | AT91C_PC12_NCS6_CFCE2;    AT91_SYS1->PIOC_ASR = AT91C_PC6_NWAIT | AT91C_PC7_A23 | AT91C_PC9_A25_CFRNW |     	AT91C_PC10_NCS4_CFCS | AT91C_PC11_NCS5_CFCE1 | AT91C_PC12_NCS6_CFCE2;  /* set up for periph A */	AT91_SYS1->PIOC_PER = AT91C_PIO_PC5;	AT91_SYS1->PIOC_ODR = AT91C_PIO_PC5;	/* Configure as input */	AT91_SYS1->PIOC_IER = AT91C_PIO_PC5;	/* Enable interrupt */	AT91_SYS1->PIOC_PPUER = AT91C_PIO_PC5;		AT91_SYS1->PIOB_PER = AT91C_CF_PB21_RDY;	AT91_SYS1->PIOB_ODR = AT91C_CF_PB21_RDY;	/* Configure PB21 RDY/-BSY as input */    AT91_SYS1->PIOB_PER = AT91C_CF_PB18_STSCHG | AT91C_CF_PB20_IOIS16 | AT91C_CF_PB21_RDY | AT91C_CF_PB5_RESET | AT91C_CF_PB6_ENABLE;  /* enable the pio */    AT91_SYS1->PIOB_OER = AT91C_CF_PB5_RESET | AT91C_CF_PB6_ENABLE;  /* enable it */    AT91_SYS1->PIOB_CODR = AT91C_CF_PB5_RESET | AT91C_CF_PB6_ENABLE;  /* clear it */	/* Setup Compact Flash, enable the address range of CS4 */    AT91_SYS1->EBI_CSA |= AT91C_EBI_CS4A_SMC_CompactFlash;//AT91C_EBI_CS4A_SMC_COMPACTFLASH;	#define SM_RWH		(4 << 28)  /* hold time, was 2 */	#define SM_RWS		(6 << 24)  /* setup time, was 6 */	#define SM_TDF		(1 << 8)  /* data float time,  */	#define SM_NWS		(32)  /* wait states, NOTE: 0=1.5, 1=2.5, etc */	/* debug only */	AT91_SYS1->EBI_SMC2_CSR[4] = SM_RWH | SM_RWS | AT91C_SMC2_ACSS_STANDARD |	                      AT91C_SMC2_DBW_16 | AT91C_SMC2_BAT | AT91C_SMC2_WSEN | SM_NWS;		return;}static int at91_cf_release(struct inode* inode,struct file* file){	MOD_DEC_USE_COUNT;	return 0;}struct file_operations at91_cf_fops = {	owner:       THIS_MODULE,
	write:		at91_cf_write,
	read:			at91_cf_read,	open:     at91_cf_open,	ioctl:		at91_cf_ioctl,	release:  at91_cf_release,};static int at91_cf_probe(){	if ( !(AT91_SYS1->PIOC_PDSR & (AT91C_CF_PC5_CD1)))	{		return 0;	}	/*if ( (AT91_SYS1->PIOB_PDSR & AT91C_CF_PB21_RDY))	{		printk("CF Card Ready\n");	}*/		return -1;}static int at91_cf_ioremap(){	card_info.cf_addr_attrib_base = (unsigned long)(ioremap(CF_ADDR_ATTR_BASE, CF_IOREMAP_SIZE));	if (check_region(card_info.cf_addr_attrib_base, CF_IOREMAP_SIZE)<0) 		return -1; 	request_region(card_info.cf_addr_attrib_base, CF_IOREMAP_SIZE,"cf card");	card_info.cf_addr_io_base = (unsigned long)(ioremap(CF_ADDR_IO_BASE, CF_IOREMAP_SIZE));	if (check_region(card_info.cf_addr_io_base, CF_IOREMAP_SIZE)<0) 		return -1; 	request_region(card_info.cf_addr_io_base, CF_IOREMAP_SIZE,"cf card");	card_info.cf_addr_mem_base = (unsigned long)(ioremap(CF_ADDR_MEM_BASE, CF_IOREMAP_SIZE));	if (check_region(card_info.cf_addr_mem_base, CF_IOREMAP_SIZE)<0) 		return -1; 	request_region(card_info.cf_addr_mem_base, CF_IOREMAP_SIZE,"cf card");		return 0;}/* * Initialize and install cf driver */static int __init at91_cf_init(void){	at91_cf_setup();	if(at91_cf_probe() == 0)	{		card_info.is_insert = 0;		printk("CF Card insert\n");	}	else		return -1;		if(at91_cf_ioremap() == -1)	{		printk("CF: io remap err, the memory is busy\n");		return -1;	}	at91_cf_setiomode();	if(register_chrdev(DEV_MAJOR,"cf card",&at91_cf_fops))
	{		printk("CF: Can not register CF card driver \n");
		return -1;
	}	printk("CF: the CF card is working now\n");		//io remap		return 0;}/* * Disable and remove the 8255A driver */static void __exit at91_cf_exit(void){	printk("CF: at91_cf_exit has been called\n");	unregister_chrdev(DEV_MAJOR,"cf card");	iounmap(card_info.cf_addr_attrib_base);	iounmap(card_info.cf_addr_io_base);	iounmap(card_info.cf_addr_mem_base);	return;}module_init(at91_cf_init);module_exit(at91_cf_exit);MODULE_AUTHOR("Ligang Wang");MODULE_DESCRIPTION("AT91 rm9200 8255a driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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