📄 at91_nand.c
字号:
/* * drivers/at91/mtd/at91_nand.c * * Copyright (c) 2003 Rick Bronson * * Derived from drivers/mtd/nand/autcpu12.c * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * * Derived from drivers/mtd/spia.c * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * *///#include "pio.h"#include "at91_nand.h"#include "types.h"//#include "mtd.h"#include "hardware.h"#include "At91rm9200.h"//#include "At91rm9200_SYS.h"//#include "errno.h"//#include "io.h"//AT91PS_SYS AT91_SYS ;/* * System peripheral registers mapped at virtual address. */AT91PS_SYS AT91_SYS = (AT91PS_SYS) AT91C_VA_BASE_SYS;extern void AT91F_DBGU_Printk(char *buffer); // \arg pointer to a string ending by \0 // extern struct nand_flash_dev nand_flash_ids[];//extern struct nand_manufacturers nand_manuf_ids[]; int at91_fio_base,this_IO_ADDR_R; /* * Chip ID list */ struct nand_flash_dev nand_flash_ids[] = { {"NAND 1MB 5V", 0x6e, 20, 0x1000, 1}, // 1Mb 5V {"NAND 2MB 5V", 0x64, 21, 0x1000, 1}, // 2Mb 5V {"NAND 4MB 5V", 0x6b, 22, 0x2000, 0}, // 4Mb 5V {"NAND 1MB 3,3V", 0xe8, 20, 0x1000, 1}, // 1Mb 3.3V {"NAND 1MB 3,3V", 0xec, 20, 0x1000, 1}, // 1Mb 3.3V {"NAND 2MB 3,3V", 0xea, 21, 0x1000, 1}, // 2Mb 3.3V {"NAND 4MB 3,3V", 0xd5, 22, 0x2000, 0}, // 4Mb 3.3V {"NAND 4MB 3,3V", 0xe3, 22, 0x2000, 0}, // 4Mb 3.3V {"NAND 4MB 3,3V", 0xe5, 22, 0x2000, 0}, // 4Mb 3.3V {"NAND 8MB 3,3V", 0xd6, 23, 0x2000, 0}, // 8Mb 3.3V {"NAND 8MB 3,3V", 0xe6, 23, 0x2000, 0}, // 8Mb 3.3V {"NAND 16MB 3,3V", 0x73, 24, 0x4000, 0},// 16Mb 3,3V {"NAND 32MB 3,3V", 0x75, 25, 0x4000, 0}, // 32Mb 3,3V {"NAND 64MB 3,3V", 0x76, 26, 0x4000, 0}, // 64Mb 3,3V {"NAND 128MB 3,3V", 0x79, 27, 0x4000, 0}, // 128Mb 3,3V {"NAND 256MB 3,3V", 0xda, 28, 0x4000, 0}, // 256Mb 3,3V //hqc 20070802 add {NULL,} }; /* * Manufacturer ID list */ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_TOSHIBA, "Toshiba"}, {NAND_MFR_SAMSUNG, "Samsung"}, {NAND_MFR_FUJITSU, "Fujitsu"}, {NAND_MFR_NATIONAL, "National"}, {0x0, "Unknown"} }; /* * Constants for hardware specific CLE/ALE/NCE function */#define NAND_CTL_SETNCE 1#define NAND_CTL_CLRNCE 2#define NAND_CTL_SETCLE 3#define NAND_CTL_CLRCLE 4#define NAND_CTL_SETALE 5#define NAND_CTL_CLRALE 6 #define NAND_ALE_HIGH (*AT91C_PIOA_SODR) |= AT91C_PIO_PA22; //set ALE = "1"#define NAND_ALE_LOW (*AT91C_PIOA_CODR) |= AT91C_PIO_PA22; //set ALE = "0"#define NAND_CLE_HIGH (*AT91C_PIOA_SODR) |= AT91C_PIO_PA21; //set CLE = "1"#define NAND_CLE_LOW (*AT91C_PIOA_CODR) |= AT91C_PIO_PA21; //set CLE = "0"#define nand_select() (*AT91C_PIOC_CODR) |= AT91C_PIO_PC15; //set CE = "0"#define nand_deselect() (*AT91C_PIOC_SODR) |= AT91C_PIO_PC15; //set CE = "1"/* * samsung K9F2G08U0M NAND flash commands */#define NAND_CMD_READ_RCB 0x35#define NAND_CMD_CACHEPROG_1 0x80#define NAND_CMD_CACHEPROG_2 0x15#define NAND_CMD_CB_PROG_1 0x85#define NAND_CMD_CB_PROG_2 0x10#define NAND_CMD_RANDOM_DI 0x85#define NAND_CMD_RANDOM_DO1 0x05#define NAND_CMD_RANDOM_DO2 0xe0//#define NAND_CMD_SEQIN 0x80#define NAND_CMD_PAGEPROG 0x10#define NAND_CMD_ERASE1 0x60 #define NAND_CMD_ERASE2 0xd0 #define NAND_CMD_READ0 0x00#define NAND_CMD_READ1 0x30#define NAND_CMD_READID 0x90 #define NAND_CMD_RESET 0xff#define NAND_CMD_STATUS 0x70 #define PAGE_DATA_MAX 2112u8 buff1[PAGE_DATA_MAX],buff2[30];void delay(void){ u16 i; for(i=0;i<100;i++);} /* * Memory mapped I/O to PCI */ u8 readb(unsigned long addr) { u8 val; nand_select();// (*AT91C_PIOC_CODR) |= AT91C_PIO_PC15; //set CE = "0" val=*(volatile u8 *)addr; nand_deselect();// (*AT91C_PIOC_SODR)|=AT91C_PIO_PC15; //set CE = "1" return val; } void writeb(u8 b, unsigned long addr) { *(volatile u8 *)addr = b; }int AT91_PIO_SmartMedia_RDY(void) { return ((*AT91C_PIOC_PDSR) & AT91C_PIO_PC14) ? 1 : 0;}/* * Send command to NAND device */// static void at91_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)static void at91_nand_command (unsigned command, int column, int page_addr){}void ST_CMD(unsigned command, unsigned flag){ register unsigned long NAND_IO_ADDR; if(flag==0) {//command /* Begin command latch cycle */ NAND_IO_ADDR = at91_fio_base + AT91_SMART_MEDIA_CLE;// NAND_CLE_HIGH; nand_select(); // (*AT91C_PIOC_CODR) |= (AT91C_PIO_PC15); //set CE = "0" writeb (command, NAND_IO_ADDR);// (*AT91C_PIOC_SODR)|=AT91C_PIO_PC15; //set CE = "1" nand_deselect();// NAND_CLE_LOW; } else {//address /* Set ALE and clear CLE to start address cycle */ NAND_IO_ADDR = at91_fio_base + AT91_SMART_MEDIA_ALE;// NAND_ALE_HIGH; nand_select();// (*AT91C_PIOC_CODR) |= (AT91C_PIO_PC15); //set CE = "0" writeb (command, NAND_IO_ADDR);// (*AT91C_PIOC_SODR)|=AT91C_PIO_PC15; //set CE = "1" nand_deselect();// NAND_ALE_LOW; } delay(); while(AT91_PIO_SmartMedia_RDY()); } void ST_ADR(unsigned command) { } void ST_DAT(unsigned command) { } void ST_INVALID(void) { } void Check_Flash_ID(void) { } void Erase_Block(int blockaddr, int len) { u32 blockpage,i; u8 addr1,addr2,addr3,val; blockpage=(blockaddr<<6); addr1=(u8)(blockpage & 0x000000c0); addr2=(u8)((blockpage & 0x0000ff00)>>8); addr3=(u8)((blockpage & 0x00010000)>>16); //write command ST_CMD(NAND_CMD_ERASE1, 0);//write address ST_CMD(addr1, 1); ST_CMD(addr2, 1); ST_CMD(addr3, 1); delay();//write command ST_CMD(NAND_CMD_ERASE2, 0); delay(); while(AT91_PIO_SmartMedia_RDY()); delay(); ST_CMD(NAND_CMD_STATUS, 0); delay(); delay(); val=readb(this_IO_ADDR_R); if(val & 0x1) AT91F_DBGU_Printk ("NAND device: block erase error \n\r"); else AT91F_DBGU_Printk ("NAND device: block erase ok \n\r"); } void Program_Page(int pageaddr, int len) { u32 i; u8 addr1,addr2,addr3,val; addr1=(u8)(pageaddr & 0x000000ff); addr2=(u8)((pageaddr & 0x0000ff00)>>8); addr3=(u8)((pageaddr & 0x00010000)>>16); //write command ST_CMD(NAND_CMD_SEQIN, 0);//write address//column address ST_CMD(0x00, 1); ST_CMD(0x00, 1);//row address ST_CMD(addr1, 1); ST_CMD(addr2, 1); ST_CMD(addr3, 1);//write data nand_select(); for(i=0;i<PAGE_DATA_MAX;i++) { writeb (buff1[i], this_IO_ADDR_R);// ST_CMD(buff1[i], 1); delay(); } nand_deselect();//write command ST_CMD(NAND_CMD_PAGEPROG, 0); delay(); while(AT91_PIO_SmartMedia_RDY()); ST_CMD(NAND_CMD_STATUS, 0); delay(); val=readb(this_IO_ADDR_R); if(val & 0x1) AT91F_DBGU_Printk ("NAND device: write error \n\r"); else AT91F_DBGU_Printk ("NAND device: write ok \n\r"); } void Read_Page(int pageaddr, int len) { u32 i; u8 addr1,addr2,addr3,val; addr1=(u8)(pageaddr & 0x000000ff); addr2=(u8)((pageaddr & 0x0000ff00)>>8); addr3=(u8)((pageaddr & 0x00010000)>>16); //write command ST_CMD(NAND_CMD_READ0, 0); delay(); //write address //column address ST_CMD(0x00, 1); ST_CMD(0x00, 1); //row address ST_CMD(addr1, 1); ST_CMD(addr2, 1); ST_CMD(addr3, 1); //write command delay(); ST_CMD(NAND_CMD_READ1, 0); delay(); while(AT91_PIO_SmartMedia_RDY()); delay(); //write data nand_select(); for(i=0;i<30;i++) { val=*(volatile u8 *)(this_IO_ADDR_R); buff2[i]=val; } nand_deselect(); } static void AT91_CfgPIO_SmartMedia(void) { /* enable PC15=SMCE, PC1=SMOE, PC3=SMWE, A21=CLE, A22=ALE */ (*AT91C_PIOC_ASR) = AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE; (*AT91C_PIOC_PDR) = AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE;// AT91C_PIO_PC15 /* Configure PC14 as input (signal READY of the SmartMedia) */ (*AT91C_PIOC_PER) |= AT91C_PIO_PC14|AT91C_PIO_PC15; /* enable direct output enable */ (*AT91C_PIOC_OER) |= AT91C_PIO_PC15; /* PC14 input, PC15 output */ (*AT91C_PIOC_ODR) |= AT91C_PIO_PC14; /* disable PC14 output */////////////////////////// /* PA21=CLE -->output ,PA22=ALE --> output */// (*AT91C_PIOA_PER) |= AT91C_PIO_PA21|AT91C_PIO_PA22; /* enable direct output enable */// (*AT91C_PIOA_OER) |= AT91C_PIO_PA21|AT91C_PIO_PA22; /* PA21 , PA22 output */} /* * Scan for the NAND device */ int nand_scan (void) { int i, nand_maf_id, nand_dev_id; /* Select the device */// nand_select (); ST_CMD(NAND_CMD_RESET, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -