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

📄 amd.c

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on
// your install media.
//
//-----------------------------------------------------------------------------
//
// Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Copyright (C) 2004-2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//-----------------------------------------------------------------------------
//
// File: amd.c
//
// Provides the implementation of the AMD lower layer flash drivers.
// Notes:
// USE_OS_SERVICES needs the following delay functions:
//     1. void StallExecution(DWORD dwMicroSec), CalibrateStallCounter()
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>

#include "nor.h"
#include "amd.h"

//------------------------------------------------------------------------------
// External Variables

//------------------------------------------------------------------------------
// Defines
#define DEFAULT_CMD_DELAY_US				4
#define POLLING_WRBUFR_LIFETIME_US          1000
#define POLLING_WRBUFR_LIFETIME_FACTOR      10     
#define POLLING_WRBYPASS_LIFETIME_US        1000
#define POLLING_WRBYPASS_LIFETIME_FACTOR    10
#define ERASE_BLOCK_TIMEOUT_MS              20000
#define ERASE_BLOCK_TIMEOUT_FACTOR          10
#define ERASE_CHIP_TIMEOUT_MS               20000
#define ERASE_CHIP_TIMEOUT_FACTOR           10

// Set to 1 to enable CFI support with Spansion S29WSxxxN devices.
#define S29WSxxxN_CFI_SUPPORT               1

// Set to 1 to enable buffer programming with Spansion S29WSxxxN devices.
#define S29WSxxxN_BUFFER_PROG_SUPPORT       0

//------------------------------------------------------------------------------
// Types
typedef struct _FLASH_PROG_INFO {
    ULONG ulDatumProgTO_us;         // Typical datum write timeout
    ULONG ulMaxDatumProgTOFactor;   // Max = factor x typical timeout
    ULONG ulBufferProgTO_us;        // Typical write buffer timeout
    ULONG ulMaxBufferProgTOFactor;  // Max = factor x typical timeout
    ULONG ulSectorEraseTO_ms;       // Typical sector erase timeout
    ULONG ulMaxSectorEraseTOFactor; // Max = factor x typical timeout
    ULONG ulChipEraseTO_ms;         // Typical chip erase timeout
    ULONG ulMaxChipEraseTOFactor;   // Max = factor x typical timeout
    BOOL bUnlockBypassSupport;
} FLASH_PROG_INFO, *PFLASH_PROG_INFO;

//------------------------------------------------------------------------------
// Global Variables

//------------------------------------------------------------------------------
// Local Variables
static FLASH_PROG_INFO g_FlashProgInfo;

//------------------------------------------------------------------------------
// Local Functions
static void PrintPriExtTable(AMD_PET_QUERY_INFO *pPET);
static void PrintFlashProgInfo(FLASH_PROG_INFO *pInfo);

//-----------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//-----------------------------------------------------------------------------

// WARNING: for relocation purpose. Do not move!
void AMDx16_RelocateBegin(void) 
{
}

//-----------------------------------------------------------------------------
//
// Function: AMDx16_IsFlashSupported
//
// Function performs check to see if flash is present and if device is 
// supported. For 16bit mode flash devices.
//
// Parameters:
//      pFlashDesc
//          [in/out] pointer to NOR flash descriptor
//
// Returns:
//      FALSE if device not supported/present
//
//-----------------------------------------------------------------------------
BOOL AMDx16_IsFlashSupported(NOR_FLASH_DESC *pFlashDesc)
{
    ULONG ulFlashBase;
    BOOL bIsPaired;
    BOOL bSuccess;
    DWORD i;
    USHORT *pusSiID;
    DWORD dwBusWidth;

    DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("AMD_IsFlashSupported+\r\n")));

    if (!pFlashDesc) {
    	DEBUGMSG(ZONE_HAL_ERROR, (TEXT("AMD_IsFlashSupported: null param\r\n")));
        return FALSE;
    }
        
    ulFlashBase = pFlashDesc->FlashBase;
    bSuccess = TRUE;

    for (i = 0; i < sizeof(NOR_FLASH_ID_DESC) / sizeof(ULONG); i++)
        *((ULONG *)&pFlashDesc->FlashID + i) = 0;

    // This flash is not paired
    bIsPaired = FALSE;

    // Check for manufacturer ID
    // issue a soft reset to the device
    // ********************************
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_RESET, CYCLE_1_DATA_RESET);

    // enter autoselect mode and determine if the manufacturer is supported 
    // ********************************************************************
    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_AUTOSELECT);

    if (!CHECK_FLASH_STATUS_INDEXED16(bIsPaired, ulFlashBase, CYCLE_4_ADDR_MFG_ID, AMD_MFG_ID_x16)) {
        ERRORMSG(1, (TEXT("No supported AMD flash detected\r\n")));
        ERRORMSG(1, (TEXT("Manufacturer: 0x%x Device: 0x%x Paired %c\r\n"), 
            pFlashDesc->FlashID.ManufacturerID, *(ULONG *)pFlashDesc->FlashID.DeviceID,
            bIsPaired ? 'T' : 'F'));
            bSuccess = FALSE;
            goto _exit;
    }

    pFlashDesc->FlashID.ManufacturerID = (USHORT)RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, CYCLE_4_ADDR_MFG_ID);

    // Note: after the device is in autoselect mode the system may read at any
    // address any number of times without initiating another autoselect 
    // command sequence.  In this context the following offset definition 
    // may appear to be is a misnomer.
    // ***********************************************************************
    pFlashDesc->FlashID.DeviceID[0] = (USHORT)RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, CYCLE_4_ADDR_DEV_ID);
    pFlashDesc->FlashID.DeviceID[1] = (USHORT)RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, CYCLE_5_ADDR_DEV_ID);
    pFlashDesc->FlashID.DeviceID[2] = (USHORT)RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, CYCLE_6_ADDR_DEV_ID);

    // exit autoselect mode by issuing a soft reset
    // ********************************************
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_RESET, CYCLE_1_DATA_RESET);

    DEBUGMSG(ZONE_HAL_INFO, (TEXT("Manufacturer: 0x%x Device: 0x%x Paired %c\r\n"), 
        pFlashDesc->FlashID.ManufacturerID, *(ULONG *)pFlashDesc->FlashID.DeviceID,
        bIsPaired ? 'T' : 'F'));

    // Look for a Common Flash Interface (CFI) device.
    WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CFI_QUERY_ADDR, CFI_QUERY_DATA);

