123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Copyright (C) 2014 Gateworks Corporation
- * Author: Tim Harvey <tharvey@gateworks.com>
- */
- #include <common.h>
- #include <malloc.h>
- #define NAND_BASE CONFIG_SYS_NAND_BASE
- /* NAND Flash Controller */
- #define rNAND_CR (*(volatile unsigned int *) (NAND_BASE + 0x00))
- #define rNAND_CLE_WR (*(volatile unsigned char *) (NAND_BASE + 0x04))
- #define rNAND_ALE_WR (*(volatile unsigned char *) (NAND_BASE + 0x08))
- #define rNAND_ID_RD (*(volatile unsigned char *) (NAND_BASE + 0x0c))
- #define rNAND_STATUS_RD (*(volatile unsigned char *) (NAND_BASE + 0x10))
- #define rNAND_DATA (*(volatile unsigned int *) (NAND_BASE + 0x14))
- #define rNAND_TX_FIFO (*(volatile unsigned int *) (NAND_BASE + 0x18))
- #define rNAND_RX_FIFO (*(volatile unsigned int *) (NAND_BASE + 0x1c))
- #define rNAND_WRBLK_START (*(volatile unsigned int *) (NAND_BASE + 0x20))
- #define rNAND_RDBLK_START (*(volatile unsigned int *) (NAND_BASE + 0x24))
- #define rEX_BCH_ENCODE_STATUS (*(volatile unsigned int *) (NAND_BASE + 0x274))
- #define rEX_BCH_DECODE_STATUS (*(volatile unsigned int *) (NAND_BASE + 0x278))
- #define rBCH_CR (*(volatile unsigned int *) (NAND_BASE + 0x27c))
- #define rBCH_NAND_STATUS (*(volatile unsigned int *) (NAND_BASE + 0x280))
- #define rBCH_DECODE_STATUS (*(volatile unsigned int *) (NAND_BASE + 0x284))
- #define rBCH_INT (*(volatile unsigned int *) (NAND_BASE + 0x288))
- #define rBCH_INT_MASK (*(volatile unsigned int *) (NAND_BASE + 0x28c))
- #define EX_BCH_DECODE_RESULT_ADDR (NAND_BASE + 0x29c)
- #define NAND_INT_GLOBAL (1<<3)
- #define NAND_INT_DECODE_ERR (1<<2)
- #define NAND_INT_DECODE_END (1<<1)
- #define NAND_INT_ENCODE_END (1<<0)
- //BCH_CR register fields defination
- #define BCH_CR_SECTOR_MODE (1<<8)
- #define BCH_CR_ENCODER_RESET (1<<3)
- #define BCH_CR_DECODER_RESET (1<<2)
- #define BCH_CR_SOFT_ECC_ENABLE (1<<1)
- #define BCH_CR_BCH_ENABLE (1<<0)
- #define CMD_ERASE1 0x60
- #define CMD_ERASE2 0xD0
- #define CMD_READ1 0x00
- #define CMD_READ2 0x30
- #define CMD_PAGEPROGRAM1 0x80
- #define CMD_PAGEPROGRAM2 0x10
- #define CMD_READ_ID 0x90
- #define CMD_RESET 0xFF
- #define CMD_RADOM_OUTPUT1 0x05
- #define CMD_RADOM_OUTPUT2 0xE0
- #define CMD_RADOM_INPUT 0x85
- #define CMD_READ_STATUS 0x70
- #define NAND_MFR_TOSHIBA 0x98
- #define NAND_MFR_SAMSUNG 0xec
- #define NAND_MFR_FUJITSU 0x04
- #define NAND_MFR_NATIONAL 0x8f
- #define NAND_MFR_RENESAS 0x07
- #define NAND_MFR_STMICRO 0x20
- #define NAND_MFR_HYNIX 0xad
- #define NAND_MFR_MICRO 0x2c
- #define NAND_MFR_AMD 0x01
- struct nand_maker{
- int id;
- const char *name;
- struct nand_dev *dev_desc;
- int (*match_id)(unsigned char *id);
- };
- struct nandflash_info {
- const char *name;
- unsigned int id;
- unsigned int id2;
- int pagesize;
- int chipsize;
- int blocksize;
- int oobsize;
- int options;
- };
- struct nand_info{
- int chipsize;
- int blksize;
- int blknum;
- int pagesize;
- int pagesblk;
- int oobsize;
- int colcycle;
- int rowcycle;
- int bchecccodesize;
- int bchsegsize;
- };
- struct nand_dev {
- const char *name;
- int id;
- int pagesize;
- int chipsize;
- int blocksize;
- };
- enum nand_chip_sel {
- NAND_CHIP0 = 0,
- NAND_CHIP1,
- NAND_CHIP2,
- NAND_CHIP3,
- };
- enum nand_data_width {
- NAND_DATA_WIDTH8 = 0,
- NAND_DATA_WIDTH16,
- };
- struct nand_dev nand_flash_ids[] = {
- // name id pagesize chipsize blocksize
- {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000},
- {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000},
- {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000},
- /*
- * These are the new chips with large page size. The pagesize and the
- * blocksize is determined from the extended id bytes
- */
- /*512 Megabit */
- {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0},
- {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0},
- /* 1 Gigabit */
- {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0},
- {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0},
- /* 2 Gigabit */
- {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0},
- /* 4 Gigabit */
- {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0},
- /* 8 Gigabit */
- {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0},
- /* 16 Gigabit */
- {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0},
- /* 32 Gigabit */
- {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0},
- /* 64 Gigabit */
- {"NAND 8GiB 3,3V 8-bit", 0xDE, 0, 8192, 0},
- /*
- * Renesas AND 1 Gigabit. Those chips do not support extended id and
- * have a strange page/block layout ! The chosen minimum blocksize is
- * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
- * planes 1 block = 2 pages, but due to plane arrangement the blocks
- * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
- * increase the eraseblock size so we chose a combined one which can be
- * erased in one go There are more speed improvements for reads and
- * writes possible, but not implemented now
- */
- {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000},
- {NULL,},
- };
- static const struct nandflash_info nandflash_devices[] = {
- {"TC58BVG0S3HTAI0", 0x98, 0xF18015F2, 2048, 128, 128, 64, 0},
- {"K9F1G08U0C", 0xec, 0xf1009540, 2048, 128, 128, 64, 0},
- {"K9F1G08U0E", 0xec, 0xf1009541, 2048, 128, 128, 64, 0},
- {"HY27UF081G2A", 0xad, 0xf1801dad, 2048, 128, 128, 64, 0},
- {"TC58NVG0S3ETA00", 0x98, 0xD1901576, 2048, 128, 128, 64, 0},
- {"TC58NVG0S3HTA00", 0x98, 0xF1801572, 2048, 128, 128, 128, 0},
- {"TC58NVG1S3HTA00", 0x98, 0xDA901576, 2048, 256, 128, 128, 0},
- {"W29N01GV", 0xEF, 0xF1809500, 2048, 128, 128, 64, 0},
- {"FMND1GXXX3D", 0xF8, 0xF1809500, 2048, 128, 128, 64, 0},
- {"XT27G02ETSIGA", 0x2C, 0xDA909506, 2048, 256, 128, 128, 0},
- //此款flash芯片不支持,在此处强制将OOB128字节
- {"9FU1G8F2AMGF", 0xC8, 0xF1801D42, 2048, 128, 128, 128, 0},
- {"TC58NVG2S0HTAI0", 0x98, 0xDC902676, 4096, 512, 256, 256, 0},
- };
- static struct nand_info nand_info;
- static void nand_reset(void)
- {
- rNAND_CLE_WR = CMD_RESET;
- do {
- rNAND_CLE_WR = CMD_READ_STATUS;
- udelay(10);//do not delete this delay avoiding to elapse the time for tWHR
- } while (!(rNAND_STATUS_RD & 0x40));
- }
- static void nand_readid(unsigned char *id)
- {
- int i;
- rNAND_CLE_WR = CMD_READ_ID;
- rNAND_ALE_WR = 0x00;
- udelay(100);
- for(i = 0; i < 8; i++)
- *id++ = rNAND_ID_RD;
- }
- static int nand_scan_table(unsigned char *flashid)
- {
- int i;
- unsigned int id = flashid[0];
- unsigned int id2 = (flashid[1] << 24) | (flashid[2] << 16) | (flashid[3] << 8) | flashid[4];
-
- for(i = 0; i < sizeof(nandflash_devices) / sizeof(nandflash_devices[0]); i++) {
- if(id == nandflash_devices[i].id && id2 == nandflash_devices[i].id2) {
- nand_info.blksize = nandflash_devices[i].blocksize * 1024;
- nand_info.chipsize = nandflash_devices[i].chipsize * 1024 * 1024;
- nand_info.pagesize = nandflash_devices[i].pagesize;
- nand_info.oobsize = nandflash_devices[i].oobsize;
- return 0;
- }
- }
- puts("NO Device in Table\n");
- return -1;
- }
- static int get_cycle(unsigned int addr)
- {
- int cycle;
- for (cycle = 0; cycle < 4; cycle++) {
- if(addr & (0xff000000 >> (8 * cycle)))
- return 4-cycle;
- }
- return 0;
- }
- static void get_samsung_nandinfo(unsigned char *id)
- {
- int extid = id[3];
- nand_info.pagesize = 2048 << (extid & 0x03);
- extid >>= 2;
- //K9GBG08U0A ID:0xECD794766443
- switch ((extid & 0x03) | ((extid >> 2) & 0x04)) {
- case 1:
- nand_info.oobsize= 128;
- break;
- case 2:
- nand_info.oobsize = 218;
- break;
- case 3:
- nand_info.oobsize = 400;
- break;
- case 4:
- nand_info.oobsize = 436;
- break;
- default:
- nand_info.oobsize = 640;
- break;
- }
- extid >>= 2;
- /* Calc blocksize */
- nand_info.blksize = (128 * 1024) << (((extid >> 1) & 0x04) | (extid & 0x03));
- }
- static void get_hynix_nandinfo(unsigned char *id)
- {
- int extid = id[3];
- /* Calc pagesize */
- nand_info.pagesize = 2048 << (extid & 0x03);
- extid >>= 2;
- switch ((extid & 0x03) | ((extid>>2) & 0x04)) {
- case 0:
- nand_info.oobsize= 128;
- break;
- case 1:
- nand_info.oobsize = 224;
- break;
- case 2:
- nand_info.oobsize = 448;
- break;
- case 3:
- nand_info.oobsize = 64;
- break;
- case 4:
- nand_info.oobsize = 32;
- break;
- case 5:
- nand_info.oobsize = 16;
- break;
- case 6:
- nand_info.oobsize = 640;
- break;
- }
- extid >>= 2;
- switch(((extid >> 1) & 0x04) | (extid & 0x03)) {
- case 0:
- nand_info.blksize = 128 << 10;
- break;
- case 1:
- nand_info.blksize = 256 << 10;
- break;
- case 2:
- nand_info.blksize = 512 << 10;
- break;
- case 3:
- nand_info.blksize = 768 << 10;
- break;
- case 4:
- nand_info.blksize = 1 << 20;
- break;
- case 5:
- nand_info.blksize = 2 << 20;
- break;
- case 6:
- nand_info.blksize = 4 << 20;
- break;
- }
- }
- static int nand_readoob(int block, int page, int offset, unsigned int *buf, int size)
- {
- int i;
- unsigned int page_addr;
- page_addr = block * nand_info.pagesblk + page;
- rBCH_NAND_STATUS = 0x1;
-
- if(nand_info.pagesize > 512) {
- rNAND_CLE_WR = CMD_READ1;//0x00;
- rNAND_ALE_WR = offset;
- rNAND_ALE_WR = nand_info.pagesize >> 8;
- } else {
- rNAND_CLE_WR = 0x50;
- rNAND_ALE_WR = offset;
- }
- //send address
- for (i = 0; i < nand_info.rowcycle; i++)
- rNAND_ALE_WR = (page_addr >> (i * 8)) & 0xff;
- if (nand_info.pagesize >= 2048)
- rNAND_CLE_WR = CMD_READ2;
- while(!(rBCH_NAND_STATUS & (1 << 18)));
- for ( i = 0; i < size; i ++)
- *buf++ = rNAND_DATA;
- return 0;
- }
- static int nand_is_bad_block(int block)
- {
- unsigned int val;
- nand_readoob(block, 0, 0, &val, 1);
- if ((val & 0xffff) != 0xffff)
- return 1;
- return 0;
- }
- static int nand_read_page(int block, int page, void *dst)
- {
- unsigned int PhyAddr;
- int i,j;
- unsigned int *data = (unsigned int *)dst;
- unsigned char *buf = (unsigned char*)dst;
- unsigned int ECCData;
- unsigned int BchDecode;
- unsigned char BchDecodeStatus;
- unsigned int ErrByteAddr[2];
- unsigned int ErrBitAddr[2];
- int nBCH_DECODE_REGs = 4, nBCH_ENCODE_REGs = 4;
- unsigned int nMaxBCHSectors;
- int result = 0;
- int nECCCodeSize;
- nECCCodeSize = nand_info.bchecccodesize;
- PhyAddr = block * nand_info.pagesblk + page;
- //clear rb bit status
- rBCH_NAND_STATUS = 0x1; //add by frank
-
- //send cmd
- rNAND_CLE_WR = CMD_READ1;//0x00;
-
- //send address
- for (i = 0; i < nand_info.colcycle; i++)
- rNAND_ALE_WR = 0x00;
- for(i = 0; i < nand_info.rowcycle; i++)
- rNAND_ALE_WR = (PhyAddr >> (i*8)) & 0xff;
- if(nand_info.pagesize >= 2048)
- rNAND_CLE_WR = CMD_READ2;
-
- nMaxBCHSectors = nand_info.pagesize/nand_info.bchsegsize;
- while (!(rBCH_NAND_STATUS & (1 << 18)));
- for(i = 0; i < nMaxBCHSectors; i++) {
- rBCH_CR |= BCH_CR_SECTOR_MODE;
-
- //enable ecc controller, it will auto caculate the ecc code while data reading in the following code
- rBCH_CR |= BCH_CR_DECODER_RESET;//reset
- rBCH_CR &= ~BCH_CR_DECODER_RESET;
- rBCH_CR |= (BCH_CR_SOFT_ECC_ENABLE|BCH_CR_BCH_ENABLE);
- //read data from fifo with block process
- rNAND_RDBLK_START = 1;
- for (j = 0; j < (nand_info.bchsegsize >> 2); j++)
- *data++ = rNAND_RX_FIFO;
- //wait for data decode end while useing block process
- while(!(rBCH_INT & NAND_INT_DECODE_END));
- rBCH_INT = 1;
- //read ecc data stored in spare area
- rNAND_CLE_WR = CMD_RADOM_OUTPUT1;//0x05;
- for (j = 0; j < nand_info.colcycle; j++)
- rNAND_ALE_WR = ((nand_info.pagesize + nand_info.oobsize - nMaxBCHSectors * nECCCodeSize
- + i * nECCCodeSize) >> (8 * j)) & 0xff;
- rNAND_CLE_WR = CMD_RADOM_OUTPUT2;//0xE0;
- switch(nECCCodeSize) {
- case 13:
- nBCH_ENCODE_REGs = 4;
- nBCH_DECODE_REGs = 4;//7 BITS
- break;
- case 23:
- nBCH_ENCODE_REGs = 6;
- nBCH_DECODE_REGs = 7;//13 BITS
- break;
- case 42:
- nBCH_ENCODE_REGs = 11;//24 BITS
- nBCH_DECODE_REGs = 12;
-
- break;
- case 53:
- nBCH_ENCODE_REGs = 14;//30 BITS
- nBCH_DECODE_REGs = 15;
- break;
- case 84:
- nBCH_ENCODE_REGs = 21;//48 BITS
- nBCH_DECODE_REGs = 24;
- break;
- }
- for (j=0; j < nBCH_ENCODE_REGs; j++)
- ECCData = rNAND_DATA;
- ECCData = ECCData; //remove compile warning
- //wait for ecc data read end
- while (rEX_BCH_DECODE_STATUS & 0x01);
- //begin to check data read at the forward step according the ecc decord result just now.
- BchDecode = rEX_BCH_DECODE_STATUS;
- BchDecodeStatus = (char)(BchDecode&0x7);
- if(BchDecodeStatus&0x2) {
- //All Data is right
- ;
- } else if(BchDecodeStatus&0x4) {
- //err more than 8 bit
- rBCH_CR &= ~BCH_CR_BCH_ENABLE;
- puts("uncorrectable ECC error\n");
- result = -1;
- } else {
- for(j=0;j<nBCH_DECODE_REGs;j++) {
- unsigned int val;
-
- val = *(volatile unsigned int*)(EX_BCH_DECODE_RESULT_ADDR + 4 * j);
- ErrByteAddr[0] = (val&0x3ff8)>>3;
- ErrBitAddr[0] = val&0x7;
- val = val >> 14;
- ErrByteAddr[1] = (val&0x3ff8)>>3;
- ErrBitAddr[1] = val&0x7;
-
- if(ErrByteAddr[0] < 1024)
- *(buf + nand_info.bchsegsize * i + ErrByteAddr[0]) ^= 1 << ErrBitAddr[0];
- if(ErrByteAddr[1] < 1024)
- *(buf + nand_info.bchsegsize * i + ErrByteAddr[1]) ^= 1 << ErrBitAddr[1];
- }
- }
- rBCH_INT = 1;
- //if there are some other sector in this page to read, then begin to send their row address
- if(i<(nMaxBCHSectors-1) && nMaxBCHSectors>1) {
- rNAND_CLE_WR = CMD_RADOM_OUTPUT1;//0x85;
- rNAND_ALE_WR = 0x00;
- rNAND_ALE_WR = ((i + 1) * nand_info.bchsegsize) >> 8;
- rNAND_CLE_WR = CMD_RADOM_OUTPUT2;
- }
- }
- rBCH_INT = 1;
- rBCH_CR &= ~BCH_CR_BCH_ENABLE;
- return result;
- }
- int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
- {
- unsigned int block, lastblock;
- unsigned int page, page_offset;
- /* offs has to be aligned to a page address! */
- block = offs / nand_info.blksize;
- lastblock = (offs + size - 1) / nand_info.blksize;
- page = (offs % nand_info.blksize) / nand_info.pagesize;
- page_offset = offs % nand_info.pagesize;
- while (block <= lastblock) {
- if (!nand_is_bad_block(block)) {
- /* Skip bad blocks */
- while (page < nand_info.pagesblk) {
- nand_read_page(block, page, dst);
- /*
- * When offs is not aligned to page address the
- * extra offset is copied to dst as well. Copy
- * the image such that its first byte will be
- * at the dst.
- */
- if (unlikely(page_offset)) {
- memmove(dst, dst + page_offset,
- nand_info.pagesize);
- dst = (void *)((int)dst - page_offset);
- page_offset = 0;
- }
- dst += nand_info.pagesize;
- page++;
- }
- page = 0;
- } else {
- lastblock++;
- }
- block++;
- }
- return 0;
- }
- void nand_init(void)
- {
- unsigned char flash_id[8];
- int i, num;
- struct nand_dev nand_dev;
- unsigned char deviceid, devicecellid, extid;
- unsigned int val;
- rNAND_CR = 0;
- rNAND_CR = (1<<22)|(1<<21)|(0<<20)|(0x4<<16)|(0x3<<12)|(0x3<<8)|(0x3<<4)|(0x4<<0);
- nand_reset();
- nand_readid(flash_id);
- if(!nand_scan_table(flash_id)) {
- nand_info.blknum = nand_info.chipsize / nand_info.blksize;
- nand_info.pagesblk = nand_info.blksize / nand_info.pagesize;
- if(nand_info.pagesize == 512)
- nand_info.colcycle = 1;
- else
- nand_info.colcycle = get_cycle(nand_info.pagesize);
- nand_info.rowcycle = get_cycle(nand_info.chipsize / nand_info.pagesize - 1);
- } else {
- deviceid = flash_id[1];
- num = sizeof(nand_flash_ids) / sizeof(nand_flash_ids[0]);
- for(i = 0; i < num; i++) {
- if(deviceid ==nand_flash_ids[i].id) {
- nand_dev = nand_flash_ids[i];
- nand_info.chipsize = nand_flash_ids[i].chipsize << 20;
- break;
- }
- }
- /* Unkown Maker */
- if(i == num) {
- puts("Unknown Maker,Not Support The Chip!!\n");
- return;
- }
- if (!nand_dev.pagesize) {
- /* The 3rd id byte holds MLC / multichip data */
- devicecellid = flash_id[2];
- /* The 4th id byte is the important one */
- extid = flash_id[3];
- /*
- * Field definitions are in the following datasheets:
- * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
- * New style (6 byte ID): Samsung K9GBG08U0M (p.40)
- *
- * Check for wraparound + Samsung ID + nonzero 6th byte
- * to decide what to do.
- */
- if ((flash_id[0] == flash_id[6]) && (flash_id[1] == flash_id[7]) &&
- // FlashId[0] == NAND_MFR_SAMSUNG &&
- (devicecellid & 0x0C) &&
- (flash_id[5] != 0x00)) {
- if(flash_id[0] == NAND_MFR_SAMSUNG) {
- get_samsung_nandinfo(flash_id);
- goto nandinfo_over;
- } else if(flash_id[0] == NAND_MFR_HYNIX) {
- get_hynix_nandinfo(flash_id);
- goto nandinfo_over;
- }
- }
- /* Calc pagesize */
- nand_info.pagesize = 1024 << (extid & 0x03);
- extid >>= 2;
- /* Calc oobsize */
- nand_info.oobsize = (8 << (extid & 0x01)) *
- (nand_info.pagesize >> 9);
- extid >>= 2;
- /* Calc blocksize. Blocksize is multiples of 64KiB */
- nand_info.blksize= (64 * 1024) << (extid & 0x03);
- }
- else {
- /*
- * Old devices have chip data hardcoded in the device id table
- */
- nand_info.blksize = nand_dev.blocksize;
- nand_info.pagesize = nand_dev.pagesize;
- nand_info.oobsize = nand_info.pagesize / 32;
- /*
- * Check for Spansion/AMD ID + repeating 5th, 6th byte since
- * some Spansion chips have blocksize that conflicts with size
- * listed in nand_ids table
- * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
- */
- if (flash_id[0] == NAND_MFR_AMD && flash_id[4] != 0x00 &&
- flash_id[5] == 0x00 && flash_id[6] == 0x00 &&
- flash_id[7] == 0x00 && nand_info.pagesize == 512) {
- nand_info.blksize = 128 * 1024;
- nand_info.blksize <<= ((flash_id[3] & 0x03) << 1);
- }
- }
- nandinfo_over:
- if(nand_info.pagesize == 512)
- nand_info.colcycle = 1;
- else
- nand_info.colcycle = get_cycle(nand_info.pagesize);
- nand_info.rowcycle = get_cycle(nand_info.chipsize / nand_info.pagesize - 1);
- nand_info.pagesblk = nand_info.blksize / nand_info.pagesize;
- nand_info.blknum = nand_info.chipsize / nand_info.blksize;
- }
- if(nand_info.oobsize == 64) {
- val = rNAND_CR;
- val &= ~(3 << 25);
- rNAND_CR = val;
- nand_info.bchsegsize = 1024;
- nand_info.bchecccodesize = 23;
- val = rBCH_CR;
- val &= ~((1 << 7) | (7 << 4));
- val |= (1 << 7) | (1 << 4);
- rBCH_CR = val;
- debug("ECC 13 bit !!\n");
- } else if(nand_info.oobsize >= 128) {
- val = rNAND_CR;
- val &= ~(3<<25);
- rNAND_CR = val;
- nand_info.bchsegsize = 1024;
- nand_info.bchecccodesize = 42;
- val = rBCH_CR;
- val &= ~((1 << 8) | (1 << 7) | (7 << 4));
- val |= (1 << 7) | (2 << 4);
- rBCH_CR = val;
- debug("ECC 24 bit !!\n");
- }
- return;
- }
- void nand_deselect(void)
- {
- }
|