免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2519 | 回复: 0
打印 上一主题 下一主题

AT91RM9200 K9K8** NAND Flash 驱动程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-14 11:57 |只看该作者 |倒序浏览
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
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP