| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181 | 
							- /*
 
-  * (C) Copyright 2006 DENX Software Engineering
 
-  * (C) Copyright 2012 Ho Ka Leung, ASTRI, kalho@astri.org
 
-  *
 
-  * See file CREDITS for list of people who contributed to this
 
-  * project.
 
-  *
 
-  * This program is free software; you can redistribute it and/or
 
-  * modify it under the terms of the GNU General Public License as
 
-  * published by the Free Software Foundation; either version 2 of
 
-  * the License, or (at your option) any later version.
 
-  *
 
-  * This program is distributed in the hope that it will be useful,
 
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
-  * GNU General Public License for more details.
 
-  *
 
-  * You should have received a copy of the GNU General Public License
 
-  * along with this program; if not, write to the Free Software
 
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 
-  * MA 02111-1307 USA
 
-  */
 
- #include <common.h>
 
- #include <linux/err.h>
 
- #include <nand.h>
 
- #include <linux/mtd/mtd.h>
 
- #include <linux/mtd/nand_ecc.h>
 
- #include <asm/arch/ark-nand.h>
 
- #include <asm/io.h>
 
- #include <errno.h>
 
- #define BIT_7_ECC_BYTE	13
 
- #define BIT_13_ECC_BYTE	23
 
- #define BIT_24_ECC_BYTE	42
 
- #define BIT_30_ECC_BYTE 53
 
- #define BIT_48_ECC_BYTE	84
 
- #define EC809_NAND_ADDR_UNALIGNED	0x1
 
- #define EC809_NAND_LEN_UNALIGNED		0x2
 
- //#define USE_DATA_INTERFACE 1
 
- //#define DEBUG
 
- #if 0
 
- static struct nand_ecclayout nand_hw_eccoob_16 = { /* small page 512 byte with 16 byte oob  */
 
-     .eccbytes = BIT_7_ECC_BYTE,
 
- 	.eccpos = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
 
-     .oobfree = {}
 
- };
 
- static struct nand_ecclayout nand_hw_eccoob_64 = { /* large page 2k with 64 byte oob */
 
-     .eccbytes = BIT_7_ECC_BYTE,
 
-     .eccpos = { 3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 
- 	   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
 
- 	},
 
-     .oobfree = { {32, 32} }
 
- };
 
- #endif
 
- static struct nand_ecclayout nand_hw_eccoob_bootstrap = { /* large page 2k with 64 byte oob */
 
-     .eccbytes = BIT_7_ECC_BYTE,
 
-     .eccpos = { 3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 
 
- 	   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
 
- 	   30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
 
- 	   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54	   	
 
- 	},
 
-     .oobfree = { {56, 8} }
 
- };
 
- static struct nand_ecclayout nand_hw_eccoob_64 = { /* large page 2k with 64 byte oob */
 
-     .eccbytes = BIT_13_ECC_BYTE,
 
-     .eccpos = {18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
 
-     	34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
 
-     	50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
 
- 	},
 
-     .oobfree = { {2, 16} }
 
- };
 
- //1024--24
 
- static struct nand_ecclayout nand_hw_eccoob_128 = { /* large page 2k with 64 byte oob */
 
-     .eccbytes = BIT_24_ECC_BYTE,
 
-     .eccpos = {44, 45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58, 59,
 
-     	 60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
 
- 		 76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,
 
- 		 92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107,
 
- 		108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
 
- 		124, 125, 126, 127
 
- 	},
 
-     .oobfree = { {2, 42} }
 
- };
 
- //1024--24
 
- static struct nand_ecclayout nand_hw_eccoob_256 = {
 
-     .eccbytes = BIT_24_ECC_BYTE,
 
-     .eccpos = {88,  89,
 
- 		90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
 
- 		100, 101, 102, 103, 104, 105,106, 107, 108, 109,
 
- 		110, 111, 112, 113, 114, 115,116, 117, 118, 119,
 
- 		120, 121, 122, 123, 124, 125,126, 127, 128, 129,
 
- 		130, 131, 132, 133, 134, 135,136, 137, 138, 139,
 
- 		140, 141, 142, 143, 144, 145,146, 147, 148, 149,
 
- 		150, 151, 152, 153, 154, 155,156, 157, 158, 159,
 
- 		160, 161, 162, 163, 164, 165,166, 167, 168, 169,
 
- 		170, 171, 172, 173, 174, 175,176, 177, 178, 179,
 
- 		180, 181, 182, 183, 184, 185,186, 187, 188, 189,
 
- 		190, 191, 192, 193, 194, 195,196, 197, 198, 199,
 
- 		200, 201, 202, 203, 204, 205,206, 207, 208, 209,
 
- 		210, 211, 212, 213, 214, 215,216, 217, 218, 219,
 
- 		220, 221, 222, 223, 224, 225,226, 227, 228, 229,
 
- 		230, 231, 232, 233, 234, 235,236, 237, 238, 239,
 
- 		240, 241, 242, 243, 244, 245,246, 247, 248, 249,
 
- 		250, 251, 252, 253, 254, 255,
 
- 	},
 
-     .oobfree = { {2, 86} }
 
- };
 
- /*static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
 
- static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
 
- static struct nand_bbt_descr Ark_OOB128_bbt_main_descr = {
 
- 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
 
- 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 
- 	.offs =	96,
 
- 	.len = 4,
 
- 	.veroffs = 100,
 
- 	.maxblocks = 4,
 
- 	.pattern = bbt_pattern
 
- };
 
- static struct nand_bbt_descr Ark_OOB128_bbt_mirror_descr = {
 
- 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
 
- 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 
- 	.offs =	96,
 
- 	.len = 4,
 
- 	.veroffs = 100,
 
- 	.maxblocks = 4,
 
- 	.pattern = mirror_pattern
 
- };
 
- static struct nand_bbt_descr Ark_OOB64_bbt_main_descr = {
 
- 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
 
- 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 
- 	.offs = 55,
 
- 	.len = 4,
 
- 	.veroffs = 59,
 
- 	.maxblocks = 4,
 
- 	.pattern = bbt_pattern
 
- };
 
- static struct nand_bbt_descr Ark_OOB64_bbt_mirror_descr = {
 
- 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
 
- 		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
 
- 	.offs =55,
 
- 	.len = 4,
 
- 	.veroffs = 59,
 
- 	.maxblocks = 4,
 
- 	.pattern = mirror_pattern
 
- };*/
 
- struct ark_nand {
 
- 	struct mtd_info		mtd;
 
- 	struct nand_chip	*nand;
 
- 	int 		max_chip;
 
- 	int			chip_num;
 
- 	int			raw_rw;
 
- };
 
- static struct ark_nand	ark_nand_info = {0};
 
- static void ark_nand_select_chip(struct mtd_info *mtd, int chipnr)
 
- {
 
- 	struct nand_chip *chip = mtd->priv;
 
- 	struct ark_nand *nand_info = chip->priv;
 
- 	unsigned int nand_cr;
 
- 	debug("ark_nand_select_chip\n");
 
- 	if(chipnr == -1){
 
- 		chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
 
- 		return;
 
- 	}
 
- 	if(chipnr < nand_info->max_chip){
 
- 		nand_cr = readl(rNAND_CR);
 
- 		nand_cr &= ~(0x3<<23);
 
- 		nand_cr |= (chipnr<<23);
 
- 		writel(nand_cr, rNAND_CR);
 
- 		nand_info->chip_num = chipnr;
 
- 	}
 
- 	return;
 
- }
 
- static void ark_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
- {
 
- 	struct nand_chip *chip = mtd->priv;
 
- 	debug("ark_nand_hwcontrol\n");
 
- 	/*
 
-      * Point the IO_ADDR to DATA and ADDRESS registers instead
 
-      * of chip address
 
-      */
 
-     switch (ctrl) {
 
-     case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
 
- 		debug("NAND_CTRL_CLE\n");
 
-         chip->IO_ADDR_W = (void  __iomem *)rNAND_CLE_WR;
 
-         break;
 
-     case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
 
- 		debug("NAND_CTRL_ALE\n");
 
-         chip->IO_ADDR_W = (void  __iomem *)rNAND_ALE_WR;
 
-         break;
 
-     case NAND_CTRL_CHANGE:
 
- 		debug("NAND_CTRL_DATA\n");
 
-         chip->IO_ADDR_W = (void  __iomem *)rNAND_DATA; /* Must be a 32-bit read at ARK1680 NFC */
 
-         break;
 
-     }
 
- 	if(ctrl & NAND_NCE){
 
- 		;	/* TODO: Chip Enable activate */
 
- 	}else{
 
- 		;	/* TODO: Chip Enable de-activate */
 
- 	}
 
- /*#ifndef USE_DATA_INTERFACE
 
- 	if ((cmd == NAND_CMD_READ0 || cmd == NAND_CMD_SEQIN) && (ctrl & NAND_CLE)) {
 
- 		writel(1, rBCH_NAND_STATUS);
 
- 	}
 
- #endif*/
 
- 	if (cmd != NAND_CMD_NONE){
 
- 		debug("cmd 0x%X\n",cmd);
 
-         writeb(cmd, chip->IO_ADDR_W);
 
- 	}
 
- }
 
- /**
 
-  * ark_nand_read_buf - read chip data into buffer
 
-  * @mtd:        MTD device structure
 
-  * @buf:        buffer to store date
 
-  * @len:        number of bytes to read
 
-  *
 
-  * Default read function for 8bit buswith
 
-  */
 
-  static int rcount = 0;
 
- void ark_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
- {
 
-         int i;
 
- 	unsigned int* tmp_buf32;
 
- 	uint8_t* tmp_buf8;
 
- 	unsigned int unaligned_flag = 0;
 
- 	unsigned int excess_len;
 
- 	unsigned int addr_aligned;
 
- 	unsigned int read_addr = rNAND_DATA;
 
- 	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
 
- 	struct ark_nand *nand_info = chip->priv;
 
- 	union{
 
-         unsigned int word;
 
-         unsigned char byte[4];
 
-     } tmp;
 
- 	debug("ark_nand_read_buf\n");
 
- 	addr_aligned = ((unsigned int)buf)%4;
 
- 	if(addr_aligned){ // Address not aligned to 32 bit word
 
- 		debug("EC809_NAND_ADDR_UNALIGNED\n");
 
- 		unaligned_flag |= EC809_NAND_ADDR_UNALIGNED;
 
- 	}
 
- 	excess_len = len % 0x4;
 
- 	if(excess_len){ // length not aligned to 32 bit word
 
- 		debug("EC809_NAND_LEN_UNALIGNED\n");
 
- 		unaligned_flag |= EC809_NAND_LEN_UNALIGNED;
 
- 	}
 
- #ifndef USE_DATA_INTERFACE
 
- 	if (len >= chip->ecc.size && !nand_info->raw_rw)
 
- 		read_addr = rNAND_RX_FIFO;
 
- #endif
 
- 	switch(unaligned_flag){
 
- 	case 0:
 
- 		tmp_buf32 = (unsigned int*)buf;
 
-         for (i = 0; i < len >> 2; i++){
 
-         	*tmp_buf32++ = readl(read_addr);
 
- 			debug("0. tmp_buf32 0x%08X\n",*(tmp_buf32-1));
 
- 			if(rcount)
 
- 				printf("%d  %d  0x%08X\n",len, i, *(tmp_buf32-1));
 
-         }
 
- 		break;
 
- 	case 1:
 
- 		tmp_buf8 = buf;
 
- 		for (i = 0; i < len >> 2; i++){
 
-             tmp.word = readl(read_addr);
 
- 			debug("0. tmp.word 0x%08X\n",tmp.word);
 
- 			*tmp_buf8++ = tmp.byte[0];
 
- 			*tmp_buf8++ = tmp.byte[1];
 
- 			*tmp_buf8++ = tmp.byte[2];
 
- 			*tmp_buf8++ = tmp.byte[3];
 
-         }
 
- 		break;
 
- 	case 2:
 
- 		tmp_buf32 = (unsigned int*)buf;
 
- 		for (i = 0; i < len >> 2; i++){
 
-         	*tmp_buf32++ = readl(read_addr);
 
- 			debug("1. tmp_buf32 0x%08X\n",*(tmp_buf32-1));
 
- 		}
 
- 		/* read the excess byte */
 
- 		tmp_buf8 = (uint8_t*)tmp_buf32;
 
- 		tmp.word = readl(read_addr);
 
- 		debug("1. tmp.word 0x%08X\n",tmp.word);
 
- 		for(i = 0; i < excess_len; i++){
 
- 			*tmp_buf8++ = tmp.byte[i];
 
- 		}
 
- 		break;
 
- 	case 3:
 
- 		tmp_buf8 = buf;
 
-         for (i = 0; i < len >> 2; i++){
 
-             tmp.word = readl(read_addr);
 
- 			debug("2. tmp.word 0x%08X\n",tmp.word);
 
-                 *tmp_buf8++ = tmp.byte[0];
 
-                 *tmp_buf8++ = tmp.byte[1];
 
-                 *tmp_buf8++ = tmp.byte[2];
 
-                 *tmp_buf8++ = tmp.byte[3];
 
-         }
 
- 		tmp.word = readl(read_addr);
 
- 		debug("3. tmp.word 0x%08X\n",tmp.word);
 
-         for(i = 0; i < excess_len; i++){
 
-             *tmp_buf8++ = tmp.byte[i];
 
-         }
 
- 		break;
 
- 	}
 
- }
 
- /**
 
-  * ark_nand_write_buf - write buffer to chip
 
-  * @mtd:        MTD device structure
 
-  * @buf:        data buffer
 
-  * @len:        number of bytes to write
 
-  *
 
-  * Default write function for 8bit buswith
 
-  */
 
- void ark_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
- {
 
-     int i;
 
-     unsigned int* tmp_buf32;
 
-     uint8_t* tmp_buf8;
 
-     unsigned int unaligned_flag = 0;
 
-     unsigned int excess_len;
 
- 	unsigned int addr_aligned;
 
- 	unsigned int write_addr = rNAND_DATA;
 
- 	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
 
- 	struct ark_nand *nand_info = chip->priv;
 
-     union{
 
-         unsigned int word;
 
-         unsigned char byte[4];
 
-     } tmp;
 
- 	debug("ark_nand_write_buf\n");
 
- 	tmp.word = 0xFFFFFFFF;
 
- 	addr_aligned = (unsigned int)buf % 4;
 
-     if(addr_aligned){ // Address not aligned to 32 bit word
 
-     	unaligned_flag |= EC809_NAND_ADDR_UNALIGNED;
 
-     }
 
-     excess_len = len % 0x4;
 
-     if(excess_len){ // length not aligned to 32 bit word
 
-     	unaligned_flag |= EC809_NAND_LEN_UNALIGNED;
 
-     }
 
- #ifndef USE_DATA_INTERFACE
 
- 	if (len >= chip->ecc.size && !nand_info->raw_rw)
 
- 		write_addr = rNAND_TX_FIFO;
 
- #endif
 
-     switch(unaligned_flag){
 
-     case 0:
 
- 		tmp_buf32 = (unsigned int*)buf;
 
-         for (i = 0; i < len >> 2; i++){
 
- 			debug("0 rNAND_DATA = 0x%08X\n",*tmp_buf32);
 
-             writel(*tmp_buf32++, write_addr);
 
- 		}
 
- 		break;
 
-     case 1:
 
-         tmp_buf8 = (uint8_t*)buf;
 
-         for (i = 0; i < len >> 2; i++){
 
- 			tmp.byte[0] = *tmp_buf8++;
 
- 			tmp.byte[1] = *tmp_buf8++;
 
- 			tmp.byte[2] = *tmp_buf8++;
 
- 			tmp.byte[3] = *tmp_buf8++;
 
- 			debug("1 rNAND_DATA = 0x%08X\n",tmp.word);
 
- 			writel(tmp.word, write_addr);
 
-         }
 
-         break;
 
-     case 2:
 
-      	tmp_buf32 = (unsigned int*)buf;
 
-         for (i = 0; i < len >> 2; i++){
 
- 			debug("2 rNAND_DATA = 0x%08X\n",*tmp_buf32);
 
- 			writel(*tmp_buf32++, write_addr);
 
- 		}
 
-         /* write the excess byte */
 
-         tmp_buf8 = (uint8_t*)tmp_buf32;
 
- 		tmp.word = 0xFFFFFFFF;
 
-         for(i = 0; i < excess_len; i++){
 
-         	*tmp_buf8++ = tmp.byte[i];
 
-         }
 
- 		debug("2.1 rNAND_DATA = 0x%08X\n",tmp.word);
 
- 		writel(tmp.word, write_addr);
 
-         break;
 
- 	case 3:
 
-         tmp_buf8 = (uint8_t*)buf;
 
-         for (i = 0; i < len >> 2; i++){
 
- 			tmp.byte[0] = *tmp_buf8++;
 
-             tmp.byte[1] = *tmp_buf8++;
 
-             tmp.byte[2] = *tmp_buf8++;
 
-             tmp.byte[3] = *tmp_buf8++;
 
- 			debug("3 rNAND_DATA = 0x%08X\n",tmp.word);
 
-             writel(tmp.word, write_addr);
 
-         }
 
- 		tmp.word = 0xFFFFFFFF;
 
-         for(i = 0; i < excess_len; i++){
 
-         	*tmp_buf8++ = tmp.byte[i];
 
-         }
 
- 		debug("3.1 rNAND_DATA = 0x%08X\n",tmp.word);
 
- 		writel(tmp.word, write_addr);
 
-         break;
 
-     }
 
- }
 
- /**
 
-  * ark_nand_verify_buf - Verify chip data against buffer
 
-  * @mtd:        MTD device structure
 
-  * @buf:        buffer containing the data to compare
 
-  * @len:        number of bytes to compare
 
-  *
 
-  * Default verify function for 8bit buswith
 
-  */
 
