?? nand.c
字號:
//
// 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.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
--*/
#include "def.h"
#include "AT4X0f.h"
#include <cspregs.h>
#include <string.h>
#define _DEFINE_CSP_REGS_
#include <drvlib.h>
#include "debug.h"
#include "nand.h"
#include "fmdext.h"
#include "smecc.h"
#include <loader.h>
#include <macros.h>
#include "oem.h"
#include "cachesync.h"
#include <macros.h>
#ifndef CACHE_SYSNC_DISCARD
#define CACHE_SYSNC_DISCARD 0
#endif
#undef RETAILMSG
#define RETAILMSG(cond,expr)
FlashInfoEx g_FlashExtInfo;
PFlashInfoEx pFlashExtInfo = &g_FlashExtInfo;
static BOOL NandCheckAndReserveBlock(DWORD dwBlockIndex);
BOOL FMD_SetBlockStatus(DWORD blockID, DWORD dwStatus);
BOOL FMDVerifyWrite(DWORD cs);
#define logh(val) do { \
NandDbgPutString ("\r\n" #val " = "); \
NandDbgPutHex ((DWORD)val); \
} while (0)
#define IS_BLOCK_BAD(blockID) ((FMD_GetBlockStatus (blockID) & BLOCK_STATUS_BAD) > 0)
#define IS_BLOCK_READONLY(blockID) ((FMD_GetBlockStatus (blockID) & BLOCK_STATUS_READONLY) > 0)
#define IS_BLOCK_RESERVED(blockID) ((FMD_GetBlockStatus (blockID) & BLOCK_STATUS_RESERVED) > 0)
#define IS_BLOCK_UNUSABLE(blockID) ((FMD_GetBlockStatus (blockID) & (BLOCK_STATUS_BAD|BLOCK_STATUS_RESERVED)) > 0)
// fs: file size in bytes
// returns sector aligned value
DWORD FILE_TO_SECTOR_SIZE (DWORD fs) { return 1 + ((fs - 1) >> g_FlashExtInfo.ucSectorSizeBits); }
DWORD FILE_TO_BLOCK_SIZE (DWORD fs) { return 1 + ((fs - 1) >> g_FlashExtInfo.ucBlockSizeBits); }
// ns: number of sectors
// N.B: returns sector aligned value since we can't tell
DWORD SECTOR_TO_FILE_SIZE (DWORD ns) { return ns << g_FlashExtInfo.ucSectorSizeBits; }
// FMD block status definitions.
#define BLOCK_STATUS_UNKNOWN 0x01
#define BLOCK_STATUS_BAD 0x02
#define BLOCK_STATUS_READONLY 0x04
#define BLOCK_STATUS_RESERVED 0x08
// FMD OEM reserved area bitfield.
#define OEM_BLOCK_RESERVED 0x01
#define OEM_BLOCK_READONLY 0x02
#define ATLAS_IMAGE_WINDOWS_CE_NBOOT 3
#define ATLAS_IMAGE_WINDOWS_CE_EBOOT 4
#define ATLAS_IMAGE_WINDOWS_NK_NB0 5
#define ATLAS_IMAGE_WINDOWS_CE_DM 7 //leon01 add for DM
#define TOC_RESERVED_BLOCK_SIZE 1
#define EBOOT_RESERVED_BLOCK_SIZE 10
#define DM_RESERVED_BLOCK_SIZE 35 //leon01 add for DM
#define NBOOT_VERSION 0x300B // Version number: AAAA.BBBB.CCCCCCCC one word, 3.0.11
#define MAX_BAD_BLOCKS 10
#define pDriverGlobals ((PDRIVER_GLOBALS) 0xC0002000)
DWORD dwDmaPhysAddr = SMDF_DMA_START_PHYSICAL;
DWORD g_nNandCS = 0; //default to 0
DWORD g_nCurImg = ATLAS_IMAGE_WINDOWS_CE_NBOOT;
//DWORD g_dwNBootBlock;
DWORD g_dwTocBlock;
DWORD g_dwEBootBlock;
DWORD g_dwNKBlock;
DWORD g_dwDMBlock = 0; //leon01 add for DM entry
DWORD g_dwSecureBlock;
DWORD g_dwSecureBlockSize = 0;
SectorInfo g_SI;
BYTE tocTemp[2048+64];
TOC* g_pTOC = (TOC*) tocTemp;
#ifndef BUILDING_NBOOT_ICE
static DWORD g_dwEbootBlockSize=EBOOT_RESERVED_BLOCK_SIZE;
static DWORD g_dwDMBlockSize=DM_RESERVED_BLOCK_SIZE;
static DWORD g_dwEbootLaunchAddr=0x8c04c000;
static DWORD g_dwEbootLoadAddr=0x8c04c000;
static DWORD g_dwDMLaunchAddr=0x8c04c000;
static DWORD g_dwDMLoadAddr=0x8c04c000;
static DWORD g_dwTOCBlockSize=TOC_RESERVED_BLOCK_SIZE;
#endif
volatile PUCHAR v_pDMAAddr = (volatile PUCHAR)(SMDF_DMA_START_PHYSICAL&~0xc0000000);
#ifndef BUILDING_NBOOT_ICE
extern DWORD g_iCurImgLength;
#endif
extern DWORD g_dwJumpAddr;
extern DWORD g_dwEntry;
extern DWORD g_dwIoClock;
BYTE WriteSectBuf[2048+64];
BYTE ReadSectBuf[2048+64];
int g_bNandDbgMuted = 0;
UCHAR g_ucNandcs[4];
#define PROTECT_NAND() do{ \
GPIO2_PAD_EN |= 0x40; \
GPIO2_CTRL6 = 0x100; \
GPIO2_CTRL6 |= 0x20; \
}while(0)
#define UNPROTECT_NAND() do { \
GPIO2_PAD_EN |= 0x40; \
GPIO2_CTRL6 = 0x140; \
GPIO2_CTRL6 |= 0x20; \
}while(0)
// When using serial port to update image,
// we don't allow any debug message through this port.
void NandDbgPutHex(unsigned long i) { if (!g_bNandDbgMuted) DbgPutHex (i); }
void NandDbgPutString(char* s) { if (!g_bNandDbgMuted) DbgPutString (s); }
void FMDSetAddress (DWORD dwSectorAddr, WORD wOffsetLarge, WORD wOffsetSmall)
{
if (g_FlashExtInfo.bHighDensity)
{
NF_SET_ADDR((dwSectorAddr<<16) + wOffsetLarge/(g_FlashExtInfo.ucDataWidth/8));
NF_SET_ADDR_HI(dwSectorAddr>>16);
}
else
{
NF_SET_ADDR((dwSectorAddr<<8) + wOffsetSmall);
NF_SET_ADDR_HI(0);
}
}
void FMDChangePointer(BOOL bDataArea)
{
if (!g_FlashExtInfo.bHighDensity)
{
NF_CMD_MODE();
NF_ADDR_CYCLE_NUM(0);
//
if (bDataArea)
{
//change the write pointer to the data area by issueing a read cmd1
NF_CMD(SMDF_CMD_READ1);
}
else
{
//change the write pointer to the spare area by issueing a read cmd2
NF_CMD(SMDF_CMD_READ2);
}
}
}
void FMDWriteFifo (PDWORD pData, DWORD dwLength)
{
DWORD dwFifoNum;
for (dwFifoNum=0; dwFifoNum<dwLength/4; dwFifoNum++)
{
NF_WR_FIFO((*(pData+dwFifoNum)));
}
}
void FMDReadFifo (PDWORD pData, DWORD dwLength)
{
DWORD dwFifoNum;
for (dwFifoNum=0; dwFifoNum<dwLength/4; dwFifoNum++)
{
NF_RD_FIFO((*(pData+dwFifoNum)));
}
}
void FMDPageProgram (void)
{
NF_CMD_MODE ();
NF_ADDR_CYCLE_NUM (0);
NF_CLR_INT (SMDF_ADD_INT);
NF_CMD (SMDF_CMD_PAGE_PROGRAM);
NF_WAIT_INT (SMDF_ADD_INT);
}
void FMDInitHardware()
{
int nand_cs = OEMGetNandCs();
if(OEMIsNorBoot())
{
nand_cs &= ~1;
//Default the cs to cs3
g_nNandCS = 3;
}
WRITE_BITFIELD(struct RSCPinMuxBits, &(v_pRscRegs->rscPinMux), nand, nand_cs);
if (0 == (v_pSMDFRegs->SmDirectRead & 0x10)) {
WRITE_BITFIELD(struct RSCPinMuxBits, &(v_pRscRegs->rscPinMux), cam, 0x1);
}
// Map SMDF register space
v_pSMDFRegs->SmDirectRead &= ~0x1;
v_pSMDFRegs->SmWait = 0x1878;
v_pSMDFRegs->SmFIFOOp = 1;
NF_INIT_DMA();
NF_INT_MASK(0);
// ENABLE POWER MANAGER CLOCK ENABLE REGISTER
WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), dma, 1);
WRITE_BITFIELD(struct pwrclkenable, &(v_pPowerRegs->pmr_clkenable), rom, 1);
NF_CS(~(1 << g_nNandCS));
}
BOOL FMDReadFlashID()
{
DWORD dwRead;
DWORD dwDeviceId;
DWORD dwManufactureId;
g_FlashExtInfo.wCmdSeqDataIn = 0x80;
g_FlashExtInfo.wCmdPageProg = 0x10;
g_FlashExtInfo.wCmdReadStat = 0x70;
g_FlashExtInfo.wCmdReadId = 0x90;
g_FlashExtInfo.wCmdBlockErase = 0xd060;
g_FlashExtInfo.wCmdReset = 0xff;
g_FlashExtInfo.wLock = 0x0;
g_FlashExtInfo.wUnlock = 0x0;
g_FlashExtInfo.wLockTight = 0x0;
g_FlashExtInfo.wReadLockStat = 0x0;
g_FlashExtInfo.wCmdCacheProg = 0x1580;
g_FlashExtInfo.wCmdCBProg = 0x1085;
g_FlashExtInfo.wCmdRandInput = 0x85;
g_FlashExtInfo.wCmdRandOutput = 0xe005;
g_FlashExtInfo.wCmdReadLast = 0x0;
//
// force to use 8-bit mode to read Flash ID
//
v_pSMDFRegs->SmDirectRead &= ~0x2;
NF_RESET_FIFO();
NF_IO_RD_MODE();
NF_LEN(4);
NF_ADDR_CYCLE_NUM(1);
NF_SET_ADDR(0);
NF_CMD(SMDF_CMD_READ_ID);
while(NF_FIFO_EMPTY());
NF_RD_FIFO(dwRead);
dwManufactureId = (dwRead & 0xff);
dwDeviceId = ((dwRead >> 8) & 0xff);
#if 0
NandDbgPutString("Manufacture ID: ");
NandDbgPutHex(dwManufactureId);
NandDbgPutString("\r\nDevice ID: ");
NandDbgPutHex(dwDeviceId);
NandDbgPutString("\r\n");
#endif
switch (dwDeviceId)
{
case DEVICE_ID_16M:
case DEVICE_ID_32M:
case DEVICE_ID_64M:
case DEVICE_ID_128M:
v_pSMDFRegs->SmDirectRead &= ~8;
g_FlashExtInfo.ucSectorSizeBits = SHIFT_512_BYTES;
g_FlashExtInfo.ucSectorsPerBlockBits = 5;
// Set flash command set
g_FlashExtInfo.wCmdReadFirst = 0x00;
g_FlashExtInfo.wCmdReadLast = 0x01;
g_FlashExtInfo.wCmdReadShare = 0x50;
g_FlashExtInfo.wCmdCacheProg = 0x00;
g_FlashExtInfo.wCmdCBProg = 0x00;
g_FlashExtInfo.wCmdRandInput = 0x00;
g_FlashExtInfo.wCmdRandOutput = 0x00;
case DEVICE_ID_K9K2G08Q0M:
case DEVICE_ID_K9K2G08U0M:
case DEVICE_ID_K9K4G08U0M:
case DEVICE_ID_128M_F1:
g_FlashExtInfo.ucDataWidth = 8;
break;
case DEVICE_ID_128M_16BITS:
case DEVICE_ID_K9K2G16Q0M:
case DEVICE_ID_K9K2G16U0M:
v_pSMDFRegs->SmDirectRead |= 0x2;
g_FlashExtInfo.ucDataWidth = 16;
break;
default:
if (!OEMGetFlashExtInfo (dwManufactureId, dwDeviceId, &g_FlashExtInfo))
{
NandDbgPutString ("\r\nID lost.");
PWR_CLOCK_DISABLE (PWRCLK_USB_EN);
while (1);
}
break;
}
switch (dwDeviceId)
{
case DEVICE_ID_16M:
g_FlashExtInfo.fi.dwNumBlocks = 1024;
g_FlashExtInfo.ucChipAddrCycleNum = 3;
break;
case DEVICE_ID_32M:
g_FlashExtInfo.fi.dwNumBlocks = 2048;
g_FlashExtInfo.ucChipAddrCycleNum = 3;
break;
case DEVICE_ID_64M:
g_FlashExtInfo.fi.dwNumBlocks = 4096;
g_FlashExtInfo.ucChipAddrCycleNum = 4;
break;
case DEVICE_ID_128M:
g_FlashExtInfo.fi.dwNumBlocks = 8192;
g_FlashExtInfo.ucChipAddrCycleNum = 4;
break;
case DEVICE_ID_128M_F1:
g_FlashExtInfo.fi.dwNumBlocks = 1024;
g_FlashExtInfo.ucSectorSizeBits = SHIFT_2048_BYTES;
g_FlashExtInfo.ucSectorsPerBlockBits = 6;
g_FlashExtInfo.ucChipAddrCycleNum = 4;
// Set flash command set
g_FlashExtInfo.wCmdReadFirst = 0x3000;
g_FlashExtInfo.wCmdReadShare = 0x3000;
break;
case DEVICE_ID_128M_16BITS:
g_FlashExtInfo.ucSectorSizeBits = SHIFT_2048_BYTES;
g_FlashExtInfo.ucSectorsPerBlockBits = 6;
g_FlashExtInfo.fi.dwNumBlocks = 512;
g_FlashExtInfo.ucChipAddrCycleNum = 4;
// These codes still not verified.
// Set flash command set
g_FlashExtInfo.wCmdReadFirst = 0x3000;
g_FlashExtInfo.wCmdReadShare = 0x3000;
break;
case DEVICE_ID_K9K2G08Q0M:
case DEVICE_ID_K9K2G08U0M:
case DEVICE_ID_K9K2G16Q0M:
case DEVICE_ID_K9K2G16U0M:
g_FlashExtInfo.ucSectorSizeBits = SHIFT_2048_BYTES;
g_FlashExtInfo.ucSectorsPerBlockBits = 6;
g_FlashExtInfo.fi.dwNumBlocks = 2048;
g_FlashExtInfo.ucChipAddrCycleNum = 5;
// Set flash command set
g_FlashExtInfo.wCmdReadFirst = 0x3000;
g_FlashExtInfo.wCmdReadShare = 0x3000;
break;
case DEVICE_ID_K9K4G08U0M:
g_FlashExtInfo.ucSectorSizeBits = SHIFT_2048_BYTES;
g_FlashExtInfo.ucSectorsPerBlockBits = 6;
g_FlashExtInfo.fi.dwNumBlocks = 4096;
g_FlashExtInfo.ucChipAddrCycleNum = 5;
// Set flash command set
g_FlashExtInfo.wCmdReadFirst = 0x3000;
g_FlashExtInfo.wCmdReadShare = 0x3000;
break;
}
g_FlashExtInfo.ucBlockSizeBits = g_FlashExtInfo.ucSectorSizeBits+g_FlashExtInfo.ucSectorsPerBlockBits;
g_FlashExtInfo.fi.wSectorsPerBlock = 1 << g_FlashExtInfo.ucSectorsPerBlockBits;
g_FlashExtInfo.fi.wDataBytesPerSector = 1 << g_FlashExtInfo.ucSectorSizeBits;
g_FlashExtInfo.fi.dwBytesPerBlock = 1 << g_FlashExtInfo.ucBlockSizeBits;
g_FlashExtInfo.wSpareDataLength = g_FlashExtInfo.fi.wDataBytesPerSector * 16 / 512;
g_FlashExtInfo.dwTotalSize = g_FlashExtInfo.fi.dwNumBlocks << g_FlashExtInfo.ucBlockSizeBits;
v_pSMDFRegs->SmPageSize = g_FlashExtInfo.dwPageSize
= g_FlashExtInfo.fi.wDataBytesPerSector + g_FlashExtInfo.wSpareDataLength;
if (g_FlashExtInfo.ucSectorSizeBits > 9)
{
g_FlashExtInfo.bHighDensity = 1;
g_FlashExtInfo.ucNumBlockCycles = g_FlashExtInfo.ucChipAddrCycleNum - 2;
}
else
{
g_FlashExtInfo.bHighDensity = 0;
g_FlashExtInfo.ucNumBlockCycles = g_FlashExtInfo.ucChipAddrCycleNum - 1;
}
return TRUE;
}
#if 0
void FMDReadUUID(void)
{
int i;
DWORD dwRead;
DWORD dwSig;
FMDInitHardware();
FMDReadFlashID();
NF_CMD_MODE();
NF_SET_ADDR(0);
NF_SET_ADDR_HI(0);
NF_ADDR_CYCLE_NUM(0);
NF_LEN(0);
NF_CMD(0x30);
NF_CMD_MODE();
NF_ADDR_CYCLE_NUM(0);
NF_CMD(0x65);
NF_CMD_MODE();
NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum+1);
NF_LEN(g_FlashExtInfo.dwPageSize);
NF_CMD(SMDF_CMD_READ1);
NF_IO_RD_MODE();
for (i=0;i<(g_FlashExtInfo.dwPageSize)/4; i++)
{
while(NF_FIFO_EMPTY());
NF_RD_FIFO(dwRead);
if (g_FlashExtInfo.bHighDensity)
{
if(i<16)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -