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

📄 amd.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 4 页
字号:
            g_FlashProgInfo.bUnlockBypassSupport? L"TRUE" : L"FALSE"));
#endif
    // TODO: If CPU is not little endian, need to take care of endianess in 
    // the structures.
 
    // Check for at least 1 erase region
    if(pFlashDesc->Geometry.NumEraseBlockRegions == 0)
    {
        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: NORInit32: invalid geometry info!\r\n")));
        bSuccess = FALSE;
        goto _exit;
    }

    // Check for device with supported interface
    if(pFlashDesc->Geometry.DevInterface != CFI_DEV_INTF_x8x16_ASYNC &&
        pFlashDesc->Geometry.DevInterface != CFI_DEV_INTF_x16_ASYNC &&
        pFlashDesc->Geometry.DevInterface != CFI_DEV_INTF_x16x32_ASYNC )
    {
        DEBUGMSG(ZONE_HAL_INFO, (TEXT("INFO: Unsupported device interface 0x%x\r\n"), 
                pFlashDesc->Geometry.DevInterface));
        bSuccess = FALSE;
        goto _exit;
    }

    // Check for supported command set.
    if(pFlashDesc->QryIDStr.PriOEMCmdSetID != AMD_CMD_SET_ID)
    {
        DEBUGMSG(ZONE_HAL_INFO, (TEXT("Unsupported Pri Cmd Set: 0x%x\r\n"),
        	    pFlashDesc->QryIDStr.PriOEMCmdSetID));
        bSuccess = FALSE;
        goto _exit;
    }

#ifdef VIRTIO_FIXME
    // Virtio is not returning correct CFI data for S29WSxxxN
    // Force correct values according to specs, especially write buffer size
    if(pFlashDesc->FlashID.DeviceID[1] == 0x2230)
    {
        pFlashDesc->SysInt.Typical.SnglWordProgTO_us = 6;
        pFlashDesc->SysInt.Typical.BlockEraseTO_ms = 0x0A;
        pFlashDesc->SysInt.Max.BlockEraseTO_ms = 2;
#if S29WSxxxN_BUFFER_PROG_SUPPORT
        pFlashDesc->Geometry.WriteBuffSize = 6;
#else
        // Force non buffer write
        pFlashDesc->Geometry.WriteBuffSize = 0;
#endif
    }
    if(pFlashDesc->FlashID.DeviceID[1] == 0x2231 || pFlashDesc->FlashID.DeviceID[1] == 0x2232)
    {
        pFlashDesc->SysInt.Typical.SnglWordProgTO_us = 6;
        pFlashDesc->SysInt.Typical.BlockEraseTO_ms = 0x0A;
        pFlashDesc->SysInt.Max.SnglWordProgTO_us = 4;
        pFlashDesc->SysInt.Max.WriteBuffTO_us = 4;

#if S29WSxxxN_BUFFER_PROG_SUPPORT
        pFlashDesc->Geometry.WriteBuffSize = 6;
#else
        // Force non buffer write
        pFlashDesc->Geometry.WriteBuffSize = 0;
#endif
    }
#endif    
    
    // Get device unique silicon ID
    pusSiID = (USHORT *)(pFlashDesc->FlashID.SiliconID);
    dwBusWidth = bIsPaired? sizeof(ULONG): sizeof(USHORT);

    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_2_ADDR_UNLOCK_x16, CYCLE_3_DATA_ENTER_SECSI);

    for(i = 0; i < 8; i++)
    {
        *(pusSiID + i) = (USHORT)(RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, i) & 0xFFFF);
    }

    // Exit Sec Si area
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_2_ADDR_UNLOCK_x16, CYCLE_3_DATA_EXIT_SECSI);
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_4_ADDR_EXIT_SECSI, CYCLE_4_DATA_EXIT_SECSI);

    // Get driver prog info & store for easy access.
    // Single datum timeouts
    if(pFlashDesc->SysInt.Typical.SnglWordProgTO_us)
        g_FlashProgInfo.ulDatumProgTO_us = (1 << pFlashDesc->SysInt.Typical.SnglWordProgTO_us);
    else
        g_FlashProgInfo.ulDatumProgTO_us = POLLING_WRBYPASS_LIFETIME_US;
    if(pFlashDesc->SysInt.Max.SnglWordProgTO_us)
        g_FlashProgInfo.ulMaxDatumProgTOFactor = 1 << pFlashDesc->SysInt.Max.SnglWordProgTO_us;
    else
        g_FlashProgInfo.ulMaxDatumProgTOFactor = POLLING_WRBYPASS_LIFETIME_FACTOR;

    // Write buffer timeouts. 
    if(pFlashDesc->SysInt.Typical.WriteBuffTO_us)
        g_FlashProgInfo.ulBufferProgTO_us = (1 << (pFlashDesc->SysInt.Typical.WriteBuffTO_us));
    else
        g_FlashProgInfo.ulBufferProgTO_us = POLLING_WRBUFR_LIFETIME_US;
    if(pFlashDesc->SysInt.Max.WriteBuffTO_us)
        g_FlashProgInfo.ulMaxBufferProgTOFactor = 1 << pFlashDesc->SysInt.Max.WriteBuffTO_us;
    else
        g_FlashProgInfo.ulMaxBufferProgTOFactor = POLLING_WRBUFR_LIFETIME_FACTOR;

    // Sector erase timeouts
    if(pFlashDesc->SysInt.Typical.BlockEraseTO_ms)
        g_FlashProgInfo.ulSectorEraseTO_ms = (1 << pFlashDesc->SysInt.Typical.BlockEraseTO_ms);
    else
        g_FlashProgInfo.ulSectorEraseTO_ms = ERASE_BLOCK_TIMEOUT_MS;
    if(pFlashDesc->SysInt.Max.BlockEraseTO_ms)
        g_FlashProgInfo.ulMaxSectorEraseTOFactor = 1 << pFlashDesc->SysInt.Max.BlockEraseTO_ms;
    else
        g_FlashProgInfo.ulMaxSectorEraseTOFactor = ERASE_BLOCK_TIMEOUT_FACTOR;

    // Chip erase timeouts
    if(pFlashDesc->SysInt.Typical.ChipEraseTO_ms)
        g_FlashProgInfo.ulChipEraseTO_ms = (1 << pFlashDesc->SysInt.Typical.ChipEraseTO_ms);
    else
        g_FlashProgInfo.ulChipEraseTO_ms = ERASE_CHIP_TIMEOUT_MS;
    if(pFlashDesc->SysInt.Max.ChipEraseTO_ms)
        g_FlashProgInfo.ulMaxChipEraseTOFactor = 1 << pFlashDesc->SysInt.Max.ChipEraseTO_ms;
    else
        g_FlashProgInfo.ulMaxChipEraseTOFactor = ERASE_CHIP_TIMEOUT_FACTOR;
    PrintFlashProgInfo(&g_FlashProgInfo);

    // Set device width
    pFlashDesc->DeviceWidth = 16;
    pFlashDesc->PairedFlash = bIsPaired;

#ifdef USE_OS_SERVICES
    // Calibrate CEDDK's counter for the StallExecution() API
    CalibrateStallCounter();
#endif

_exit:
    // exit CFI query mode by issuing a soft reset
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_RESET, CYCLE_1_DATA_RESET);

    DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("AMD_IsFlashSupported-\r\n")));
    return bSuccess;
}

//-----------------------------------------------------------------------------
//
// Function: AMDx16_Program
//
// Function performs programming of AMD 16bit mode flash devices.
//
// Programming Notes:
// DQ7 indicates the programming is complete however this does not
// guarantee the value that was programmed to the device is correct
// Test to make sure the data programmed is the data that is being
// read from the device.
// ****************************************************************
// Note:
// Just prior to the completion of an Embedded Program or Erase 
// operation, DQ7 may change asynchronously with DQ0朌Q6 while 
// Output Enable (OE#) is asserted low. That is, the device may 
// change from providing status information to valid data on DQ7. 
// Depending on when the system samples the DQ7 output, it may read 
// the status or valid data.  Even if the device has completed 
// the program or erase operation and DQ7 has valid data, the data 
// outputs on DQ0朌Q6 may be still invalid.  Valid data on DQ0朌Q7 
// will appear on successive read cycles.
// **************************************************************** 
// If DQ5 is a 1, it may not necessarily be true that a time out has 
// occurred and the value should be checked once more to see if it 
// was successfully programmed.
// In addition the value that was programmed may have this bit set
// in which case the check for the proper value is also required.
// *****************************************************************
//
// Parameters:
//      pFlashDesc
//          [in] pointer to NOR flash descriptor
//
//      ulStartAddress
//          [in] start address to start programming
//
//      pData
//          [in] ptr to data buffer
//
//      ulLen
//          [in] length of data
//
// Returns:
//      FALSE if programming failed
//
//-----------------------------------------------------------------------------
BOOL AMDx16_Program(NOR_FLASH_DESC *pFlashDesc, ULONG ulProgramAddress, UCHAR *pData, ULONG ulLen, BOOL bIgnore0to1)
{
    ULONG ulFlashBase;
    BOOL bIsPaired;
    ULONG *pulData;
    ULONG i;
    ULONG j;
    ULONG retry;
    DWORD dwBusWidth;
    ULONG ulWriteBufferSize;
    ULONG ulBufAlignBytes;
    ULONG dwNumPages;
    ULONG ulProgBytes;                                                    
    ULONG ulDataToWrite;
    ULONG ulDataWritten;
    ULONG ulBufDatumSize;
    ULONG ulFlashSectorAddr;
    ULONG ulSectorSize;
    ULONG ulCurRegion;
    ULONG ulCurBlock;
    ULONG ulNumRegionBlocks;
    BOOL bDone;
    BOOL bSuccess;
    ULONG ulIgnoreBuffer[AMD_BUF_PROG_MAX_DATUM];
#ifdef DEBUG
    ULONG ulPageStart;
#endif
    DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("AMDx16_Program+: 0x%x 0x%x 0x%x\r\n"),
            ulProgramAddress, pData, ulLen));

    if(!pFlashDesc && !pData)
    {
    	DEBUGMSG(ZONE_HAL_ERROR, (TEXT("AMDx16_Program: null param\r\n")));
        return FALSE;
    }
        
    bIsPaired = pFlashDesc->PairedFlash;
    ulFlashBase = pFlashDesc->FlashBase;

    // Let the flash know the size of the buffer we plan to send (note that this is a 0-based word count and we simulatenously
    // write it to both flash parts (upper and lower).
    ulWriteBufferSize = (pFlashDesc->Geometry.WriteBuffSize)?
                            (bIsPaired? 
                                ((1 << pFlashDesc->Geometry.WriteBuffSize) * 2) : 
                                (1 << pFlashDesc->Geometry.WriteBuffSize)) : 
                            0;

    dwNumPages = (ulWriteBufferSize)? (ulLen / ulWriteBufferSize) : 0;
    ulBufAlignBytes = (ulWriteBufferSize)? ulProgramAddress % ulWriteBufferSize : 0;
    pulData = (ULONG *)pData;
    bSuccess = TRUE;

    DEBUGMSG(ZONE_HAL_INFO, (TEXT("ulWriteBufferSize 0x%x\r\n"), ulWriteBufferSize));

    // Use bypass mode single datum non-buffered program method for
    // 1. no write buffer support or data < 1 page.
    // 2. Align program address to write buffer page
    // Refer to single word program operation in flash specification 
    // for more details
    dwBusWidth = bIsPaired? sizeof(ULONG) : sizeof(USHORT);

    if(ulBufAlignBytes != 0 || dwNumPages == 0) 
    {
        ulProgBytes = (ulWriteBufferSize)? ulBufAlignBytes : ulLen;
                            
        DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("dwBufAlignBytes 0x%x dwNumPages 0x%x ulProgBytes 0x%x\r\n"), 
                                ulBufAlignBytes, dwNumPages, ulProgBytes));

        for(i = 0; i < ulProgBytes; i += dwBusWidth)
        {
            bDone = FALSE;
            ulDataToWrite = bIsPaired? *(ULONG *)pulData : *(USHORT *)pulData;

            if(bIgnore0to1)
            {
                ulDataWritten = bIsPaired? *(volatile ULONG *)ulProgramAddress : *(volatile USHORT *)ulProgramAddress;
                ulDataToWrite &= ulDataWritten;
            }
            DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("Before: [0x%x] 0x%x\r\n"), 
                                ulProgramAddress, bIsPaired? *((volatile ULONG *)(ulProgramAddress)) : 
                                    *((volatile USHORT *)(ulProgramAddress)) ));

            if(g_FlashProgInfo.bUnlockBypassSupport)
            {
                // Send unlock bypass enter command for first datum
                if(i == 0)
                {
                    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
                    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
                    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_3_ADDR_CMD_x16, CYCLE_3_DATA_UNLOCK_BYPASS);
                }
                WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_PROGRAM_BYPASS, CYCLE_1_DATA_PROGRAM_BYPASS);
                WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
            }
            else
            {
                // 4 cycle per datum program 
                WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
                WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
                WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, UNLOCK_ADDR1_x16, CYCLE_3_DATA_PROGRAM);
                WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
            }
            j = 0;
            while(!bDone && bSuccess && j++ < CHECK_STATUS_TIMEOUT)
            {
                ulDataWritten = bIsPaired? *((volatile ULONG *)(ulProgramAddress)) : 
                                    *((volatile USHORT *)(ulProgramAddress));
                DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("[0x%x] 0x%x : expect 0x%x\r\n"), 
                                    ulProgramAddress, ulDataWritten, ulDataToWrite));
                
                // D7 will be driven to complement of D7 written to the FLASH.  
                // When it is driven to the value just written,
                // the program operation is complete.
                if((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16)) == (ulDataToWrite & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16)))
                {
                    // Spec indiates that D7 may be valid while other data lines are still invalid.
                    if(ulDataWritten != ulDataToWrite)
                    {
                        // Try reading again before we report an error.  We want to avoid 
                        // reporting an error here because EBOOT has no recovery and
                        // will terminate the flashing procedure.
                        for (retry = 10; retry > 0 && !bDone; retry--)
                        {
                        
                            ulDataWritten = bIsPaired? *((volatile ULONG *)(ulProgramAddress)) : *((volatile USHORT *)(ulProgramAddress));
                            if(ulDataWritten == ulDataToWrite)
                            {
                                // page is programmed properly
                                bDone = TRUE;
                            }
                        }

                        // Now report an error if the value we wanted did not get programmed
                        if (!bDone)
                        {
                            // programming failure
                            ERRORMSG(ZONE_HAL_ERROR, (TEXT("Program failure [0x%x] 0x%x : expect 0x%x\r\n"), 
                                    ulProgramAddress, ulDataWritten, ulDataToWrite));
                            bSuccess = FALSE;
                        }
                    }
                    else
                    {
                        // datum is programmed properly
                        bDone = TRUE;
                    }

                }
                else
                {
                    if((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ5_X16)) == CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ5_X16))

⌨️ 快捷键说明

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