⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c64xx.c

📁 uboot200903最新版本的通用uboot
💻 C
字号:
/* * (C) Copyright 2006 DENX Software Engineering * * Implementation for U-Boot 1.1.6 by Samsung * * (C) Copyright 2008 * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> * * 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 <nand.h>#include <s3c6400.h>#include <asm/io.h>#include <asm/errno.h>#define MAX_CHIPS	2static int nand_cs[MAX_CHIPS] = {0, 1};#ifdef CONFIG_NAND_SPL#define printf(arg...) do {} while (0)#endif/* Nand flash definition values by jsgood */#ifdef 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;	printf("%s:\t", header);	for (i = 0; i < 64; i++)		printf("%02x ", chip->oob_poi[i]);	printf("\n");}#endif /* S3C_NAND_DEBUG */#ifdef CONFIG_NAND_SPLstatic u_char nand_read_byte(struct mtd_info *mtd){	struct nand_chip *this = mtd->priv;	return readb(this->IO_ADDR_R);}static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	for (i = 0; i < len; i++)		writeb(buf[i], this->IO_ADDR_W);}static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len){	int i;	struct nand_chip *this = mtd->priv;	for (i = 0; i < len; i++)		buf[i] = readb(this->IO_ADDR_R);}#endifstatic void s3c_nand_select_chip(struct mtd_info *mtd, int chip){	int ctrl = readl(NFCONT);	switch (chip) {	case -1:		ctrl |= 6;		break;	case 0:		ctrl &= ~2;		break;	case 1:		ctrl &= ~4;		break;	default:		return;	}	writel(ctrl, NFCONT);}/* * Hardware specific access to control-lines function * Written by jsgood */static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl){	struct nand_chip *this = mtd->priv;	if (ctrl & NAND_CTRL_CHANGE) {		if (ctrl & NAND_CLE)			this->IO_ADDR_W = (void __iomem *)NFCMMD;		else if (ctrl & NAND_ALE)			this->IO_ADDR_W = (void __iomem *)NFADDR;		else			this->IO_ADDR_W = (void __iomem *)NFDATA;		if (ctrl & NAND_NCE)			s3c_nand_select_chip(mtd, *(int *)this->priv);		else			s3c_nand_select_chip(mtd, -1);	}	if (cmd != NAND_CMD_NONE)		writeb(cmd, this->IO_ADDR_W);}/* * Function for checking device ready pin * Written by jsgood */static int s3c_nand_device_ready(struct mtd_info *mtdinfo){	return !!(readl(NFSTAT) & NFSTAT_RnB);}#ifdef CONFIG_SYS_S3C_NAND_HWECC/* * 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;	/*	 * The original driver used 4-bit ECC for "new" MLC chips, i.e., for	 * those with non-zero ID[3][3:2], which anyway only holds for ST	 * (Numonyx) chips	 */	nfconf = readl(NFCONF) & ~NFCONF_ECC_4BIT;	writel(nfconf, NFCONF);	/* Initialize & unlock */	nfcont = readl(NFCONT);	nfcont |= NFCONT_INITECC;	nfcont &= ~NFCONT_MECCLOCK;	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;	/* Lock */	nfcont = readl(NFCONT);	nfcont |= NFCONT_MECCLOCK;	writel(nfcont, NFCONT);	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;	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, nfmeccdata0, nfmeccdata1, err_byte_addr;	u_char err_type, repaired;	/* SLC: Write ecc to compare */	nfmeccdata0 = (calc_ecc[1] << 16) | calc_ecc[0];	nfmeccdata1 = (calc_ecc[3] << 16) | calc_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		 */		err_byte_addr = (nfestat0 >> 7) & 0x7ff;		repaired = dat[err_byte_addr] ^ (1 << ((nfestat0 >> 4) & 0x7));		printf("S3C NAND: 1 bit error detected at byte %ld. "		       "Correcting from 0x%02x to 0x%02x...OK\n",		       err_byte_addr, dat[err_byte_addr], repaired);		dat[err_byte_addr] = repaired;		ret = 1;		break;	case 2: /* Multiple error */	case 3: /* ECC area error */		printf("S3C NAND: ECC uncorrectable error detected. "		       "Not correctable.\n");		ret = -1;		break;	}	return ret;}#endif /* CONFIG_SYS_S3C_NAND_HWECC *//* * 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){	static int chip_n;	if (chip_n >= MAX_CHIPS)		return -ENODEV;	NFCONT_REG = (NFCONT_REG & ~NFCONT_WP) | NFCONT_ENABLE | 0x6;	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->select_chip	= s3c_nand_select_chip;	nand->options		= 0;#ifdef CONFIG_NAND_SPL	nand->read_byte		= nand_read_byte;	nand->write_buf		= nand_write_buf;	nand->read_buf		= nand_read_buf;#endif#ifdef CONFIG_SYS_S3C_NAND_HWECC	nand->ecc.hwctl		= s3c_nand_enable_hwecc;	nand->ecc.calculate	= s3c_nand_calculate_ecc;	nand->ecc.correct	= s3c_nand_correct_data;	/*	 * If you get more than 1 NAND-chip with different page-sizes on the	 * board one day, it will get more complicated...	 */	nand->ecc.mode		= NAND_ECC_HW;	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;#else	nand->ecc.mode		= NAND_ECC_SOFT;#endif /* ! CONFIG_SYS_S3C_NAND_HWECC */	nand->priv		= nand_cs + chip_n++;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -