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

📄 nandboot.c

📁 dm6437的NAND Secondary Boot
💻 C
📖 第 1 页 / 共 2 页
字号:
	row_addr = (block << (gNandInfo.blkShift - gNandInfo.pageShift)) | page;
	flash_write_addr_bytes( gNandInfo.numRowAddrBytes, row_addr );
}

static Uint32 flash_read_data()
{
	volatile FLASHPtr addr;
	FLASHData cmdword;
	cmdword.l = 0x0;

	addr.cp = flash_make_addr (gNandInfo.flashBase, NAND_DATA_OFFSET );
	switch (gNandInfo.busWidth)
	{
	    case BUS_8BIT:
            cmdword.c = *addr.cp;
            break;
        case BUS_16BIT:
            cmdword.w = *addr.wp;
            break;
	}
	return cmdword.l;
}

static void flash_read_bytes(void* pDest, Uint32 numBytes)
{
    volatile FLASHPtr destAddr, srcAddr;
	Uint32 i;
	
	destAddr.cp = (VUint8*) pDest;
	srcAddr.cp = flash_make_addr (gNandInfo.flashBase, NAND_DATA_OFFSET );
	switch (gNandInfo.busWidth)
	{
    case BUS_8BIT:
        for(i=0;i<( numBytes );i++)
	        *destAddr.cp++ = *srcAddr.cp;
        break;
    case BUS_16BIT:
        for(i=0;i<( numBytes >> 1);i++)
	        *destAddr.wp++ = *srcAddr.wp;
        break;
    }
}

static void flash_swap_data(Uint32* data)
{
    Uint32 i,temp = *data;
    volatile FLASHPtr  dataAddr, tempAddr;
    
    dataAddr.cp = flash_make_addr((Uint32) data, 3);
    tempAddr.cp = flash_make_addr((Uint32) &temp,0);
        
    switch (gNandInfo.busWidth)
	{
    case BUS_8BIT:
        for(i=0; i<4; i++)
	        *dataAddr.cp-- = *tempAddr.cp++;
        break;
    case BUS_16BIT:
        for(i=0; i<2; i++)
	        *dataAddr.wp-- = *tempAddr.wp++;
        break;
    }
}

// Basic NAND init
static Uint32 NAND_Init()
{
    Uint32 width, *CSRegs;

    // Set NAND flash base address
    gNandInfo.flashBase = (Uint32)(NAND_DATA_ADDR);
    
    //Get the CSOffset (can be 0 through 3 - corresponds with CS2 through CS5)
    gNandInfo.CSOffset = ( (gNandInfo.flashBase & (0x0FFFFFFF)) >> 25) - 1;
    
    // Setting the nand_width = 0(8 bit NAND) or 1(16 bit NAND). AEMIF CS2 bus Width
	//   is fixed in the DM6437 to be 8-bit.
	width = ((SYSTEM->BOOTCFG)&(SYS_BOOTCFG_8_16_MASK))>>16;
    gNandInfo.busWidth = (width)?BUS_16BIT:BUS_8BIT;

    // Setup AEMIF registers for NAND
    CSRegs = (Uint32*) &(NAND_AB1CR);
    CSRegs[gNandInfo.CSOffset] = 0x3FFFFFFC | width;        // Set correct ABxCR reg
    NAND_NANDFCR |= (0x1 << (gNandInfo.CSOffset));        // NAND enable for CSx
    NAND_ECCReadAndRestart();
                         
	// Send reset command to NAND
	NAND_clearEIRR();
	flash_write_cmd( NAND_RESET );

	if ( NAND_WaitForRdy() != BOOT_SUCCESS )
        return BOOT_FAIL;
		
	return NAND_GetDetails();
}

// Detailed NAND device discovery
// Get details of the NAND flash used from the id and the table of NAND devices
static Uint32 NAND_GetDetails()
{
	Uint32 manfID,deviceID,i,j;
	
	// Issue device read ID command
    flash_write_cmd( NAND_RDID);
    flash_write_addr( NAND_RDIDADD);
    
	// Read ID bytes
	manfID   = flash_read_data( ) & 0xFF;
	deviceID = flash_read_data( ) & 0xFF;
	j        = flash_read_data( ) & 0xFF;
	j        = flash_read_data( ) & 0xFF;

	i=0;

	while (gNandDevInfo[i].devID != 0x00)
	{
		if(deviceID == gNandDevInfo[i].devID)
		{
		    gNandInfo.manfID            = (Uint8) manfID;
			gNandInfo.devID             = (Uint8) gNandDevInfo[i].devID;
			gNandInfo.pagesPerBlock     = gNandDevInfo[i].pagesPerBlock;
			gNandInfo.numBlocks         = gNandDevInfo[i].numBlocks;
			gNandInfo.bytesPerPage      = NANDFLASH_PAGESIZE(gNandDevInfo[i].bytesPerPage);
			break;
		}

		i++;
	}

    gNandInfo.manfID            = (Uint8) manfID;
	gNandInfo.devID             = (Uint8) gNandDevInfo[i].devID;
	gNandInfo.pagesPerBlock     = gNandDevInfo[i].pagesPerBlock;
	gNandInfo.numBlocks         = gNandDevInfo[i].numBlocks;
	gNandInfo.bytesPerPage      = NANDFLASH_PAGESIZE(gNandDevInfo[i].bytesPerPage);

	// Device not supported
    if(gNandDevInfo[i].devID == 0x00)
		return BOOT_FAIL;
			
	// Assign the big_block flag
	gNandInfo.bigBlock = (gNandInfo.bytesPerPage>MAX_BYTES_PER_OP)?TRUE:FALSE;
	
	// Assign the bytes per operation value
	gNandInfo.bytesPerOp = (gNandInfo.bytesPerPage>MAX_BYTES_PER_OP)?MAX_BYTES_PER_OP:gNandInfo.bytesPerPage;
	
	// Assign the number of operations per page value
	gNandInfo.numOpsPerPage = (gNandInfo.bytesPerOp < MAX_BYTES_PER_OP)?1:(gNandInfo.bytesPerPage >> MAX_BYTES_PER_OP_SHIFT);
	
	// Assign the number of spare bytes per operation
	gNandInfo.spareBytesPerOp = gNandInfo.bytesPerOp >> SPAREBYTES_PER_OP_SHIFT;
	
	// Setup address shift values	
	j = 0;
	while( (gNandInfo.pagesPerBlock >> j) > 1)
	{
		j++;
	}
	gNandInfo.blkShift = j;        
	gNandInfo.pageShift = (gNandInfo.bigBlock)?16:8;
	gNandInfo.blkShift += gNandInfo.pageShift;
	
	// Set number of column address bytes needed
	gNandInfo.numColAddrBytes = gNandInfo.pageShift >> 3;
	
	j = 0;
	while( (gNandInfo.numBlocks >> j) > 1)
	{
		j++;
	}
				
	// Set number of row address bytes needed
	if ( (gNandInfo.blkShift + j) <= 24 )
	{
	    gNandInfo.numRowAddrBytes = 3 - gNandInfo.numColAddrBytes;
	}
	else if ((gNandInfo.blkShift + j) <= 32)
	{
	    gNandInfo.numRowAddrBytes = 4 - gNandInfo.numColAddrBytes;
	}
	else
	{
	    gNandInfo.numRowAddrBytes = 5 - gNandInfo.numColAddrBytes;
	}
	
	// Set the ECC bit mask
	gNandInfo.ECCMask = 0x00000000;
	for (j = 0; (((gNandInfo.bytesPerOp*8)>>j) > 0x1); j++)
	{
	    gNandInfo.ECCMask |= (0x00010001<<j);
	}
	
	gNandInfo.ECCOffset = (gNandInfo.bigBlock)?2:0;
				    		
	return BOOT_SUCCESS;
}

static Uint32 NAND_ECCReadAndRestart ()
{
    VUint32 retval,temp;
    
	// Dummy read of CS3 memory region (used to flush CS2 writes)
	temp = *((VUint32*)(((VUint8*)gNandInfo.flashBase) + 0x02000000));

    // Read and mask appropriate (based on CSn space flash is in) ECC regsiter
    retval = ((VUint32*)(&(NAND_NANDF1ECC)))[gNandInfo.CSOffset] & gNandInfo.ECCMask;
    
    // Write appropriate bit to start ECC calcualtions 
    NAND_NANDFCR |= (1<<(8 + (gNandInfo.CSOffset)));
    
	// Dummy read on CFG bus to guarantee ECC bit is set before we do anything else
	temp = NAND_ERCSR;
    
    return retval;
}

// NAND_ECCCorrection - correct single bit errors
static Uint32 NAND_ECCCorrection(Uint32 ECCold, Uint32 ECCnew, Uint8 *data)
{
	Uint16 ECCxorVal, byteAddr, bitAddr;

	ECCxorVal = (Uint16) ((ECCold & 0xFFFF0000) >> 16) ^  // write ECCo
	                     ((ECCold & 0x0000FFFF) >> 0 ) ^  // write ECCe
				         ((ECCnew & 0xFFFF0000) >> 16) ^  // read ECCo 
				         ((ECCnew & 0x0000FFFF) >> 0 );   // read ECCe

	if ( ECCxorVal == (0x0000FFFF & gNandInfo.ECCMask) )
	{
		// Single Bit error - can be corrected
        ECCxorVal = (Uint16) ((ECCold & 0xFFFF0000) >> 16) ^ ((ECCnew & 0xFFFF0000) >> 16);
        byteAddr = (ECCxorVal >> 3);
        bitAddr = (ECCxorVal & 0x7);
        data[byteAddr] ^= (0x1 << bitAddr);
        return BOOT_SUCCESS;
	}
	else
	{
        // Multiple Bit error - nothing we can do
        return BOOT_FAIL;
	}
}