- /*static int ark_nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
- {
 
-     int i,j;
 
-     const uint8_t* tmp_buf8;
 
-     unsigned int excess_len;
 
-     union{
 
-         unsigned int word;
 
-         unsigned char byte[4];
 
-     } tmp;
 
- 	debug("ark_nand_verify_buf\n");
 
- 	tmp_buf8 = buf;
 
-     excess_len = len % 0x4;
 
- 	for (i = 0; i < len >> 2; i++){
 
- 		tmp.word = readl(rNAND_DATA);
 
- 		for (j = 0; j < 4; j++){
 
- 			if(tmp.byte[j] != *tmp_buf8++)
 
- 				return -EFAULT;
 
- 		}
 
- 	}
 
- 	if(excess_len){
 
- 		tmp.word = readl(rNAND_DATA);
 
- 		for(i = 0; i < excess_len; i++){
 
- 			if(tmp.byte[i] != *tmp_buf8++)
 
- 				return -EFAULT;
 
- 		}
 
- 	}
 
- 	return 0;
 
- }*/
 
- static void ark_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 
- {
 
- 	debug("ark_nand_enable_hwecc\n");
 
- #if 0
 
- 	switch(mode){
 
- 		case NAND_ECC_READ:
 
- 			writel(readl(rBCH_CR) | BCH_CR_SECTOR_MODE,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) | BCH_CR_DECODER_RESET,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) & ~BCH_CR_DECODER_RESET,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) | BCH_CR_BCH_ENABLE,
 
-                                rBCH_CR);
 
- 			printf("\r\n>>>>>NAND_ECC_READ rBCH_CR 0x%08X\n",readl(rBCH_CR));
 
- 			break;
 
- 		case NAND_ECC_WRITE:
 
- 			writel(readl(rBCH_CR) | BCH_CR_SECTOR_MODE,
 
-                                rBCH_CR);
 
-                         writel(readl(rBCH_CR) | BCH_CR_ENCODER_RESET,
 
-                                rBCH_CR);
 
-                         writel(readl(rBCH_CR) & ~BCH_CR_ENCODER_RESET,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) | (BCH_CR_SOFT_ECC_ENABLE|BCH_CR_BCH_ENABLE),
 
-                                rBCH_CR);
 
- 			printf("\r\n>>>>>sNAND_ECC_WRITE rBCH_CR 0x%08X\n",readl(rBCH_CR));
 
- 			break;
 
- #else
 
- 	switch(mode){
 
- 		case NAND_ECC_READ:
 
- 			writel(readl(rBCH_CR) | BCH_CR_SECTOR_MODE,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) | BCH_CR_DECODER_RESET,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) & ~BCH_CR_DECODER_RESET,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) | (BCH_CR_SOFT_ECC_ENABLE|BCH_CR_BCH_ENABLE),
 
-                                rBCH_CR);
 
- 			debug("\r\n>>>>>NAND_ECC_READ rBCH_CR 0x%08X\n",readl(rBCH_CR));
 
- #ifndef USE_DATA_INTERFACE
 
- 			writel(1, rNAND_RDBLK_START);
 
- #endif
 
- 			break;
 
- 		case NAND_ECC_WRITE:
 
- 			writel(readl(rBCH_CR) | BCH_CR_SECTOR_MODE,
 
-                                rBCH_CR);
 
-             writel(readl(rBCH_CR) | BCH_CR_ENCODER_RESET,
 
-                                rBCH_CR);
 
-             writel(readl(rBCH_CR) & ~BCH_CR_ENCODER_RESET,
 
-                                rBCH_CR);
 
- 			writel(readl(rBCH_CR) | (BCH_CR_SOFT_ECC_ENABLE|BCH_CR_BCH_ENABLE),
 
-                                rBCH_CR);
 
- 			debug("\r\n>>>>>sNAND_ECC_WRITE rBCH_CR 0x%08X\n",readl(rBCH_CR));
 
- #ifndef USE_DATA_INTERFACE
 
- 			writel(1, rNAND_WRBLK_START);
 
- #endif
 
- 			break;
 
- #endif
 
- 		case NAND_ECC_READSYN:
 
- #ifndef USE_DATA_INTERFACE
 
-             //wait for data decode end while useing block process
 
-             while(!(readl(rBCH_INT) & NAND_INT_DECODE_END));
 
- 			debug("NAND_ECC_READSYN rBCH_INT 0x%08X\n",readl(rBCH_INT));
 
-             writel(1, rBCH_INT);
 
- #endif
 
- 			debug("\r\n>>>>NAND_ECC_READSYN rBCH_CR 0x%08X\n",readl(rBCH_CR));
 
- 			break;
 
- 	}
 
- }
 
- #if 0  //512---7bit
 
- #else //1024---7bit
 
- static int ark_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 
-                                     u_char *ecc_code)
 
- {
 
- 	struct nand_chip *chip = mtd->priv;
 
- 	unsigned int bch_encode_no = 0;
 
- 	int i;
 
- 	union{
 
- 		unsigned int word;
 
- 		unsigned char byte[4];
 
- 	} tmp;
 
- 	debug("ark_nand_calculate_ecc\n");
 
- #ifndef USE_DATA_INTERFACE
 
- 	//wait for data encode end with block process
 
-     while(!(readl(rBCH_INT) & NAND_INT_ENCODE_END));
 
- 	debug("rBCH_INT 0x%08X\n",readl(rBCH_INT));
 
-     writel(1, rBCH_INT);
 
- #endif
 
- 	writel(readl(rBCH_CR) & ~BCH_CR_BCH_ENABLE,
 
-                rBCH_CR);  //disable BCH for write ECC Code
 
- #if 1
 
- 	debug("rBCH_NAND_STATUS 0x%08X : 0x%x\n", rBCH_NAND_STATUS, readl(rBCH_NAND_STATUS));
 
- #ifdef USE_DATA_INTERFACE
 
-         while((readl(rBCH_NAND_STATUS) & 0x3F) != 0 ); //wait for fsm to idle state
 
- #else
 
-         while((readl(rBCH_NAND_STATUS) >> 14) & 0x0F); //wait for all data in fifo to be transfered over.
 
-         while((readl(rBCH_NAND_STATUS) & 0x3F)  != 0 );//wait for fsm to idle state
 
- #endif
 
-         debug("wait rBCH_NAND_STATUS done\n");
 
- #endif
 
- 	switch(chip->ecc.bytes){
 
- 	case BIT_7_ECC_BYTE:
 
-     	bch_encode_no = 4;
 
-         break;
 
-     case BIT_13_ECC_BYTE:
 
-         bch_encode_no = 6;
 
-         break;
 
-     case BIT_24_ECC_BYTE:
 
-         bch_encode_no = 11;
 
-         break;
 
-     case BIT_30_ECC_BYTE:
 
-         bch_encode_no = 14;
 
-         break;
 
-     case BIT_48_ECC_BYTE:
 
-         bch_encode_no = 21;
 
-         break;
 
-     }
 
- 	for(i = 0; i < bch_encode_no; i++){
 
- 		tmp.word = readl(EX_BCH_ENCODE_RESULT_ADDR + i*4);
 
- 		*ecc_code++ = tmp.byte[0];
 
- 		*ecc_code++ = tmp.byte[1];
 
- 		*ecc_code++ = tmp.byte[2];
 
- 		*ecc_code++ = tmp.byte[3];
 
- 		debug("EX_BCH_ENCODE_RESULT_ADDR %d: 0x%08X\n", i, tmp.word);
 
- 	}
 
- 	return 0;
 
- }
 
- static int ark_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 
-                                    u_char *read_ecc, u_char *calc_ecc)
 
- {
 
- 	struct nand_chip *chip = mtd->priv;
 
- 	unsigned int bch_decode_no = 0;
 
- 	unsigned char bch_decode_status;
 
- 	unsigned int err_byte_addr[2];
 
-     unsigned int err_bit_addr[2];
 
- 	int i = 0, ret = 0;
 
- 	debug("ark_nand_correct_data\n");
 
- 	switch(chip->ecc.bytes){
 
-     case BIT_7_ECC_BYTE:
 
-         bch_decode_no = 4; /* no. of loops to correct 2 bits per loop   */
 
-         break;
 
-     case BIT_13_ECC_BYTE:
 
-         bch_decode_no = 7;
 
-         break;
 
-     case BIT_24_ECC_BYTE:
 
-         bch_decode_no = 12;
 
-         break;
 
-     case BIT_30_ECC_BYTE:
 
-         bch_decode_no = 15;
 
-         break;
 
-     case BIT_48_ECC_BYTE:
 
-         bch_decode_no = 24;
 
-         break;
 
- 	}
 
- 	//wait for ecc data read end
 
- 	while(readl(rEX_BCH_DECODE_STATUS)&0x01);
 
- #ifdef DEBUG
 
- 	debug("ECC code:");
 
- 	for(i = 0; i<chip->ecc.bytes; i++)
 
- 		debug("0x%X ",*read_ecc++);
 
- 	debug("\n");
 
- #endif
 
- /*
 
- 	printf("\r\nECC code:");
 
- 	for(i = 0; i<chip->ecc.bytes; i++)
 
- 		printf("0x%x ",*read_ecc++);
 
- 	temp=readl(rEX_BCH_DECODE_STATUS);
 
- 	printf("\n!! status:0x%x\n",temp);
 
- 	temp=readl(rBCH_CR);
 
- 	printf("\n!!rBCH_CR status:0x%x\n",temp);
 
- */
 
- 	bch_decode_status = (unsigned char)(readl(rEX_BCH_DECODE_STATUS) & 0x7);
 
- 	if(bch_decode_status & 0x2)
 
- 	{    //All Data is right
 
- 		debug("\nAll data are correct\n");
 
- 		//continue;
 
- 	}
 
- 	else if(bch_decode_status & 0x4)
 
- 	{   //err more than 8 bit
 
- 		writel(readl(rBCH_CR) & ~BCH_CR_BCH_ENABLE,
 
-                        rBCH_CR);
 
- 		printf("\n!!Read Data err more than 8 bit and Group = %d status:0x%x\n",i,bch_decode_status);
 
- 		return -EBADMSG;
 
- 	}
 
- 	else
 
- 	{
 
- 		for(i=0; i<bch_decode_no; i++){
 
- 			unsigned int val;
 
- 			val = readl(EX_BCH_DECODE_RESULT_ADDR+4*i);
 
- 			err_byte_addr[0] = (val&0x3ff8)>>3;
 
- 			err_bit_addr[0] = val&0x7;
 
- 			val = val >> 14;
 
- 			err_byte_addr[1] = (val&0x3ff8)>>3;
 
- 			err_bit_addr[1] = val&0x7;
 
- 			if(err_byte_addr[0] < 1024){
 
- 				(*(dat+err_byte_addr[0]) )^= (1<<err_bit_addr[0]);
 
- 				ret++;
 
-                         }
 
- 			if(err_byte_addr[1] < 1024){
 
- 				(*(dat+err_byte_addr[1]) )^= (1<<err_bit_addr[1]);
 
- 				ret++;
 
- 			}
 
- 		}
 
- 	}
 
- 	debug("Bit error no.: %d\n",ret);
 
-     return ret;
 
- }
 
- #endif
 
- /**
 
-  * ark_nand_read_page_raw_syndrome - [Intern] read raw page data without ecc
 
-  * @mtd:        mtd info structure
 
-  * @chip:       nand chip info structure
 
-  * @buf:        buffer to store read data
 
-  * @page:       page number to read
 
-  *
 
-  * We need a special oob layout and handling even when OOB isn't used.
 
-  */
 
- static int ark_nand_read_page_raw_syndrome(struct mtd_info *mtd,
 
-                                              struct nand_chip *chip,
 
-                                              uint8_t *buf, int oob_required, int page)
 
- {
 
- 	struct ark_nand *nand_info = chip->priv;
 
- 	debug("ark_nand_read_page_raw_syndrome\n");
 
- 	debug("page %d, mtd->writesize %d\n",page, mtd->writesize);
 
- 	nand_info->raw_rw = 1;
 
-     chip->read_buf(mtd, buf, mtd->writesize);
 
-     chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
- 	nand_info->raw_rw = 0;
 
-     return 0;
 
- }
 
- /**
 
-  * ark_nand_read_page_syndrome - hardware ecc syndrom based page read
 
-  * @mtd:        mtd info structure
 
-  * @chip:       nand chip info structure
 
-  * @buf:        buffer to store read data
 
-  * @page:       page number to read
 
-  *
 
-  */
 
- static int ark_nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 
-                                          uint8_t *buf, int oob_required, int page)
 
