Exemplo n.º 1
0
static int nand_read_buffer(struct nfc_config *conf, uint32_t offs,
			    unsigned int size, void *dest)
{
	int first_seed, page, ret;

	size = ALIGN(size, conf->page_size);
	page = offs / conf->page_size;
	first_seed = page % conf->nseeds;

	for (; size; size -= conf->page_size) {
		if (nand_load_page(conf, offs))
			return -1;

		ret = nand_read_page(conf, offs, dest, conf->page_size);
		/*
		 * The ->nseeds value should be equal to the number of pages
		 * in an eraseblock. Since we don't know this information in
		 * advance we might have picked a wrong value.
		 */
		if (ret < 0 && conf->randomize) {
			int cur_seed = page % conf->nseeds;

			/*
			 * We already tried all the seed values => we are
			 * facing a real corruption.
			 */
			if (cur_seed < first_seed)
				return -EIO;

			/* Try to adjust ->nseeds and read the page again... */
			conf->nseeds = cur_seed;

			if (nand_reset_column())
				return -EIO;

			/* ... it still fails => it's a real corruption. */
			if (nand_read_page(conf, offs, dest, conf->page_size))
				return -EIO;
		} else if (ret && conf->randomize) {
			memset(dest, 0xff, conf->page_size);
		}

		page++;
		offs += conf->page_size;
		dest += conf->page_size;
	}

	return 0;
}
Exemplo n.º 2
0
void copy_nand2sdram()
{
	unsigned long bootSize = (unsigned long)(&bss_start) - 0x30000000;		//uboot代码长度
	unsigned long blockTotal,pageTotal;

	
	blockTotal = 	(
						(bootSize + NAND_BLOCK_MASK ) & (~NAND_BLOCK_MASK)
					) 	/ NAND_BLOCK_SIZE;
	pageTotal  = 	(
						(bootSize + NAND_PAGE_MASK ) & (~NAND_PAGE_MASK)
					)	/ NAND_PAGE_SIZE;
	


	//烧录进FLASH,不带坏块检测
	unsigned char *lpdstData = (unsigned char *)0x30000000;	//SDRAM 0x30000000地址的代码
	unsigned int off_data,page_addr;
	int pcPoint;

	//查看PC指针位置,如果指针在0~4096表示在SRAM中运行,拷贝Nand到SDRAM
	//否则表示代码在SDRAM中,跳过Nand拷贝
	pcPoint = _where_lr();
	if(pcPoint < 4096) {
		nand_init();
		off_data = 0;
		page_addr = 0;
		while(off_data < bootSize) 
		{
			nand_read_page(
						page_addr,
						(unsigned char*)(lpdstData + off_data));

			// printk("colum 0x%8.8x write data off %d page_addr %d\r\n",off_data,off_data,page_addr);
			// PrintNandFlash((unsigned char*)(lpsrcData + off_data),16);
			off_data  += NAND_PAGE_SIZE;
			page_addr += NAND_PAGE_ADDR;
		}
	}

}
static int nand_load(unsigned int offs, unsigned int uboot_size, uchar *dst)
{
	unsigned int block, lastblock, page;

	/* offs has to be aligned to a page address! */
	block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
	lastblock = (offs + uboot_size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
	page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;

	while (block <= lastblock) {
		while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
			nand_read_page(block, page, dst);
			dst += CONFIG_SYS_NAND_PAGE_SIZE;
			page++;
		}
		page = 0;
		block++;
	}

	return;
}
Exemplo n.º 4
0
/* read a block data to buf
 * return 1 if the block is bad or ECC error can't be corrected for any page
 * return 0 on sucess
 */ 