// NAND_ReadPage
static Uint32 NAND_ReadPage(Uint32 block, Uint32 page, Uint8 *dest) {
	Uint32 eccValue[MAX_NUM_ECCS];
    Uint32 spareValue[MAX_SPARE_BYTES_PER_OP];
	Uint8 i;
	
    // Write read command
    flash_write_cmd( NAND_LO_PAGE );
	
	// Write address bytes
	flash_write_addr_cycles( block, page );

    // Additional confirm command for big_block devices
	if(gNandInfo.bigBlock) flash_write_cmd( NAND_READ_30H );

	// Wait for data to be available
	if(NAND_WaitForRdy() != BOOT_SUCCESS)
		return BOOT_FAIL;

	// Starting the ECC in the NANDFCR register for CS2(bit no.8)
	NAND_ECCReadAndRestart();

    // Read the page data
    for (i=0; i < gNandInfo.numOpsPerPage; i++)
    {
        // Actually read bytes
		flash_read_bytes( (void*)(dest), gNandInfo.bytesPerOp );
	    // Get the ECC Value
	    eccValue[i] = NAND_ECCReadAndRestart();    
	    //Increment pointer
	    dest += gNandInfo.bytesPerOp;
	}

	// Reset page pointer
	dest -= gNandInfo.bytesPerPage;
	
	// Read spare are to see if this is Bad Block
	    for (i=0; i<gNandInfo.numOpsPerPage; i++)
		{
	        flash_read_bytes( (void*)(spareValue), gNandInfo.spareBytesPerOp );
	        flash_swap_data( (Uint32*)(spareValue+gNandInfo.ECCOffset) );
		    // Check for BAD Block Indicator
		    if (spareValue[BAD_BLOCK_FLAG_OFFSET] == BAD_BLOCK_FLAG) {
			    return BOOT_FAIL;
		    }
		    // Verify ECC value
			if(eccValue[i] != spareValue[gNandInfo.ECCOffset])
			{
			    if (NAND_ECCCorrection(spareValue[gNandInfo.ECCOffset],
				                       eccValue[i],
	                                   dest + (i*gNandInfo.bytesPerOp) ) != BOOT_SUCCESS)
				{
	                return BOOT_FAIL;
				}
	        }
	    }
    // Return status check result
	return NAND_WaitForStatus();
}

/* Wait for the status to be ready 
Polling for the pad_wait_i(bit 0) of NANDFSR */
static Uint32 NAND_WaitForRdy() {
    Uint32 status;
	VUint32 cnt = NAND_BOOT_TIMEOUT;

//	waitloop(1000);
  	status = (NAND_NANDEIRR & NANDEIRR_RB_READY) == NANDEIRR_RB_READY;
	while((!(status)) && (cnt > 0)){
  	  status = (NAND_NANDEIRR & NANDEIRR_RB_READY) == NANDEIRR_RB_READY;
	  --cnt;
	}   

	// Clear Interrupt
	NAND_clearEIRR();

  	if(cnt <= 0)
  		return BOOT_FAIL;
 	return BOOT_SUCCESS;
}


/* Wait for the status to be ready in register 
 There were some problems reported in DM320 with Ready/Busy pin
 not working with all NANDs. So this check has also been added */
static Uint32 NAND_WaitForStatus()
{
	volatile Uint32 cnt;
	Uint32 status;
	cnt = NAND_BOOT_TIMEOUT;

    do{
	    flash_write_cmd(NAND_STATUS);
	    status = flash_read_data() & (NAND_STATUS_ERROR | NAND_STATUS_BUSY);
        cnt--;
  	} while((cnt>0) && !status);

    if(cnt == 0)
	    return BOOT_FAIL;  		
	return BOOT_SUCCESS;
}


void LPSCTransition(Uint8 module, Uint8 state)
{
    while (PSC->PTSTAT & 0x00000001);
	PSC->MDCTL[module] = ((PSC->MDCTL[module]) & (0xFFFFFFE0)) | (state);
	PSC->PTCMD |= 0x00000001;
	while ((PSC->PTSTAT) & 0x00000001);
	while (((PSC->MDSTAT[module]) & 0x1F) != state);	
}

//--------------------------------------------------------------------
// Revision History:
//  2007-May-11   - Updated with new NAND basic functions and support
//                  table
//  2007-June-21  - Added Bad Block Avoidance
//--------------------------------------------------------------------

⌨️ 快捷键说明

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