📄 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 + -