#if S29WSxxxN_CFI_SUPPORT
        // From S29WSxxxN spec:
        // CFI query command is valid when device is ready to read array data or
        // when device is in autoselect mode. Address will equal 55h on all
        // future devices, but 555h for WS256N/128N/064N.
        // So we do both just to be compatible.
        WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, 0x555, CFI_QUERY_DATA);
#endif
        if (!CHECK_FLASH_STATUS_INDEXED16(bIsPaired, ulFlashBase, CFI_QS_OFFSET_QRY_ID_Q, CFI_DATA_QUERY_ID_Q) ||
            !CHECK_FLASH_STATUS_INDEXED16(bIsPaired, ulFlashBase, CFI_QS_OFFSET_QRY_ID_R, CFI_DATA_QUERY_ID_R) ||
            !CHECK_FLASH_STATUS_INDEXED16(bIsPaired, ulFlashBase, CFI_QS_OFFSET_QRY_ID_Y, CFI_DATA_QUERY_ID_Y))
        {
            // TODO - add JEDEC check & fake CFI info to support.
            // This flash doesn't support CFI.
            ERRORMSG(ZONE_ERROR, (TEXT("ERROR: AMD: CFI not supported\r\n")));
            bSuccess = FALSE;
            goto _exit;
        }

    DEBUGMSG(ZONE_HAL_INFO, (TEXT("INFO: CFI device detected at 0x%x. Paired(%c)\r\n"), 
        ulFlashBase, bIsPaired? 'T':'F'));
    
    // Use the CFI to collect information on it. Also, assume that both
    // high and low word flash parts are the same if paired.
    for (i = 0; i < sizeof(CFI_FLASH_QUERY_ID_STRING); i++) {
        *((UCHAR *)&pFlashDesc->QryIDStr + i) = 
            (UCHAR)(RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, CFI_QS_OFFSET_QRY_ID + i) & 0xFF);
    }
    
    for (i = 0; i < sizeof(CFI_FLASH_SYSINTERFACE_INFO); i++) {
        *((UCHAR *)&pFlashDesc->SysInt + i) = 
            (UCHAR)(RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, CFI_QS_OFFSET_SYSINTF + i) & 0xFF);
    }
    
    for (i = 0; i < sizeof(CFI_FLASH_GEOMETRY_INFO); i++) {
        *((UCHAR *)&pFlashDesc->Geometry + i) = 
            (UCHAR)(RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, CFI_QS_OFFSET_DEVGEOM + i) & 0xFF);
    }

    // Get Primary extended table 
    if (pFlashDesc->QryIDStr.PriExtTableAddr != 0) {
        AMD_PET_QUERY_INFO pet;
        for (i = 0; i < sizeof(AMD_PET_QUERY_INFO); i++) {
            *((PUCHAR)&pet + i) = 
                (UCHAR)((RD_FLASH_INDEXED16(bIsPaired, ulFlashBase, 
                    pFlashDesc->QryIDStr.PriExtTableAddr + i)) & 0xFF);
        }
    
        if (!CHECK_FLASH_STATUS_INDEXED16(bIsPaired, ulFlashBase, 
                pFlashDesc->QryIDStr.PriExtTableAddr, CFI_DATA_PET_ID_P) ||
            !CHECK_FLASH_STATUS_INDEXED16(bIsPaired, ulFlashBase, 
                pFlashDesc->QryIDStr.PriExtTableAddr+1, CFI_DATA_PET_ID_R) ||
            !CHECK_FLASH_STATUS_INDEXED16(bIsPaired, ulFlashBase, 
                pFlashDesc->QryIDStr.PriExtTableAddr+2, CFI_DATA_PET_ID_I)) {
            DEBUGMSG(ZONE_HAL_ERROR, (TEXT("INFO: invalid Primary vendor extended table data!\r\n")));
            // Default unlock bypass support to TRUE since most part do support
            // nowadays.
            // TODO: enable unlock bypass support based on JEDEC device ID
            g_FlashProgInfo.bUnlockBypassSupport = TRUE;
            DEBUGMSG(ZONE_HAL_INFO, (TEXT("INFO: Default unlock bypass support: %s!\r\n"),
                g_FlashProgInfo.bUnlockBypassSupport? L"TRUE" : L"FALSE"));
        } else {
            if (pet.UnlockBypassSupport || pet.ACCVmin || pet.ACCVmax) {
                g_FlashProgInfo.bUnlockBypassSupport = TRUE;
                DEBUGMSG(ZONE_HAL_INFO, (TEXT("INFO: Unlock bypass supported.\r\n")));
            } else {
                g_FlashProgInfo.bUnlockBypassSupport = FALSE;
                DEBUGMSG(ZONE_HAL_INFO, (TEXT("INFO: Unlock bypass not supported.\r\n")));
            }
            
    	    PrintPriExtTable(&pet);
        }
    }

    // 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;
    }
    
    // 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);

⌨️ 快捷键说明

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