加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

u-boot for tiny210 ver2.2(by liukun321咕唧咕唧)

发布时间:2020-12-15 06:17:41 所属栏目:百科 来源:网络整理
导读:前三个版本都不支持nandflash的读写,这次更新(ver2.2)添加了nandflash驱动及yaffs文件系统的烧写功能。在kasim的建议下我从ver2.2开始用git源代码仓库管理我的源码。并发布上一版本的补丁文件。 你可以点击下面的链接浏览u-boot for tiny210 ver2.2 源码

前三个版本都不支持nandflash的读写,这次更新(ver2.2)添加了nandflash驱动及yaffs文件系统的烧写功能。在kasim的建议下我从ver2.2开始用git源代码仓库管理我的源码。并发布上一版本的补丁文件。
你可以点击下面的链接浏览u-boot for tiny210 ver2.2 源码:

Git source u-boot for tiny210 ver2.2

下面的提供了在CSDN资源库的下载链接:

ver2.2源码下载:? u-boot for tiny210 ver2.2

下面的提供了补丁包的下载链接:

ver2.2补丁下载:?u-boot-for-tiny210-patch-ver2.2

下面的链接提供了前几次修改的源码:

ver1.0源码下载:u-boot for tiny210 ver1.0
ver2.0源码下载:u-boot for tiny210 ver2.0
ver2.1源码下载:u-boot for tiny210 ver2.1

你还可以参考下三篇blog从头构建自己的u-boot for tiny210

ver1.0?? ver2.0? ?ver2.1?

?

ver2.2的基本功能:

1. SD boot,基于linaro u-boot的SPL功能实现

2. 从SD卡的FAT分区上加载文件到SDRAM

3. 将环境变量保存至SD卡

4. 添加DM9000网卡驱动,开启网络功能(例如:tftp,nfs等)

5. 添加TAB键命令自动补全功能

6.修复bug:

修复bug 1:SD卡保存环境变量出现Writing to MMC(0)... mmc_send_cmd: error during transfer: 0x00208001 mmc write failed。

修复bug 2:每次启动只能保存一次环境变量。

+7.添加NandFlash驱动,开启所有Nand cmd。

+8.添加Yaffs文件系统烧写支持。

?

?

参照本文后面内容修改完后:

编译u-boot
$make ARCH=arm CROSS_COMPILE=/opt/FriendlyARM/toolschain/4.5.1/bin/arm-none-linux-gnueabi- tiny210_config
$make ARCH=arm CROSS_COMPILE=/opt/FriendlyARM/toolschain/4.5.1/bin/arm-none-linux-gnueabi- all spl
由于我的系统下装有两套交叉工具链,所以没有把 ?/opt/FriendlyARM/toolschain/4.5.1/bin/?添加到环境变量,在使用工具链时要指明路径。

将u-boot镜像写入SD卡
将SD卡通过读卡器接上电脑(或直接插入笔记本卡槽),通过"cat /proc/partitions"找出SD卡对应的设备,我的设备节点是/dev/sdb.

执行下面的命令
$sudo dd iflag=dsync oflag=dsync if=spl/tiny210-spl.bin of=/dev/sdb seek=1
$sudo dd iflag=dsync oflag=dsync if=u-boot.bin of=/dev/sdb??seek=49
?
?
将SD卡插入开发板启动:

?

?

启动:

?

部分NAND CMD测试:

?

?

下面简要介绍ver2.2的修改步骤

左边的数字为旧行号,右边的数字为新行号,大家可以对应行号阅读修改部分的源码,或自己从ver2.1修改至ver2.2

1.tiny210-u-boot-version2.1/board/samsung/tiny210/Makefile 在此目录下修改Makefile

( 4 / 0)
? ? ? ?
? 31 31
? 32 32 ifdef CONFIG_SPL_BUILD
? 33 33 COBJS += mmc_boot.o
? ? 34 #COBJS += nand.o
? ? 35 #COBJS += nand_cp.o
? 34 36 endif
? ? 37 COBJS += nand.o
? ? 38 COBJS += nand_cp.o
? 35 39
? 36 40 SOBJS := lowlevel_init.o mem_setup.o
? 37 41
? 17 int add_mtd_device(struct mtd_info *mtd)
?
?
2.??tiny210-u-boot-version2.1/drivers/mtd/nand/nand.c
修改此目录下的nand.c??(4 / 1)
? ? ? ?
? 64 64 * Add MTD device so that we can reference it later
? 65 65 * via the mtdcore infrastructure (e.g. ubi).
? 66 66 */
? 67 ? sprintf(dev_name[i],"nand%d",i);
? ? 67 #if CONFIG_NAND_NO_USE_CHIP_NAME
? ? 68 sprintf(dev_name[i],i);
? 68 69 mtd->name = dev_name[i++];
? ? 70 #endif
? 69 71 add_mtd_device(mtd);
? ? 72
? 70 73 #endif
? 71 74 } else
? 72 75 mtd->name = NULL;
?
?
3.tiny210-u-boot-version2.1/include/configs/tiny210.h
修改此目录下的tiny210.h?(33 /0)
? ? ? ?
? 430 430 #define CONFIG_CMDLINE_EDITING
? 431 431 #define CONFIG_AUTO_COMPLETE
? 432 432 #define CONFIG_SYS_HUSH_PARSER
? ? 433
? ? 434 /*****************************Modified by lk for nand driver*************/
? ? 435 #define CONFIG_CMD_NAND
? ? 436 #if defined(CONFIG_CMD_NAND)
? ? 437 #define CONFIG_CMD_NAND_YAFFS
? ? 438 #define CONFIG_CMD_MTDPARTS
? ? 439 #define CONFIG_SYS_MAX_NAND_DEVICE 1
? ? 440 #define CONFIG_SYS_NAND_BASE (0xB0E000000)
? ? 441 #define NAND_MAX_CHIPS 1
? ? 442
? ? 443 #define CONFIG_MTD_DEVICE /* needed for mtdparts commands add by lkmcu */
? ? 444
? ? 445 #define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
? ? 446 #define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
? ? 447 #define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
? ? 448 #define CONFIG_CMD_NAND_YAFFS_SKIPFB
? ? 449
? ? 450 #define CONFIG_NAND_USE_CHIP_NAME 1
? ? 451
? ? 452 #if 0
? ? 453
? ? 454 #define CONFIG_MTD_DEBUG
? ? 455 #define CONFIG_MTD_DEBUG_VERBOSE
? ? 456
? ? 457 #define CFG_NAND_SKIP_BAD_DOT_I 1
? ? 458 #define CFG_NAND_HWECC
? ? 459
? ? 460 #define CONFIG_NAND_BL1_8BIT_ECC
? ? 461 #endif
? ? 462 #undef CFG_NAND_FLASH_BBT
? ? 463 #endif
? ? 464
? ? 465
? 433 466 #endif /* __CONFIG_H */
?
?
4.tiny210-u-boot-version2.1/include/linux/mtd/mtd-abi.h
修改此目录下的mtd-abi.h(2 /0)
? ? ? ?
? 126 126 uint32_t eccpos[128];
? 127 127 uint32_t oobavail;
? 128 128 struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
? ? 129 uint32_t useecc;
? ? 130 uint32_t reserved;
? 129 131 };
? 130 132
? 131 133 /**
?
5.在 tiny210-u-boot-version2.1/board/samsung/tiny210/ ?目录下添加nand.c nand_cp.c(本版本未启用nand_cp.c文件)。nand.c文件内容如下:
#include <common.h>

#if defined(CONFIG_CMD_NAND)
#include <nand.h>
#include <bedbug/regs.h>
#include <s5pc110.h>

#include <asm/io.h>
#include <asm/errno.h>

/* Nand flash definition values by jsgood */
#define S3C_NAND_TYPE_UNKNOWN	0x0
#define S3C_NAND_TYPE_SLC	0x1
#define S3C_NAND_TYPE_MLC	0x2
#undef	S3C_NAND_DEBUG