- {
 
- 	int i, eccsize = chip->ecc.size;
 
- 	int eccbytes = chip->ecc.bytes;
 
- 	int eccsteps = chip->ecc.steps;
 
- 	uint8_t *p = buf;
 
- 	uint8_t *oob = chip->oob_poi;
 
- 	int oob_pos = 0, pos = 0;
 
- 	debug("ark_nand_read_page_syndrome\n");
 
- 	oob_pos += mtd->writesize;
 
-     if(chip->ecc.prepad){
 
-         oob_pos += chip->ecc.prepad;
 
- 		oob += chip->ecc.prepad;
 
- 	}
 
-     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 
- 	    int stat;
 
- 	    chip->ecc.hwctl(mtd, NAND_ECC_READ);
 
- 	    chip->read_buf(mtd, p, eccsize);
 
- 	    chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
 
- 		if (mtd->writesize > 512){
 
- 			chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
 
- 		}else{
 
- 			chip->cmdfunc(mtd, NAND_CMD_READ0, oob_pos, page);
 
- 		}
 
- 		oob_pos += eccbytes;
 
-         chip->read_buf(mtd, oob, eccbytes);
 
-         stat = chip->ecc.correct(mtd, p, oob, NULL);
 
- 		oob += eccbytes;
 
- 		if (stat < 0) {
 
- 			mtd->ecc_stats.failed++;
 
- 		} else {
 
- 			mtd->ecc_stats.corrected += stat;
 
- 		}
 
- 		if(eccsteps > 1)
 
- 		{
 
- 			pos += eccsize;
 
- 			if (mtd->writesize > 512)
 
- 			{
 
- 	        	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1);
 
- 	        }
 
- 			else
 
- 			{
 
- 	        	chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page);
 
- 	        }
 
- 		}
 
-     }
 
- 	writel(1,rBCH_INT);
 
-     writel(readl(rBCH_CR) & ~BCH_CR_BCH_ENABLE, rBCH_CR);
 
- 	/* the whole oob area if there is prepad or postpad area */
 
-     if (chip->ecc.prepad){
 
- 		oob_pos = mtd->writesize;
 
-         if (mtd->writesize > 512){
 
-         	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
 
-         }else{
 
-         	chip->cmdfunc(mtd, NAND_CMD_READ0, oob_pos, page);
 
-         }
 
-         chip->read_buf(mtd, chip->oob_poi, chip->ecc.prepad);
 
- 	}
 
- 	if (chip->ecc.postpad){
 
- 		oob_pos = mtd->writesize + chip->ecc.prepad + (chip->ecc.steps * chip->ecc.bytes);
 
- 	    if (mtd->writesize > 512){
 
- 	    	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
 
- 	    }else{
 
- 	    	chip->cmdfunc(mtd, NAND_CMD_READ0, oob_pos, page);
 
- 	    }
 
- 	    chip->read_buf(mtd, (chip->oob_poi + chip->ecc.prepad + (chip->ecc.steps * chip->ecc.bytes)),
 
- 		chip->ecc.postpad);
 
-  	}
 
- 	return 0;
 
- }
 
- /**
 
-  * ark_nand_read_oob_syndrome - OOB data read function
 
-  * @mtd:        mtd info structure
 
-  * @chip:       nand chip info structure
 
-  * @page:       page number to read
 
-  * @sndcmd:     flag whether to issue read command or not
 
-  */
 
- static int ark_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 
-                              int page)
 
- {
 
- 	debug("ark_nand_read_oob_syndrome\n");
 
-     chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
 
-     chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-     return 0;
 
- }
 
- /**
 
-  * ark_nand_write_oob_syndrome - OOB data write function for HW ECC
 
-  *                           with syndrome - only for large page flash !
 
-  * @mtd:        mtd info structure
 
-  * @chip:       nand chip info structure
 
-  * @page:       page number to write
 
-  */
 
- static int ark_nand_write_oob_syndrome(struct mtd_info *mtd,
 
-                                    struct nand_chip *chip, int page)
 
- {
 
-     int status = 0;
 
-     const uint8_t *buf = chip->oob_poi;
 
-     int length = mtd->oobsize;
 
- 	debug("ark_nand_write_oob_syndrome\n");
 
-     chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
 
-     chip->write_buf(mtd, buf, length);
 
-     /* Send command to program the OOB data */
 
-     chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 
-     status = chip->waitfunc(mtd, chip);
 
-     return status & NAND_STATUS_FAIL ? -EIO : 0;
 
- }
 
- /**
 
-  * ark_nand_write_page_raw_syndrome - raw page write function
 
-  * @mtd:        mtd info structure
 
-  * @chip:       nand chip info structure
 
-  * @buf:        data buffer
 
-  *
 
-  * We need a special oob layout and handling even when ECC isn't checked.
 
-  */
 
- static int ark_nand_write_page_raw_syndrome(struct mtd_info *mtd,
 
-                                         struct nand_chip *chip,
 
-                                         const uint8_t *buf,
 
-                                         int oob_required, int page)
 
- {
 
- 	struct ark_nand *nand_info = chip->priv;
 
- 	debug("ark_nand_write_page_raw_syndrome\n");
 
- 	nand_info->raw_rw = 1;
 
- 	chip->write_buf(mtd, buf, mtd->writesize);
 
-     chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
 
- 	nand_info->raw_rw = 0;
 
- 	return 0;
 
- }
 
- /**
 
-  * ark_nand_write_page_syndrome - hardware ecc syndrom based page write
 
-  * @mtd:        mtd info structure
 
-  * @chip:       nand chip info structure
 
-  * @buf:        data buffer
 
-  *
 
-  * The hw generator calculates the error syndrome automatically. Therefor
 
-  * we need a special oob layout and handling.
 
-  */
 
- static int ark_nand_write_page_syndrome(struct mtd_info *mtd,
 
-                                            struct nand_chip *chip, const uint8_t *buf,
 
-                                            int oob_required, int page)
 