int nand_read_block(unsigned char *buf, ulong block_addr)
{
	int i, offset = 0;
	uchar oob_buf[16];
 	
	/* check bad block */
	/* 0th and 5th words need be 0xffff */
	if (nand_read_oob(oob_buf, block_addr) ||
//		oob_buf[0] != 0xff || oob_buf[1] != 0xff ||
//		oob_buf[10] != 0xff || oob_buf[11] != 0xff ){
		oob_buf[5] != 0xff){
		printf("Skipped bad block at 0x%x\n", block_addr);
 		return NAND_READ_SKIPPED_BAD_BLOCK;    /* skip bad block */
	}

	/* read the block page by page*/
	for (i=0; i<32; i++){
		if (nand_read_page(buf+offset, block_addr + offset))
			return NAND_READ_ECC_FAILURE;
		offset += PAGE_SIZE;
	}

	return NAND_READ_SUCCESS;
}
Exemplo n.º 5
0
void nand_spl_init(void)
{
    ulong  buffer[6];
    u8    page_buf[CONFIG_NAND_PAGE_SIZE];
    ulong ddr_magic=0x88888888;
    ulong erase_addr1=0, erase_addr2=0;
    ulong  ecc;
    int i;

    erase_addr1 = IFX_CFG_FLASH_DDR_CFG_START_ADDR;
    erase_addr2 = IFX_CFG_FLASH_DDR_CFG_START_ADDR + IFX_CFG_FLASH_DDR_CFG_SIZE;

    serial_init();

    buffer[0] = 0;

    asm("sync");
    nand_read_page((131072/CONFIG_NAND_PAGE_SIZE)-1,page_buf);
    asm("sync");

    for(i=0; i<6; i++) {
        buffer[i] = *(volatile u32*)(page_buf+CONFIG_NAND_PAGE_SIZE-24+i*4); /*last 24 bytes of 16k bytes*/
    }
    if(buffer[0]==ddr_magic)
    {
        ecc=buffer[1]^buffer[2]^buffer[3]^buffer[4];
        if(ecc!=buffer[5]) {
            REG32(0xBe1a7f20)=0xff;
        } else {
            REG32(0xBe1a7f20)=0;
        }
    }
    else {
        REG32(0xBe1a7f20)=0xff;
    }

    /* Clear Error log registers */
    REG32(MC_ERRCAUSE)= 0;
    REG32(MC_ERRADDR) = 0;
    asm("sync");
    /* Enable DDR module in memory controller */
    REG32(MC_CON)= REG32(MC_CON)|MC_DDRRAM_ENABLE;
    asm("sync");
    if(REG32(0xBe1a7f20)==0xff) {
        REG32(MC_DC21)= 0;
        REG32(MC_DC22)=0;
    } else {
        REG32(MC_DC15)= buffer[1];
        REG32(MC_DC21)= buffer[2];
        REG32(MC_DC22)= buffer[3];
        REG32(MC_DC24)= buffer[4];
    }
    asm("sync");
    REG32(MC_DC03) = 0x00000100;
    while((REG32(0xbf800070)& 0x08)!=0x08);

    asm("sync");
    tune_ddr();

    asm("sync");
    nand_boot();

}
Exemplo n.º 6
0
static int nand_detect_ecc_config(struct nfc_config *conf, u32 offs,
				  void *dest)
{
	/* NAND with pages > 4k will likely require 1k sector size. */
	int min_ecc_size = conf->page_size > 4096 ? 1024 : 512;
	int page = offs / conf->page_size;
	int ret;

	/*
	 * In most cases, 1k sectors are preferred over 512b ones, start
	 * testing this config first.
	 */
	for (conf->ecc_size = 1024; conf->ecc_size >= min_ecc_size;
	     conf->ecc_size >>= 1) {
		int max_ecc_strength = nand_max_ecc_strength(conf);

		nand_apply_config(conf);

		/*
		 * We are starting from the maximum ECC strength because
		 * most of the time NAND vendors provide an OOB area that
		 * barely meets the ECC requirements.
		 */
		for (conf->ecc_strength = max_ecc_strength;
		     conf->ecc_strength >= 0;
		     conf->ecc_strength--) {
			conf->randomize = false;
			if (nand_reset_column())
				return -EIO;

			/*
			 * Only read the first sector to speedup detection.
			 */
			ret = nand_read_page(conf, offs, dest, conf->ecc_size);
			if (!ret) {
				return 0;
			} else if (ret > 0) {
				/*
				 * If page is empty we can't deduce anything
				 * about the ECC config => stop the detection.
				 */
				return -EINVAL;
			}

			conf->randomize = true;
			conf->nseeds = ARRAY_SIZE(random_seed);
			do {
				if (nand_reset_column())
					return -EIO;

				if (!nand_read_page(conf, offs, dest,
						    conf->ecc_size))
					return 0;

				/*
				 * Find the next ->nseeds value that would
				 * change the randomizer seed for the page
				 * we're trying to read.
				 */
				while (conf->nseeds >= 16) {
					int seed = page % conf->nseeds;

					conf->nseeds >>= 1;
					if (seed != page % conf->nseeds)
						break;
				}
			} while (conf->nseeds >= 16);
		}
	}

	return -EINVAL;
}