/* Nand flash global values by jsgood */
int cur_ecc_mode = 0;
int nand_type = S3C_NAND_TYPE_UNKNOWN;

/* Nand flash oob definition for SLC 512b page size by jsgood */
static struct nand_ecclayout s3c_nand_oob_16 = {
	.useecc = MTD_NANDECC_AUTOPLACE,/* Only for U-Boot */
	.eccbytes = 4,.eccpos = {1,2,3,4},.oobfree = {
		{.offset = 6,. length = 10}}
};

/* Nand flash oob definition for SLC 2k page size by jsgood */
static struct nand_ecclayout s3c_nand_oob_64 = {
	.useecc = MTD_NANDECC_AUTOPLACE,/* Only for U-Boot */
	.eccbytes = 16,.eccpos = {40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55},.oobfree = {
		{.offset = 2,.length = 38}}
};
 
/* Nand flash oob definition for MLC 2k page size by jsgood */
static struct nand_ecclayout s3c_nand_oob_mlc_64 = {
	.useecc = MTD_NANDECC_AUTOPLACE,/* Only for U-Boot */
	.eccbytes = 32,.eccpos = {
		   32,33,34,35,36,37,38,39,40,55,56,57,58,59,60,61,62,63},.length = 28}}
};

/* Nand flash oob definition for 4Kb page size with 8_bit ECC */
static struct nand_ecclayout s3c_nand_oob_128 = {
        .useecc = MTD_NANDECC_AUTOPLACE,.eccbytes = 104,.eccpos = {
                   24,25,26,27,28,29,30,31,32,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 = {
                {.offset = 2,.length = 22}}
};
#if defined(S3C_NAND_DEBUG)
/*
 * Function to print out oob buffer for debugging
 * Written by jsgood
 */
static void print_oob(const char *header,struct mtd_info *mtd)
{
	int i;
	struct nand_chip *chip = mtd->priv;

	printk("%s:t",header);

	for(i = 0; i < 64; i++)
		printk("%02x ",chip->oob_poi[i]);

	printk("n");
}
#endif

/*
 * Hardware specific access to control-lines function
 * Written by jsgood
 */
static void s3c_nand_hwcontrol(struct mtd_info *mtd,int dat,unsigned int ctrl)
{
	unsigned int cur;

#if 1
	if (ctrl & NAND_CTRL_CHANGE) {
		if (ctrl & NAND_NCE) {
			if (dat != NAND_CMD_NONE) {
				cur = readl(NFCONT);
				/* Forced Enable CS */
				cur &= ~NFCONT_CS;

				writel(cur,NFCONT);
			}
		} else {
			cur = readl(NFCONT);
			/* Forced Enable CS */
			cur |= NFCONT_CS;

			writel(cur,NFCONT);
		}
	}

	if (dat != NAND_CMD_NONE) {
		if (ctrl & NAND_CLE)
			writeb(dat,NFCMMD);
		else if (ctrl & NAND_ALE)
			writeb(dat,NFADDR);
	}
#endif
}

/*
 * Function for checking device ready pin
 * Written by jsgood
 */
static int s3c_nand_device_ready(struct mtd_info *mtdinfo)
{
	while (!(readl(NFSTAT) & NFSTAT_RnB)) {}
	return 1;
}

/*
 * We don't use bad block table
 */
static int s3c_nand_scan_bbt(struct mtd_info *mtdinfo)
{
	return nand_default_bbt(mtdinfo);
}

#if defined(CFG_NAND_HWECC)

/*
 * Function for checking ECCEncDone in NFSTAT
 * Written by jsgood
 */
static void s3c_nand_wait_enc(void)
{
	while (!(readl(NFECCSTAT) & NFSTAT_ECCENCDONE)) {}
}

/*
 * Function for checking ECCDecDone in NFSTAT
 * Written by jsgood
 */
static void s3c_nand_wait_dec(void)
{
	while (!(readl(NFECCSTAT) & NFSTAT_ECCDECDONE)) {}
}

/*
 * Function for checking ECC Busy
 * Written by jsgood
 */
static void s3c_nand_wait_ecc_busy(void)
{
	while (readl(NFECCSTAT) & NFESTAT0_ECCBUSY) {}
}

/*
 * This function is called before encoding ecc codes to ready ecc engine.
 * Written by jsgood
 */
static void s3c_nand_enable_hwecc(struct mtd_info *mtd,int mode)
{
	u_long nfcont,nfconf;

	cur_ecc_mode = mode;

	nfconf = readl(NFCONF);

 	if (nand_type == S3C_NAND_TYPE_SLC)
		nfconf &= ~NFCONF_ECC_MLC;	/* SLC */
	else
		nfconf |= NFCONF_ECC_MLC;	/* MLC */

	writel(nfconf,NFCONF);
	printf("NFCONF = %xn",nfconf);
	/* Initialize & unlock */
	nfcont = readl(NFCONT);
	nfcont |= NFCONT_INITMECC;
	nfcont &= ~NFCONT_MECCLOCK;

	if (nand_type == S3C_NAND_TYPE_MLC) {
		if (mode == NAND_ECC_WRITE)
			nfcont |= NFCONT_ECC_ENC;
		else if (mode == NAND_ECC_READ)
			nfcont &= ~NFCONT_ECC_ENC;
	}

	writel(nfcont,NFCONT);
}

/*
 * This function is called immediately after encoding ecc codes.
 * This function returns encoded ecc codes.
 * Written by jsgood
 */
static int s3c_nand_calculate_ecc(struct mtd_info *mtd,const u_char *dat,u_char *ecc_code)
{
	u_long nfcont,nfmecc0,nfmecc1;

	/* Lock */
	nfcont = readl(NFCONT);
	nfcont |= NFCONT_MECCLOCK;
	writel(nfcont,NFCONT);

	if (nand_type == S3C_NAND_TYPE_SLC) {
		nfmecc0 = readl(NFMECC0);

		ecc_code[0] = nfmecc0 & 0xff;
		ecc_code[1] = (nfmecc0 >> 8) & 0xff;
		ecc_code[2] = (nfmecc0 >> 16) & 0xff;
		ecc_code[3] = (nfmecc0 >> 24) & 0xff;
	} else {
		if (cur_ecc_mode == NAND_ECC_READ)
			s3c_nand_wait_dec();
		else {
			s3c_nand_wait_enc();

			nfmecc0 = readl(NFMECC0);
			nfmecc1 = readl(NFMECC1);

			ecc_code[0] = nfmecc0 & 0xff;
			ecc_code[1] = (nfmecc0 >> 8) & 0xff;
			ecc_code[2] = (nfmecc0 >> 16) & 0xff;
			ecc_code[3] = (nfmecc0 >> 24) & 0xff;
			ecc_code[4] = nfmecc1 & 0xff;
			ecc_code[5] = (nfmecc1 >> 8) & 0xff;
			ecc_code[6] = (nfmecc1 >> 16) & 0xff;
			ecc_code[7] = (nfmecc1 >> 24) & 0xff;
		}
	}

	return 0;
}

/*
 * This function determines whether read data is good or not.
 * If SLC,must write ecc codes to controller before reading status bit.
 * If MLC,status bit is already set,so only reading is needed.
 * If status bit is good,return 0.
 * If correctable errors occured,do that.
 * If uncorrectable errors occured,return -1.
 * Written by jsgood
 */
static int s3c_nand_correct_data(struct mtd_info *mtd,u_char *dat,u_char *read_ecc,u_char *calc_ecc)
{
	int ret = -1;
	u_long nfestat0,nfestat1,nfmeccdata0,nfmeccdata1,nfmlcbitpt;
	u_char err_type;

	if (nand_type == S3C_NAND_TYPE_SLC) {
		/* SLC: Write ecc to compare */
		nfmeccdata0 = (read_ecc[1] << 16) | read_ecc[0];
		nfmeccdata1 = (read_ecc[3] << 16) | read_ecc[2];
		writel(nfmeccdata0,NFMECCDATA0);
		writel(nfmeccdata1,NFMECCDATA1);

		/* Read ecc status */
		nfestat0 = readl(NFESTAT0);
		err_type = nfestat0 & 0x3;

		switch (err_type) {
		case 0: /* No error */
			ret = 0;
			break;

		case 1: /* 1 bit error (Correctable)
			   (nfestat0 >> 7) & 0x7ff	:error byte number
			   (nfestat0 >> 4) & 0x7	:error bit number */
			printk("s3c-nand: 1 bit error detected at byte %ld,correcting from "
					"0x%02x ",(nfestat0 >> 7) & 0x7ff,dat[(nfestat0 >> 7) & 0x7ff]);
			dat[(nfestat0 >> 7) & 0x7ff] ^= (1 << ((nfestat0 >> 4) & 0x7));
			printk("to 0x%02x...OKn",dat[(nfestat0 >> 7) & 0x7ff]);
			ret = 1;
			break;

		case 2: /* Multiple error */
		case 3: /* ECC area error */
			printk("s3c-nand: ECC uncorrectable error detectedn");
			ret = -1;
			break;
		}
	} else {
		/* MLC: */
		s3c_nand_wait_ecc_busy();

		nfestat0 = readl(NFESTAT0);
		nfestat1 = readl(NFESTAT1);
		nfmlcbitpt = readl(NFMLCBITPT);

		err_type = (nfestat0 >> 26) & 0x7;

		/* No error,If free page (all 0xff) */
		if ((nfestat0 >> 29) & 0x1) {
			err_type = 0;
		} else {
			/* No error,If all 0xff from 17th byte in oob (in case of JFFS2 format) */
			if (dat) {
				if (dat[17] == 0xff && dat[26] == 0xff && dat[35] == 0xff && dat[44] == 0xff && dat[54] == 0xff)
					err_type = 0;
			}
		}

		switch (err_type) {
		case 5: /* Uncorrectable */
			printk("s3c-nand: ECC uncorrectable error detectedn");
			ret = -1;
			break;

		case 4: /* 4 bit error (Correctable) */
			dat[(nfestat1 >> 16) & 0x3ff] ^= ((nfmlcbitpt >> 24) & 0xff);

		case 3: /* 3 bit error (Correctable) */
			dat[nfestat1 & 0x3ff] ^= ((nfmlcbitpt >> 16) & 0xff);

		case 2: /* 2 bit error (Correctable) */
			dat[(nfestat0 >> 16) & 0x3ff] ^= ((nfmlcbitpt >> 8) & 0xff);

		case 1: /* 1 bit error (Correctable) */
			printk("s3c-nand: %d bit(s) error detected,corrected successfullyn",err_type);
			dat[nfestat0 & 0x3ff] ^= (nfmlcbitpt & 0xff);
			ret = err_type;
			break;

		case 0: /* No error */
			ret = 0;
			break;
		}
	}

	return ret;
}

#if defined(CONFIG_NAND_BL1_8BIT_ECC) && defined(CONFIG_S5PC110)
/***************************************************************
 * jsgood: Temporary 8 Bit H/W ECC supports for BL1 (6410/6430 only)
 ***************************************************************/
static void s3c_nand_wait_ecc_busy_8bit(void)
{
	while (readl(NFECCSTAT) & NFESTAT0_ECCBUSY) {
	}
}

void s3c_nand_enable_hwecc_8bit(struct mtd_info *mtd,int mode)
{
	u_long nfreg;
	
	cur_ecc_mode = mode;

	if(cur_ecc_mode == NAND_ECC_WRITE){

	/* 8 bit selection */
	nfreg = readl(NFCONF);
	nfreg &= ~(0x3 << 23);
	nfreg |= (0x3<< 23);
	writel(nfreg,NFCONF);
	
	/* Set ECC type */
	nfreg = readl(NFECCCONF);
	nfreg &= 0xf;
	nfreg |= 0x3;
	writel(nfreg,NFECCCONF);

	/* set 8/12/16bit Ecc direction to Encoding */
	nfreg = readl(NFECCCONT);
	nfreg &= ~(0x1 << 16);
	nfreg |= (0x1 << 16);
	writel(nfreg,NFECCCONT);

	/* set 8/12/16bit ECC message length  to msg */
	nfreg = readl(NFECCCONF);
	nfreg &= ~((0x3ff<<16));
	nfreg |= (0x1ff << 16);
	writel(nfreg,NFECCCONF);

	/* write '1' to clear this bit. */
	/* clear illegal access status bit */
	nfreg = readl(NFSTAT);
	nfreg |= (0x1 << 4);
	nfreg |= (0x1 << 5);
	writel(nfreg,NFSTAT);

	/* clear 8/12/16bit ecc encode done */
	nfreg = readl(NFECCSTAT);
	nfreg |= (0x1 << 25);
	writel(nfreg,NFECCSTAT);

	nfreg = readl(NFCONT);
	nfreg &= ~(0x1 << 1);
	writel(nfreg,NFCONT);
	
	/* Initialize & unlock */
	nfreg = readl(NFCONT);
	nfreg &= ~NFCONT_MECCLOCK;
	nfreg |= NFCONT_INITECC;	
	writel(nfreg,NFCONT);

	/* Reset ECC value. */
	nfreg = readl(NFECCCONT);
	nfreg |= (0x1 << 2);
	writel(nfreg,NFECCCONT);
	
	}else{

	/* set 8/12/16bit ECC message length  to msg */
	nfreg = readl(NFECCCONF);
	nfreg &= ~((0x3ff<<16));
	nfreg |= (0x1ff << 16);
	writel(nfreg,NFECCCONF);
	
	/* set 8/12/16bit Ecc direction to Decoding */
	nfreg = readl(NFECCCONT);
	nfreg &= ~(0x1 << 16);
	writel(nfreg,NFECCCONT);
	
	/* write '1' to clear this bit. */
	/* clear illegal access status bit */
	nfreg = readl(NFSTAT);
	nfreg |= (0x1 << 4);
	nfreg |= (0x1 << 5);
	writel(nfreg,NFSTAT);

	/* Lock */
	nfreg = readl(NFCONT);
	nfreg |= NFCONT_MECCLOCK;
	writel(nfreg,NFCONT);

	nfreg = readl(NFCONT);
	nfreg &= ~(0x1 << 1);
	writel(nfreg,NFCONT);

	/* clear 8/12/16bit ecc decode done */
	nfreg = readl(NFECCSTAT);
	nfreg |= (0x1 << 24);
	writel(nfreg,NFECCSTAT);
	
	/* Initialize & lock */
	nfreg = readl(NFCONT);
	nfreg &= ~NFCONT_MECCLOCK;
	nfreg |= NFCONT_MECCLOCK;
	writel(nfreg,NFCONT);

	/* write '1' to clear this bit. */
	nfreg = readl(NFSTAT);
	nfreg &= ~(1<<4);
	nfreg |= (1<<4);
	writel(nfreg,NFSTAT);

	while(!(nfreg &(1<<4))){
		nfreg = readl(NFSTAT);
		}

	/* write '1' to clear this bit. */
	nfreg = readl(NFSTAT);
	nfreg &= ~(1<<4);
	nfreg |= (1<<4);
	writel(nfreg,NFSTAT);
	
	/* Initialize & unlock */
	nfreg = readl(NFCONT);
	nfreg &= ~NFCONT_MECCLOCK;
	nfreg |= NFCONT_INITECC;	
	writel(nfreg,NFECCCONT);
	}

}

int s3c_nand_calculate_ecc_8bit(struct mtd_info *mtd,nfeccprgecc0,nfeccprgecc1,nfeccprgecc2,nfeccprgecc3;

	if (cur_ecc_mode == NAND_ECC_READ) {
		/* Lock */
		nfcont = readl(NFCONT);
		nfcont |= NFCONT_MECCLOCK;
		writel(nfcont,NFCONT);
		
		s3c_nand_wait_dec();

		/* clear 8/12/16bit ecc decode done */
		nfcont = readl(NFECCSTAT);
		nfcont |= (1<<24);
		writel(nfcont,NFECCSTAT);

		s3c_nand_wait_ecc_busy_8bit();

		if(readl(NFSTAT)&(1<<5))
		{
			/* clear illegal access status bit */
			nfcont = readl(NFSTAT);
			nfcont |= (1<<5);
			writel(nfcont,NFSTAT);

			printf("n Accessed locked area!! n");
			
			nfcont = readl(NFCONT);
			nfcont |= (1<<1);
			writel(nfcont,NFCONT);
			
			return -1;
		}
		
		nfcont = readl(NFCONT);
		nfcont |= (1<<1);
		writel(nfcont,NFCONT);

		
	} else {
		/* Lock */
		nfcont = readl(NFCONT);
		nfcont |= NFCONT_MECCLOCK;
		writel(nfcont,NFCONT);
		
		s3c_nand_wait_enc();

		/* clear 8/12/16bit ecc encode done */
		nfcont = readl(NFECCSTAT);
		nfcont |= (1<<25);
		writel(nfcont,NFECCSTAT);

		nfeccprgecc0 = readl(NFECCPRGECC0);
		nfeccprgecc1 = readl(NFECCPRGECC1);
		nfeccprgecc2 = readl(NFECCPRGECC2);
		nfeccprgecc3 = readl(NFECCPRGECC3);
	
		ecc_code[0] = nfeccprgecc0 & 0xff;
		ecc_code[1] = (nfeccprgecc0 >> 8) & 0xff;
		ecc_code[2] = (nfeccprgecc0 >> 16) & 0xff;
		ecc_code[3] = (nfeccprgecc0 >> 24) & 0xff;
		ecc_code[4] = nfeccprgecc1 & 0xff;
		ecc_code[5] = (nfeccprgecc1 >> 8) & 0xff;
		ecc_code[6] = (nfeccprgecc1 >> 16) & 0xff;
		ecc_code[7] = (nfeccprgecc1 >> 24) & 0xff;
		ecc_code[8] = nfeccprgecc2 & 0xff;
		ecc_code[9] = (nfeccprgecc2 >> 8) & 0xff;
		ecc_code[10] = (nfeccprgecc2 >> 16) & 0xff;
		ecc_code[11] = (nfeccprgecc2 >> 24) & 0xff;
		ecc_code[12] = nfeccprgecc3 & 0xff;

		

	}

	return 0;
}

int s3c_nand_correct_data_8bit(struct mtd_info *mtd,u_char *dat)
{
	int ret = -1;
	u_long nf8eccerr0,nf8eccerr1,nf8eccerr2,nf8eccerr3,nf8eccerr4,nfmlc8bitpt0,nfmlc8bitpt1;
	u_char err_type;

	s3c_nand_wait_ecc_busy_8bit();

	nf8eccerr0 = readl(NFECCSECSTAT);
	nf8eccerr1 = readl(NFECCERL0);
	nf8eccerr2 = readl(NFECCERL1);
	nf8eccerr3 = readl(NFECCERL2);
	nf8eccerr4 = readl(NFECCERL3);
	nfmlc8bitpt0 = readl(NFECCERP0);
	nfmlc8bitpt1 = readl(NFECCERP1);

	err_type = (nf8eccerr0) & 0xf;

	/* No error,If free page (all 0xff) */
	if ((nf8eccerr0 >> 29) & 0x1)
		err_type = 0;

	switch (err_type) {
	case 9: /* Uncorrectable */
		printk("s3c-nand: ECC uncorrectable error detectedn");
		ret = -1;
		break;

	case 8: /* 8 bit error (Correctable) */
		dat[(nf8eccerr4 >> 16) & 0x3ff] ^= ((nfmlc8bitpt1 >> 24) & 0xff);

	case 7: /* 7 bit error (Correctable) */
		dat[(nf8eccerr4) & 0x3ff] ^= ((nfmlc8bitpt1 >> 16) & 0xff);

	case 6: /* 6 bit error (Correctable) */
		dat[(nf8eccerr3 >> 16) & 0x3ff] ^= ((nfmlc8bitpt1 >> 8) & 0xff);

	case 5: /* 5 bit error (Correctable) */
		dat[(nf8eccerr3) & 0x3ff] ^= ((nfmlc8bitpt1) & 0xff);

	case 4: /* 8 bit error (Correctable) */
		dat[(nf8eccerr2 >> 16) & 0x3ff] ^= ((nfmlc8bitpt0 >> 24) & 0xff);

	case 3: /* 7 bit error (Correctable) */
		dat[(nf8eccerr2) & 0x3ff] ^= ((nfmlc8bitpt0>> 16) & 0xff);

	case 2: /* 6 bit error (Correctable) */
		dat[(nf8eccerr1 >> 16) & 0x3ff] ^= ((nfmlc8bitpt0>> 8) & 0xff);

	case 1: /* 1 bit error (Correctable) */
		printk("s3c-nand: %d bit(s) error detected,err_type);
		dat[(nf8eccerr1) & 0x3ff] ^= ((nfmlc8bitpt0) & 0xff);
		ret = err_type;
		break;

	case 0: /* No error */
		ret = 0;
		break;
	}

	return ret;
}

void s3c_nand_write_page_8bit(struct mtd_info *mtd,struct nand_chip *chip,const uint8_t *buf)
{	
	u_long nfreg;
	int i,eccsize = 512;
	int eccbytes = 13;
	int eccsteps = mtd->writesize / eccsize;
	int badoffs = mtd->writesize == 512 ? NAND_SMALL_BADBLOCK_POS : NAND_LARGE_BADBLOCK_POS;

	uint8_t *ecc_calc = chip->buffers->ecccalc;
	uint8_t *p = buf;
	
	for (i = 0; eccsteps; eccsteps--,i += eccbytes,p += eccsize) {
		s3c_nand_enable_hwecc_8bit(mtd,NAND_ECC_WRITE);
		chip->write_buf(mtd,p,eccsize);
		s3c_nand_calculate_ecc_8bit(mtd,&ecc_calc[i]);
	}

	chip->oob_poi[badoffs] = 0xff;
	for (i = 0; i <= eccbytes * (mtd->writesize / eccsize); i++) {
#if defined(CONFIG_EVT1)
		chip->oob_poi[i+12] = ecc_calc[i];
#else
		chip->oob_poi[i] = ecc_calc[i];
#endif
	}

	chip->write_buf(mtd,chip->oob_poi,mtd->oobsize);
}

int s3c_nand_read_page_8bit(struct mtd_info *mtd,uint8_t *buf)
{
	u_long nfreg;
	int i,stat,eccsize = 512;
	int eccbytes = 13;
	int eccsteps = mtd->writesize / eccsize;
	int col = 0;
	uint8_t *p = buf;
	
	/* Step1: read whole oob */
	col = mtd->writesize;
#if defined(CONFIG_EVT1)
	chip->cmdfunc(mtd,NAND_CMD_RNDOUT,col+12,-1);
#else
	chip->cmdfunc(mtd,col,-1);
#endif
	chip->read_buf(mtd,mtd->oobsize);

	col = 0;

	for (i = 0; eccsteps; eccsteps--,p += eccsize) {

		chip->cmdfunc(mtd,-1);
		s3c_nand_enable_hwecc_8bit(mtd,NAND_ECC_READ);
		chip->read_buf(mtd,eccsize);
		chip->write_buf(mtd,chip->oob_poi + (((mtd->writesize / eccsize) - eccsteps) * eccbytes),eccbytes);
		s3c_nand_calculate_ecc_8bit(mtd,0);
		stat = s3c_nand_correct_data_8bit(mtd,p);

		if (stat == -1)
			mtd->ecc_stats.failed++;

		col = eccsize * ((mtd->writesize / eccsize) + 1 - eccsteps);
	}

	return 0;
}

int s3c_nand_read_oob_8bit(struct mtd_info *mtd,int page,int sndcmd)
{
        int eccbytes = chip->ecc.bytes;
        int secc_start = mtd->oobsize - eccbytes;

        if (sndcmd) {
                chip->cmdfunc(mtd,NAND_CMD_READOOB,page);
                sndcmd = 0;
        }

        chip->read_buf(mtd,0); //secc_start);
        return sndcmd;
}

int s3c_nand_write_oob_8bit(struct mtd_info *mtd,int page)
{
        int status = 0;
        int eccbytes = chip->ecc.bytes;
        int secc_start = mtd->oobsize - eccbytes;

        chip->cmdfunc(mtd,NAND_CMD_SEQIN,mtd->writesize,page);

        /* spare area */
        chip->write_buf(mtd,0); //secc_start);

        /* 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;
}

/********************************************************/
#endif

static int s3c_nand_write_oob_1bit(struct mtd_info *mtd,int page)
{
	uint8_t *ecc_calc = chip->buffers->ecccalc;
	int status = 0;
	int eccbytes = chip->ecc.bytes;
	int secc_start = mtd->oobsize - eccbytes;
	int i;

	chip->cmdfunc(mtd,page);

	/* spare area */
	chip->ecc.hwctl(mtd,NAND_ECC_WRITE);
	chip->write_buf(mtd,secc_start);
	chip->ecc.calculate(mtd,&ecc_calc[chip->ecc.total]);

	for (i = 0; i < eccbytes; i++)
		chip->oob_poi[secc_start + i] = ecc_calc[chip->ecc.total + i];

	chip->write_buf(mtd,chip->oob_poi + secc_start,eccbytes);

	/* Send command to program the OOB data */
	chip->cmdfunc(mtd,-1);

	status = chip->waitfunc(mtd,chip);

	return status & NAND_STATUS_FAIL ? -EIO : 0;
}

static int s3c_nand_read_oob_1bit(struct mtd_info *mtd,int sndcmd)
{
	uint8_t *ecc_calc = chip->buffers->ecccalc;
	int eccbytes = chip->ecc.bytes;
	int secc_start = mtd->oobsize - eccbytes;

	if (sndcmd) {
		chip->cmdfunc(mtd,page);
		sndcmd = 0;
	}

	chip->ecc.hwctl(mtd,NAND_ECC_READ);
	chip->read_buf(mtd,&ecc_calc[chip->ecc.total]);
	chip->read_buf(mtd,eccbytes);

	/* jffs2 special case */
	if (!(chip->oob_poi[2] == 0x85 && chip->oob_poi[3] == 0x19))
		chip->ecc.correct(mtd,0);

	return sndcmd;
}

static void s3c_nand_write_page_1bit(struct mtd_info *mtd,const uint8_t *buf)
{
	int i,eccsize = chip->ecc.size;
	int eccbytes = chip->ecc.bytes;
	int eccsteps = chip->ecc.steps;
	int secc_start = mtd->oobsize - eccbytes;
	uint8_t *ecc_calc = chip->buffers->ecccalc;
	const uint8_t *p = buf;

	uint32_t *eccpos = chip->ecc.layout->eccpos;

	/* main area */
	for (i = 0; eccsteps; eccsteps--,p += eccsize) {
		chip->ecc.hwctl(mtd,eccsize);
		chip->ecc.calculate(mtd,&ecc_calc[i]);
	}

	for (i = 0; i < chip->ecc.total; i++)
		chip->oob_poi[eccpos[i]] = ecc_calc[i];

	/* spare area */
	chip->ecc.hwctl(mtd,eccbytes);
}

static int s3c_nand_read_page_1bit(struct mtd_info *mtd,uint8_t *buf)
{
	int i,eccsize = chip->ecc.size;
	int eccbytes = chip->ecc.bytes;
	int eccsteps = chip->ecc.steps;
	int secc_start = mtd->oobsize - eccbytes;
	int col = 0;
	uint8_t *p = buf;
	uint32_t *mecc_pos = chip->ecc.layout->eccpos;
	uint8_t *ecc_calc = chip->buffers->ecccalc;

	col = mtd->writesize;
	chip->cmdfunc(mtd,-1);

	/* spare area */
	chip->ecc.hwctl(mtd,0);

	col = 0;

	/* main area */
	for (i = 0; eccsteps; eccsteps--,p += eccsize) {
		chip->cmdfunc(mtd,-1);
		chip->ecc.hwctl(mtd,&ecc_calc[i]);

		stat = chip->ecc.correct(mtd,chip->oob_poi + mecc_pos[0] + ((chip->ecc.steps - eccsteps) * eccbytes),0);
		if (stat == -1)
			mtd->ecc_stats.failed++;

		col = eccsize * (chip->ecc.steps + 1 - eccsteps);
	}

	return 0;
}

/*
 * Hardware specific page read function for MLC.
 * Written by jsgood
 */
static int s3c_nand_read_page_4bit(struct mtd_info *mtd,eccsize = chip->ecc.size;
	int eccbytes = chip->ecc.bytes;
	int eccsteps = chip->ecc.steps;
	int col = 0;
	uint8_t *p = buf;
	uint32_t *mecc_pos = chip->ecc.layout->eccpos;

	/* Step1: read whole oob */
	col = mtd->writesize;
	chip->cmdfunc(mtd,-1);
	chip->read_buf(mtd,mtd->oobsize);

	col = 0;
	for (i = 0; eccsteps; eccsteps--,eccbytes);
		chip->ecc.calculate(mtd,0);
		stat = chip->ecc.correct(mtd,0);

		if (stat == -1)
			mtd->ecc_stats.failed++;

		col = eccsize * (chip->ecc.steps + 1 - eccsteps);
	}

	return 0;
}

/*
 * Hardware specific page write function for MLC.
 * Written by jsgood
 */
static void s3c_nand_write_page_4bit(struct mtd_info *mtd,eccsize = chip->ecc.size;
	int eccbytes = chip->ecc.bytes;
	int eccsteps = chip->ecc.steps;
	const uint8_t *p = buf;
	uint8_t *ecc_calc = chip->buffers->ecccalc;
	uint32_t *mecc_pos = chip->ecc.layout->eccpos;

	/* Step1: write main data and encode mecc */
	for (i = 0; eccsteps; eccsteps--,&ecc_calc[i]);
	}

	/* Step2: save encoded mecc */
	for (i = 0; i < chip->ecc.total; i++)
		chip->oob_poi[mecc_pos[i]] = ecc_calc[i];

	chip->write_buf(mtd,mtd->oobsize);
}
#endif

/*
 * Board-specific NAND initialization. The following members of the
 * argument are board-specific (per include/linux/mtd/nand.h):
 * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device
 * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device
 * - hwcontrol: hardwarespecific function for accesing control-lines
 * - dev_ready: hardwarespecific function for  accesing device ready/busy line
 * - enable_hwecc?: function to enable (reset)  hardware ecc generator. Must
 *   only be provided if a hardware ECC is available
 * - eccmode: mode of ecc,see defines
 * - chip_delay: chip dependent delay for transfering data from array to
 *   read regs (tR)
 * - options: various chip options. They can partly be set to inform
 *   nand_scan about special functionality. See the defines for further
 *   explanation
 * Members with a "?" were not set in the merged testing-NAND branch,* so they are not set here either.
 */
int board_nand_init(struct nand_chip *nand)
{	unsigned int  cur;
#if defined(CFG_NAND_HWECC)
	int i;
	u_char tmp;
	struct nand_flash_dev *type = NULL;
#endif
	/*Modified by lk*/
        cur = MP01CON_REG;
	cur = (0x3<<12)|(0x3<<8)|(cur&(~(0xff<<8)));
	
	MP01CON_REG = cur; 
	cur = MP03CON_REG;
	cur = (cur&(~(0xfff<<0)));
	cur = (cur&(~(0xf<<16)));
	cur |= (0x2<<16)|(0x2<<8)|(0x2<<4)|(0x2<<0);
	MP03CON_REG = cur; 
	
	NFCONF_REG |= (7<<12)|(7<<8)|(7<<4)|(2<<23)|(1<<1);//NFCONF_VAL;
	NFCONT_REG |= (3<<4)|(1<<0);//NFCONT_VAL;
	

	NFCONT_REG              &= ~((0x1<<16)|(0x1<<6)|(0x1<<7));
	/*Modified by lk*/	

	nand->IO_ADDR_R		= (void __iomem *)(NFDATA);
	nand->IO_ADDR_W		= (void __iomem *)(NFDATA);
	nand->cmd_ctrl		= s3c_nand_hwcontrol;
	nand->dev_ready		= s3c_nand_device_ready;
	nand->scan_bbt		= s3c_nand_scan_bbt;
	nand->options		= 0;

#if defined(CFG_NAND_FLASH_BBT)
		nand->options 		|= NAND_USE_FLASH_BBT;
#else
		nand->options		|= NAND_SKIP_BBTSCAN;
#endif

#if defined(CFG_NAND_HWECC)
	nand->ecc.mode		= NAND_ECC_HW;
	nand->ecc.hwctl		= s3c_nand_enable_hwecc;
	nand->ecc.calculate	= s3c_nand_calculate_ecc;
	nand->ecc.correct	= s3c_nand_correct_data;

	s3c_nand_hwcontrol(0,NAND_CMD_READID,NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
	s3c_nand_hwcontrol(0,0x00,NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE);
	s3c_nand_hwcontrol(0,NAND_NCE | NAND_ALE);
	s3c_nand_hwcontrol(0,NAND_CMD_NONE,NAND_NCE | NAND_CTRL_CHANGE);
	s3c_nand_device_ready(0);

	tmp = readb(nand->IO_ADDR_R); /* Maf. ID */
	tmp = readb(nand->IO_ADDR_R); /* Device ID */

	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
		if (tmp == nand_flash_ids[i].id) {
			type = &nand_flash_ids[i];
			break;
		}
	}
	printf("id = %xn",nand_flash_ids[i].id);

	nand->cellinfo = readb(nand->IO_ADDR_R);	/* 3rd byte */
	tmp = readb(nand->IO_ADDR_R);			/* 4th byte */

	if (!type->pagesize) {
		if (((nand->cellinfo >> 2) & 0x3) == 0) {
			nand_type = S3C_NAND_TYPE_SLC;
			nand->ecc.size = 512;
			nand->ecc.bytes	= 4;

			if ((1024 << (tmp & 0x3)) > 512) {
				nand->ecc.read_page = s3c_nand_read_page_1bit;
				nand->ecc.write_page = s3c_nand_write_page_1bit;
				nand->ecc.read_oob = s3c_nand_read_oob_1bit;
				nand->ecc.write_oob = s3c_nand_write_oob_1bit;
				nand->ecc.layout = &s3c_nand_oob_64;
				nand->ecc.hwctl = s3c_nand_enable_hwecc;
                                nand->ecc.calculate = s3c_nand_calculate_ecc;
                                nand->ecc.correct = s3c_nand_correct_data;
                                nand->options |= NAND_NO_SUBPAGE_WRITE;
			} else {
				nand->ecc.layout = &s3c_nand_oob_16;
			}
		} else {
			nand_type = S3C_NAND_TYPE_MLC;
			nand->options |= NAND_NO_SUBPAGE_WRITE;	/* NOP = 1 if MLC */
			nand->ecc.read_page = s3c_nand_read_page_4bit;
			nand->ecc.write_page = s3c_nand_write_page_4bit;
			nand->ecc.size = 512;
			nand->ecc.bytes = 8;	/* really 7 bytes */
			nand->ecc.layout = &s3c_nand_oob_mlc_64;
		}
	} else {
		nand_type = S3C_NAND_TYPE_SLC;
		nand->ecc.size = 512;
		nand->cellinfo = 0;
		nand->ecc.bytes = 4;
		nand->ecc.layout = &s3c_nand_oob_16;
	}
#else
	nand->ecc.mode = NAND_ECC_SOFT;
#endif
	return 0;
}
#endif /* (CONFIG_CMD_NAND) */

?
?
添加nand_cp.c
/*
 * $Id: nand_cp.c,v 1.1 2008/11/20 01:08:36 boyko Exp $
 *
 * (C) Copyright 2006 Samsung Electronics
 *
 * 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
 */

/*
 * You must make sure that all functions in this file are designed
 * to load only U-Boot image.
 *
 * So,DO NOT USE in common read.
 *
 * By scsuh.
 */


#include <common.h>

#ifdef CONFIG_S5PC11X
#include <asm/io.h>
#include <linux/mtd/nand.h>
#include <regs.h>

#define NAND_CONTROL_ENABLE()	(NFCONT_REG |= (1 << 0))

/*
 * address format
 *              17 16         9 8            0
 * --------------------------------------------
 * | block(12bit) | page(5bit) | offset(9bit) |
 * --------------------------------------------
 */

static int nandll_read_page (uchar *buf,ulong addr,int large_block)
{
        int i;
	int page_size = 512;

	if (large_block)
		page_size = 2048;

        NAND_ENABLE_CE();

        NFCMD_REG = NAND_CMD_READ0;

        /* Write Address */
        NFADDR_REG = 0;

	if (large_block)
	        NFADDR_REG = 0;

	NFADDR_REG = (addr) & 0xff;
	NFADDR_REG = (addr >> 8) & 0xff;
	NFADDR_REG = (addr >> 16) & 0xff;

	if (large_block)
		NFCMD_REG = NAND_CMD_READSTART;

        NF_TRANSRnB();

	/* for compatibility(2460). u32 cannot be used. by scsuh */
	for(i=0; i < page_size; i++) {
                *buf++ = NFDATA8_REG;
        }

        NAND_DISABLE_CE();
        return 0;
}

/*
 * Read data from NAND.
 */
static int nandll_read_blocks (ulong dst_addr,ulong size,int large_block)
{
        uchar *buf = (uchar *)dst_addr;
        int i;
	uint page_shift = 9;

	if (large_block)
		page_shift = 11;

        /* Read pages */
        for (i = 0; i < (size>>page_shift); i++,buf+=(1<<page_shift)) {
                nandll_read_page(buf,i,large_block);
        }

        return 0;
}

int copy_uboot_to_ram (void)
{
	int large_block = 0;
	int i;
	vu_char id;

	NAND_CONTROL_ENABLE();
        NAND_ENABLE_CE();
        NFCMD_REG = NAND_CMD_READID;
        NFADDR_REG =  0x00;

	/* wait for a while */
        for (i=0; i<200; i++);
	id = NFDATA8_REG;
	id = NFDATA8_REG;

	if (id > 0x80)
		large_block = 1;

	/* read NAND Block.
	 * 128KB ->240KB because of U-Boot size increase. by scsuh
	 * So,read 0x3c000 bytes not 0x20000(128KB).
	 */
	return nandll_read_blocks(CFG_PHY_UBOOT_BASE,COPY_BL2_SIZE,large_block);
}
 
#endif

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读