- {
 
-     int i, eccsize = chip->ecc.size;
 
-     int eccbytes = chip->ecc.bytes;
 
-     int eccsteps = chip->ecc.steps;
 
-     const uint8_t *p = buf;
 
-     uint8_t *oob = chip->oob_poi;
 
- 	debug("ark_nand_write_page_syndrome\n");
 
- 	debug("eccsize %d, eccbytes %d, eccsteps %d\n", eccsize, eccbytes, eccsteps);
 
- 	debug("rBCH_NAND_STATUS 0x%x\n", readl(rBCH_NAND_STATUS));
 
- 	if(chip->ecc.prepad){
 
- 		oob += chip->ecc.prepad;
 
- 	}
 
-     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 
-         chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
 
-         chip->write_buf(mtd, p, eccsize);
 
-         chip->ecc.calculate(mtd, p, oob);
 
- 		oob += eccbytes;
 
-     }
 
- 	debug("ark_nand: write ecc\n");
 
- 	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
 
- 	return 0;
 
- }
 
- static int ark_nand_hw_init(struct nand_chip *chip)
 
- {
 
- 	unsigned int val;
 
- 	debug("ark_nand_hw_init\n");
 
- 	writel(0, rNAND_CR);
 
- 	val =0;
 
- #ifdef CONFIG_ARK1668EFAMILY
 
- 	val =(NAND_PAGE_TYPE(0) )|NAND_SEL_CHIP(0)| NAND_PRO_WRITE|NAND_CE_ENABLE |
 
- 		NAND_WR_SETPASS |NAND_RD_TRP_NUM(4) |NAND_RD_TREH_NUM(3)|
 
- 		NAND_WR_HOLD_NUM(3)|NAND_WR_WP_NUM(3)|NAND_WR_SET_NUM(4);
 
- #else
 
- 	val =(NAND_PAGE_TYPE(0) )|NAND_SEL_CHIP(0)| NAND_PRO_WRITE|NAND_CE_ENABLE |
 
- 		NAND_WR_SETPASS |NAND_RD_TRP_NUM(2) |NAND_RD_TREH_NUM(1)|
 
- 		NAND_WR_HOLD_NUM(3)|NAND_WR_WP_NUM(3)|NAND_WR_SET_NUM(4);
 
- #endif
 
-     
 
- 	/* val =(NAND_PAGE_TYPE(0) )|NAND_SEL_CHIP(0)| NAND_PRO_WRITE|NAND_CE_ENABLE |
 
- 		NAND_WR_SETPASS |NAND_RD_TRP_NUM(2) |NAND_RD_TREH_NUM(2)|
 
- 		NAND_WR_HOLD_NUM(2)|NAND_WR_WP_NUM(2)|NAND_WR_SET_NUM(2); */
 
- 	writel(val,rNAND_CR);
 
- 	return 0;
 
- }
 
- static int ark_dev_ready(struct mtd_info *mtd)
 
- {
 
- 	struct nand_chip *chip = mtd->priv;
 
- 	struct ark_nand *nand_info = chip->priv;
 
- 	//return readl(rBCH_NAND_STATUS) & (1 << (18 + nand_info->chip_num));
 
- 	return readl(rBCH_NAND_STATUS) & (1 << (6 + nand_info->chip_num));
 
- }
 
- static int ark_hwecc_nand_init_param(struct nand_chip *chip, struct mtd_info *mtd)
 
- {
 
- 	u32 val;
 
- 	chip->ecc.mode = NAND_ECC_HW_SYNDROME;
 
- 	chip->ecc.calculate = ark_nand_calculate_ecc;
 
-     chip->ecc.hwctl = ark_nand_enable_hwecc;
 
-     chip->ecc.correct = ark_nand_correct_data;
 
- 	chip->ecc.read_page = ark_nand_read_page_syndrome;
 
- 	chip->ecc.read_page_raw = ark_nand_read_page_raw_syndrome;
 
- 	chip->ecc.read_oob = ark_nand_read_oob_syndrome;
 
- 	chip->ecc.write_page = ark_nand_write_page_syndrome;
 
- 	chip->ecc.write_page_raw = ark_nand_write_page_raw_syndrome;
 
- 	chip->ecc.write_oob = ark_nand_write_oob_syndrome;
 
- 	chip->ecc.size = 1024;
 
- 	if (mtd->oobsize == 64) {
 
- 		chip->ecc.bytes = BIT_13_ECC_BYTE; // should be 13 bytes but the ECC encoder register is in 32 bit word
 
- 		chip->ecc.strength = 13;
 
- 		chip->ecc.layout = &nand_hw_eccoob_64;
 
- 		chip->ecc.prepad = nand_hw_eccoob_64.eccpos[0];
 
- 		chip->ecc.postpad = nand_hw_eccoob_64.oobfree[0].offset;
 
- 		val = readl(rBCH_CR);
 
- 		val &= ~(0x7 << 4);
 
- 		val |= (1 << 8) | (1 << 7) | (1 << 4) | (1 << 0);
 
- 		writel(val, rBCH_CR);
 
- 	} else if(mtd->oobsize >= 128 && mtd->oobsize < 256) {
 
- 		chip->ecc.bytes = BIT_24_ECC_BYTE; // should be 13 bytes but the ECC encoder register is in 32 bit word
 
- 		chip->ecc.strength = 24;
 
- 		chip->ecc.layout = &nand_hw_eccoob_128;
 
- 		chip->ecc.prepad = nand_hw_eccoob_128.eccpos[0];
 
- 		chip->ecc.postpad = nand_hw_eccoob_128.oobfree[0].offset;
 
- 		val = readl(rBCH_CR);
 
- 		val &= ~(0x7 << 4);
 
- 		val |= (1 << 8) | (1 << 7) | (2 << 4) | (1 << 0);
 
- 		writel(val, rBCH_CR);
 
- 	} else if(mtd->oobsize >= 256) {
 
- 		chip->ecc.bytes = BIT_24_ECC_BYTE;
 
- 		chip->ecc.strength = 24;
 
- 		chip->ecc.layout = &nand_hw_eccoob_256;
 
- 		chip->ecc.prepad = nand_hw_eccoob_256.eccpos[0];
 
- 		chip->ecc.postpad = nand_hw_eccoob_256.oobfree[0].offset;
 
- 		val = readl(rBCH_CR);
 
- 		val &= ~(0x7 << 4);
 
- 		val |= (1 << 8) | (1 << 7) | (2 << 4) | (1 << 0);
 
- 		writel(val, rBCH_CR);
 
- 	 }
 
- 	return 0;
 
- }
 
