724 lines
20 KiB
C
724 lines
20 KiB
C
// Copyright (C) 2008-2009 Apple, Inc. All rights reserved.
|
|
//
|
|
// This document is the property of Apple, Inc.
|
|
// It is considered confidential and proprietary.
|
|
//
|
|
// This document may not be reproduced or transmitted in any form,
|
|
// in whole or in part, without the express written permission of
|
|
// Apple, Inc.
|
|
//
|
|
|
|
#include "WMRFeatures.h"
|
|
#if WMR_BUILDING_IBOOT
|
|
#include "nandid.h"
|
|
#include <drivers/nand_device_tree.h>
|
|
#include <target/nand_spec_tables.h>
|
|
#include <sys.h>
|
|
#include <debug.h>
|
|
#else
|
|
#include "NandSpec.h"
|
|
#include "NandSpecTables.h"
|
|
#endif
|
|
|
|
#include "WMROAM.h"
|
|
#include "FIL.h"
|
|
|
|
// =============================================================================
|
|
// Preprocessor Definitions
|
|
|
|
#define WITH_NAND_DT_CONFIG (WITH_NAND_FILESYSTEM && WITH_DEVICETREE)
|
|
|
|
// =============================================================================
|
|
// Extern global variables
|
|
|
|
// =============================================================================
|
|
// Private Function Declarations
|
|
|
|
static BOOL32 isSameChipId(const NandChipId chipId1, const NandChipId chipId2);
|
|
static BOOL32 isSameConfigId(const NandConfigId* configId1, const NandConfigId* configId2);
|
|
|
|
static const NandGeometry* lookupNandGeometry(const NandChipId chipId);
|
|
static const NandTiming* lookupNandTiming(const NandConfigId* configId);
|
|
static const NandBoardSupport* lookupBoardSupport(const NandConfigId* configId);
|
|
static BOOL32 isValidChipId(const NandChipId chipId);
|
|
static BOOL32 getChipIdAndTotalCECountAndCEMap(const NandChipId* chipIds, NandChipId* foundChipId, UInt32* totalCECount, UInt32* ceMap);
|
|
static BOOL32 areChipIdsIdentical(const NandChipId* chipIds, NandChipId* chipId);
|
|
static UInt32 setBitCount(UInt32 x);
|
|
static BOOL32 checkCESymmetryAndGetPackageCnt(NandLandingMap *landingMap, UInt32 ceMap, UInt8* pkgCnt);
|
|
|
|
// =============================================================================
|
|
// Private Global Variables
|
|
#if WITH_NAND_DT_CONFIG
|
|
static NandInfo currentNandInfo;
|
|
static UInt32 currentCECount = 0;
|
|
static UInt32 currentCEBitmap = 0;
|
|
static UInt32 currentActiveDataBus = 0;
|
|
#endif //WITH_NAND_DT_CONFIG
|
|
static UInt32 currentCorrectableBits = 0;
|
|
static UInt32 currentRefreshThreshold = 0;
|
|
static BOOL32 ppnDevice = FALSE32;
|
|
static BOOL32 toggleDevice = FALSE32;
|
|
static BOOL32 _retire_on_invalid_refresh;
|
|
static void *_ppn_feature_list = NULL;
|
|
static UInt32 _ppn_feature_size = 0;
|
|
static void *_dbg_chipids_list = NULL;
|
|
static UInt32 _dbg_chipids_size = 0;
|
|
|
|
static UInt32 _dqsHalfCycleClocks;
|
|
static UInt32 _ceSetupClocks;
|
|
static UInt32 _ceHoldClocks;
|
|
static UInt32 _ADLClocks;
|
|
static UInt32 _WHRClocks;
|
|
|
|
static UInt32 _readPreClocks;
|
|
static UInt32 _readPostClocks;
|
|
static UInt32 _writePreClocks;
|
|
static UInt32 _writePostClocks;
|
|
|
|
static UInt32 _readSetupClocks;
|
|
static UInt32 _readHoldClocks;
|
|
static UInt32 _readDccycleClocks;
|
|
static UInt32 _writeSetupClocks;
|
|
static UInt32 _writeHoldClocks;
|
|
|
|
static UInt32 _regDQSTimingCtrl;
|
|
|
|
// =============================================================================
|
|
// Local constants
|
|
|
|
|
|
// =============================================================================
|
|
// Private Function Definitions
|
|
|
|
// compare the contents of a buffer to the given value, repeated
|
|
static BOOL32 comparePattern(const UInt8 *buffer, UInt8 value, UInt32 length)
|
|
{
|
|
UInt32 idx;
|
|
|
|
for (idx = 0; idx < length; ++idx)
|
|
{
|
|
if (buffer[idx] != value)
|
|
{
|
|
return FALSE32;
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE32;
|
|
}
|
|
|
|
static BOOL32 isSameChipId(const NandChipId chipId1,
|
|
const NandChipId chipId2)
|
|
{
|
|
UInt32 idx;
|
|
// Treat 0x00 as dont-care
|
|
for (idx = 0; idx < COMPARE_NAND_CHIP_ID_SIZE; ++idx)
|
|
{
|
|
if (chipId1[idx] && chipId2[idx] && (chipId1[idx] != chipId2[idx]))
|
|
{
|
|
return FALSE32;
|
|
}
|
|
}
|
|
return TRUE32;
|
|
}
|
|
|
|
static BOOL32 isSameConfigId(const NandConfigId* configId1,
|
|
const NandConfigId* configId2)
|
|
{
|
|
if (0 == WMR_MEMCMP(configId1, configId2, sizeof(NandConfigId)))
|
|
{
|
|
return TRUE32;
|
|
}
|
|
else
|
|
{
|
|
return FALSE32;
|
|
}
|
|
}
|
|
|
|
static const NandGeometry* lookupNandGeometry(const NandChipId chipId)
|
|
{
|
|
UInt32 count = sizeof(_nandGeometryTable) / sizeof(_nandGeometryTable[0]);
|
|
UInt32 idx;
|
|
|
|
for (idx = 0; idx < count; idx++)
|
|
{
|
|
const NandGeometry* geometry = &_nandGeometryTable[idx];
|
|
if (isSameChipId(chipId, geometry->chipId))
|
|
{
|
|
return geometry;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#if AND_ENABLE_NAND_DESCRIPTION_TEXT
|
|
static const NandDescription* lookupNandDescription(const NandPackageId* packageId)
|
|
{
|
|
UInt32 idx;
|
|
|
|
for (idx = 0; idx < _nandDescriptionTableSize; idx++)
|
|
{
|
|
const NandDescription* description = &_nandDescriptionTable[idx];
|
|
if (isSamePackageId(packageId, &(description->packageId)))
|
|
{
|
|
return description;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
static const NandTiming* lookupNandTiming(const NandConfigId* configId)
|
|
{
|
|
UInt32 count = sizeof(_nandTimingTable) / sizeof(_nandTimingTable[0]);
|
|
UInt32 idx;
|
|
|
|
for (idx = 0; idx < count; idx++)
|
|
{
|
|
const NandTiming* timing = &_nandTimingTable[idx];
|
|
if (isSameConfigId(configId, &(timing->configId)))
|
|
{
|
|
return timing;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const NandBoardSupport* lookupBoardSupport(const NandConfigId* configId)
|
|
{
|
|
UInt32 count = sizeof(_nandBoardSupportTable) / sizeof(_nandBoardSupportTable[0]);
|
|
UInt32 idx;
|
|
|
|
for (idx = 0; idx < count; idx++)
|
|
{
|
|
const NandBoardSupport* support = &_nandBoardSupportTable[idx];
|
|
if (isSameConfigId(configId, &(support->configId)))
|
|
{
|
|
return support;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static BOOL32 isValidChipId(NandChipId const chipId)
|
|
{
|
|
if (comparePattern(&chipId[0], 0x00, NAND_CHIP_ID_SIZE) ||
|
|
comparePattern(&chipId[0], 0xFF, NAND_CHIP_ID_SIZE))
|
|
{
|
|
return FALSE32;
|
|
}
|
|
else
|
|
{
|
|
return TRUE32;
|
|
}
|
|
}
|
|
|
|
static BOOL32 getChipIdAndTotalCECountAndCEMap(const NandChipId* chipIds, NandChipId* foundChipId, UInt32* totalCECount, UInt32* ceMap)
|
|
{
|
|
BOOL32 found = FALSE32;
|
|
UInt32 i;
|
|
|
|
*ceMap = 0;
|
|
*totalCECount = 0;
|
|
|
|
for (i = 0; i < NAND_MAX_CE_COUNT_TOTAL; i++)
|
|
{
|
|
if (isValidChipId(chipIds[i]))
|
|
{
|
|
if (!found)
|
|
{
|
|
WMR_MEMSET(foundChipId, 0, sizeof(NandChipId));
|
|
WMR_MEMCPY(foundChipId, chipIds[i], VALID_NAND_CHIP_ID_SIZE);
|
|
found = TRUE32;
|
|
}
|
|
(*totalCECount)++;
|
|
(*ceMap) |= (1 << i);
|
|
}
|
|
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
static BOOL32 areChipIdsIdentical(const NandChipId* chipIds, NandChipId* chipId)
|
|
{
|
|
UInt32 i;
|
|
|
|
for (i = 0; i < NAND_MAX_CE_COUNT_TOTAL; i++)
|
|
{
|
|
if (isValidChipId(chipIds[i]) && (!isSameChipId(*chipId, chipIds[i])))
|
|
{
|
|
return FALSE32;
|
|
}
|
|
}
|
|
|
|
return TRUE32;
|
|
}
|
|
|
|
static UInt32 setBitCount(UInt32 x)
|
|
{
|
|
// Count the ones
|
|
UInt32 cnt = 0;
|
|
|
|
while (x)
|
|
{
|
|
if (x & 1)
|
|
{
|
|
cnt++;
|
|
}
|
|
x = x >> 1;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
static BOOL32 checkCESymmetryAndGetPackageCnt(NandLandingMap *landingMap, UInt32 ceMap, UInt8* pkgCnt)
|
|
{
|
|
UInt32 mask;
|
|
UInt32 i = 0;
|
|
UInt32 cePerPkg = setBitCount((*landingMap)[0] & ceMap);
|
|
|
|
*pkgCnt = 0;
|
|
|
|
do
|
|
{
|
|
mask = (*landingMap)[i];
|
|
|
|
if (mask & ceMap)
|
|
{
|
|
if (cePerPkg != setBitCount(mask & ceMap))
|
|
{
|
|
return FALSE32;
|
|
}
|
|
(*pkgCnt)++;
|
|
}
|
|
i++;
|
|
}
|
|
while (mask != 0);
|
|
|
|
return TRUE32;
|
|
}
|
|
|
|
// =============================================================================
|
|
// Public Function Definitions
|
|
BOOL32 findNandInfo(const NandChipId* chipIds,
|
|
NandInfo* nandInfo,
|
|
const UInt32 numActiveDataBus)
|
|
{
|
|
NandConfigId detectedConfigId;
|
|
NandChipId chipId;
|
|
UInt32 totalCECount;
|
|
UInt32 ceMap;
|
|
UInt32 i;
|
|
|
|
nandInfo->boardInfo = &_nandBoardInfo;
|
|
nandInfo->boardSupport = NULL;
|
|
nandInfo->configTiming = NULL;
|
|
nandInfo->format = &_nandFormatRaw;
|
|
|
|
WMR_MEMSET(&detectedConfigId, 0, sizeof(NandConfigId));
|
|
|
|
if (!getChipIdAndTotalCECountAndCEMap(chipIds, &chipId, &totalCECount, &ceMap))
|
|
{
|
|
WMR_PRINT(INIT, "No NAND Detected\n");
|
|
return FALSE32;
|
|
}
|
|
|
|
if (!areChipIdsIdentical(chipIds, &chipId))
|
|
{
|
|
WMR_PRINT(INIT, "Chip IDs not identical!\n");
|
|
return FALSE32;
|
|
}
|
|
|
|
if (!checkCESymmetryAndGetPackageCnt(&_nandBoardInfo.landingMap, ceMap, &(detectedConfigId.packageCnt)))
|
|
{
|
|
WMR_PRINT(INIT, "Chip IDs not symmetrical!\n");
|
|
return FALSE32;
|
|
}
|
|
|
|
detectedConfigId.connectedBusCnt = numActiveDataBus;
|
|
|
|
nandInfo->geometry = lookupNandGeometry(chipId);
|
|
|
|
if (!nandInfo->geometry)
|
|
{
|
|
WMR_PRINT(INIT, "Unknown Chip ID!\n");
|
|
return FALSE32;
|
|
}
|
|
|
|
for (i = 0; i < detectedConfigId.packageCnt; i++)
|
|
{
|
|
WMR_MEMCPY(&(detectedConfigId.packageIds[i].chipId), nandInfo->geometry->chipId, sizeof(NandChipId));
|
|
detectedConfigId.packageIds[i].ceCnt = totalCECount / detectedConfigId.packageCnt;
|
|
}
|
|
|
|
nandInfo->boardSupport = lookupBoardSupport(&detectedConfigId);
|
|
nandInfo->configTiming = lookupNandTiming(&detectedConfigId);
|
|
|
|
if (!nandInfo->boardSupport)
|
|
{
|
|
WMR_PRINT(INIT, "Board support not found!\n");
|
|
return FALSE32;
|
|
}
|
|
|
|
if (!nandInfo->configTiming)
|
|
{
|
|
WMR_PRINT(INIT, "Nand timing not found!\n");
|
|
return FALSE32;
|
|
}
|
|
|
|
#if WITH_NAND_DT_CONFIG
|
|
currentNandInfo = *nandInfo;
|
|
currentCECount = totalCECount;
|
|
currentCEBitmap = ceMap;
|
|
currentActiveDataBus = numActiveDataBus;
|
|
#endif //WITH_NAND_DT_CONFIG
|
|
|
|
return TRUE32;
|
|
}
|
|
|
|
void setECCLevels(UInt32 numCorrectableBits, UInt32 refreshThresholdBits)
|
|
{
|
|
currentCorrectableBits = numCorrectableBits;
|
|
currentRefreshThreshold = refreshThresholdBits;
|
|
}
|
|
|
|
#if WITH_NAND_DT_CONFIG
|
|
void addNandProperty(DTNode *node, char *name, uint32_t value)
|
|
{
|
|
uint32_t propSize = 0;
|
|
void *propData = NULL;
|
|
|
|
if (FindProperty(node, &name, &propData, &propSize) &&
|
|
(propSize == sizeof(value)))
|
|
{
|
|
*(uint32_t*)propData = value;
|
|
}
|
|
else
|
|
{
|
|
WMR_PRINT(ERROR, "Failed to find NAND property: %s\n", name);
|
|
}
|
|
}
|
|
|
|
static void fillPpnFeatures(DTNode *node)
|
|
{
|
|
char *propName = "ppn-features";
|
|
void *propData = NULL;
|
|
UInt32 propSize = 0;
|
|
UInt32 totalSize = sizeof(_ppn_feature_size) + _ppn_feature_size;
|
|
UInt8 *cursor;
|
|
|
|
if (!FindProperty(node, &propName, &propData, &propSize) ||
|
|
(totalSize > propSize))
|
|
{
|
|
WMR_PANIC("expected device tree property %s of at least %u bytes", propName, (unsigned)totalSize);
|
|
}
|
|
|
|
cursor = propData;
|
|
|
|
WMR_MEMCPY(cursor, &_ppn_feature_size, sizeof(_ppn_feature_size));
|
|
cursor += sizeof(_ppn_feature_size);
|
|
|
|
WMR_MEMCPY(cursor, _ppn_feature_list, _ppn_feature_size);
|
|
cursor += _ppn_feature_size;
|
|
}
|
|
|
|
static void fillNandPpnProperties(DTNode *node)
|
|
{
|
|
const NandPpn *ppn = currentNandInfo.ppn;
|
|
|
|
addNandProperty(node, "ppn-spec-version", ppn->specVersion);
|
|
addNandProperty(node, "blocks-cau", ppn->blocksPerCau);
|
|
addNandProperty(node, "caus-ce", ppn->causPerCe);
|
|
addNandProperty(node, "slc-pages", ppn->slcPagesPerBlock);
|
|
addNandProperty(node, "mlc-pages", ppn->mlcPagesPerBlock);
|
|
addNandProperty(node, "match-oddeven-caus", ppn->matchOddEvenCaus);
|
|
addNandProperty(node, "cau-bits", ppn->bitsPerCau);
|
|
addNandProperty(node, "page-bits", ppn->bitsPerPage);
|
|
addNandProperty(node, "block-bits", ppn->bitsPerBlock);
|
|
addNandProperty(node, "max-transaction-size", ppn->maxTransactionSize);
|
|
|
|
fillPpnFeatures(node);
|
|
}
|
|
|
|
static void fillDbgChipIds(DTNode *node)
|
|
{
|
|
char *propName = "dbg-chipids";
|
|
void *propData = NULL;
|
|
UInt32 propSize = 0;
|
|
UInt32 totalSize = _dbg_chipids_size;
|
|
UInt8 *cursor;
|
|
|
|
if (NULL == _dbg_chipids_list)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (!FindProperty(node, &propName, &propData, &propSize) ||
|
|
(totalSize > propSize))
|
|
{
|
|
WMR_PRINT(ERROR, "expected device tree property %s of at least %lu bytes", propName, totalSize);
|
|
goto exit;
|
|
}
|
|
|
|
cursor = propData;
|
|
|
|
WMR_MEMCPY(cursor, _dbg_chipids_list, _dbg_chipids_size);
|
|
cursor += _dbg_chipids_size;
|
|
|
|
exit:
|
|
|
|
return;
|
|
}
|
|
|
|
void fillNandConfigProperties(DTNode *node)
|
|
{
|
|
uint32_t propSize = 0;
|
|
void *propData = NULL;
|
|
char *propName = NULL;
|
|
|
|
if (0 == currentCECount) {
|
|
fillDbgChipIds(node);
|
|
return;
|
|
}
|
|
|
|
// Configuration
|
|
addNandProperty(node, "#ce", currentCECount);
|
|
addNandProperty(node, "ce-bitmap", currentCEBitmap);
|
|
|
|
propName = "device-readid";
|
|
if (FindProperty(node, &propName, &propData, &propSize) &&
|
|
(propSize == NAND_CHIP_ID_SIZE))
|
|
{
|
|
WMR_MEMCPY(propData, currentNandInfo.geometry->chipId, NAND_CHIP_ID_SIZE);
|
|
}
|
|
|
|
// Geometry
|
|
addNandProperty(node, "#databus", currentActiveDataBus);
|
|
addNandProperty(node, "#ce-blocks", currentNandInfo.geometry->blocksPerCS);
|
|
addNandProperty(node, "#block-pages", currentNandInfo.geometry->pagesPerBlock);
|
|
addNandProperty(node, "#page-bytes", currentNandInfo.geometry->dataBytesPerPage);
|
|
addNandProperty(node, "#spare-bytes", currentNandInfo.geometry->spareBytesPerPage);
|
|
addNandProperty(node, "#die-ce", currentNandInfo.geometry->diesPerCS);
|
|
|
|
// Formatting
|
|
addNandProperty(node, "bbt-format", currentNandInfo.geometry->initialBBType);
|
|
addNandProperty(node, "vendor-type", currentNandInfo.boardSupport->vsType);
|
|
addNandProperty(node, "ecc-threshold", currentRefreshThreshold);
|
|
addNandProperty(node, "ecc-correctable", currentCorrectableBits);
|
|
|
|
// Bus Timing
|
|
addNandProperty(node, "read-setup-clks", _readSetupClocks);
|
|
addNandProperty(node, "read-hold-clks", _readHoldClocks);
|
|
addNandProperty(node, "read-dccycle-clks", _readDccycleClocks);
|
|
addNandProperty(node, "write-setup-clks", _writeSetupClocks);
|
|
addNandProperty(node, "write-hold-clks", _writeHoldClocks);
|
|
|
|
// NAND Format parameters
|
|
addNandProperty(node, "meta-per-logical-page", currentNandInfo.format->metaPerLogicalPage);
|
|
addNandProperty(node, "valid-meta-per-logical-page", currentNandInfo.format->validMetaPerLogicalPage);
|
|
if (currentNandInfo.format->logicalPageSize == 0)
|
|
{
|
|
// Use native page size
|
|
UInt32 pageSize = currentNandInfo.geometry->dataBytesPerPage;
|
|
addNandProperty(node, "logical-page-size", pageSize);
|
|
}
|
|
else
|
|
{
|
|
addNandProperty(node, "logical-page-size", currentNandInfo.format->logicalPageSize);
|
|
}
|
|
|
|
if (toggleDevice)
|
|
{
|
|
addNandProperty(node, "toggle-device", 1);
|
|
addNandProperty(node, "enable-diff-dqs", _nandBoardInfo.useDiffDQSMode);
|
|
addNandProperty(node, "enable-diff-re", _nandBoardInfo.useDiffREMode);
|
|
addNandProperty(node, "enable-vref", _nandBoardInfo.useVref);
|
|
|
|
addNandProperty(node, "dqs-half-cycle-clks", _dqsHalfCycleClocks);
|
|
|
|
addNandProperty(node, "ce-setup-clks", _ceSetupClocks);
|
|
addNandProperty(node, "ce-hold-clks", _ceHoldClocks);
|
|
addNandProperty(node, "adl-clks", _ADLClocks);
|
|
addNandProperty(node, "whr-clks", _WHRClocks);
|
|
|
|
addNandProperty(node, "read-pre-clks", _readPreClocks);
|
|
addNandProperty(node, "read-post-clks", _readPostClocks);
|
|
addNandProperty(node, "write-pre-clks", _writePreClocks);
|
|
addNandProperty(node, "write-post-clks", _writePostClocks);
|
|
|
|
addNandProperty(node, "reg-dqs-delay", _regDQSTimingCtrl);
|
|
}
|
|
else
|
|
{
|
|
addNandProperty(node, "toggle-device", 0);
|
|
}
|
|
|
|
if (ppnDevice == TRUE32)
|
|
{
|
|
addNandProperty(node, "ppn-device", 1);
|
|
fillNandPpnProperties(node);
|
|
}
|
|
else
|
|
{
|
|
addNandProperty(node, "ppn-device", 0);
|
|
}
|
|
|
|
addNandProperty(node, "retire-on-invalid-refresh", _retire_on_invalid_refresh);
|
|
|
|
}
|
|
|
|
#endif //WITH_NAND_CONFIG
|
|
|
|
void reportToggleModeFMCTimingValues(UInt32 dqsHalfCycleClocks,
|
|
UInt32 ceSetupClocks,
|
|
UInt32 ceHoldClocks,
|
|
UInt32 adlClocks,
|
|
UInt32 whrClocks,
|
|
UInt32 readPreClocks,
|
|
UInt32 readPostClocks,
|
|
UInt32 writePreClocks,
|
|
UInt32 writePostClocks,
|
|
UInt32 regDQSTimingCtrl)
|
|
{
|
|
_dqsHalfCycleClocks = dqsHalfCycleClocks;
|
|
_ceSetupClocks = ceSetupClocks;
|
|
_ceHoldClocks = ceHoldClocks;
|
|
_ADLClocks = adlClocks;
|
|
_WHRClocks = whrClocks;
|
|
_readPreClocks = readPreClocks;
|
|
_readPostClocks = readPostClocks;
|
|
_writePreClocks = writePreClocks;
|
|
_writePostClocks = writePostClocks;
|
|
_regDQSTimingCtrl = regDQSTimingCtrl;
|
|
}
|
|
|
|
void setToggleMode()
|
|
{
|
|
toggleDevice = TRUE32;
|
|
}
|
|
|
|
|
|
void reportFMCTimingValues(UInt32 readSetupClocks,
|
|
UInt32 readHoldClocks,
|
|
UInt32 readDccycleClocks,
|
|
UInt32 writeSetupClocks,
|
|
UInt32 writeHoldClocks)
|
|
{
|
|
_readSetupClocks = readSetupClocks;
|
|
_readHoldClocks = readHoldClocks;
|
|
_readDccycleClocks = readDccycleClocks;
|
|
_writeSetupClocks = writeSetupClocks;
|
|
_writeHoldClocks = writeHoldClocks;
|
|
}
|
|
|
|
void setNandIdPpnConfig(const NandChipId* chipIds,
|
|
NandInfo* nandInfo,
|
|
UInt32 busses,
|
|
UInt32 ces)
|
|
{
|
|
#if WITH_NAND_DT_CONFIG
|
|
currentActiveDataBus = busses;
|
|
currentNandInfo = *nandInfo;
|
|
|
|
getChipIdAndTotalCECountAndCEMap(chipIds, (NandChipId*)¤tNandInfo.geometry->chipId, ¤tCECount, ¤tCEBitmap);
|
|
WMR_ASSERT(ces == currentCECount);
|
|
#endif //WITH_NAND_DT_CONFIG
|
|
nandInfo->format = &_nandFormatPpn;
|
|
ppnDevice = TRUE32;
|
|
}
|
|
|
|
void setPPNOptions(BOOL32 retire_on_invalid_refresh)
|
|
{
|
|
_retire_on_invalid_refresh = retire_on_invalid_refresh;
|
|
}
|
|
|
|
void reportPpnFeatures(void *list, UInt32 size)
|
|
{
|
|
_ppn_feature_list = list;
|
|
_ppn_feature_size = size;
|
|
}
|
|
|
|
void reportDbgChipIds(void *list, UInt32 size)
|
|
{
|
|
_dbg_chipids_list = list;
|
|
_dbg_chipids_size = size;
|
|
}
|
|
|
|
// Bitmap of valid CEs (all CEs are identical to CE0) gets cross-checked
|
|
// against landing map from nand table
|
|
// If a valid CE bit is set on an invalid landing bit, returns error
|
|
BOOL32 checkPpnLandingMap(UInt32 validCEMap)
|
|
{
|
|
NandLandingMap *landingMap;
|
|
UInt32 i = 0;
|
|
UInt32 current;
|
|
UInt32 intersect, remainder;
|
|
|
|
landingMap = &_nandBoardInfo.landingMap;
|
|
remainder = validCEMap;
|
|
|
|
do {
|
|
current = (*landingMap)[i];
|
|
intersect = remainder & current;
|
|
remainder &= ~intersect;
|
|
i++;
|
|
} while ((current != 0) && (remainder != 0));
|
|
|
|
if (remainder != 0)
|
|
{
|
|
WMR_PRINT(ERROR, "Valid CE bit detected on an invalid landing bit!\n");
|
|
return FALSE32;
|
|
}
|
|
return TRUE32;
|
|
}
|
|
|
|
const NandFormat * getPPNFormat(void)
|
|
{
|
|
return &_nandFormatPpn;
|
|
}
|
|
|
|
BOOL32 targetSupportsToggle(void)
|
|
{
|
|
return _nandBoardInfo.useToggleMode ? TRUE32 : FALSE32;
|
|
}
|
|
|
|
BOOL32 targetSupportsDiffDQS(void)
|
|
{
|
|
return _nandBoardInfo.useDiffDQSMode ? TRUE32 : FALSE32;
|
|
}
|
|
|
|
BOOL32 targetSupportsDiffRE(void)
|
|
{
|
|
return _nandBoardInfo.useDiffREMode ? TRUE32 : FALSE32;
|
|
}
|
|
|
|
BOOL32 targetSupportsVREF(void)
|
|
{
|
|
return _nandBoardInfo.useVref ? TRUE32 : FALSE32;
|
|
}
|
|
|
|
BOOL32 targetSupportsSHC(void)
|
|
{
|
|
return _nandBoardInfo.useSingleHostChannel;
|
|
}
|
|
|
|
BOOL32 targetSupportsSingleCE(void)
|
|
{
|
|
return _nandBoardInfo.allowSingleChipEnable;
|
|
}
|
|
|
|
// Run only NAND chip identification
|
|
int flash_nand_id(void)
|
|
{
|
|
OAM_Init();
|
|
|
|
if (FIL_SUCCESS != FIL_Init())
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|