📄 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 function for vfs */ssize_t 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 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 cf_open(struct inode* inode,struct file* file){ MOD_INC_USE_COUNT; return 0; }/* * Handle commands from user-space. */static int cf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ return 0; }static void 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 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 cf_release(struct inode* inode,struct file* file){ MOD_DEC_USE_COUNT; return 0;}struct file_operations cf_fops = { owner: THIS_MODULE, write: cf_write, read: cf_read, open: cf_open, ioctl: cf_ioctl, release: cf_release,};static int 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 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 cf_init(void){ cf_setup(); if(cf_probe() == 0) { card_info.is_insert = 0; printk("CF Card insert\n"); } else return -1; if(cf_ioremap() == -1) { printk("CF: io remap err, the memory is busy\n"); return -1; } cf_setiomode(); if(register_chrdev(DEV_MAJOR,"cf card",&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 cf_exit(void){ printk("CF: 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(cf_init);module_exit(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 + -