- 论坛徽章:
- 0
|
AT91RM9200 K9K8** NAND Flash 驱动程序
CPU:AT91RM9200
NAND:K9K8G08
不同容量的NAND需要做相应的调整,同时需要对控制脚相应的进行调整
驱动程序如下,希望对需要的有所帮助,验证通过。
/*********************************************************************************************
File Name: char K9F1G_statu(void)
description:
writer: Liuxinmin
version: 1.0
date: 2009 10 20
last chage: 2009 10 19
*********************************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
#include
#include
#include
#include
#include
#include
#include
//#include "can0.h"
#include
#include
/*****************************************************************************************************************/
#define K9F1G08R0A
#define FLASH_READ_START 0x00 //read 1st. Cycle
#define FLASH_READ_END 0x30 //read 2nd. Cycle
#define FLASH_READ_FOR_COPY_BANK_START 0x00 //Read for Copy Back 1st.cycle
#define FLASH_READ_FOR_COPY_BANK_END 0x35 //Read for Copy Back 2nd.cycle
#define FLASH_READ_ID 0x90 //read device id
#define FLASH_RESET 0xFF //reset device
#define FLASH_PAGE_PROGRAM_START 0x80 //Page Program 1st.cycle
#define FLASH_PAGE_PROGRAM_END 0x10 //Page Program 2nd.cycle
#define FLASH_CACHE_PROGRAM_START 0x80 //Cache Program 1st.cycle
#define FLASH_CACHE_PROGRAM_END 0x15 //Cache Program 2nd.cycle
#define FLASH_COPY_BANK_PROGRAM_START 0x00 //Copy-Back Program 1st.cycle
#define FLASH_COPY_BANK_PROGRAM_END 0x30 //Copy-Back Program 2nd.cycle
#define FLASH_BLOCK_ERASE_START 0x60 //EraseBlock 1st.cycle
#define FLASH_BLOCK_ERASE_END 0xD0 //Erase Block end cyc
#define FLASH_RANDOM_DATA_INPUT 0x85 //Random Data Input
#define FLASH_RANDOM_DATA_OUTPUT_START 0x05 //Random Data Output 1st.cycle
#define FLASH_RANDOM_DATA_OUTPUT_END 0xE0 //Random Data Output 2nd.cyc
#define FLASH_READ_STTUS 0x70 //Read Status
#define K9F1G_ADDRESS_ADDRESS (0x40000000|(0x1PIOC_ODSR = AT91C_PIO_PC3;AT91_SYS->PIOC_SODR = AT91C_PIO_PC3;}
//PC3 should be low now
//#define K9F1G_WE_LOW() {AT91_SYS->PIOC_ODSR = 0; AT91_SYS->PIOC_SODR = AT91C_PIO_PC3;}
//PC3 should be high now
//#define K9F1G_RE_HIGH() {AT91_SYS->PIOC_ODSR = AT91C_PIO_PC1;AT91_SYS->PIOC_SODR = AT91C_PIO_PC1;}
//PC3 should be low now
//#define K9F1G_RE_LOW() {AT91_SYS->PIOC_ODSR = 0; AT91_SYS->PIOC_SODR = AT91C_PIO_PC1;}
/*****************************************************************************************************************/
//declare the varias
static unsigned int flash_address_add=0;
static unsigned int flash_command_add=0;
static unsigned int flash_data_add=0;
//declare the function
static int flash_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
static ssize_t flash_read(struct file*, char*, size_t, loff_t*);
static ssize_t flash_write(struct file*, const char*, size_t, loff_t*);
static int flash_open(struct inode*, struct file*);
static int flash_release(struct inode*, struct file*);
struct file_operations flash_simon_fops = {
// owner: THIS_MODULE,
ioctl: flash_ioctl,
write: flash_write,
read: flash_read,
open: flash_open,
release: flash_release
};
static unsigned int FlashWriteAddress=0;
static unsigned int FlashReadAddress=0;
static unsigned int block_address = 0;
/***************************************************************************************************
function name: delay_flash(int nb)
function description: delay the CPU not to do anything,just delay
function.
****************************************************************************************************/
void delay_flash(int nb)
{
while(nb--);
}
/*************************************************************************************
Name: char K9F1G_statu(void)
Function: get the K9F1G Busy or Ready statu
return:
1:ready
0:busy
writer: Liuxinmin
date:2009 10 20
last chage:2009 10 20
*************************************************************************************/
unsigned int K9F1G_statu(void) {
int statu;
statu = ((AT91_SYS->PIOC_PDSR ) & AT91C_PIO_PC15);
return statu;
}
void K9F1G_CE_HIGH()
{
#ifdef newboard
AT91_SYS->PIOC_SODR = AT91C_PIO_PC13;
#else
AT91_SYS->PIOA_SODR = AT91C_PIO_PA0;
#endif
}
void K9F1G_CE_LOW()
{
#ifdef newboard
AT91_SYS->PIOC_CODR = AT91C_PIO_PC13; //clear the output reg
#else
AT91_SYS->PIOA_CODR = AT91C_PIO_PA0;
#endif
}
int K9F1G_READ_ID()
{
int i;
unsigned char id[5];
//outb(FLASH_READ_ID,flash_command_add);
printk(" Physical address=%X\r\n ",K9F1G_DATA_ADDRESS);
printk(" Physical address+1PIOC_PER = AT91C_PIO_PC13; //enable the peripheral control
AT91_SYS->PIOC_OER = AT91C_PIO_PC13; //output enable
AT91_SYS->PIOC_SODR = AT91C_PIO_PC13;
#if 0
/*init the PA0*/
AT91_SYS->PIOC_MDDR = AT91C_PIO_PC13; //disable the Multi function
AT91_SYS->PIOC_PER = AT91C_PIO_PC13; //enable the peripheral control
AT91_SYS->PIOC_OER = AT91C_PIO_PC13; //output enable
AT91_SYS->PIOC_IFDR = AT91C_PIO_PC13;
//AT91_SYS->PIOA_CODR = AT91C_PIO_PA0;
AT91_SYS->PIOC_IDR = AT91C_PIO_PC13; //disable the interrupt
//AT91_SYS->PIOC_MDDR = AT91C_PIO_PC13; //disable the Multi function
//AT91_SYS->PIOA_PPUER = AT91C_PIO_PA0;
//AT91_SYS->PIOA_OWER = AT91C_PIO_PA0; //enable write the PIO_ODSR for PA0
AT91_SYS->PIOC_SODR = AT91C_PIO_PC13;
//AT91_SYS->PIOA_ODSR = AT91C_PIO_PA0;
/*init the PC1 and PC3 for */
/*should init the PC1 and PC3 as SMC signal*/
AT91_SYS->PIOC_PER = AT91_SYS->PIOC_PER | AT91C_PIO_PC1 | AT91C_PIO_PC3; //enable the peripheral control
AT91_SYS->PIOC_OER = AT91_SYS->PIOC_OER | AT91C_PIO_PC1 | AT91C_PIO_PC3; //output enable
AT91_SYS->PIOC_IFDR = AT91_SYS->PIOC_IFDR | AT91C_PIO_PC1 | AT91C_PIO_PC3;
AT91_SYS->PIOC_CODR = AT91_SYS->PIOC_CODR | AT91C_PIO_PC1 | AT91C_PIO_PC3;
AT91_SYS->PIOC_IDR = AT91_SYS->PIOC_IDR | AT91C_PIO_PC1 | AT91C_PIO_PC3; //disable the interrupt
AT91_SYS->PIOC_MDER = AT91_SYS->PIOC_MDER | AT91C_PIO_PC1 | AT91C_PIO_PC3;
AT91_SYS->PIOC_PPUER = AT91_SYS->PIOC_PPUER | AT91C_PIO_PC1 | AT91C_PIO_PC3;
AT91_SYS->PIOC_OWER = AT91_SYS->PIOC_OWER | AT91C_PIO_PC1 | AT91C_PIO_PC3; //enable write the PIO_ODSR for PA22
#endif
/*init the PC15 for R/-B signal*/
AT91_SYS->PIOC_ODR = AT91C_PIO_PC15; //disable the output
AT91_SYS->PIOC_PER = AT91C_PIO_PC15; //enable the peripheral control
AT91_SYS->PIOC_PPUER = AT91C_PIO_PC15; //disable the pullup
#if 0
AT91_SYS->PIOC_ODR = AT91C_PIO_PC15; //disable the output
AT91_SYS->PIOC_IFER = AT91C_PIO_PC15; //enable the filter
AT91_SYS->PIOC_CODR = AT91C_PIO_PC15; //clean the output reg
AT91_SYS->PIOC_IER = AT91C_PIO_PC15; //disable the interrupt
AT91_SYS->PIOC_MDDR = AT91C_PIO_PC15; //enable the multidriver
AT91_SYS->PIOC_PPUDR = AT91C_PIO_PC15; //disable the pullup
AT91_SYS->PIOC_OWDR = AT91C_PIO_PC15; //disable the output write
#endif
}
/*************************************************************************************
*************************************************************************************/
void K9F1G_state(void)
{
;
}
/*************************************************************************************
function name:unsigned int Write_K9F1G_Data(unsigned int WriteAddress,
unsigned char *WriteData,
unsigned int Write_count)
*************************************************************************************/
unsigned int Write_K9F1G_Data(unsigned int WriteAddress,unsigned char *WriteData, unsigned int Write_count)
{
int address_loop;
char state=0;
unsigned char address_in_8_bit[5];
int state_count=0;
if (WriteAddress >= 0x40000000)
{
printk("Write Error:NAND flash address out of range!");
return 0;
}
if (Write_count > 2048)
{
return 0;
}
//deal with the address,
/*the address cycle
1st Cycle A0 A1 A2 A3 A4 A5 A6 A7
2nd Cycle A8 A9 A10 A11 *L *L *L *L
3rd Cycle A12 A13 A14 A15 A16 A17 A18 A19
4th Cycle A20 A21 A22 A23 A24 A25 A26 A27
5th Cycle A28 A29 A30 *L *L *L *L *L
*/
address_in_8_bit[0] = WriteAddress & 0x000000ff;
address_in_8_bit[1] = (WriteAddress & 0x00000f00) >> 8;
address_in_8_bit[2] = (WriteAddress & 0x000ff000) >> 12;
address_in_8_bit[3] = (WriteAddress & 0x0ff00000) >> 20;
address_in_8_bit[4] = (WriteAddress & 0x70000000) >> 28;
//begin the page program progress
//send the page program command start
K9F1G_CE_LOW();
outb(FLASH_PAGE_PROGRAM_START,flash_command_add);
//send the page program address
for (address_loop = 0; address_loop = 0x40000000)
{
printk("Read Error:NAND flash address out of range!");
return 0;
}
if (Read_count > 2112)
{
return 0;
}
//deal with the address,
/*the address cycle
1st Cycle A0 A1 A2 A3 A4 A5 A6 A7
2nd Cycle A8 A9 A10 A11 *L *L *L *L
3rd Cycle A12 A13 A14 A15 A16 A17 A18 A19
4th Cycle A20 A21 A22 A23 A24 A25 A26 A27
5th Cycle A28 A29 A30 *L *L *L *L *L
*/
address_in_8_bit[0] = ReadAddress & 0x000000ff;
address_in_8_bit[1] = (ReadAddress & 0x00000f00) >> 8;
address_in_8_bit[2] = (ReadAddress & 0x000ff000) >> 12;
address_in_8_bit[3] = (ReadAddress & 0x0ff00000) >> 20;
address_in_8_bit[4] = (ReadAddress & 0x70000000) >> 28;
//begin the page program progress
//send the page program command start
K9F1G_CE_LOW();
outb( FLASH_READ_START,flash_command_add);
//send the page program address
for (address_loop = 0; address_loop = 0x40000000)
{
printk("Erase Error:NAND flash address out of range!");
return 1;
}
//deal with the address,
/*the address cycle
1st Cycle A0 A1 A2 A3 A4 A5 A6 A7
2nd Cycle A8 A9 A10 A11 *L *L *L *L
3rd Cycle A12 A13 A14 A15 A16 A17 A18 A19
4th Cycle A20 A21 A22 A23 A24 A25 A26 A27
5th Cycle A28 A29 A30 *L *L *L *L *L
*/
address_in_8_bit[0] = (temp & 0xff000)>>12;
address_in_8_bit[1] = (temp & 0xff00000) >> 20;
address_in_8_bit[2] = (temp & 0x070000000) >> 28;
//begin the page program progress
//send the page program command start
//printk("test1:the flash state:%d\n",K9F1G_statu());
K9F1G_CE_LOW();
outb( FLASH_BLOCK_ERASE_START,flash_command_add);
//send the FLASH_BLOCK_ERASE_START address --2 bytes
for (address_loop = 0; address_loop EBI_CSA = (AT91_SYS->EBI_CSA) | AT91C_EBI_CS3A_SMC_SmartMedia;
//AT91_SYS->EBI_SMC2_CSR[3] = 0x33024000;
//AT91_SYS->EBI_CSA = (AT91_SYS->EBI_CSA) | AT91C_EBI_CS3A_SMC_SmartMedia;
//K9F1G_init_CPU(); //init the SJA1000;
AT91_SYS->PMC_PCER |=1 PIOC_ASR = AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE;
AT91_SYS->EBI_CSA = (AT91_SYS->EBI_CSA) | AT91C_EBI_CS3A_SMC_SmartMedia;
AT91_SYS->EBI_SMC2_CSR[3] = ( AT91C_SM_RWH | AT91C_SM_RWS |
AT91C_SMC2_ACSS_STANDARD |
AT91C_SMC2_DBW_8 | AT91C_SM_TDF |
AT91C_SMC2_WSEN | AT91C_SM_NWS);
AT91_SYS->PIOC_PDR = AT91C_PC1_BFRDY_SMOE|AT91C_PC3_BFBAA_SMWE;
//AT91_SYS->PIOC_MDER = AT91C_PC1_BFRDY_SMOE|AT91C_PC3_BFBAA_SMWE;
#ifdef newboard
AT91_SYS->PIOC_MDDR = AT91C_PIO_PC13;
AT91_SYS->PIOC_PER = AT91C_PIO_PC13; //enable the peripheral control
AT91_SYS->PIOC_OER = AT91C_PIO_PC13; //output enable
AT91_SYS->PIOC_SODR = AT91C_PIO_PC13;
/*init the PC15 for R/-B signal*/
AT91_SYS->PIOC_ODR = AT91C_PIO_PC15; //disable the output
AT91_SYS->PIOC_PER = AT91C_PIO_PC15; //enable the peripheral control
AT91_SYS->PIOC_PPUER = AT91C_PIO_PC15; //disable the pullup
#else
AT91_SYS->PIOA_MDDR = AT91C_PIO_PA0;
AT91_SYS->PIOA_PER = AT91C_PIO_PA0; //enable the peripheral control
AT91_SYS->PIOA_OER = AT91C_PIO_PA0; //output enable
AT91_SYS->PIOA_SODR = AT91C_PIO_PA0;
/*init the PC15 for R/-B signal*/
AT91_SYS->PIOC_ODR = AT91C_PIO_PC15; //disable the output
AT91_SYS->PIOC_PER = AT91C_PIO_PC15; //enable the peripheral control
AT91_SYS->PIOC_PPUER = AT91C_PIO_PC15; //disable the pullup
#endif
//AT91_SYS->EBI_SMC2_CSR[3] = 0x2BFF;
// AT91_SYS->EBI_SMC2_CSR[3] = AT91C_SMC2_NWS|AT91C_SMC2_WSEN|AT91C_SMC2_TDF|AT91C_SMC2_DBW_8|AT91C_SMC2_ACSS_STANDARD|AT91C_SMC2_RWSETUP|AT91C_SMC2_RWHOLD;
//remap the address
flash_data_add = K9F1G_DATA_ADDRESS;
flash_data_add = (unsigned int)(ioremap(K9F1G_DATA_ADDRESS,(K9F1G_ADDRESS_ADDRESS - K9F1G_DATA_ADDRESS + 1024) ));
flash_command_add = flash_data_add + (K9F1G_COMMAND_ADDRESS -K9F1G_DATA_ADDRESS) ;
flash_address_add = flash_data_add + (K9F1G_ADDRESS_ADDRESS -K9F1G_DATA_ADDRESS) ;
if (check_region(flash_data_add, (K9F1G_ADDRESS_ADDRESS-K9F1G_DATA_ADDRESS)+0x1024)2112)
{
//read is out of range
return 0;
}
if( Read_K9F1G_Data(FlashReadAddress,data_buff,read_count) !=0)
{
copy_to_user(buff, data_buff, read_count);
return read_count;
}
else
return 0;
}
ssize_t flash_write(struct file* file, const char* ch, size_t count,loff_t* offp)
{
// unsigned char temp;
int write_count;
unsigned char data_buff[2048];
write_count=count;
if((write_count4096))
{
//the write data is out of range
return 0;
}
copy_from_user(data_buff, ch, count);
return (Write_K9F1G_Data(FlashWriteAddress,data_buff, write_count));
}
static int flash_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int err= 0 ;
// unsigned int tmp,i;
//int flash_block_address;
//char len[4];
// unsigned int sector_point;
//unsigned char info_data[BUF_SIZE];
// unsigned char file_name[12]; //last write file name "XXXXXXXX.XXX"
// unsigned char file_descript[20];
unsigned char read_start_address[4];
unsigned char write_start_address[4];
unsigned char flash_block_address[4];
/* don't even decode wrong cmds: better returning ENOTTY than EFAULT */
if (_IOC_TYPE(cmd) != FLASH_IOC_MAGIC) return -ENOTTY;
if (_IOC_NR(cmd) > FLASH_IOC_MAXNR) return -ENOTTY;
/*
* the type is a bitmask, and VERIFY_WRITE catches R/W
* transfers. Note that the type is user-oriented, while
* verify_area is kernel-oriented, so the concept of "read" and
* "write" is reversed
*/
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
if (err) return -EFAULT;
switch (cmd)
{
//
case FLASH_IO_BLOCK_ERASE:
/* copy_from_user(len,(unsigned char *)arg,BLOCK_NUM_LEN);
//Block number is 4 bytes long len[3]len[2]len[1]len[0]
tmp=0;
for(i=0;i=0;i--)
{
//printk("%X",flash_block_address);
block_address=(block_address=0x40000000)||(block_address= 0x40000000)
{
printk("Erase Error:NAND flash address out of range!");
return 1;
}
//deal with the address,
/*the address cycle
1st Cycle A0 A1 A2 A3 A4 A5 A6 A7
2nd Cycle A8 A9 A10 A11 *L *L *L *L
3rd Cycle A12 A13 A14 A15 A16 A17 A18 A19
4th Cycle A20 A21 A22 A23 A24 A25 A26 A27
5th Cycle A28 A29 A30 *L *L *L *L *L
*/
address_in_8_bit[0] = (temp & 0xff000)>>12;
address_in_8_bit[1] = (temp & 0xff00000) >> 20;
address_in_8_bit[2] = (temp & 0x030000000) >> 28;
//begin the page program progress
//send the page program command start
printk("test1:the flash state:%d\n",K9F1G_statu());
K9F1G_CE_LOW();
outb( FLASH_BLOCK_ERASE_START,flash_command_add);
//send the FLASH_BLOCK_ERASE_START address --2 bytes
for (address_loop = 0; address_loop =0;wr_add--)
{
printk("%X",write_start_address[wr_add]);
FlashReadAddress=(FlashWriteAddress=0;rd_add--)
{
printk("%X",read_start_address[rd_add]);
FlashReadAddress=(FlashReadAddress
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15746/showart_2148689.html |
|