- static int ark_nand_init(struct nand_chip *chip, int devnum)
 
- {
 
- 	struct mtd_info *mtd;
 
- 	struct ark_nand *nand_info = &ark_nand_info;
 
- 	int ret;
 
- 	ark_nand_hw_init(chip);
 
- 	debug("board_nand_init\n");
 
- 	mtd = nand_to_mtd(chip);
 
- 	mtd->priv = chip;
 
- 	chip->priv = nand_info;
 
- 	nand_info->max_chip = 4;
 
- 	nand_info->chip_num = 0;
 
- 	/* 5 us command delay time */
 
-     chip->chip_delay = 100;
 
- 	chip->IO_ADDR_R = (void __iomem *)rNAND_STATUS_RD;
 
- 	chip->IO_ADDR_W = (void __iomem *)rNAND_DATA;
 
- #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
 
-     chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
 
- #endif
 
- 	chip->options |= NAND_NO_SUBPAGE_WRITE;//refer kernel
 
- 	chip->cmd_ctrl = ark_nand_hwcontrol;
 
-     chip->select_chip = ark_nand_select_chip;
 
-     chip->write_buf = ark_nand_write_buf;
 
-     chip->read_buf = ark_nand_read_buf;
 
- 	chip->dev_ready = ark_dev_ready;
 
- #if 0 /* TODO: it needs to be fixed due to the 32 bit width of the data read write register */
 
-         nand->verify_buf = ark_nand_verify_buf;
 
- #endif
 
- 	ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
 
- 	if (ret)
 
- 		return ret;
 
- 	ret = ark_hwecc_nand_init_param(chip, mtd);
 
- 	if (ret)
 
- 		return ret;
 
- 	ret = nand_scan_tail(mtd);
 
- 	if (!ret)
 
- 		nand_register(devnum, mtd);
 
- 	return ret;
 
- }
 
- static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
 
- void board_nand_init(void)
 
- {
 
- 	struct nand_chip *nand = &nand_chip[0];
 
- 	if (ark_nand_init(nand, 0))
 
- 		puts("ARK NAND init failed\n");
 
- }
 
- static int do_switchecc(cmd_tbl_t *cmdtp, int flag, int argc,
 
- 		       char * const argv[])
 
- {
 
- 	struct nand_chip *chip = &nand_chip[0];
 
- 	struct mtd_info *mtd = nand_to_mtd(chip);
 
- 	ulong bootecc;
 
- 	unsigned int val;
 
- 	
 
- 	if (argc >= 2) {
 
- 		bootecc = simple_strtoul(argv[1], NULL, 16);
 
- 		if (bootecc) {
 
- 			chip->ecc.size = 512;
 
- 			chip->ecc.steps = mtd->writesize / chip->ecc.size;
 
- 			chip->ecc.bytes = BIT_7_ECC_BYTE; // should be 13 bytes but the ECC encoder register is in 32 bit word
 
- 			chip->ecc.strength = 7;
 
- 			chip->ecc.layout = &nand_hw_eccoob_bootstrap;
 
- 			chip->ecc.prepad = nand_hw_eccoob_bootstrap.eccpos[0];
 
- 			chip->ecc.postpad = nand_hw_eccoob_bootstrap.oobfree[0].offset;
 
- 			val = readl(rBCH_CR);
 
- 			val &= ~((1 << 7) | (0x7 << 4));
 
- 			val |= (1 << 8) | (1 << 0);
 
- 			writel(val, rBCH_CR);
 
- 		} else {
 
- 			chip->ecc.size = 1024;
 
- 			chip->ecc.steps = mtd->writesize / chip->ecc.size;
 
- 			if (mtd->oobsize == 64) {
 
- 				chip->ecc.bytes = BIT_13_ECC_BYTE; // should be 13 bytes but the ECC encoder register is in 32 bit word
 
- 				chip->ecc.strength = 13;
 
- 				chip->ecc.layout = &nand_hw_eccoob_64;
 
- 				chip->ecc.prepad = nand_hw_eccoob_64.eccpos[0];
 
- 				chip->ecc.postpad = nand_hw_eccoob_64.oobfree[0].offset;
 
- 				val = readl(rBCH_CR);
 
- 				val &= ~(0x7 << 4);
 
- 				val |= (1 << 8) | (1 << 7) | (1 << 4) | (1 << 0);
 
- 				writel(val, rBCH_CR);
 
- 			} else if(mtd->oobsize >= 128 && mtd->oobsize <256) {
 
- 				chip->ecc.bytes = BIT_24_ECC_BYTE; // should be 13 bytes but the ECC encoder register is in 32 bit word
 
- 				chip->ecc.strength = 24;
 
- 				chip->ecc.layout = &nand_hw_eccoob_128;
 
- 				chip->ecc.prepad = nand_hw_eccoob_128.eccpos[0];
 
- 				chip->ecc.postpad = nand_hw_eccoob_128.oobfree[0].offset;
 
- 				val = readl(rBCH_CR);
 
- 				val &= ~(0x7 << 4);
 
- 				val |= (1 << 8) | (1 << 7) | (2 << 4) | (1 << 0);
 
- 				writel(val, rBCH_CR);
 
- 			} else if(mtd->oobsize >= 256) {
 
- 				chip->ecc.bytes = BIT_24_ECC_BYTE;
 
- 				chip->ecc.strength = 24;
 
- 				chip->ecc.layout = &nand_hw_eccoob_256;
 
- 				chip->ecc.prepad = nand_hw_eccoob_256.eccpos[0];
 
- 				chip->ecc.postpad = nand_hw_eccoob_256.oobfree[0].offset;
 
- 				val = readl(rBCH_CR);
 
- 				val &= ~(0x7 << 4);
 
- 				val |= (1 << 8) | (1 << 7) | (2 << 4) | (1 << 0);
 
- 				writel(val, rBCH_CR);
 
- 			}
 
- 		}
 
- 	}
 
- 	return 0;
 
- }
 
- U_BOOT_CMD(switchecc, 4, 1, do_switchecc,
 
- 	"switch or restore nand ecc to/from bootstrap setting",
 
- 	"1:to bootstrap ecc; 0:restore to normal ecc"
 
- );
 
 
  |