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

📄 nand_boot_jz4740.c

📁 mips cpu 君正4730 4740的 ucosii 源码 包括系统 摄像头 网络 文件系统等等测试
💻 C
字号:
/* * Copyright (C) 2007 Ingenic Semiconductor Inc. * Author: Peter <jlwei@ingenic.cn> * * 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 <nand.h>#include <pavo.h>#include <jz4740.h>#define uchar u8/* * NAND flash definitions */#define NAND_DATAPORT	0xb8000000#define NAND_ADDRPORT	0xb8010000#define NAND_COMMPORT	0xb8008000#define ECC_BLOCK	512#define ECC_POS		6#define PAR_SIZE	9#define __nand_enable()		(REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)#define __nand_disable()	(REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))#define __nand_ecc_rs_encoding() \	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)#define __nand_ecc_rs_decoding() \	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)#define __nand_ecc_disable()	(REG_EMC_NFECR &= ~EMC_NFECR_ECCE)#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))static inline void __nand_dev_ready(void){	unsigned int timeout = 10000;	while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);	while (!(REG_GPIO_PXPIN(2) & 0x40000000));}#define __nand_cmd(n)		(REG8(NAND_COMMPORT) = (n))#define __nand_addr(n)		(REG8(NAND_ADDRPORT) = (n))#define __nand_data8()		REG8(NAND_DATAPORT)#define __nand_data16()		REG16(NAND_DATAPORT)/* * NAND flash parameters */static int bus_width = 8;static int page_size = 2048;static int oob_size = 64;static int ecc_count = 4;static int row_cycle = 3;static int page_per_block = NAND_PAGE_PER_BLOCK;static int bad_block_pos = 0;static int block_size = NAND_BLOCK_SIZE;//131072;static unsigned char oob_buf[128] = {0};/* * External routines */extern void flush_cache_all(void);extern int serial_init(void);extern void serial_puts(const char *s);extern void sdram_init(void);extern void pll_init(void);/* * NAND flash routines */static inline void nand_read_buf16(void *buf, int count){	int i;	u16 *p = (u16 *)buf;	for (i = 0; i < count; i += 2)		*p++ = __nand_data16();}static inline void nand_read_buf8(void *buf, int count){	int i;	u8 *p = (u8 *)buf;	u8 d;	for (i = 0; i < count; i++)		*p++ =  __nand_data8();			}static inline void nand_read_buf(void *buf, int count, int bw){		if (bw == 8)		nand_read_buf8(buf, count);	else		nand_read_buf16(buf, count);}static void rs_correct(unsigned char *buf, int idx, int mask){	int i, j;	unsigned short d, d1, dm;	i = (idx * 9) >> 3;	j = (idx * 9) & 0x7;	i = (j == 0) ? (i - 1) : i;	j = (j == 0) ? 7 : (j - 1);	d = (buf[i] << 8) | buf[i - 1];	d1 = (d >> j) & 0x1ff;	d1 ^= mask;	dm = ~(0x1ff << j);	d = (d & dm) | (d1 << j);	buf[i - 1] = d & 0xff;	buf[i] = (d >> 8) & 0xff;}static int nand_read_oob(int page_addr, uchar *buf, int size){	int col_addr;	if (page_size == 2048)		col_addr = 2048;	else		col_addr = 0;	if (page_size == 2048)		/* Send READ0 command */		__nand_cmd(NAND_CMD_READ0);	else		/* Send READOOB command */		__nand_cmd(NAND_CMD_READOOB);	/* Send column address */	__nand_addr(col_addr & 0xff);	if (page_size == 2048)		__nand_addr((col_addr >> 8) & 0xff);	/* Send page address */	__nand_addr(page_addr & 0xff);	__nand_addr((page_addr >> 8) & 0xff);	if (row_cycle == 3)		__nand_addr((page_addr >> 16) & 0xff);	/* Send READSTART command for 2048 ps NAND */	if (page_size == 2048)		__nand_cmd(NAND_CMD_READSTART);	/* Wait for device ready */	__nand_dev_ready();	/* Read oob data */	nand_read_buf(buf, size, bus_width);	return 0;}static int nand_read_page(int block, int page, uchar *dst, uchar *oobbuf){	int page_addr = page + block * page_per_block;	uchar *databuf = dst, *tmpbuf;	int i, j;	/*	 * Read oob data	 */	nand_read_oob(page_addr, oobbuf, oob_size);	/*	 * Read page data	 */	/* Send READ0 command */	__nand_cmd(NAND_CMD_READ0);	/* Send column address */	__nand_addr(0);	if (page_size == 2048)		__nand_addr(0);	/* Send page address */	__nand_addr(page_addr & 0xff);	__nand_addr((page_addr >> 8) & 0xff);	if (row_cycle == 3)		__nand_addr((page_addr >> 16) & 0xff);	/* Send READSTART command for 2048 ps NAND */	if (page_size == 2048)		__nand_cmd(NAND_CMD_READSTART);	/* Wait for device ready */	//serial_puts("1\r\n");	__nand_dev_ready();	/* Read page data */	tmpbuf = databuf;	for (i = 0; i < ecc_count; i++) {		volatile unsigned char *paraddr = (volatile unsigned char *)EMC_NFPAR0;		unsigned int stat;	       		/* Enable RS decoding */		REG_EMC_NFINTS = 0x0;		__nand_ecc_rs_decoding();		/* Read data */		nand_read_buf((void *)tmpbuf, ECC_BLOCK, bus_width);		/* Set PAR values */		for (j = 0; j < PAR_SIZE; j++) {			*paraddr++ = oobbuf[ECC_POS + i*PAR_SIZE + j];		}		/* Set PRDY */ 		REG_EMC_NFECR |= EMC_NFECR_PRDY;		               /* Wait for completion */				__nand_ecc_decode_sync();				/* Disable decoding */		__nand_ecc_disable();		/* Check result of decoding */		stat = REG_EMC_NFINTS;		if (stat & EMC_NFINTS_ERR) {			/* Error occurred */			if (stat & EMC_NFINTS_UNCOR) {				/* Uncorrectable error occurred */			}			else {				unsigned int errcnt, index, mask;				errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;				switch (errcnt) {				case 4:					index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;					mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;					rs_correct(databuf, index, mask);				case 3:					index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;					mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;					rs_correct(databuf, index, mask);				case 2:					index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;					mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;					rs_correct(databuf, index, mask);				case 1:					index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;					mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;					rs_correct(databuf, index, mask);					break;				default:					break;				}			}		}		tmpbuf += ECC_BLOCK;	}	return 0;}static int nand_load(int offs, int uboot_size, uchar *dst){	int block;	int blockcopy_count;	int page;	__nand_enable();       	/*	 * offs has to be aligned to a block address!	 */	block = offs / block_size;	blockcopy_count = 0;		while (blockcopy_count < (uboot_size / block_size)) {		for (page = 0; page < page_per_block; page++) {						nand_read_page(block, page, dst, oob_buf);						if (page == 0) {				if (oob_buf[bad_block_pos] != 0xff) {					block++;					/*					 * Skip bad block					 */					continue;				}			}			dst += page_size;		}		block++;		blockcopy_count++;	}	__nand_disable();	return 0;}static void gpio_init(void){	/*	 * Initialize SDRAM pins	 */	__gpio_as_sdram_32bit();	/*	 * Initialize UART0 pins	 */	__gpio_as_uart0();}void nand_boot(void){	int boot_sel, ret;	void (*uboot)(void);    unsigned int c;  	/*	 * Init hardware	 */	gpio_init();	serial_init();	serial_puts("\n\nNAND Secondary Program Loader\n\n");	pll_init();	sdram_init();	#if 0	for(ret = 0;ret < 16 * 1024 * 1024 ;ret++)	{		//serial_puts_hex(ret);		//serial_puts("\n");	    		*(volatile unsigned int *)(0xa0000000 + (ret* 4)) = 0xaaaaaaaa;		c = *(volatile unsigned int *)(0xa0000000 + (ret* 4));        if(c != 0xaaaaaaaa)		{			serial_puts("aa error data:");			serial_puts_hex((unsigned int)c);			serial_puts("\n");		}		*(volatile unsigned int *)(0xa0000000 + (ret*4)) = 0x55555555;		c = *(volatile unsigned int *)(0xa0000000 + (ret*4));        if(c != 0x55555555)		{			serial_puts("55 error data:");			serial_puts_hex((unsigned int)c);			serial_puts("\n");		}					}	#endif	#if 0	for(ret = 0;ret < 16 * 1024 * 1024 ;ret++)		*(volatile unsigned int *)(0xa0000000 + (ret* 4)) = ret;	for(ret = 0;ret < 16 * 1024 * 1024 ;ret++)	{		c = *(volatile unsigned int *)(0xa0000000 + (ret*4));        if(c != ret)		{			serial_puts_hex(ret);			serial_puts(" error data: ");			serial_puts_hex((unsigned int)c);			serial_puts("\n");			//while(1);  		}	}	#endif			#if 0	serial_puts("\n\nWrite Ram 0x00555555");    *(volatile unsigned int *)(0xa0555555) = 0xaaaaaaaa;	serial_puts("\n\nWrite Ram 0x00aaaaaa");	*(volatile unsigned int *)(0xa0aaaaaa) = 0x55555555;    serial_puts("\n\nRead Ram 0x00555555");	ret = *(volatile unsigned int *)(0xa0555555);    serial_puts_hex(ret);	serial_puts("\n\nRead Ram 0x00aaaaaa");	ret = *(volatile unsigned int *)(0xa0aaaaaa);    serial_puts_hex(ret);	#endif		/*	 * Decode boot select	 */	boot_sel = REG_EMC_BCR >> 30;	if (boot_sel == 0x2)		page_size = 512;	else		page_size = 2048;#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R3)	bus_width = 8;	row_cycle = 3;#endif#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R2)	bus_width = 8;	row_cycle = 2;#endif#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R3)	bus_width = 16;	row_cycle = 3;#endif#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R2)	bus_width = 16;	row_cycle = 2;#endif	page_per_block = (page_size == 2048) ? 64 : 32;	bad_block_pos = (page_size == 2048) ? 0 : 5;	oob_size = page_size / 32;	block_size = page_size * page_per_block;	ecc_count = page_size / ECC_BLOCK;	/*	 * Load U-Boot image from NAND into RAM	 */        serial_puts("\n\nLoad UCOS image from NAND into RAM\n\n"); 		ret = nand_load(CFG_NAND_UCOS_OFFS, CFG_NAND_UCOS_SIZE,			(uchar *)CFG_NAND_UCOS_DST);	uboot = (void (*)(void))CFG_NAND_UCOS_START;	serial_puts("Starting UCOS ...\n");	/*	 * Flush caches	 */	jz_flush_dcache();	jz_flush_icache();	/*	 * Jump to U-Boot image	 */	(*uboot)();}void serial_puts_hex(unsigned int d){	unsigned char c[12];	char i;	for(i = 0; i < 8;i++)	{		c[i] = (d >> ((7 - i) * 4)) & 0xf;		if(c[i] < 10)			c[i] += 0x30;		else			c[i] += (0x41 - 10);	}	c[8] = '\n';	c[9] = 0;	serial_puts(c);}

⌨️ 快捷键说明

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