nand.c
来自「Centrality Atlas II development software」· C语言 代码 · 共 688 行 · 第 1/2 页
C
688 行
/* * $QNXLicenseC: * Copyright 2007,2008, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ *///#include "atlasii.h"#include "nand.h"extern void Show_LED(int led, int val);extern int bootcs;extern int updatecs;unsignedcrc16(uint8_t *buf, int len) { unsigned crc = 0; uint8_t *end; end = buf + len; while(buf < end) { if(crc & 1) crc |= 0x10000; crc = ((crc>>1) + *buf++) & 0xffff; } return(crc);}unsigned nand_init() { uint8_t id[4]; uint8_t nandcs=0; dev=&chip_dev; dev->iobase =_SMDF_MODULE_BASE; dev->io_brdg = ATLASII_IOBRDG_FLUSH; dev->io_data = dev->iobase + ATLASII_SM_FIFO_DATA; dev->io_address = dev->iobase + ATLASII_SM_LOW_ADDR; dev->io_command = dev->iobase + ATLASII_SM_CMD; //where we are booting from if(updatecs==1 && bootcs==7) //booting from SM cardn update to on boards nand { *(volatile unsigned char*)(EXT_PIO_BASE+0x1C00)=0x0f; *(volatile unsigned char*)(EXT_PIO_BASE+0x1E00)=0; nandcs=3; } else if(updatecs==1 && bootcs==0) //booting from on boards nand and update to SM card { *(volatile unsigned char*)(EXT_PIO_BASE+0x1C00)=0x0f; *(volatile unsigned char*)(EXT_PIO_BASE+0x1E00)=0x08; nandcs=3; } else nandcs=0; *(volatile unsigned int *)(_RSC_MODULE_BASE+0x4) &= ~0x0F00; *(volatile unsigned int *)(_RSC_MODULE_BASE+0x4) |= 0x0d00; if (0 == (in32(dev->iobase+ATLASII_SM_CTRL) & 0x10)) { *(volatile unsigned int *)(_RSC_MODULE_BASE+0x4) |= 0x1; //CAM_EN } out32(dev->iobase+ATLASII_SM_CTRL, in32(dev->iobase+ATLASII_SM_CTRL) & (~0x1)); //IO-Read mode out32(dev->iobase+ATLASII_SM_CTRL, in32(dev->iobase+ATLASII_SM_CTRL) & (~0x2)); //force 8-bit out32(dev->iobase+ATLASII_SM_WAIT, 0x1878); //Set Wait Reg out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x1); //Start FIFO out32(dev->iobase+ATLASII_SM_ECC_SET, 0x0); //disable hardware ECC //NAND bank select ser_putstr((unsigned char *)"bootcs = "); ser_puthex(bootcs); ser_putstr((unsigned char *)" updatecs = "); ser_puthex(updatecs); ser_putstr((unsigned char *)" nandcs = "); ser_puthex(nandcs); ser_putstr((unsigned char *)"\n"); out32(dev->iobase+ATLASII_SM_BANK_SEL, (~(0x1<<nandcs)) & 0xF); //clear all Intrrupt out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xe); // Reset the part nand_write_cmd(dev, NANDCMD_RESET); if(nand_wait_INT(dev, MAX_RESET_USEC, NAND_STATUS_WT_CMD) != 0) return -1; //ser_putstr("NAND: Timeout on RESET\n"); if(nand_read_flashid(dev, id, 4)!=0) return -1; //ser_putstr("NAND: Timeout on ReadID\n"); switch(id[1]) { // 16M case 0x73: dev->numblks = 1024; dev->addrcycles = 3; break; // 32M case 0x75: dev->numblks = 2048; dev->addrcycles = 3; break; // 64M case 0x76: dev->numblks = 4096; dev->addrcycles = 4; break; // 128M case 0x72: case 0x74: case 0x78: case 0x79: dev->numblks = 8192; dev->addrcycles = 4; break; default: ser_putstr((unsigned char *)"nand_init: Unsupported NAND chip\n"); return -1; break; } // We glue to physical pages at the driver and report back their combined size dev->sparesize = SPARESIZE; dev->blksize = (DATASIZE) * PAGES2BLK; return(0);}unsigned nand_wait_INT(NAND_CHIP *dev, uint32_t usec, uint32_t sts) { for(; usec>0 && !(in32(dev->iobase+ATLASII_SM_INT_STATUS)&sts); usec--) ; if(usec==0) return -1; else { //clear intr out32(dev->iobase+ATLASII_SM_INT_STATUS, in32(dev->iobase+ATLASII_SM_INT_STATUS) |sts); return 0; }}// Accessing the command reg automatically sets ALE=0, CLE=1voidnand_write_cmd(NAND_CHIP *dev, int command) { //enter to command mode out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD); out32(dev->io_command, (uint8_t) command);}int nand_read_flashid(NAND_CHIP *dev, uint8_t *id, int data_cycles){ int i=100000000; out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x2); //Reset FIFO out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x0); //Reset FIFO //enter to io read mode out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_READ); //set io-len out32(dev->iobase+ATLASII_SM_DMA_IO_LEN, 0x4); //set addr num out32(dev->iobase+ATLASII_SM_ADD_NUM, 0x1); //set low addr=0; out32(dev->iobase+ATLASII_SM_LOW_ADDR, 0x0); //clear intr out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xf); //set command out32(dev->io_command, NANDCMD_IDREAD); //read id command out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x1); //Reset FIFO //wait command end while((in32(dev->iobase+ATLASII_SM_FIFO_STATUS) & 0x80) && i--) ; if(i<=0) return -1; *(uint32_t *)id = in32(dev->iobase+ATLASII_SM_FIFO_DATA); ser_putstr((unsigned char *)"nand_read_flashid: id="); ser_puthex(*(uint32_t *)id); ser_putstr((unsigned char *)"\n"); out32(dev->io_brdg, 1); while (in32(dev->io_brdg)); return (0);}int nand_read_status(NAND_CHIP *dev, uint8_t *databuffer){ out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x2); //Reset FIFO out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x0); //Reset FIFO //enter to io read mode out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_READ); //set addr num out32(dev->iobase+ATLASII_SM_ADD_NUM, 0); //set low addr=0; out32(dev->iobase+ATLASII_SM_HIGH_ADDR, 0x0); out32(dev->iobase+ATLASII_SM_LOW_ADDR, 0x0); //set io-len out32(dev->iobase+ATLASII_SM_DMA_IO_LEN, 0x4); out32(dev->iobase+ATLASII_SM_FIFO_CTRL, 0x4<<2); //clear intr out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xf); //set command out32(dev->io_command, NANDCMD_STATUSREAD); //read status command out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x1); //Reset FIFO //wait command end if(nand_wait_INT(dev, MAX_READ_USEC, NAND_STATUS_WT_FIFO) != 0) return(-1); else *(uint32_t *)databuffer = in32(dev->iobase+ATLASII_SM_FIFO_DATA); out32(dev->io_brdg, 1); while (in32(dev->io_brdg)); out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x2); //Reset FIFO return 0;}//op=0, read data//op=1, read spareint nand_read_page(NAND_CHIP *dev, unsigned page, uint8_t *databuffer, int data_cycles, int op){ if(op==0) { //Reset ECC out32(dev->iobase+ATLASII_SM_ECC_SET, 0x07); out32(dev->iobase+ATLASII_SM_ECC_SET, 0x05); } out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x2); //Reset FIFO out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x0); //Reset FIFO //enter to io read mode out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_READ); //set io-len out32(dev->iobase+ATLASII_SM_DMA_IO_LEN, data_cycles); //set addr num out32(dev->iobase+ATLASII_SM_ADD_NUM, 0x4); //set low addr=0; out32(dev->iobase+ATLASII_SM_LOW_ADDR, page<<8); out32(dev->iobase+ATLASII_SM_HIGH_ADDR, 0); //clear intr out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xf); //set command if(op==1) out32(dev->io_command, NANDCMD_SPAREREAD); //read2 command else out32(dev->io_command, NANDCMD_READ); //read1 command out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x1); //Reset FIFO //wait command end if(nand_read_data(dev, databuffer, data_cycles)!=0) return -1; return data_cycles;}//op=0, write data//op=1, write spareint nand_write_page(NAND_CHIP *dev, unsigned page, uint8_t *databuffer, int data_cycles, int op){ if(op==0) { //Reset ECC out32(dev->iobase+ATLASII_SM_ECC_SET, 0x07); out32(dev->iobase+ATLASII_SM_ECC_SET, 0x05); } //change the write pointer to either data area or spare area out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD); out32(dev->iobase+ATLASII_SM_ADD_NUM, 0x0); //clear intr out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xf); if(op==0) out32(dev->io_command, NANDCMD_READ); //read1 command else out32(dev->io_command, NANDCMD_SPAREREAD); //read2 command //wait for the command end if(nand_wait_INT(dev, MAX_READ_USEC, NAND_STATUS_WT_CMD) !=0) return (-1); out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x2); //Reset FIFO out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x0); //Reset FIFO //enter to io write mode out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_WRITE); //set io-len out32(dev->iobase+ATLASII_SM_DMA_IO_LEN, data_cycles); //set addr num out32(dev->iobase+ATLASII_SM_ADD_NUM, 0x4); //set low addr=0; out32(dev->iobase+ATLASII_SM_LOW_ADDR, page<<8); out32(dev->iobase+ATLASII_SM_HIGH_ADDR, 0); //clear interrupt out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xf); //set command out32(dev->io_command, NANDCMD_PROGRAM); //write command out32(dev->iobase+ATLASII_SM_FIFO_OP, 0x1); //Reset FIFO if(nand_write_data(dev, databuffer, data_cycles)!=0) return -1; //wait command end if(nand_wait_INT(dev, MAX_POST_USEC, NAND_STATUS_WT_IO) != 0) return(-2); //enter to command mode out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD); out32(dev->iobase+ATLASII_SM_ADD_NUM, 0x0); //clear interrupt out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xf); //set command out32(dev->io_command, NANDCMD_PROGRAMCONFIRM); //write confirm command if(nand_wait_INT(dev, MAX_POST_USEC, NAND_STATUS_WT_CMD) != 0) return(-3); return 0;}int nand_erase_blk(NAND_CHIP *dev, unsigned blk){ out32(dev->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD); out32(dev->iobase+ATLASII_SM_ADD_NUM, 0x3); //set low addr=0; out32(dev->iobase+ATLASII_SM_LOW_ADDR, (blk<<5)); out32(dev->iobase+ATLASII_SM_HIGH_ADDR, 0); //clear interrupt out32(dev->iobase+ATLASII_SM_INT_STATUS, 0xf); //set command out32(dev->io_command, 0xD060); //blk erase command //wait command end if(nand_wait_INT(dev, MAX_ERASE_USEC, NAND_STATUS_WT_CMD) != 0) return(-1); return 0;}// Accessing the data reg automatically sets ALE=0, CLE=0intnand_write_data(NAND_CHIP *dev, uint8_t *databuffer, int data_cycles) { int i; volatile unsigned *tmp; volatile unsigned val;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?