first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+192
View File
@@ -0,0 +1,192 @@
// *****************************************************************************
//
// File: H2FIL.c
//
// *****************************************************************************
//
// Notes:
//
// *****************************************************************************
//
// Copyright (C) 2008-2010 Apple, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi.h"
#include "H2fmi_ppn.h"
#include <WMROAM.h>
#include <WMRFeatures.h>
#include <FIL.h>
/*****************************************************************************/
/* Static variables definitions */
/*****************************************************************************/
/*****************************************************************************/
/* Code Implementation */
/*****************************************************************************/
static LowFuncTbl stLowFuncTbl =
{
.GetDeviceInfo = h2fmiGetDeviceInfo,
.Reset = h2fmiReset,
.CalcCurrentTiming = h2fmiCalcCurrentTimings,
.SetWhiteningState = h2fmiSetWhiteningState,
.SetWhiteningMetadataState = h2fmiSetWhiteningMetadataState,
.RegisterCurrentTransaction = h2fmiRegisterCurrentTransaction,
#if (defined(AND_SUPPORT_BLOCK_STORAGE) && AND_SUPPORT_BLOCK_STORAGE)
.SetDeviceInfo = h2fmiSetDeviceInfo,
.ReadWithECC = h2fmiReadSinglePage,
.ReadNoECC = h2fmiReadNoECC,
.ReadMultiplePages = h2fmiReadSequentialPages,
.ReadScatteredPages = h2fmiReadScatteredPages,
#endif
#if (AND_FPART_ONLY || AND_SUPPORT_BLOCK_STORAGE)
.ReadMaxECC = h2fmiReadSinglePageMaxECC,
#endif
#if ((defined(AND_SUPPORT_NVRAM) && AND_SUPPORT_NVRAM) || (defined(AND_SUPPORT_FW_AREA) && AND_SUPPORT_FW_AREA))
.ReadBLPage = h2fmiReadBootpage,
#endif
#if !H2FMI_READONLY
.WriteMultiplePages = h2fmiWriteMultiplePages,
.Write = h2fmiWriteSinglePage,
.WriteScatteredPages = h2fmiWriteScatteredPages,
.WriteMaxECC = h2fmiWriteSinglePageMaxECC,
#endif // !H2FMI_READONLY
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
.Erase = h2fmiEraseSingleBlock,
.EraseMultiple = NULL,
.WriteBLPage = h2fmiWriteBootpage,
#endif // !defined(AND_READONLY)
};
#if WITH_PPN
static LowFuncTbl stLowFuncTblPpn = {
#if (AND_SUPPORT_BLOCK_STORAGE || AND_SUPPORT_NVRAM || AND_SUPPORT_FW_AREA)
.GetDeviceInfo = h2fmiGetDeviceInfo,
.Reset = h2fmiReset,
.CalcCurrentTiming = h2fmiCalcCurrentTimings,
.SetWhiteningState = h2fmiSetWhiteningState,
.SetWhiteningMetadataState = h2fmiSetWhiteningMetadataState,
.RegisterCurrentTransaction = h2fmiRegisterCurrentTransaction,
.ReadWithECC = h2fmiPpnReadSinglePage,
#endif
#if (defined(AND_SUPPORT_BLOCK_STORAGE) && AND_SUPPORT_BLOCK_STORAGE)
.SetDeviceInfo = h2fmiSetDeviceInfo,
.ReadNoECC = NULL,
.ReadMultiplePages = NULL,
.ReadScatteredPages = NULL,
.ReadMaxECC = NULL,
#elif (defined(AND_FPART_ONLY) && AND_FPART_ONLY)
.ReadNoECC = NULL,
.ReadMaxECC = NULL,
#endif
#if ((defined(AND_SUPPORT_NVRAM) && AND_SUPPORT_NVRAM) || (defined(AND_SUPPORT_FW_AREA) && AND_SUPPORT_FW_AREA))
.ReadBLPage = h2fmiPpnReadBootpage,
#endif
#if !H2FMI_READONLY
.WriteMultiplePages = NULL,
.Write = h2fmiPpnWriteSinglePage,
.WriteScatteredPages = NULL,
.WriteMaxECC = NULL,
#endif // !H2FMI_READONLY
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
.Erase = h2fmiPpnEraseSingleBlock,
.EraseMultiple = NULL,
.WriteBLPage = h2fmiPpnWriteBootpage,
#endif
.PerformCommandList = h2fmiPpnPerformCommandList,
};
#endif //WITH_PPN
extern h2fmi_t g_fmi0;
/*****************************************************************************/
/* Code Implementation */
/*****************************************************************************/
Int32
FIL_Init(void)
{
Int32 nFILRet;
static BOOL32 bInitDone = FALSE32;
if (TRUE32 == bInitDone)
{
h2fmiPrintConfig();
return FIL_SUCCESS;
}
nFILRet = h2fmiInit();
if (nFILRet != FIL_SUCCESS)
{
return nFILRet;
}
#if !WITH_PPN
if (g_fmi0.is_ppn)
{
WMR_PRINT(ERROR, "[FIL:ERR] Build does not support PPN!\n");
return FIL_UNSUPPORTED_ERROR;
}
#endif // WITH_PPN
bInitDone = TRUE32;
return FIL_SUCCESS;
}
LowFuncTbl*
FIL_GetFuncTbl()
{
LowFuncTbl *ppn = NULL;
#if WITH_PPN
ppn = &stLowFuncTblPpn;
#endif // WITH_PPN
return (g_fmi0.is_ppn ? ppn : &stLowFuncTbl);
}
BOOL32 FIL_GetStruct(UInt32 dwStructType, void* pvoidStructBuffer, UInt32* pdwStructSize)
{
WMR_PRINT(INF, "[FIL:INF] FIL_GetStruct(0x%08X)\n", dwStructType);
return h2fmiGetStruct(dwStructType, pvoidStructBuffer, pdwStructSize);
}
#if AND_SUPPORT_BLOCK_STORAGE
BOOL32 FIL_SetStruct(UInt32 dwStructType, void* pvoidStructBuffer, UInt32 dwStructSize)
{
WMR_PRINT(INF,
"[FIL:INF] FIL_SetStruct(0x%08X, %d)\n", dwStructType, dwStructSize);
return h2fmiSetStruct(dwStructType, pvoidStructBuffer, dwStructSize);
}
#endif //AND_SUPPORT_BLOCK_STORAGE
void FIL_Close(void)
{
// do nothing
}
/*
void FIL_SwitchToPpn(void)
{
stLowFuncTbl.GetDeviceInfo = h2fmi_ppn_get_device_info;
}
*/
File diff suppressed because it is too large. Load diff
+69
View File
@@ -0,0 +1,69 @@
// *****************************************************************************
//
// File: H2fmi.h
//
// *****************************************************************************
//
// Notes:
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#ifndef _H2FMI_H_
#define _H2FMI_H_
#include <WMRTypes.h>
// =============================================================================
// public interface function declarations
// =============================================================================
Int32 h2fmiInit(void);
void h2fmiPrintConfig(void);
BOOL32 h2fmi_ppn_fil_init(void);
void h2fmi_ppn_recover_nand(void); //PPN
void h2fmiSetDeviceInfo(UInt32 dwParamType, UInt32 dwVal);
UInt32 h2fmiGetDeviceInfo(UInt32 dwParamType);
void h2fmiSetWhiteningState(BOOL32 enable);
void h2fmiSetWhiteningMetadataState(BOOL32 enable);
void h2fmiReset(void);
Int32 h2fmiReadNoECC(UInt16 wBank, UInt32 dwPpn, UInt8* pabDataBuf, UInt8* pabSpareBuf);
Int32 h2fmiReadSequentialPages(UInt32* padwPpn, UInt8* pabDataBuf, UInt8* pabMetaBuf, UInt16 wNumOfPagesToRead, UInt8* pbMaxCorrectedBits, UInt8* pdwaSectorStats, BOOL32 bDisableWhitening);
Int32 h2fmiReadScatteredPages(UInt16* pawBanks, UInt32* padwPpn, UInt8* pabDataBuf, UInt8* pabMetaBuf, UInt16 wNumOfPagesToRead, UInt8* pbMaxCorrectedBits, UInt8* pdwaSectorStats, BOOL32 bDisableWhitening);
Int32 h2fmiReadSinglePage(UInt16 wBank, UInt32 dwPpn, UInt8* pabDataBuf, UInt8* pabMetaBuf, UInt8* pbMaxCorrectedBits, UInt8* pdwaSectorStats, BOOL32 bDisableWhitening);
Int32 h2fmiReadSinglePageMaxECC(UInt16 wBank, UInt32 dwPpn, UInt8* pabDataBuf);
Int32 h2fmiPrintParameters(void);
Int32 h2fmiWriteMultiplePages(UInt32* padwPpn, UInt8* pabDataBuf, UInt8* pabMetaBuf, UInt16 wNumOfPagesToWrite, BOOL32 boolAligned, BOOL32 boolCorrectBank, UInt16* pwFailingCE, BOOL32 bDisableWhitening, UInt32 *pwFailingPageNum);
Int32 h2fmiWriteScatteredPages(UInt16 *pawBanks, UInt32 *padwPpn, UInt8 *pabDataBuf, UInt8 *pabMetaBuf, UInt16 wNumOfPagesToWrite, UInt16 *pawFailingCE, BOOL32 bDisableWhitening, UInt32 *pwFailingPageNum);
Int32 h2fmiWriteSinglePage(UInt16 wBank, UInt32 dwPpn, UInt8* pabDataBuf, UInt8* pabMetaBuf, BOOL32 bDisableWhitening);
Int32 h2fmiWriteSinglePageMaxECC(UInt16 wBank, UInt32 dwPpn, UInt8* pabDataBuf);
Int32 h2fmiEraseSingleBlock(UInt16 wBank, UInt32 wPbn);
void h2fmiCalcCurrentTimings(void);
BOOL32 h2fmiGetStruct(UInt32 dwStructType, void* pvoidStructBuffer, UInt32* pdwStructSize);
BOOL32 h2fmiSetStruct(UInt32 dwStructType, void* pvoidStructBuffer, UInt32 pdwStructSize);
void h2fmiRegisterCurrentTransaction(UInt64 ddwLba, UInt32 dwNum, void* pDest);
Int32 h2fmiWriteBootpage(UInt16 wCS, UInt32 dwPpn, UInt8 *pabData);
Int32 h2fmiReadBootpage(UInt16 wCS, UInt32 dwPpn, UInt8* pabData);
Int32 h2fmiReadBootpagePio(UInt16 wCS, UInt32 dwPpn, UInt8* pabData);
#endif // _H2FMI_H_
// ********************************** EOF **************************************
+502
View File
@@ -0,0 +1,502 @@
// *****************************************************************************
//
// File: H2fmi_regs.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position
//
// - consider adding definitions for extracting value from register position
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "WMRFeatures.h"
#if defined(H2FMI_EFI) && H2FMI_EFI
#include "SoC.h"
#else
#include <platform/soc/hwregbase.h>
#endif
#include <WMRTypes.h>
#ifndef _H2FMI_8920REGS_H_
#define _H2FMI_8922REGS_H_
// =============================================================================
// register bases and offsets
// =============================================================================
#define FMI0 ((UInt32*)FMI0_BASE_ADDR)
#define FMI1 ((UInt32*)FMI1_BASE_ADDR)
#define FMI_OFFSET (0x000)
#define FMC_OFFSET (0x400)
#define ECC_OFFSET (0x800)
#define FMC0 ((volatile UInt32*)((UInt32)FMI0 + FMC_OFFSET))
#define FMC1 ((volatile UInt32*)((UInt32)FMI1 + FMC_OFFSET))
#define FMI_BA(offset) ((UInt32)(FMI_OFFSET + offset))
#define FMC_BA(offset) ((UInt32)(FMC_OFFSET + offset))
#define ECC_BA(offset) ((UInt32)(ECC_OFFSET + offset))
#define FMI_CONFIG FMI_BA(0x00)
#define FMI_CONTROL FMI_BA(0x04)
#define FMI_STATUS FMI_BA(0x08)
#define FMI_INT_PEND FMI_BA(0x0C)
#define FMI_INT_EN FMI_BA(0x10)
#define FMI_DATA_BUF FMI_BA(0x14)
#define FMI_META_FIFO FMI_BA(0x18)
#define FMI_DEBUG0 FMI_BA(0x1C)
#define FMI_DEBUG1 FMI_BA(0x20)
#define FMI_DEBUG2 FMI_BA(0x24)
#define FMC_ON FMC_BA(0x00)
#define FMC_VER FMC_BA(0x04)
#define FMC_IF_CTRL FMC_BA(0x08)
#define FMC_CE_CTRL FMC_BA(0x0C)
#define FMC_RW_CTRL FMC_BA(0x10)
#define FMC_CMD FMC_BA(0x14)
#define FMC_ADDR0 FMC_BA(0x18)
#define FMC_ADDR1 FMC_BA(0x1C)
#define FMC_ADDRNUM FMC_BA(0x20)
#define FMC_DATANUM FMC_BA(0x24)
#define FMC_UNDEF0 FMC_BA(0x28)
#define FMC_UNDEF1 FMC_BA(0x2C)
#define FMC_TO_CTRL FMC_BA(0x30)
#define FMC_TO_CNT FMC_BA(0x34)
#define FMC_UNDEF2 FMC_BA(0x38)
#define FMC_UNDEF3 FMC_BA(0x3C)
#define FMC_INTMASK FMC_BA(0x40)
#define FMC_STATUS FMC_BA(0x44)
#define FMC_NAND_STATUS FMC_BA(0x48)
#define FMC_RBB_CONFIG FMC_BA(0x4C)
#define FMC_LOCK0_L FMC_BA(0x50)
#define FMC_LOCK0_H FMC_BA(0x54)
#define FMC_LOCK1_L FMC_BA(0x58)
#define FMC_LOCK1_H FMC_BA(0x5C)
#define FMC_LOCK2_L FMC_BA(0x60)
#define FMC_LOCK2_H FMC_BA(0x64)
#define FMC_ALARMCMD FMC_BA(0x68)
#define FMC_REJECTCMD FMC_BA(0x6C)
#define ECC_VERSION ECC_BA(0x00)
#define ECC_CON0 ECC_BA(0x04)
#define ECC_CON1 ECC_BA(0x08)
#define ECC_RESULT ECC_BA(0x0C)
#define ECC_PND ECC_BA(0x10)
#define ECC_MASK ECC_BA(0x14)
#define ECC_HISTORY ECC_BA(0x18)
#define ECC_CORE_SW_RESET ECC_BA(0x1C)
#define ECC_LOC0 ECC_BA(0x20)
#define ECC_LOC1 ECC_BA(0x24)
#define ECC_LOC2 ECC_BA(0x28)
#define ECC_LOC3 ECC_BA(0x2C)
#define ECC_LOC4 ECC_BA(0x30)
#define ECC_LOC5 ECC_BA(0x34)
#define ECC_LOC6 ECC_BA(0x38)
#define ECC_UNDEF0 ECC_BA(0x3C)
#define ECC_PARITY0 ECC_BA(0x40)
#define ECC_PARITY1 ECC_BA(0x44)
#define ECC_PARITY2 ECC_BA(0x48)
#define ECC_PARITY3 ECC_BA(0x4C)
#define ECC_PARITY4 ECC_BA(0x50)
#define ECC_PARITY5 ECC_BA(0x54)
#define ECC_PARITY6 ECC_BA(0x58)
// =============================================================================
// FMI_CONFIG bitfields
// =============================================================================
#define FMI_CONFIG__DMA_BURST(n) (((n) & 0x7) << 17)
#define FMI_CONFIG__LBA_MODE(v) (((v) & 0x3) << 15)
#define FMI_CONFIG__ECC_MODE(m) (((m) & 0x1) << 14)
#define FMI_CONFIG__META_PER_ENVELOPE(n) (((n) & 0x3F) << 8)
#define FMI_CONFIG__META_PER_PAGE(n) (((n) & 0x3F) << 2)
#define FMI_CONFIG__PAGE_SIZE(n) (((n) & 0x03) << 0)
#define FMI_CONFIG__DMA_BURST__32_CYCLES FMI_CONFIG__DMA_BURST(5)
#define FMI_CONFIG__DMA_BURST__16_CYCLES FMI_CONFIG__DMA_BURST(4)
#define FMI_CONFIG__DMA_BURST__8_CYCLES FMI_CONFIG__DMA_BURST(3)
#define FMI_CONFIG__DMA_BURST__4_CYCLES FMI_CONFIG__DMA_BURST(2)
#define FMI_CONFIG__DMA_BURST__2_CYCLES FMI_CONFIG__DMA_BURST(1)
#define FMI_CONFIG__DMA_BURST__1_CYCLES FMI_CONFIG__DMA_BURST(0)
#define FMI_CONFIG__LBA_MODE__NORMAL FMI_CONFIG__LBA_MODE(0)
#define FMI_CONFIG__LBA_MODE__BYPASS_ECC FMI_CONFIG__LBA_MODE(1)
#define FMI_CONFIG__LBA_MODE__LBA_TYPE_AB FMI_CONFIG__LBA_MODE(2)
#define FMI_CONFIG__LBA_MODE__LBA_TYPE_C FMI_CONFIG__LBA_MODE(3)
#define FMI_CONFIG__ECC_MODE__16BIT FMI_CONFIG__ECC_MODE(1)
#define FMI_CONFIG__ECC_MODE__8BIT FMI_CONFIG__ECC_MODE(0)
#define FMI_CONFIG__PAGE_SIZE__2K FMI_CONFIG__PAGE_SIZE(0)
#define FMI_CONFIG__PAGE_SIZE__4K FMI_CONFIG__PAGE_SIZE(1)
#define FMI_CONFIG__PAGE_SIZE__8K FMI_CONFIG__PAGE_SIZE(2)
#define FMI_CONFIG__PAGE_SIZE__512 FMI_CONFIG__PAGE_SIZE(3)
// =============================================================================
// FMI_CONTROL bitfields
// =============================================================================
#define FMI_CONTROL__MODE(m) (((m) & 0x3) << 1)
#define FMI_CONTROL__START_BIT (0x1UL << 0)
#define FMI_CONTROL__MODE__IDLE FMI_CONTROL__MODE(0)
#define FMI_CONTROL__MODE__READ FMI_CONTROL__MODE(1)
#define FMI_CONTROL__MODE__WRITE FMI_CONTROL__MODE(2)
#define FMI_CONTROL__MODE__UNDEF FMI_CONTROL__MODE(3)
// =============================================================================
// FMI_STATUS bitfields
// =============================================================================
#define FMI_STATUS__FMC_ACTIVE (0x1UL << 3)
#define FMI_STATUS__ECC_ACTIVE (0x1UL << 2)
#define FMI_STATUS__DMA_ACTIVE (0x1UL << 1)
#define FMI_STATUS__BUS_ACTIVE (0x1UL << 0)
// =============================================================================
// FMI_INT_PEND bitfields
// =============================================================================
#define FMI_INT_PEND__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_PEND__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_PEND__ECC_DONE (0x1UL << 19)
#define FMI_INT_PEND__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_PEND__FMC_READY_BUSY(n) (((n) & 0xFF) << 10)
#define FMI_INT_PEND__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_PEND__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_PEND__FMC_NSERR (0x1UL << 7)
#define FMI_INT_PEND__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_PEND__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_PEND__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_PEND__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_PEND__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_PEND__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_PEND__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_INT_EN bitfields
// =============================================================================
#define FMI_INT_EN__ECC_INTERRUPT (0x1UL << 14)
#define FMI_INT_EN__ECC_READY_BUSY (0x1UL << 13)
#define FMI_INT_EN__ECC_DONE (0x1UL << 12)
#define FMI_INT_EN__FMC_INTERRUPT (0x1UL << 11)
#define FMI_INT_EN__FMC_READY_BUSY (0x1UL << 10)
#define FMI_INT_EN__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_EN__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_EN__FMC_NSERR (0x1UL << 7)
#define FMI_INT_EN__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_EN__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_EN__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_EN__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_EN__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_EN__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_EN__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_DEBUG0 bitfields
// =============================================================================
#define FMI_DEBUG0__DMA_BLOCK_COUNT(n) (((n) & 0x1F) << 24)
#define FMI_DEBUG0__DATA_TC_RECEIVED (0x1UL << 23)
#define FMI_DEBUG0__DATA_DMA_DONE (0x1UL << 22)
#define FMI_DEBUG0__DMA_DATA_RW_PTR(n) (((n) & 0x7F) << 15)
#define FMI_DEBUG0__META_BYTE_COUNT(n) (((n) & 0x3F) << 9)
#define FMI_DEBUG0__FMC_TASKS_PENDING(n) (((n) & 0x3) << 7)
#define FMI_DEBUG0__ECC_TASKS_PENDING(n) (((n) & 0x3) << 5)
#define FMI_DEBUG0__DMA_TASKS_PENDING(n) (((n) & 0x3) << 3)
#define FMI_DEBUG0__FMC_TARGET_BUFFER(b) (((b) & 0x1) << 2)
#define FMI_DEBUG0__ECC_TARGET_BUFFER(b) (((b) & 0x1) << 1)
#define FMI_DEBUG0__DMA_TARGET_BUFFER(b) (((b) & 0x1) << 0)
// =============================================================================
// FMI_DEBUG1 bitfields
// =============================================================================
#define FMI_DEBUG1__META_TC_RECEIVED (0x1UL << 28)
#define FMI_DEBUG1__NEXT_META_LOCATION(n) (((n) & 0x3F) << 22)
#define FMI_DEBUG1__FMC_PAGE_DONE (0x1UL << 21)
#define FMI_DEBUG1__FMC_BLOCK_COUNT(n) (((n) & 0x1F) << 16)
#define FMI_DEBUG1__META_FIFO_LEVEL(n) (((n) & 0x3F) << 10)
#define FMI_DEBUG1__META_FIFO_WRITE_PTR(n) (((n) & 0x1F) << 5)
#define FMI_DEBUG1__META_FIFO_READ_PTR(n) (((n) & 0x1F) << 0)
// =============================================================================
// FMI_DEBUG2 bitfields
// =============================================================================
#define FMI_DEBUG2__BUFFER_1_META_BYTES(n) (((n) & 0x3F) << 24)
#define FMI_DEBUG2__BUFFER_0_META_BYTES(n) (((n) & 0x3F) << 18)
#define FMI_DEBUG2__META_BYTES_REMAINING(n) (((n) & 0x3F) << 12)
#define FMI_DEBUG2__PAUSED_AHB_ADDRESS(n) (((n) & 0xFF) << 4)
#define FMI_DEBUG2__AHB_STATE(n) (((n) & 0x3) << 1)
#define FMI_DEBUG2__PAUSED_AHB_BUS (0x1UL << 0)
// =============================================================================
// FMC_ON bitfields
// =============================================================================
#define FMC_ON__SWRST (0x1UL << 8)
#define FMC_ON__LOCK_ON (0x1UL << 4)
#define FMC_ON__CLKGATING_RDY (0x1UL << 1)
#define FMC_ON__ENABLE (0x1UL << 0)
#define FMC_ON__DISABLE (!FMC_ON__ENABLE)
// =============================================================================
// FMC_IF_CTRL bitfields
// =============================================================================
#define FMC_IF_CTRL__WPB (0x1UL << 21)
#define FMC_IF_CTRL__RBBEN (0x1UL << 20)
#define FMC_IF_CTRL__DCCYCLE(v) (((v) & 0xF) << 16)
#define FMC_IF_CTRL__REB_SETUP(v) (((v) & 0xF) << 12)
#define FMC_IF_CTRL__REB_HOLD(v) (((v) & 0xF) << 8)
#define FMC_IF_CTRL__WEB_SETUP(v) (((v) & 0xF) << 4)
#define FMC_IF_CTRL__WEB_HOLD(v) (((v) & 0xF) << 0)
#define FMC_IF_CTRL__GET_DCCYCLE(v) (((v) & 0xF0000) >> 16)
#define FMC_IF_CTRL__GET_REB_SETUP(v) (((v) & 0x0F000) >> 12)
#define FMC_IF_CTRL__GET_REB_HOLD(v) (((v) & 0x00F00) >> 8)
#define FMC_IF_CTRL__GET_WEB_SETUP(v) (((v) & 0x000F0) >> 4)
#define FMC_IF_CTRL__GET_WEB_HOLD(v) (((v) & 0x0000F) >> 0)
#define FMC_IF_CTRL__TIMING_MAX_CLOCKS (0xFUL)
// =============================================================================
// FMC_CE_CTRL bitfields
// =============================================================================
#define FMC_CE_CTRL__CE_COUNT (8)
#define FMC_CE_CTRL__CEB(n) (0x1UL << ((n) & 0x7))
#define FMC_CE_CTRL__CEB7 FMC_CE_CTRL__CEB(7)
#define FMC_CE_CTRL__CEB6 FMC_CE_CTRL__CEB(6)
#define FMC_CE_CTRL__CEB5 FMC_CE_CTRL__CEB(5)
#define FMC_CE_CTRL__CEB4 FMC_CE_CTRL__CEB(4)
#define FMC_CE_CTRL__CEB3 FMC_CE_CTRL__CEB(3)
#define FMC_CE_CTRL__CEB2 FMC_CE_CTRL__CEB(2)
#define FMC_CE_CTRL__CEB1 FMC_CE_CTRL__CEB(1)
#define FMC_CE_CTRL__CEB0 FMC_CE_CTRL__CEB(0)
// =============================================================================
// FMC_RW_CTRL bitfields
// =============================================================================
#define FMC_RW_CTRL__REBHOLD (0x1UL << 6)
#define FMC_RW_CTRL__WR_MODE (0x1UL << 5)
#define FMC_RW_CTRL__RD_MODE (0x1UL << 4)
#define FMC_RW_CTRL__ADDR_MODE (0x1UL << 3)
#define FMC_RW_CTRL__CMD3_MODE (0x1UL << 2)
#define FMC_RW_CTRL__CMD2_MODE (0x1UL << 1)
#define FMC_RW_CTRL__CMD1_MODE (0x1UL << 0)
// =============================================================================
// FMC_CMD bitfields
// =============================================================================
#define FMC_CMD__CMD3(c) (((c) & 0xFF) << 16)
#define FMC_CMD__CMD2(c) (((c) & 0xFF) << 8)
#define FMC_CMD__CMD1(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR0 bitfields
// =============================================================================
#define FMC_ADDR0__SEQ3(a) (((a) & 0xFF) << 24)
#define FMC_ADDR0__SEQ2(a) (((a) & 0xFF) << 16)
#define FMC_ADDR0__SEQ1(a) (((a) & 0xFF) << 8)
#define FMC_ADDR0__SEQ0(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR1 bitfields
// =============================================================================
#define FMC_ADDR1__SEQ7(a) (((a) & 0xFF) << 24)
#define FMC_ADDR1__SEQ6(a) (((a) & 0xFF) << 16)
#define FMC_ADDR1__SEQ5(a) (((a) & 0xFF) << 8)
#define FMC_ADDR1__SEQ4(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDRNUM bitfields
// =============================================================================
#define FMC_ADDRNUM__NUM(n) (((n) & 0x7) << 0)
// =============================================================================
// FMC_DATANUM bitfields
// =============================================================================
#define FMC_DATANUM__NUM(n) (((n) & 0x3F) << 0)
// =============================================================================
// FMC_TO_CTRL bitfields
// =============================================================================
#define FMC_TO_CTRL__EN (0x1UL << 12)
#define FMC_TO_CTRL__DIV(d) (((d) & 0xF) << 8)
#define FMC_TO_CTRL__VAL(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_TO_CNT bitfields
// =============================================================================
#define FMC_TO_CNT__CNT(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_INTMASK bitfields
// =============================================================================
#define FMC_INTMASK__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_INTMASK__RBBDONE7 FMC_INTMASK__RBBDONE(7)
#define FMC_INTMASK__RBBDONE6 FMC_INTMASK__RBBDONE(6)
#define FMC_INTMASK__RBBDONE5 FMC_INTMASK__RBBDONE(5)
#define FMC_INTMASK__RBBDONE4 FMC_INTMASK__RBBDONE(4)
#define FMC_INTMASK__RBBDONE3 FMC_INTMASK__RBBDONE(3)
#define FMC_INTMASK__RBBDONE2 FMC_INTMASK__RBBDONE(2)
#define FMC_INTMASK__RBBDONE1 FMC_INTMASK__RBBDONE(1)
#define FMC_INTMASK__RBBDONE0 FMC_INTMASK__RBBDONE(0)
#define FMC_INTMASK__TIMEOUT (0x1UL << 7)
#define FMC_INTMASK__NSERR (0x1UL << 6)
#define FMC_INTMASK__NSRBBDONE (0x1UL << 5)
#define FMC_INTMASK__TRANSDONE (0x1UL << 4)
#define FMC_INTMASK__ADDRESSDONE (0x1UL << 3)
#define FMC_INTMASK__CMD3DONE (0x1UL << 2)
#define FMC_INTMASK__CMD2DONE (0x1UL << 1)
#define FMC_INTMASK__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_STATUS bitfields
// =============================================================================
#define FMC_STATUS__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_STATUS__EMERGENCY2 (0x1UL << 21)
#define FMC_STATUS__EMERGENCY01 (0x1UL << 20)
#define FMC_STATUS__RDATADIRTY (0x1UL << 16)
#define FMC_STATUS__RBBDONE7 FMC_STATUS__RBBDONE(7)
#define FMC_STATUS__RBBDONE6 FMC_STATUS__RBBDONE(6)
#define FMC_STATUS__RBBDONE5 FMC_STATUS__RBBDONE(5)
#define FMC_STATUS__RBBDONE4 FMC_STATUS__RBBDONE(4)
#define FMC_STATUS__RBBDONE3 FMC_STATUS__RBBDONE(3)
#define FMC_STATUS__RBBDONE2 FMC_STATUS__RBBDONE(2)
#define FMC_STATUS__RBBDONE1 FMC_STATUS__RBBDONE(1)
#define FMC_STATUS__RBBDONE0 FMC_STATUS__RBBDONE(0)
#define FMC_STATUS__TIMEOUT (0x1UL << 7)
#define FMC_STATUS__NSERR (0x1UL << 6)
#define FMC_STATUS__NSRBBDONE (0x1UL << 5)
#define FMC_STATUS__TRANSDONE (0x1UL << 4)
#define FMC_STATUS__ADDRESSDONE (0x1UL << 3)
#define FMC_STATUS__CMD3DONE (0x1UL << 2)
#define FMC_STATUS__CMD2DONE (0x1UL << 1)
#define FMC_STATUS__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_RBB_CONFIG bitfields
// =============================================================================
#define FMC_RBB_CONFIG__POL(v) (((v) & 0xFF) << 8)
#define FMC_RBB_CONFIG__POS(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_ALARMCMD bitfields
// =============================================================================
#define FMC_ALARMCMD__READ1(v) (((v) & 0xFF) << 16)
#define FMC_ALARMCMD__PROG1(v) (((v) & 0xFF) << 8)
#define FMC_ALARMCMD__ERASE1(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_REJECTCMD bitfields
// =============================================================================
#define FMC_REJECTCMD__READ2(v) (((v) & 0xFF) << 16)
#define FMC_REJECTCMD__PROG2(v) (((v) & 0xFF) << 8)
#define FMC_REJECTCMD__ERASE2(v) (((v) & 0xFF) << 0)
// =============================================================================
// ECC_CON0 bitfields
// =============================================================================
#define ECC_CON0__META_LENGTH(n) (((n) & 0x1F) << 8)
#define ECC_CON0__MODE_SEL(m) (((m) & 0x1) << 2)
#define ECC_CON0__START_ENC (0x1UL << 1)
#define ECC_CON0__START_DEC (0x1UL << 0)
#define ECC_CON0__MODE_SEL__16BIT ECC_CON0__MODE_SEL(1)
#define ECC_CON0__MODE_SEL__8BIT ECC_CON0__MODE_SEL(0)
// =============================================================================
// ECC_CON1 bitfields
// =============================================================================
#define ECC_CON1__ERROR_ALERT_LEVEL(n) (((n) & 0x1F) << 8)
#define ECC_CON1__INT_ENABLE(b) (((b) & 0x1) << 7)
#define ECC_CON1__INT_ENABLE__ENABLE ECC_CON1__INT_ENABLE(1)
#define ECC_CON1__INT_ENABLE__DISABLE ECC_CON1__INT_ENABLE(0)
// =============================================================================
// ECC_RESULT bitfields
// =============================================================================
#define ECC_RESULT__ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_RESULT__ERROR_FLAG (0x1UL << 0)
// =============================================================================
// ECC_PND bitfields
// =============================================================================
#define ECC_PND__BCH_ALL_FF (0x1UL << 6)
#define ECC_PND__SECTOR_ERROR_ALERT (0x1UL << 5)
#define ECC_PND__READY_BUSY (0x1UL << 4)
#define ECC_PND__UNCORRECTABLE (0x1UL << 3)
#define ECC_PND__DEC_DONE (0x1UL << 2)
#define ECC_PND__ENC_DONE (0x1UL << 1)
#define ECC_PND__ENC_DEC_DONE (0x1UL << 0)
// =============================================================================
// ECC_MASK bitfields
// =============================================================================
#define ECC_MASK__SECTOR_ERR_ALERT_MASK (0x1UL << 5)
#define ECC_MASK__UNCORRECTABLE_MASK (0x1UL << 3)
#define ECC_MASK__DEC_DONE_MASK (0x1UL << 2)
#define ECC_MASK__ENC_DONE_MASK (0x1UL << 1)
#define ECC_MASK__ENC_DEC_DONE_MASK (0x1UL << 0)
// =============================================================================
// ECC_HISTORY bitfields
// =============================================================================
#define ECC_HISTORY__ERROR_COUNT_CLEAR (0x1UL << 24)
#define ECC_HISTORY__ERROR_COUNT(n) (((n) & 0x1FFF) << 11)
#define ECC_HISTORY__DECODING_NUMBER_CLEAR (0x1UL << 10)
#define ECC_HISTORY__DECODING_NUMBER(n) (((n) & 0x3FF) << 0)
// =============================================================================
// SoC-Specific Tuning
// =============================================================================
// These values have not been validated, but they are not used for H2P products
#define FMI_TX_PROP_DELAY_NS (15)
#define FMI_RX_PROP_DELAY_NS (15)
#endif // _H2FMI_8920REGS_H_
// ********************************** EOF **************************************
+535
View File
@@ -0,0 +1,535 @@
// *****************************************************************************
//
// File: H2fmi_regs.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position
//
// - consider adding definitions for extracting value from register position
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "WMRFeatures.h"
#if defined(H2FMI_EFI) && H2FMI_EFI
#include "SoC.h"
#else
#include <platform/soc/hwregbase.h>
#endif
#include <WMRTypes.h>
#ifndef _H2FMI_8922REGS_H_
#define _H2FMI_8922REGS_H_
// =============================================================================
// register bases and offsets
// =============================================================================
#define FMI0 ((UInt32*)FMI0_BASE_ADDR)
#define FMI1 ((UInt32*)FMI1_BASE_ADDR)
#define FMI_OFFSET (0x00000)
#define FMC_OFFSET (0x40000)
#define ECC_OFFSET (0x80000)
#define FMC0 ((volatile UInt32*)((UInt32)FMI0 + FMC_OFFSET))
#define FMC1 ((volatile UInt32*)((UInt32)FMI1 + FMC_OFFSET))
#define FMI_BA(offset) ((UInt32)(FMI_OFFSET + offset))
#define FMC_BA(offset) ((UInt32)(FMC_OFFSET + offset))
#define ECC_BA(offset) ((UInt32)(ECC_OFFSET + offset))
#define FMI_CONFIG FMI_BA(0x00)
#define FMI_CONTROL FMI_BA(0x04)
#define FMI_STATUS FMI_BA(0x08)
#define FMI_INT_PEND FMI_BA(0x0C)
#define FMI_INT_EN FMI_BA(0x10)
#define FMI_DATA_BUF FMI_BA(0x14)
#define FMI_META_FIFO FMI_BA(0x18)
#define FMI_DEBUG0 FMI_BA(0x1C)
#define FMI_DEBUG1 FMI_BA(0x20)
#define FMI_DEBUG2 FMI_BA(0x24)
#define FMI_DEBUG3 FMI_BA(0x28)
#define FMI_HW_VERSION FMI_BA(0x30)
#define FMI_DATA_SIZE FMI_BA(0x34)
#define FMI_BUFFER_0_BASE FMI_BA(0x1000)
#define FMI_BUFFER_1_BASE FMI_BA(0x1800)
#define FMI_BUFFER_LEN (0x45F)
#define FMC_ON FMC_BA(0x00)
#define FMC_VER FMC_BA(0x04)
#define FMC_IF_CTRL FMC_BA(0x08)
#define FMC_CE_CTRL FMC_BA(0x0C)
#define FMC_RW_CTRL FMC_BA(0x10)
#define FMC_CMD FMC_BA(0x14)
#define FMC_ADDR0 FMC_BA(0x18)
#define FMC_ADDR1 FMC_BA(0x1C)
#define FMC_ADDRNUM FMC_BA(0x20)
#define FMC_DATANUM FMC_BA(0x24)
#define FMC_UNDEF0 FMC_BA(0x28)
#define FMC_UNDEF1 FMC_BA(0x2C)
#define FMC_TO_CTRL FMC_BA(0x30)
#define FMC_TO_CNT FMC_BA(0x34)
#define FMC_UNDEF2 FMC_BA(0x38)
#define FMC_UNDEF3 FMC_BA(0x3C)
#define FMC_INTMASK FMC_BA(0x40)
#define FMC_STATUS FMC_BA(0x44)
#define FMC_NAND_STATUS FMC_BA(0x48)
#define FMC_RBB_CONFIG FMC_BA(0x4C)
#define FMC_LOCK0_L FMC_BA(0x50)
#define FMC_LOCK0_H FMC_BA(0x54)
#define FMC_LOCK1_L FMC_BA(0x58)
#define FMC_LOCK1_H FMC_BA(0x5C)
#define FMC_LOCK2_L FMC_BA(0x60)
#define FMC_LOCK2_H FMC_BA(0x64)
#define FMC_ALARMCMD FMC_BA(0x68)
#define FMC_REJECTCMD FMC_BA(0x6C)
#define ECC_VERSION ECC_BA(0x00)
#define ECC_CON0 ECC_BA(0x04)
#define ECC_CON1 ECC_BA(0x08)
#define ECC_RESULT ECC_BA(0x0C)
#define ECC_PND ECC_BA(0x10)
#define ECC_MASK ECC_BA(0x14)
#define ECC_HISTORY ECC_BA(0x18)
#define ECC_CORE_SW_RESET ECC_BA(0x1C)
#define ECC_LOC0 ECC_BA(0x20)
#define ECC_LOC1 ECC_BA(0x24)
#define ECC_LOC2 ECC_BA(0x28)
#define ECC_LOC3 ECC_BA(0x2C)
#define ECC_LOC4 ECC_BA(0x30)
#define ECC_LOC5 ECC_BA(0x34)
#define ECC_LOC6 ECC_BA(0x38)
#define ECC_UNDEF0 ECC_BA(0x3C)
#define ECC_PARITY0 ECC_BA(0x40)
#define ECC_PARITY1 ECC_BA(0x44)
#define ECC_PARITY2 ECC_BA(0x48)
#define ECC_PARITY3 ECC_BA(0x4C)
#define ECC_PARITY4 ECC_BA(0x50)
#define ECC_PARITY5 ECC_BA(0x54)
#define ECC_PARITY6 ECC_BA(0x58)
// =============================================================================
// FMI_CONFIG bitfields
// =============================================================================
#define FMI_CONFIG__DMA_BURST(n) (((n) & 0x7) << 0)
#define FMI_CONFIG__ECC_CORRECTABLE_BITS(m) (((m) & 0x1f) << 3)
#define FMI_CONFIG__DMA_BURST__32_CYCLES FMI_CONFIG__DMA_BURST(5)
#define FMI_CONFIG__DMA_BURST__16_CYCLES FMI_CONFIG__DMA_BURST(4)
#define FMI_CONFIG__DMA_BURST__8_CYCLES FMI_CONFIG__DMA_BURST(3)
#define FMI_CONFIG__DMA_BURST__4_CYCLES FMI_CONFIG__DMA_BURST(2)
#define FMI_CONFIG__DMA_BURST__2_CYCLES FMI_CONFIG__DMA_BURST(1)
#define FMI_CONFIG__DMA_BURST__1_CYCLES FMI_CONFIG__DMA_BURST(0)
// =============================================================================
// FMI_CONTROL bitfields
// =============================================================================
#define FMI_CONTROL__ECC_PAUSE (0x1UL << 7)
#define FMI_CONTROL__BUFFER_1_LOCK(m) (((m) & 0x3) << 5)
#define FMI_CONTROL__BUFFER_0_LOCK(m) (((m) & 0x3) << 3)
#define FMI_CONTROL__MODE(m) (((m) & 0x3) << 1)
#define FMI_CONTROL__START_BIT (0x1UL << 0)
#define FMI_CONTROL__MODE__IDLE FMI_CONTROL__MODE(0)
#define FMI_CONTROL__MODE__READ FMI_CONTROL__MODE(1)
#define FMI_CONTROL__MODE__WRITE FMI_CONTROL__MODE(2)
#define FMI_CONTROL__MODE__SOFTWARE_RESET FMI_CONTROL__MODE(3)
#define FMI_CONTROL__BUFFER_0_LOCK_FREE FMI_CONTROL__BUFFER_0_LOCK(0)
#define FMI_CONTROL__BUFFER_0_LOCK_DMA FMI_CONTROL__BUFFER_0_LOCK(1)
#define FMI_CONTROL__BUFFER_0_LOCK_ECC FMI_CONTROL__BUFFER_0_LOCK(2)
#define FMI_CONTROL__BUFFER_0_LOCK_FMC FMI_CONTROL__BUFFER_0_LOCK(3)
#define FMI_CONTROL_BUFFER_1_LOCK_FREE FMI_CONTROL__BUFFER_1_LOCK(0)
#define FMI_CONTROL_BUFFER_1_LOCK_DMA FMI_CONTROL__BUFFER_1_LOCK(1)
#define FMI_CONTROL_BUFFER_1_LOCK_ECC FMI_CONTROL__BUFFER_1_LOCK(2)
#define FMI_CONTROL_BUFFER_1_LOCK_FMC FMI_CONTROL__BUFFER_1_LOCK(3)
// =============================================================================
// FMI_STATUS bitfields
// =============================================================================
#define FMI_STATUS__FMC_ACTIVE (0x1UL << 3)
#define FMI_STATUS__ECC_ACTIVE (0x1UL << 2)
#define FMI_STATUS__DMA_ACTIVE (0x1UL << 1)
#define FMI_STATUS__BUS_ACTIVE (0x1UL << 0)
// =============================================================================
// FMI_INT_PEND bitfields
// =============================================================================
#define FMI_INT_PEND__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_PEND__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_PEND__ECC_DONE (0x1UL << 19)
#define FMI_INT_PEND__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_PEND__FMC_READY_BUSY(n) (((n) & 0xFF) << 10)
#define FMI_INT_PEND__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_PEND__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_PEND__FMC_NSERR (0x1UL << 7)
#define FMI_INT_PEND__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_PEND__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_PEND__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_PEND__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_PEND__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_PEND__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_PEND__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_INT_EN bitfields
// =============================================================================
#define FMI_INT_EN__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_EN__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_EN__ECC_DONE (0x1UL << 19)
#define FMI_INT_EN__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_EN__FMC_READY_BUSY (0x1UL << 10)
#define FMI_INT_EN__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_EN__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_EN__FMC_NSERR (0x1UL << 7)
#define FMI_INT_EN__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_EN__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_EN__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_EN__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_EN__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_EN__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_EN__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_DEBUG0 bitfields
// =============================================================================
#define FMI_DEBUG0__DMA_SECTOR_COUNT(n) (((n) & 0x7F) << 25)
#define FMI_DEBUG0__DATA_TC_RECEIVED (0x1UL << 24)
#define FMI_DEBUG0__DMA_WORD_COUNT(n) (((n) & 0x1FF) << 15)
#define FMI_DEBUG0__META_BYTE_COUNT(n) (((n) & 0x3F) << 9)
#define FMI_DEBUG0__FMC_TASKS_PENDING(n) (((n) & 0x3) << 7)
#define FMI_DEBUG0__ECC_TASKS_PENDING(n) (((n) & 0x3) << 5)
#define FMI_DEBUG0__DMA_TASKS_PENDING(n) (((n) & 0x3) << 3)
#define FMI_DEBUG0__FMC_TARGET_BUFFER(b) (((b) & 0x1) << 2)
#define FMI_DEBUG0__ECC_TARGET_BUFFER(b) (((b) & 0x1) << 1)
#define FMI_DEBUG0__DMA_TARGET_BUFFER(b) (((b) & 0x1) << 0)
// =============================================================================
// FMI_DEBUG1 bitfields
// =============================================================================
#define FMI_DEBUG1__METADATA_TC_RECEIVED(n) (0x1UL << 27)
#define FMI_DEBUG1__METADATA_ADDRESS(n) (((n) & 0x7FF) << 16)
#define FMI_DEBUG1__META_FIFO_LEVEL(n) (((n) & 0x3F) << 10)
#define FMI_DEBUG1__META_FIFO_WRITE_PTR(n) (((n) & 0x1F) << 5)
#define FMI_DEBUG1__META_FIFO_READ_PTR(n) (((n) & 0x1F) << 0)
// =============================================================================
// FMI_DEBUG2 bitfields
// =============================================================================
#define FMI_DEBUG2__BUFFER_1_META_BYTES(n) (((n) & 0x3F) << 19)
#define FMI_DEBUG2__BUFFER_0_META_BYTES(n) (((n) & 0x3F) << 13)
#define FMI_DEBUG2__META_BYTES_REMAINING(n) (((n) & 0x3F) << 7)
#define FMI_DEBUG2__DATA_STATE(n) (((n) & 0xF) << 3)
#define FMI_DEBUG2__AHB_STATE(n) (((n) & 0x7) << 0)
// =============================================================================
// FMI_DEBUG3 bitfields
// =============================================================================
#define FMI_DEBUG3__PAUSED_AHB_ADDRESS(n) (((n) & 0xFF) << 9)
#define FMI_DEBUG3__PAUSE_AHB_BUS (0x1UL << 8)
#define FMI_DEBUG3__FMC_PAGE_DONE (0x1UL << 7)
#define FMI_DEBUG3__FMC_BLOCK_COUNT(n) (((n) & 0x7F) << 0)
// =============================================================================
// FMI_DATA_SIZE bifields
// =============================================================================
#define FMI_DATA_SIZE__META_BYTES_PER_SECTOR(n) (((n) & 0x3F) << 25)
#define FMI_DATA_SIZE__META_BYTES_PER_PAGE(n) (((n) & 0x3F) << 19)
#define FMI_DATA_SIZE__BYTES_PER_SECTOR(n) (((n) & 0x7FF) << 8)
#define FMI_DATA_SIZE__SECTORS_PER_PAGE(n) (((n) & 0xFF) << 0)
// =============================================================================
// FMC_ON bitfields
// =============================================================================
#define FMC_ON__SWRST (0x1UL << 8)
#define FMC_ON__LOCK_ON (0x1UL << 4)
#define FMC_ON__CLKGATING_RDY (0x1UL << 1)
#define FMC_ON__ENABLE (0x1UL << 0)
#define FMC_ON__DISABLE (!FMC_ON__ENABLE)
// =============================================================================
// FMC_IF_CTRL bitfields
// =============================================================================
#define FMC_IF_CTRL__WPB (0x1UL << 21)
#define FMC_IF_CTRL__RBBEN (0x1UL << 20)
#define FMC_IF_CTRL__DCCYCLE(v) (WMR_MIN((v), 0xF) << 16)
#define FMC_IF_CTRL__REB_SETUP(v) (WMR_MIN((v), 0xF) << 12)
#define FMC_IF_CTRL__REB_HOLD(v) (WMR_MIN((v), 0xF) << 8)
#define FMC_IF_CTRL__WEB_SETUP(v) (WMR_MIN((v), 0xF) << 4)
#define FMC_IF_CTRL__WEB_HOLD(v) (WMR_MIN((v), 0xF) << 0)
#define FMC_IF_CTRL__GET_DCCYCLE(v) (((v) & 0xF0000) >> 16)
#define FMC_IF_CTRL__GET_REB_SETUP(v) (((v) & 0x0F000) >> 12)
#define FMC_IF_CTRL__GET_REB_HOLD(v) (((v) & 0x00F00) >> 8)
#define FMC_IF_CTRL__GET_WEB_SETUP(v) (((v) & 0x000F0) >> 4)
#define FMC_IF_CTRL__GET_WEB_HOLD(v) (((v) & 0x0000F) >> 0)
#define FMC_IF_CTRL__TIMING_MAX_CLOCKS (0xFUL)
// =============================================================================
// FMC_CE_CTRL bitfields
// =============================================================================
#define FMC_CE_CTRL__CE_COUNT (8)
#define FMC_CE_CTRL__CEB(n) (0x1UL << ((n) & 0x7))
#define FMC_CE_CTRL__CEB7 FMC_CE_CTRL__CEB(7)
#define FMC_CE_CTRL__CEB6 FMC_CE_CTRL__CEB(6)
#define FMC_CE_CTRL__CEB5 FMC_CE_CTRL__CEB(5)
#define FMC_CE_CTRL__CEB4 FMC_CE_CTRL__CEB(4)
#define FMC_CE_CTRL__CEB3 FMC_CE_CTRL__CEB(3)
#define FMC_CE_CTRL__CEB2 FMC_CE_CTRL__CEB(2)
#define FMC_CE_CTRL__CEB1 FMC_CE_CTRL__CEB(1)
#define FMC_CE_CTRL__CEB0 FMC_CE_CTRL__CEB(0)
// =============================================================================
// FMC_RW_CTRL bitfields
// =============================================================================
#define FMC_RW_CTRL__REBHOLD (0x1UL << 6)
#define FMC_RW_CTRL__WR_MODE (0x1UL << 5)
#define FMC_RW_CTRL__RD_MODE (0x1UL << 4)
#define FMC_RW_CTRL__ADDR_MODE (0x1UL << 3)
#define FMC_RW_CTRL__CMD3_MODE (0x1UL << 2)
#define FMC_RW_CTRL__CMD2_MODE (0x1UL << 1)
#define FMC_RW_CTRL__CMD1_MODE (0x1UL << 0)
// =============================================================================
// FMC_CMD bitfields
// =============================================================================
#define FMC_CMD__CMD3(c) (((c) & 0xFF) << 16)
#define FMC_CMD__CMD2(c) (((c) & 0xFF) << 8)
#define FMC_CMD__CMD1(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR0 bitfields
// =============================================================================
#define FMC_ADDR0__SEQ3(a) (((a) & 0xFF) << 24)
#define FMC_ADDR0__SEQ2(a) (((a) & 0xFF) << 16)
#define FMC_ADDR0__SEQ1(a) (((a) & 0xFF) << 8)
#define FMC_ADDR0__SEQ0(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR1 bitfields
// =============================================================================
#define FMC_ADDR1__SEQ7(a) (((a) & 0xFF) << 24)
#define FMC_ADDR1__SEQ6(a) (((a) & 0xFF) << 16)
#define FMC_ADDR1__SEQ5(a) (((a) & 0xFF) << 8)
#define FMC_ADDR1__SEQ4(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDRNUM bitfields
// =============================================================================
#define FMC_ADDRNUM__NUM(n) (((n) & 0x7) << 0)
// =============================================================================
// FMC_DATANUM bitfields
// =============================================================================
#define FMC_DATANUM__NUM(n) (((n) & 0x3FF) << 0)
// =============================================================================
// FMC_TO_CTRL bitfields
// =============================================================================
#define FMC_TO_CTRL__EN (0x1UL << 12)
#define FMC_TO_CTRL__DIV(d) (((d) & 0xF) << 8)
#define FMC_TO_CTRL__VAL(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_TO_CNT bitfields
// =============================================================================
#define FMC_TO_CNT__CNT(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_INTMASK bitfields
// =============================================================================
#define FMC_INTMASK__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_INTMASK__RBBDONE7 FMC_INTMASK__RBBDONE(7)
#define FMC_INTMASK__RBBDONE6 FMC_INTMASK__RBBDONE(6)
#define FMC_INTMASK__RBBDONE5 FMC_INTMASK__RBBDONE(5)
#define FMC_INTMASK__RBBDONE4 FMC_INTMASK__RBBDONE(4)
#define FMC_INTMASK__RBBDONE3 FMC_INTMASK__RBBDONE(3)
#define FMC_INTMASK__RBBDONE2 FMC_INTMASK__RBBDONE(2)
#define FMC_INTMASK__RBBDONE1 FMC_INTMASK__RBBDONE(1)
#define FMC_INTMASK__RBBDONE0 FMC_INTMASK__RBBDONE(0)
#define FMC_INTMASK__TIMEOUT (0x1UL << 7)
#define FMC_INTMASK__NSERR (0x1UL << 6)
#define FMC_INTMASK__NSRBBDONE (0x1UL << 5)
#define FMC_INTMASK__TRANSDONE (0x1UL << 4)
#define FMC_INTMASK__ADDRESSDONE (0x1UL << 3)
#define FMC_INTMASK__CMD3DONE (0x1UL << 2)
#define FMC_INTMASK__CMD2DONE (0x1UL << 1)
#define FMC_INTMASK__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_STATUS bitfields
// =============================================================================
#define FMC_STATUS__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_STATUS__EMERGENCY2 (0x1UL << 21)
#define FMC_STATUS__EMERGENCY01 (0x1UL << 20)
#define FMC_STATUS__RDATADIRTY (0x1UL << 16)
#define FMC_STATUS__RBBDONE7 FMC_STATUS__RBBDONE(7)
#define FMC_STATUS__RBBDONE6 FMC_STATUS__RBBDONE(6)
#define FMC_STATUS__RBBDONE5 FMC_STATUS__RBBDONE(5)
#define FMC_STATUS__RBBDONE4 FMC_STATUS__RBBDONE(4)
#define FMC_STATUS__RBBDONE3 FMC_STATUS__RBBDONE(3)
#define FMC_STATUS__RBBDONE2 FMC_STATUS__RBBDONE(2)
#define FMC_STATUS__RBBDONE1 FMC_STATUS__RBBDONE(1)
#define FMC_STATUS__RBBDONE0 FMC_STATUS__RBBDONE(0)
#define FMC_STATUS__TIMEOUT (0x1UL << 7)
#define FMC_STATUS__NSERR (0x1UL << 6)
#define FMC_STATUS__NSRBBDONE (0x1UL << 5)
#define FMC_STATUS__TRANSDONE (0x1UL << 4)
#define FMC_STATUS__ADDRESSDONE (0x1UL << 3)
#define FMC_STATUS__CMD3DONE (0x1UL << 2)
#define FMC_STATUS__CMD2DONE (0x1UL << 1)
#define FMC_STATUS__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_RBB_CONFIG bitfields
// =============================================================================
#define FMC_RBB_CONFIG__POL(v) (((v) & 0xFF) << 8)
#define FMC_RBB_CONFIG__POS(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_ALARMCMD bitfields
// =============================================================================
#define FMC_ALARMCMD__READ1(v) (((v) & 0xFF) << 16)
#define FMC_ALARMCMD__PROG1(v) (((v) & 0xFF) << 8)
#define FMC_ALARMCMD__ERASE1(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_REJECTCMD bitfields
// =============================================================================
#define FMC_REJECTCMD__READ2(v) (((v) & 0xFF) << 16)
#define FMC_REJECTCMD__PROG2(v) (((v) & 0xFF) << 8)
#define FMC_REJECTCMD__ERASE2(v) (((v) & 0xFF) << 0)
// =============================================================================
// ECC_CON0 bitfields
// =============================================================================
#define ECC_CON0__INFORMATION_LENGTH(n) (((n) & 0x7FF) << 16)
#define ECC_CON0__ECC_CORRECTION_MODE(m) (((m) & 0x1F) << 4)
#define ECC_CON0__START_ENC (0x1UL << 1)
#define ECC_CON0__START_DEC (0x1UL << 0)
// =============================================================================
// ECC_CON1 bitfields
// =============================================================================
#define ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(n) (((n) & 0x1F) << 16)
#define ECC_CON1__ERROR_ALERT_LEVEL(n) (((n) & 0x1F) << 8)
#define ECC_CON1__INT_ENABLE(b) (((b) & 0x1) << 7)
#define ECC_CON1__INT_ENABLE__ENABLE ECC_CON1__INT_ENABLE(1)
#define ECC_CON1__INT_ENABLE__DISABLE ECC_CON1__INT_ENABLE(0)
// =============================================================================
// ECC_RESULT bitfields
// =============================================================================
#define ECC_RESULT__ERROR_ALERT (0x1UL << 21)
#define ECC_RESULT__ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_RESULT__ERROR_CNT_SHIFT (16)
#define ECC_RESULT__ERROR_CNT_MASK (0x1FUL << ECC_RESULT__ERROR_CNT_SHIFT)
#define ECC_RESULT__STUCK_BIT_EXCEEDED (0x1UL << 14)
#define ECC_RESULT__STUCK_BIT_CNT(n) (((n) & 0x3F) << 8)
#define ECC_RESULT__ALL_FF (0x1UL << 3)
#define ECC_RESULT__ALL_ZERO (0x1UL << 2)
#define ECC_RESULT__FREE_PAGE (0x1UL << 1)
#define ECC_RESULT__UNCORRECTABLE (0x1UL << 0)
#define ECC_RESULT__FIFO_RESET (0x1UL << 0) // Same as uncorrectable bit
// =============================================================================
// ECC_PND bitfields
// =============================================================================
#define ECC_PND__MAX_STUCK_BIT_CNT(n) (((n) & 0x3F) << 24)
#define ECC_PND__MAX_ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_PND__MAX_ERROR_CNT_SHIFT (16)
#define ECC_PND__MAX_ERROR_CNT_MASK (0x1FUL << ECC_PND__MAX_ERROR_CNT_SHIFT)
#define ECC_PND__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_PND__SOME_ALL_FF (0x1UL << 8)
#define ECC_PND__SOME_ALL_ZERO (0x1UL << 7)
#define ECC_PND__ALL_FREE_PAGE (0x1UL << 6)
#define ECC_PND__SOME_ERROR_ALERT (0x1UL << 5)
#define ECC_PND__READY_BUSY (0x1UL << 4)
#define ECC_PND__ANY_UNCORRECTABLE (0x1UL << 3)
#define ECC_PND__ENC_DONE (0x1UL << 2)
#define ECC_PND__DEC_DONE (0x1UL << 1)
#define ECC_PND__ENC_DEC_DONE (0x1UL << 0)
// =============================================================================
// ECC_MASK bitfields
// =============================================================================
#define ECC_MASK__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_MASK__SOME_ALL_FF_MASK (0x1UL << 8)
#define ECC_MASK__SOME_ALL_ZERO_MASK (0x1UL << 7)
#define ECC_MASK__SOME_ERROR_ALERT_MASK (0x1UL << 5)
#define ECC_MASK__ANY_UNCORRECTABLE_MASK (0x1UL << 3)
#define ECC_MASK__ENC_DONE_MASK (0x1UL << 2)
#define ECC_MASK__DEC_DONE_MASK (0x1UL << 1)
#define ECC_MASK__ENC_DEC_DONE_MASK (0x1UL << 0)
// =============================================================================
// ECC_HISTORY bitfields
// =============================================================================
#define ECC_HISTORY__ERROR_COUNT_CLEAR (0x1UL << 26)
#define ECC_HISTORY__ERROR_COUNT(n) (((n) & 0x7FFF) << 11)
#define ECC_HISTORY__DECODING_NUMBER_CLEAR (0x1UL << 10)
#define ECC_HISTORY__DECODING_NUMBER(n) (((n) & 0x1FF) << 0)
// =============================================================================
// SoC-Specific Tuning
// =============================================================================
#define FMI_TX_PROP_DELAY_NS (6)
#define FMI_RX_PROP_DELAY_NS (6)
#endif // _H2FMI_8922REGS_H_
// ********************************** EOF *************************************
+767
View File
@@ -0,0 +1,767 @@
// *****************************************************************************
//
// File: H2fmi_regs.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position
//
// - consider adding definitions for extracting value from register position
//
// *****************************************************************************
//
// Copyright (C) 2009 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "WMRFeatures.h"
#if defined(H2FMI_EFI) && H2FMI_EFI
#include "SoC.h"
#else
#include <platform/soc/hwregbase.h>
#endif
#include <WMRTypes.h>
#ifndef _H2FMI_8940REGS_H_
#define _H2FMI_8940REGS_H_
// =============================================================================
// register bases and offsets
// =============================================================================
#define FMI0 ((UInt32*)FMI0_BASE_ADDR)
#define FMI1 ((UInt32*)FMI1_BASE_ADDR)
#define FMI2 ((UInt32*)FMI2_BASE_ADDR)
#define FMI3 ((UInt32*)FMI3_BASE_ADDR)
#define FMI_OFFSET (0x00000)
#define FMC_OFFSET (0x40000)
#define ECC_OFFSET (0x80000)
#define CMD_OFFSET (0xC0000)
#define FMC0 ((volatile UInt32*)((UInt32)FMI0 + FMC_OFFSET))
#define FMC1 ((volatile UInt32*)((UInt32)FMI1 + FMC_OFFSET))
#define FMC2 ((volatile UInt32*)((UInt32)FMI2 + FMC_OFFSET))
#define FMC3 ((volatile UInt32*)((UInt32)FMI3 + FMC_OFFSET))
#define FMI_BA(offset) ((UInt32)(FMI_OFFSET + offset))
#define FMC_BA(offset) ((UInt32)(FMC_OFFSET + offset))
#define ECC_BA(offset) ((UInt32)(ECC_OFFSET + offset))
#define CMD_BA(offset) ((UInt32)(CMD_OFFSET + offset))
#define FMI_CONFIG FMI_BA(0x00)
#define FMI_CONTROL FMI_BA(0x04)
#define FMI_STATUS FMI_BA(0x08)
#define FMI_INT_PEND FMI_BA(0x0C)
#define FMI_INT_EN FMI_BA(0x10)
#define FMI_DATA_BUF FMI_BA(0x14)
#define FMI_META_FIFO FMI_BA(0x18)
#define FMI_DEBUG0 FMI_BA(0x1C)
#define FMI_HW_VERSION FMI_BA(0x30)
#define FMI_DATA_SIZE FMI_BA(0x34)
#define FMI_RAW_PAGE_SIZE FMI_BA(0x38)
#define FMI_SCRAMBLER_SEED_FIFO FMI_BA(0x3C)
#define FMI_SEED_FIFO_LOW_LEVEL FMI_BA(0x40)
#define FMI_METADATA_FIFO_PTR FMI_BA(0x44)
#define FMI_SEED_FIFO_PTR FMI_BA(0x48)
#define FMI_RANDOMIZER_VERSION FMI_BA(0x4C)
#define FMI_BUFFER_0_BASE FMI_BA(0x1000)
#define FMI_BUFFER_1_BASE FMI_BA(0x1800)
#define FMI_BUFFER_LEN (0x45F)
#define FMC_ON FMC_BA(0x00)
#define FMC_VER FMC_BA(0x04)
#define FMC_IF_CTRL FMC_BA(0x08)
#define FMC_CE_CTRL FMC_BA(0x0C)
#define FMC_RW_CTRL FMC_BA(0x10)
#define FMC_CMD FMC_BA(0x14)
#define FMC_ADDR0 FMC_BA(0x18)
#define FMC_ADDR1 FMC_BA(0x1C)
#define FMC_ADDRNUM FMC_BA(0x20)
#define FMC_DATANUM FMC_BA(0x24)
#define FMC_UNDEF0 FMC_BA(0x28)
#define FMC_UNDEF1 FMC_BA(0x2C)
#define FMC_TO_CTRL FMC_BA(0x30)
#define FMC_TO_CNT FMC_BA(0x34)
#define FMC_UNDEF2 FMC_BA(0x38)
#define FMC_UNDEF3 FMC_BA(0x3C)
#define FMC_INTMASK FMC_BA(0x40)
#define FMC_STATUS FMC_BA(0x44)
#define FMC_NAND_STATUS FMC_BA(0x48)
#define FMC_RBB_CONFIG FMC_BA(0x4C)
#define FMC_LOCK0_L FMC_BA(0x50)
#define FMC_LOCK0_H FMC_BA(0x54)
#define FMC_LOCK1_L FMC_BA(0x58)
#define FMC_LOCK1_H FMC_BA(0x5C)
#define FMC_LOCK2_L FMC_BA(0x60)
#define FMC_LOCK2_H FMC_BA(0x64)
#define FMC_ALARMCMD FMC_BA(0x68)
#define FMC_REJECTCMD FMC_BA(0x6C)
#define FMC_DQS_TIMING_CTRL FMC_BA(0x70)
#define FMC_TOGGLE_CTRL_1 FMC_BA(0x74)
#define FMC_TOGGLE_CTRL_2 FMC_BA(0x78)
#define FMC_TOGGLE_CTRL_3 FMC_BA(0x7C)
#define ECC_VERSION ECC_BA(0x00)
#define ECC_CON0 ECC_BA(0x04)
#define ECC_CON1 ECC_BA(0x08)
#define ECC_RESULT ECC_BA(0x0C)
#define ECC_PND ECC_BA(0x10)
#define ECC_MASK ECC_BA(0x14)
#define ECC_HISTORY ECC_BA(0x18)
#define ECC_CORE_SW_RESET ECC_BA(0x1C)
#define ECC_PAGE_ERROR_FIFO ECC_BA(0x24)
#define ECC_PAGE_ERROR_FIFO_PTR ECC_BA(0x28)
#define ECC_RESULTS_FIFO_PTR ECC_BA(0x2C)
#define COMMAND_FIFO CMD_BA(0x00)
#define COMMAND_FIFO_PTR CMD_BA(0x04)
#define COMMAND_FIFO_LOW CMD_BA(0x08)
#define COMMAND_COUNT CMD_BA(0x0C)
#define COMMAND_INT_CODE CMD_BA(0x10)
#define OPERAND_FIFO CMD_BA(0x14)
#define OPERAND_FIFO_PTR CMD_BA(0x18)
#define OPERAND_FIFO_LOW CMD_BA(0x1C)
#define SEQ_INT_PEND CMD_BA(0x20)
#define SEQ_INT_EN CMD_BA(0x24)
#define SEQ_MACRO_CONTROL CMD_BA(0x28)
#define TIMEOUT_VALUE CMD_BA(0x2C)
#define SEQUENCER_MACROS(n) CMD_BA(0x1000 + ((n) & 0xFF))
#define SEQUENCER_COMMANDS(n) CMD_BA(0x2000 + ((n) & 0x7F))
#define SEQUENCER_OPERANDS(n) CMD_BA(0x3000 + ((n) & 0x7F))
// =============================================================================
// FMI_CONFIG bitfields
// =============================================================================
#define FMI_CONFIG__DMA_BURST(n) (((n) & 0x7) << 0)
#define FMI_CONFIG__ECC_CORRECTABLE_BITS(m) (((m) & 0x1f) << 3)
#define FMI_CONFIG__ENABLE_WHITENING (0x1UL << 8)
#define FMI_CONFIG__DMA_BURST__32_CYCLES FMI_CONFIG__DMA_BURST(5)
#define FMI_CONFIG__DMA_BURST__16_CYCLES FMI_CONFIG__DMA_BURST(4)
#define FMI_CONFIG__DMA_BURST__8_CYCLES FMI_CONFIG__DMA_BURST(3)
#define FMI_CONFIG__DMA_BURST__4_CYCLES FMI_CONFIG__DMA_BURST(2)
#define FMI_CONFIG__DMA_BURST__2_CYCLES FMI_CONFIG__DMA_BURST(1)
#define FMI_CONFIG__DMA_BURST__1_CYCLES FMI_CONFIG__DMA_BURST(0)
// =============================================================================
// FMI_CONTROL bitfields
// =============================================================================
#define FMI_CONTROL__SEQUENCER_TIMEOUT_ENABLE (0x1UL << 12)
#define FMI_CONTROL__RESET_SEED (0x1UL << 11)
#define FMI_CONTROL__RAW_READ_MODE (0x1UL << 10)
#define FMI_CONTROL__RESET_SEQUENCER (0x1UL << 9)
#define FMI_CONTROL__ENABLE_SEQUENCER (0x1UL << 8)
#define FMI_CONTROL__ECC_PAUSE (0x1UL << 7)
#define FMI_CONTROL__BUFFER_1_LOCK(m) (((m) & 0x3) << 5)
#define FMI_CONTROL__BUFFER_0_LOCK(m) (((m) & 0x3) << 3)
#define FMI_CONTROL__MODE(m) (((m) & 0x3) << 1)
#define FMI_CONTROL__START_BIT (0x1UL << 0)
#define FMI_CONTROL__MODE__IDLE FMI_CONTROL__MODE(0)
#define FMI_CONTROL__MODE__READ FMI_CONTROL__MODE(1)
#define FMI_CONTROL__MODE__WRITE FMI_CONTROL__MODE(2)
#define FMI_CONTROL__MODE__SOFTWARE_RESET FMI_CONTROL__MODE(3)
#define FMI_CONTROL__BUFFER_0_LOCK_FREE FMI_CONTROL__BUFFER_0_LOCK(0)
#define FMI_CONTROL__BUFFER_0_LOCK_DMA FMI_CONTROL__BUFFER_0_LOCK(1)
#define FMI_CONTROL__BUFFER_0_LOCK_ECC FMI_CONTROL__BUFFER_0_LOCK(2)
#define FMI_CONTROL__BUFFER_0_LOCK_FMC FMI_CONTROL__BUFFER_0_LOCK(3)
#define FMI_CONTROL_BUFFER_1_LOCK_FREE FMI_CONTROL__BUFFER_1_LOCK(0)
#define FMI_CONTROL_BUFFER_1_LOCK_DMA FMI_CONTROL__BUFFER_1_LOCK(1)
#define FMI_CONTROL_BUFFER_1_LOCK_ECC FMI_CONTROL__BUFFER_1_LOCK(2)
#define FMI_CONTROL_BUFFER_1_LOCK_FMC FMI_CONTROL__BUFFER_1_LOCK(3)
// =============================================================================
// FMI_STATUS bitfields
// =============================================================================
#define FMI_STATUS__FMC_ACTIVE (0x1UL << 3)
#define FMI_STATUS__ECC_ACTIVE (0x1UL << 2)
#define FMI_STATUS__DMA_ACTIVE (0x1UL << 1)
#define FMI_STATUS__BUS_ACTIVE (0x1UL << 0)
// =============================================================================
// FMI_INT_PEND bitfields
// =============================================================================
#define FMI_INT_PEND__SEQUENCER_INTERRUPT (0x1UL << 28)
#define FMI_INT_PEND__SEED_FIFO_EMPTY (0x1UL << 27)
#define FMI_INT_PEND__SEED_FIFO_LOW (0x1UL << 26)
#define FMI_INT_PEND__SEED_FIFO_OVERFLOW (0x1UL << 25)
#define FMI_INT_PEND__ECC_RESULTS_FIFO_UNDERFLOW (0x1UL << 24)
#define FMI_INT_PEND__ECC_RESULTS_FIFO_OVERFLOW (0x1UL << 23)
#define FMI_INT_PEND__LAST_ECC_DONE (0x1UL << 22)
#define FMI_INT_PEND__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_PEND__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_PEND__ECC_DONE (0x1UL << 19)
#define FMI_INT_PEND__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_PEND__FMC_READY_BUSY(n) (((n) & 0xFF) << 10)
#define FMI_INT_PEND__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_PEND__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_PEND__FMC_NSERR (0x1UL << 7)
#define FMI_INT_PEND__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_PEND__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_PEND__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_PEND__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_PEND__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_PEND__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_PEND__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_INT_EN bitfields
// =============================================================================
#define FMI_INT_EN__SEQUENCER_INTERRUPT (0x1UL << 28)
#define FMI_INT_EN__SEED_FIFO_EMPTY (0x1UL << 27)
#define FMI_INT_EN__SEED_FIFO_LOW (0x1UL << 26)
#define FMI_INT_EN__SEED_FIFO_OVERFLOW (0x1UL << 25)
#define FMI_INT_EN__ECC_RESULTS_FIFO_UNDERFLOW (0x1UL << 24)
#define FMI_INT_EN__ECC_RESULTS_FIFO_OVERFLOW (0x1UL << 23)
#define FMI_INT_EN__LAST_ECC_DONE (0x1UL << 22)
#define FMI_INT_EN__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_EN__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_EN__ECC_DONE (0x1UL << 19)
#define FMI_INT_EN__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_EN__FMC_READY_BUSY (0x1UL << 10)
#define FMI_INT_EN__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_EN__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_EN__FMC_NSERR (0x1UL << 7)
#define FMI_INT_EN__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_EN__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_EN__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_EN__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_EN__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_EN__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_EN__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_DEBUG0 bitfields
// =============================================================================
#define FMI_DEBUG0__FMC_TASKS_PENDING(n) (((n) & 0x3) << 7)
#define FMI_DEBUG0__ECC_TASKS_PENDING(n) (((n) & 0x3) << 5)
#define FMI_DEBUG0__DMA_TASKS_PENDING(n) (((n) & 0x3) << 3)
#define FMI_DEBUG0__FMC_TARGET_BUFFER(b) (((b) & 0x1) << 2)
#define FMI_DEBUG0__ECC_TARGET_BUFFER(b) (((b) & 0x1) << 1)
#define FMI_DEBUG0__DMA_TARGET_BUFFER(b) (((b) & 0x1) << 0)
// =============================================================================
// FMI_DATA_SIZE bifields
// =============================================================================
#define FMI_DATA_SIZE__META_BYTES_PER_SECTOR(n) (((n) & 0x3F) << 25)
#define FMI_DATA_SIZE__META_BYTES_PER_PAGE(n) (((n) & 0x3F) << 19)
#define FMI_DATA_SIZE__BYTES_PER_SECTOR(n) (((n) & 0x7FF) << 8)
#define FMI_DATA_SIZE__SECTORS_PER_PAGE(n) (((n) & 0xFF) << 0)
// =============================================================================
// FMI_SEED_FIFO_LOW_LEVEL bitfields
// =============================================================================
#define FMI_SEED_FIFO_LOW_LEVEL__LEVEL(x) (((x) & 0x7) << 0)
// =============================================================================
// METADATA_FIFO_PTR bitfields
// =============================================================================
#define METADATA_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define METADATA_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define METADATA_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// SEED_FIFO_PTR bitfields
// =============================================================================
#define SEED_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x7)
#define SEED_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x7)
#define SEED_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0xF)
// =============================================================================
// FMC_ON bitfields
// =============================================================================
#define FMC_ON__SWRST (0x1UL << 8)
#define FMC_ON__ASYNC_DRIVE_DQS (0x1UL << 6)
#define FMC_ON__ASYNC_CEB_AUTO_DISABLE (0x1UL << 5)
#define FMC_ON__LOCK_ON (0x1UL << 4)
#define FMC_ON__DDR_NAND_TYPE_TOGGLE (0x0UL << 3)
#define FMC_ON__DDR_NAND_TYPE_ONFI (0x1UL << 3)
#define FMC_ON__DDR_ENABLE (0x1UL << 2)
#define FMC_ON__CLKGATING_RDY (0x1UL << 1)
#define FMC_ON__ENABLE (0x1UL << 0)
#define FMC_ON__DISABLE (!FMC_ON__ENABLE)
// =============================================================================
// FMC_IF_CTRL bitfields
// =============================================================================
#define FMC_IF_CTRL__WPB (0x1UL << 21)
#define FMC_IF_CTRL__RBBEN (0x1UL << 20)
//<rdar://problem/8076977> Change DCCycle calculation for h4p due to silicon bug
#define FMC_IF_CTRL__DCCYCLE(v) (((v) & 0xF) << 16)
#define FMC_IF_CTRL__REB_SETUP(v) (((v) & 0xF) << 12)
#define FMC_IF_CTRL__REB_HOLD(v) (((v) & 0xF) << 8)
#define FMC_IF_CTRL__WEB_SETUP(v) (((v) & 0xF) << 4)
#define FMC_IF_CTRL__WEB_HOLD(v) (((v) & 0xF) << 0)
#define FMC_IF_CTRL__GET_DCCYCLE(v) (((v) & 0xF0000) >> 16)
#define FMC_IF_CTRL__GET_REB_SETUP(v) (((v) & 0x0F000) >> 12)
#define FMC_IF_CTRL__GET_REB_HOLD(v) (((v) & 0x00F00) >> 8)
#define FMC_IF_CTRL__GET_WEB_SETUP(v) (((v) & 0x000F0) >> 4)
#define FMC_IF_CTRL__GET_WEB_HOLD(v) (((v) & 0x0000F) >> 0)
#define FMC_IF_CTRL__REB_SETUP_MASK (0x0000000F << 12)
#define FMC_IF_CTRL__TIMING_MAX_CLOCKS (0xFUL)
// =============================================================================
// FMC_CE_CTRL bitfields
// =============================================================================
#define FMC_CE_CTRL__CE_COUNT (8)
#define FMC_CE_CTRL__CEB(n) (0x1UL << ((n) & 0x7))
#define FMC_CE_CTRL__CEB7 FMC_CE_CTRL__CEB(7)
#define FMC_CE_CTRL__CEB6 FMC_CE_CTRL__CEB(6)
#define FMC_CE_CTRL__CEB5 FMC_CE_CTRL__CEB(5)
#define FMC_CE_CTRL__CEB4 FMC_CE_CTRL__CEB(4)
#define FMC_CE_CTRL__CEB3 FMC_CE_CTRL__CEB(3)
#define FMC_CE_CTRL__CEB2 FMC_CE_CTRL__CEB(2)
#define FMC_CE_CTRL__CEB1 FMC_CE_CTRL__CEB(1)
#define FMC_CE_CTRL__CEB0 FMC_CE_CTRL__CEB(0)
// =============================================================================
// FMC_RW_CTRL bitfields
// =============================================================================
#define FMC_RW_CTRL__NAND_TIMING_USER_TAT(x) (((x) & 0xFFFF) << 24)
#define FMC_RW_CTRL__RD_DONE_REB_CEB_HOLD (0x1UL << 7)
#define FMC_RW_CTRL__REBHOLD (0x1UL << 6)
#define FMC_RW_CTRL__WR_MODE (0x1UL << 5)
#define FMC_RW_CTRL__RD_MODE (0x1UL << 4)
#define FMC_RW_CTRL__ADDR_MODE (0x1UL << 3)
#define FMC_RW_CTRL__CMD3_MODE (0x1UL << 2)
#define FMC_RW_CTRL__CMD2_MODE (0x1UL << 1)
#define FMC_RW_CTRL__CMD1_MODE (0x1UL << 0)
// =============================================================================
// FMC_CMD bitfields
// =============================================================================
#define FMC_CMD__CMD3(c) (((c) & 0xFF) << 16)
#define FMC_CMD__CMD2(c) (((c) & 0xFF) << 8)
#define FMC_CMD__CMD1(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR0 bitfields
// =============================================================================
#define FMC_ADDR0__SEQ3(a) (((a) & 0xFF) << 24)
#define FMC_ADDR0__SEQ2(a) (((a) & 0xFF) << 16)
#define FMC_ADDR0__SEQ1(a) (((a) & 0xFF) << 8)
#define FMC_ADDR0__SEQ0(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR1 bitfields
// =============================================================================
#define FMC_ADDR1__SEQ7(a) (((a) & 0xFF) << 24)
#define FMC_ADDR1__SEQ6(a) (((a) & 0xFF) << 16)
#define FMC_ADDR1__SEQ5(a) (((a) & 0xFF) << 8)
#define FMC_ADDR1__SEQ4(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDRNUM bitfields
// =============================================================================
#define FMC_ADDRNUM__NUM(n) (((n) & 0x7) << 0)
// =============================================================================
// FMC_DATANUM bitfields
// =============================================================================
#define FMC_DATANUM__NUM(n) (((n) & 0x3FF) << 0)
// =============================================================================
// FMC_TO_CTRL bitfields
// =============================================================================
#define FMC_TO_CTRL__EN (0x1UL << 12)
#define FMC_TO_CTRL__DIV(d) (((d) & 0xF) << 8)
#define FMC_TO_CTRL__VAL(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_TO_CNT bitfields
// =============================================================================
#define FMC_TO_CNT__CNT(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_INTMASK bitfields
// =============================================================================
#define FMC_INTMASK__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_INTMASK__RBBDONE7 FMC_INTMASK__RBBDONE(7)
#define FMC_INTMASK__RBBDONE6 FMC_INTMASK__RBBDONE(6)
#define FMC_INTMASK__RBBDONE5 FMC_INTMASK__RBBDONE(5)
#define FMC_INTMASK__RBBDONE4 FMC_INTMASK__RBBDONE(4)
#define FMC_INTMASK__RBBDONE3 FMC_INTMASK__RBBDONE(3)
#define FMC_INTMASK__RBBDONE2 FMC_INTMASK__RBBDONE(2)
#define FMC_INTMASK__RBBDONE1 FMC_INTMASK__RBBDONE(1)
#define FMC_INTMASK__RBBDONE0 FMC_INTMASK__RBBDONE(0)
#define FMC_INTMASK__TIMEOUT (0x1UL << 7)
#define FMC_INTMASK__NSERR (0x1UL << 6)
#define FMC_INTMASK__NSRBBDONE (0x1UL << 5)
#define FMC_INTMASK__TRANSDONE (0x1UL << 4)
#define FMC_INTMASK__ADDRESSDONE (0x1UL << 3)
#define FMC_INTMASK__CMD3DONE (0x1UL << 2)
#define FMC_INTMASK__CMD2DONE (0x1UL << 1)
#define FMC_INTMASK__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_STATUS bitfields
// =============================================================================
#define FMC_STATUS__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_STATUS__EMERGENCY2 (0x1UL << 21)
#define FMC_STATUS__EMERGENCY01 (0x1UL << 20)
#define FMC_STATUS__RDATADIRTY (0x1UL << 16)
#define FMC_STATUS__RBBDONE7 FMC_STATUS__RBBDONE(7)
#define FMC_STATUS__RBBDONE6 FMC_STATUS__RBBDONE(6)
#define FMC_STATUS__RBBDONE5 FMC_STATUS__RBBDONE(5)
#define FMC_STATUS__RBBDONE4 FMC_STATUS__RBBDONE(4)
#define FMC_STATUS__RBBDONE3 FMC_STATUS__RBBDONE(3)
#define FMC_STATUS__RBBDONE2 FMC_STATUS__RBBDONE(2)
#define FMC_STATUS__RBBDONE1 FMC_STATUS__RBBDONE(1)
#define FMC_STATUS__RBBDONE0 FMC_STATUS__RBBDONE(0)
#define FMC_STATUS__TIMEOUT (0x1UL << 7)
#define FMC_STATUS__NSERR (0x1UL << 6)
#define FMC_STATUS__NSRBBDONE (0x1UL << 5)
#define FMC_STATUS__TRANSDONE (0x1UL << 4)
#define FMC_STATUS__ADDRESSDONE (0x1UL << 3)
#define FMC_STATUS__CMD3DONE (0x1UL << 2)
#define FMC_STATUS__CMD2DONE (0x1UL << 1)
#define FMC_STATUS__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_RBB_CONFIG bitfields
// =============================================================================
#define FMC_RBB_CONFIG__POL(v) (((v) & 0xFF) << 8)
#define FMC_RBB_CONFIG__POS(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_ALARMCMD bitfields
// =============================================================================
#define FMC_ALARMCMD__READ1(v) (((v) & 0xFF) << 16)
#define FMC_ALARMCMD__PROG1(v) (((v) & 0xFF) << 8)
#define FMC_ALARMCMD__ERASE1(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_REJECTCMD bitfields
// =============================================================================
#define FMC_REJECTCMD__READ2(v) (((v) & 0xFF) << 16)
#define FMC_REJECTCMD__PROG2(v) (((v) & 0xFF) << 8)
#define FMC_REJECTCMD__ERASE2(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_DQS_TIMING_CTRL bitfields
// =============================================================================
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL(x) (((x) & 0x1FF) << 16)
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL_GET(x) (((x) & 0x01FF0000) >> 16)
#define FMC_DQS_TIMING_CTRL__DQS_WRITE_FINE_TIMING(x) (((x) & 0xF) << 4)
#define FMC_DQS_TIMING_CTRL__DQS_WRITE_COARSE_DIRECTION (0x1UL << 3)
#define FMC_DQS_TIMING_CTRL__WR_DQS_COARSE_TIMING (((x) & 0x7) << 0)
#define FMC_DQS_TIMING_CTRL__DEFAULT_VAL (0x00C40000)
// =============================================================================
// FMC_TOGGLE_CTRL_1 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_1_DDR_RD_PRE_TIME(x) (((x) & 0xFF) << 24)
#define FMC_TOGGLE_CTRL_1_DDR_RD_POST_TIME(x) (((x) & 0xFF) << 16)
#define FMC_TOGGLE_CTRL_1_DDR_WR_PRE_TIME(x) (((x) & 0xFF) << 8)
#define FMC_TOGGLE_CTRL_1_DDR_WR_POST_TIME(x) (((x) & 0xFF) << 0)
#define FMC_TOGGLE_CTRL_1__TIMING_MAX_CLOCKS (0xFF)
// =============================================================================
// FMC_TOGGLE_CTRL_2 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_2_CE_SETUP_TIME(x) (((x) & 0xFF) << 24)
#define FMC_TOGGLE_CTRL_2_CE_HOLD_TIME(x) (((x) & 0xFF) << 16)
#define FMC_TOGGLE_CTRL_2_NAND_TIMING_ADL(x) (((x) & 0xFF) << 8)
#define FMC_TOGGLE_CTRL_2_NAND_TIMING_WHR(x) (((x) & 0xFF) << 0)
#define FMC_TOGGLE_CTRL_2__TIMING_MAX_CLOCKS (0xFF)
// =============================================================================
// FMC_TOGGLE_CTRL_2 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_3_ONFI_WR_CLK_STOP_EN (0x1UL << 31)
#define FMC_TOGGLE_CTRL_3_ONFI_TIMING_CAD (((x) & 0xF) << 0)
// =============================================================================
// ECC_CON0 bitfields
// =============================================================================
#define ECC_CON0__INFORMATION_LENGTH(n) (((n) & 0x7FF) << 16)
#define ECC_CON0__ECC_CORRECTION_MODE(m) (((m) & 0x1F) << 4)
#define ECC_CON0__START_ENC (0x1UL << 1)
#define ECC_CON0__START_DEC (0x1UL << 0)
// =============================================================================
// ECC_CON1 bitfields
// =============================================================================
#define ECC_CON1__IMPLICIT_WRITE_MARK (1UL << 31)
#define ECC_CON1__SLAVE_MODE (1UL << 29)
#define ECC_CON1__SKIP_FREE_PAGE_FLD (1UL << 25)
#define ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(n) (((n) & 0x1F) << 16)
#define ECC_CON1__ERROR_ALERT_LEVEL(n) (((n) & 0x1F) << 8)
#define ECC_CON1__INT_ENABLE(b) (((b) & 0x1) << 7)
#define ECC_CON1__INT_ENABLE__ENABLE ECC_CON1__INT_ENABLE(1)
#define ECC_CON1__INT_ENABLE__DISABLE ECC_CON1__INT_ENABLE(0)
// =============================================================================
// ECC_RESULT bitfields
// =============================================================================
#define ECC_RESULT__ERROR_ALERT (0x1UL << 21)
#define ECC_RESULT__ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_RESULT__ERROR_CNT_SHIFT (16)
#define ECC_RESULT__ERROR_CNT_MASK (0x1FUL << ECC_RESULT__ERROR_CNT_SHIFT)
#define ECC_RESULT__STUCK_BIT_EXCEEDED (0x1UL << 14)
#define ECC_RESULT__STUCK_BIT_CNT(n) (((n) & 0x3F) << 8)
#define ECC_RESULT__DECODED_BUFFER_IDX (0x1UL << 6)
#define ECC_RESULT__ALL_FF (0x1UL << 3)
#define ECC_RESULT__ALL_ZERO (0x1UL << 2)
#define ECC_RESULT__FREE_PAGE (0x1UL << 1)
#define ECC_RESULT__UNCORRECTABLE (0x1UL << 0)
#define ECC_RESULT__FIFO_RESET (0x1UL << 0) // Same as uncorrectable bit
// =============================================================================
// ECC_PND bitfields
// =============================================================================
#define ECC_PND__MAX_STUCK_BIT_CNT(n) (((n) & 0x3F) << 24)
#define ECC_PND__MAX_ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_PND__MAX_ERROR_CNT_SHIFT (16)
#define ECC_PND__MAX_ERROR_CNT_MASK (0x1FUL << ECC_PND__MAX_ERROR_CNT_SHIFT)
#define ECC_PND__DETECTOR_DONE (0x1UL << 14)
#define ECC_PND__B1_DEC_DONE (0x1UL << 13)
#define ECC_PND__B0_DEC_DONE (0x1UL << 12)
#define ECC_PND__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_PND__SOME_ALL_FF (0x1UL << 8)
#define ECC_PND__SOME_ALL_ZERO (0x1UL << 7)
#define ECC_PND__ALL_FREE_PAGE (0x1UL << 6)
#define ECC_PND__SOME_ERROR_ALERT (0x1UL << 5)
#define ECC_PND__READY_BUSY (0x1UL << 4)
#define ECC_PND__ANY_UNCORRECTABLE (0x1UL << 3)
#define ECC_PND__ENC_DONE (0x1UL << 2)
#define ECC_PND__DEC_DONE (0x1UL << 1)
#define ECC_PND__ENC_DEC_DONE (0x1UL << 0)
// =============================================================================
// ECC_MASK bitfields
// =============================================================================
#define ECC_MASK__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_MASK__SOME_ALL_FF_MASK (0x1UL << 8)
#define ECC_MASK__SOME_ALL_ZERO_MASK (0x1UL << 7)
#define ECC_MASK__SOME_ERROR_ALERT_MASK (0x1UL << 5)
#define ECC_MASK__ANY_UNCORRECTABLE_MASK (0x1UL << 3)
#define ECC_MASK__ENC_DONE_MASK (0x1UL << 2)
#define ECC_MASK__DEC_DONE_MASK (0x1UL << 1)
#define ECC_MASK__ENC_DEC_DONE_MASK (0x1UL << 0)
// =============================================================================
// ECC_HISTORY bitfields
// =============================================================================
#define ECC_HISTORY__ERROR_COUNT_CLEAR (0x1UL << 26)
#define ECC_HISTORY__ERROR_COUNT(n) (((n) & 0x7FFF) << 11)
#define ECC_HISTORY__DECODING_NUMBER_CLEAR (0x1UL << 10)
#define ECC_HISTORY__DECODING_NUMBER(n) (((n) & 0x1FF) << 0)
// =============================================================================
// RESULT_FIFO_PTR bitfields
// =============================================================================
#define ECC_RESULTS_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define ECC_RESULTS_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define ECC_RESULTS_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// COMMAND_FIFO bitfields
// =============================================================================
#define COMMAND_FIFO_SIZE (32)
#define OPERAND_FIFO_SIZE (32)
#define COMMAND_FIFO__COMMAND(cmd) ((cmd) << 24)
#define COMMAND_FIFO__OPERAND(op) (((op) & 0xFFFFFF) << 0)
#if 0 // DEPRECATED
#define OPCODE_ADDR(n) (n)
#endif // DEPRECATED
#define OPCODE_COMMAND (0x08)
#define OPCODE_ENABLE_CE (0x09)
#define OPCODE_WAIT_FOR_READY (0x0A)
#define OPCODE_TX_PAGE (0x0B)
#define OPCODE_SEND_INTERRUPT (0x0C)
#define OPCODE_PAUSE (0x0D)
#define OPCODE_TIMED_WAIT (0x0E)
#define OPCODE_LOAD_NEXT_WORD (0x0F)
#define OPCODE_LOAD_FROM_FIFO (0x10)
#define OPCODE_MACRO (0x11)
#define OPCODE_POLL (0x12)
#define OPCODE_WAIT_FOR_INT (0x13)
#define CMD_ADDRESS(bytes, addr) (COMMAND_FIFO__COMMAND(OPCODE_ADDR(bytes)) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFFF))
#define CMD_COMMAND(cmd) (COMMAND_FIFO__COMMAND(OPCODE_COMMAND) | \
COMMAND_FIFO__OPERAND((cmd) & 0xFF))
#define CMD_ENABLE_CHIP(mask) (COMMAND_FIFO__COMMAND(OPCODE_ENABLE_CE) | \
COMMAND_FIFO__OPERAND((mask) & 0xFF))
#define CMD_WAIT_FOR_READY(code,mask,cond) (COMMAND_FIFO__COMMAND(OPCODE_WAIT_FOR_READY) | \
COMMAND_FIFO__OPERAND((code) << 16 | (mask) << 8 | (cond) << 0))
#define CMD_TX_PAGE (COMMAND_FIFO__COMMAND(OPCODE_TX_PAGE))
#define CMD_SEND_INTERRUPT(code) (COMMAND_FIFO__COMMAND(OPCODE_SEND_INTERRUPT) | \
COMMAND_FIFO__OPERAND(code))
#define CMD_PAUSE (COMMAND_FIFO__COMMAND(OPCODE_PAUSE))
#define CMD_TIMED_WAIT(clks) (COMMAND_FIFO__COMMAND(OPCODE_TIMED_WAIT) | \
COMMAND_FIFO__OPERAND(clks))
#define CMD_LOAD_NEXT_WORD(addr) (COMMAND_FIFO__COMMAND(OPCODE_LOAD_NEXT_WORD) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_LOAD_FROM_FIFO(addr) (COMMAND_FIFO__COMMAND(OPCODE_LOAD_FROM_FIFO) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_MACRO(seq,len) (COMMAND_FIFO__COMMAND(OPCODE_MACRO) | \
COMMAND_FIFO__OPERAND(((seq) << 8) | (len)))
#define CMD_POLL(addr) (COMMAND_FIFO__COMMAND(OPCODE_POLL) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_WAIT_FOR_INT(irq,bit) (COMMAND_FIFO__COMMAND(OPCODE_WAIT_FOR_INT) | \
COMMAND_FIFO__OPERAND((irq) << 8 | (bit) << 0))
// =============================================================================
// COMMAND_FIFO_PTR bitfields
// =============================================================================
#define COMMAND_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define COMMAND_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define COMMAND_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// COMMAND_FIFO_LOW bitfields
// =============================================================================
#define COMMAND_FIFO_LOW__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// COMMAND_COUNT bitfields
// =============================================================================
#define COMMAND_COUNT__MAX_COUNT (32)
// =============================================================================
// COMMAND_INT_CODE bitfields
// =============================================================================
#define COMMAND_INT_CODE__READ(regval) ((regval) & 0xFFFFFF)
#define COMMAND_INT_CODE__WAIT_FOR_READY_CODE(regval) ((regval >> 16) & 0xFF)
#define COMMAND_INT_CODE__WAIT_FOR_READY_STATUS(regval) ((regval >> 0) & 0xFF)
// =============================================================================
// OPERAND_FIFO_PTR bitfields
// =============================================================================
#define OPERAND_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define OPERAND_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define OPERAND_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// OPERAND_FIFO_LOW bitfields
// =============================================================================
#define OPERAND_FIFO_LOW__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// SEQ_INT_PEND bitfields
// =============================================================================
#define SEQ_INT_PEND__TIMEOUT (0x1UL << 7)
#define SEQ_INT_PEND__OPERAND_FIFO_EMPTY (0x1UL << 6)
#define SEQ_INT_PEND__OPERAND_FIFO_LOW (0x1UL << 5)
#define SEQ_INT_PEND__OPERAND_FIFO_OVERFLOW (0x1UL << 4)
#define SEQ_INT_PEND__COMMAND_FIFO_EMPTY (0x1UL << 3)
#define SEQ_INT_PEND__COMMAND_FIFO_LOW (0x1UL << 2)
#define SEQ_INT_PEND__COMMAND_FIFO_OVERFLOW (0x1UL << 1)
#define SEQ_INT_PEND__SEQUENCER_SIGNAL (0x1UL << 0)
// =============================================================================
// SEQ_INT_EN bitfields
// =============================================================================
#define SEQ_INT_EN__TIMEOUT (0x1UL << 7)
#define SEQ_INT_EN__OPERAND_FIFO_EMPTY (0x1UL << 6)
#define SEQ_INT_EN__OPERAND_FIFO_LOW (0x1UL << 5)
#define SEQ_INT_EN__OPERAND_FIFO_OVERFLOW (0x1UL << 4)
#define SEQ_INT_EN__COMMAND_FIFO_EMPTY (0x1UL << 3)
#define SEQ_INT_EN__COMMAND_FIFO_LOW (0x1UL << 2)
#define SEQ_INT_EN__COMMAND_FIFO_OVERFLOW (0x1UL << 1)
#define SEQ_INT_EN__SEQUENCER_SIGNAL (0x1UL << 0)
// =============================================================================
// SEQ_MACRO_CONTROL bitfields
// =============================================================================
#define SEQ_MACRO_CONTROL__WORD_COUNT(cnt) (((cnt) & 0x3F) << 8)
#define SEQ_MACRO_CONTROL__MACRO_ADDRESS(addr) (((addr) & 0x3F) << 0)
#define SEQ_MACRO_CONTROL__GET_WORD_COUNT(regval) (((regval) >> 8) & 0x3F)
#define SEQ_MACRO_CONTROL__GET_MACRO_ADDRESS(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// SoC-Specific Tuning
// =============================================================================
#define FMI_TX_PROP_DELAY_NS (6)
#define FMI_RX_PROP_DELAY_NS (6)
#endif // _H2FMI_8940REGS_H_
// ********************************** EOF *************************************
+799
View File
@@ -0,0 +1,799 @@
// *****************************************************************************
//
// File: H2fmi_regs.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position
//
// - consider adding definitions for extracting value from register position
//
// *****************************************************************************
//
// Copyright (C) 2010 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "WMRFeatures.h"
#if defined(H2FMI_EFI) && H2FMI_EFI
#include "SoC.h"
#else
#include <platform/soc/hwregbase.h>
#endif
#include <WMRTypes.h>
#ifndef _H2FMI_8945REGS_H_
#define _H2FMI_8945REGS_H_
// =============================================================================
// register bases and offsets
// =============================================================================
#define FMI0 ((UInt32*)FMI0_BASE_ADDR)
#define FMI1 ((UInt32*)FMI1_BASE_ADDR)
#define FMI2 ((UInt32*)FMI2_BASE_ADDR)
#define FMI3 ((UInt32*)FMI3_BASE_ADDR)
#define FMI_OFFSET (0x00000)
#define FMC_OFFSET (0x40000)
#define ECC_OFFSET (0x80000)
#define CMD_OFFSET (0xC0000)
#define FMC0 ((volatile UInt32*)((UInt32)FMI0 + FMC_OFFSET))
#define FMC1 ((volatile UInt32*)((UInt32)FMI1 + FMC_OFFSET))
#define FMC2 ((volatile UInt32*)((UInt32)FMI2 + FMC_OFFSET))
#define FMC3 ((volatile UInt32*)((UInt32)FMI3 + FMC_OFFSET))
#define FMI_BA(offset) ((UInt32)(FMI_OFFSET + offset))
#define FMC_BA(offset) ((UInt32)(FMC_OFFSET + offset))
#define ECC_BA(offset) ((UInt32)(ECC_OFFSET + offset))
#define CMD_BA(offset) ((UInt32)(CMD_OFFSET + offset))
#define FMI_CONFIG FMI_BA(0x00)
#define FMI_CONTROL FMI_BA(0x04)
#define FMI_STATUS FMI_BA(0x08)
#define FMI_INT_PEND FMI_BA(0x0C)
#define FMI_INT_EN FMI_BA(0x10)
#define FMI_DATA_BUF FMI_BA(0x14)
#define FMI_META_FIFO FMI_BA(0x18)
#define FMI_DEBUG0 FMI_BA(0x1C)
#define FMI_HW_VERSION FMI_BA(0x30)
#define FMI_DATA_SIZE FMI_BA(0x34)
#define FMI_RAW_PAGE_SIZE FMI_BA(0x38)
#define FMI_SCRAMBLER_SEED_FIFO FMI_BA(0x3C)
#define FMI_SEED_FIFO_LOW_LEVEL FMI_BA(0x40)
#define FMI_METADATA_FIFO_PTR FMI_BA(0x44)
#define FMI_SEED_FIFO_PTR FMI_BA(0x48)
#define FMI_RANDOMIZER_VERSION FMI_BA(0x4C)
#define FMI_BUFFER_0_BASE FMI_BA(0x1000)
#define FMI_BUFFER_1_BASE FMI_BA(0x1800)
#define FMI_BUFFER_LEN (0x45F)
#define FMI_META_FIFO_BASE FMI_BA(0x2000)
#define FMI_META_FIFO_LENGTH (32)
#define FMI_SEED_FIFO_BASE FMI_BA(0x3000)
#define FMI_SEED_FIFO_LENGTH (8)
#define FMI_ECC_RESULT_FIFO_BASE FMI_BA(0x81000)
#define FMI_ECC_RESULT_FIFO_LENGTH (32)
#define FMI_ECC_PAGE_FIFO_BASE FMI_BA(0xC1000)
#define FMI_ECC_PAGE_FIFO_LENGTH (32)
#define FMC_ON FMC_BA(0x00)
#define FMC_VER FMC_BA(0x04)
#define FMC_IF_CTRL FMC_BA(0x08)
#define FMC_CE_CTRL FMC_BA(0x0C)
#define FMC_RW_CTRL FMC_BA(0x10)
#define FMC_CMD FMC_BA(0x14)
#define FMC_ADDR0 FMC_BA(0x18)
#define FMC_ADDR1 FMC_BA(0x1C)
#define FMC_ADDRNUM FMC_BA(0x20)
#define FMC_DATANUM FMC_BA(0x24)
#define FMC_UNDEF0 FMC_BA(0x28)
#define FMC_UNDEF1 FMC_BA(0x2C)
#define FMC_TO_CTRL FMC_BA(0x30)
#define FMC_TO_CNT FMC_BA(0x34)
#define FMC_UNDEF2 FMC_BA(0x38)
#define FMC_UNDEF3 FMC_BA(0x3C)
#define FMC_INTMASK FMC_BA(0x40)
#define FMC_STATUS FMC_BA(0x44)
#define FMC_NAND_STATUS FMC_BA(0x48)
#define FMC_RBB_CONFIG FMC_BA(0x4C)
#define FMC_DQS_TIMING_CTRL FMC_BA(0x70)
#define FMC_TOGGLE_CTRL_1 FMC_BA(0x74)
#define FMC_TOGGLE_CTRL_2 FMC_BA(0x78)
#define FMC_TOGGLE_CTRL_3 FMC_BA(0x7C)
#define ECC_VERSION ECC_BA(0x00)
#define ECC_CON0 ECC_BA(0x04)
#define ECC_CON1 ECC_BA(0x08)
#define ECC_RESULT ECC_BA(0x0C)
#define ECC_PND ECC_BA(0x10)
#define ECC_MASK ECC_BA(0x14)
#define ECC_HISTORY ECC_BA(0x18)
#define ECC_CORE_SW_RESET ECC_BA(0x1C)
#define ECC_PAGE_ERROR_FIFO ECC_BA(0x24)
#define ECC_PAGE_ERROR_FIFO_PTR ECC_BA(0x28)
#define ECC_RESULTS_FIFO_PTR ECC_BA(0x2C)
#define COMMAND_FIFO CMD_BA(0x00)
#define COMMAND_FIFO_PTR CMD_BA(0x04)
#define COMMAND_FIFO_LOW CMD_BA(0x08)
#define COMMAND_COUNT CMD_BA(0x0C)
#define COMMAND_INT_CODE CMD_BA(0x10)
#define OPERAND_FIFO CMD_BA(0x14)
#define OPERAND_FIFO_PTR CMD_BA(0x18)
#define OPERAND_FIFO_LOW CMD_BA(0x1C)
#define SEQ_INT_PEND CMD_BA(0x20)
#define SEQ_INT_EN CMD_BA(0x24)
#define SEQ_MACRO_CONTROL CMD_BA(0x28)
#define TIMEOUT_VALUE CMD_BA(0x2C)
#define STORE_FIFO CMD_BA(0x30)
#define STORE_FIFO_PTR CMD_BA(0x34)
#define STORE_FIFO_HIGH CMD_BA(0x38)
#define SEQUENCER_MACROS(n) CMD_BA(0x1000 + ((n) & 0xFF))
#define SEQUENCER_COMMANDS(n) CMD_BA(0x2000 + ((n) & 0x7F))
#define SEQUENCER_OPERANDS(n) CMD_BA(0x3000 + ((n) & 0x7F))
#define SEQUENCER_STORES(n) CMD_BA(0x4000 + ((n) & 0x7F))
// =============================================================================
// FMI_CONFIG bitfields
// =============================================================================
#define FMI_CONFIG__DMA_BURST(n) (((n) & 0x7) << 0)
#define FMI_CONFIG__ECC_CORRECTABLE_BITS(m) (((m) & 0x1f) << 3)
#define FMI_CONFIG__META_DMA_BURST_SIZE(n) (((n) & 0x7) << 9)
#define FMI_CONFIG__META_DMA_BURST_WIDTH(n) (((n) & 0x3) << 12)
#define FMI_CONFIG__SCRAMBLE_SEED (0x1UL << 14)
#define FMI_CONFIG__ENABLE_WHITENING (0x1UL << 8)
#define FMI_CONFIG__DMA_BURST__32_CYCLES FMI_CONFIG__DMA_BURST(5)
#define FMI_CONFIG__DMA_BURST__16_CYCLES FMI_CONFIG__DMA_BURST(4)
#define FMI_CONFIG__DMA_BURST__8_CYCLES FMI_CONFIG__DMA_BURST(3)
#define FMI_CONFIG__DMA_BURST__4_CYCLES FMI_CONFIG__DMA_BURST(2)
#define FMI_CONFIG__DMA_BURST__2_CYCLES FMI_CONFIG__DMA_BURST(1)
#define FMI_CONFIG__DMA_BURST__1_CYCLES FMI_CONFIG__DMA_BURST(0)
#define FMI_CONFIG__META_DMA_BURST__32_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(5)
#define FMI_CONFIG__META_DMA_BURST__16_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(4)
#define FMI_CONFIG__META_DMA_BURST__8_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(3)
#define FMI_CONFIG__META_DMA_BURST__4_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(2)
#define FMI_CONFIG__META_DMA_BURST__2_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(1)
#define FMI_CONFIG__META_DMA_BURST__1_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(0)
#define FMI_CONFIG__META_DMA_BURST__4_BYTES FMI_CONFIG__META_DMA_BURST_WIDTH(2)
#define FMI_CONFIG__META_DMA_BURST__2_BYTES FMI_CONFIG__META_DMA_BURST_WIDTH(1)
#define FMI_CONFIG__META_DMA_BURST__1_BYTES FMI_CONFIG__META_DMA_BURST_WIDTH(0)
// =============================================================================
// FMI_CONTROL bitfields
// =============================================================================
#define FMI_CONTROL__PAUSE_WHEN_STORE_FIFO_FULL (0x1UL << 14)
#define FMI_CONTROL__DISABLE_STREAMING (0x1UL << 13)
#define FMI_CONTROL__SEQUENCER_TIMEOUT_ENABLE (0x1UL << 12)
#define FMI_CONTROL__RESET_SEED (0x1UL << 11)
#define FMI_CONTROL__RAW_READ_MODE (0x1UL << 10)
#define FMI_CONTROL__RESET_SEQUENCER (0x1UL << 9)
#define FMI_CONTROL__ENABLE_SEQUENCER (0x1UL << 8)
#define FMI_CONTROL__ECC_PAUSE (0x1UL << 7)
#define FMI_CONTROL__BUFFER_1_LOCK(m) (((m) & 0x3) << 5)
#define FMI_CONTROL__BUFFER_0_LOCK(m) (((m) & 0x3) << 3)
#define FMI_CONTROL__MODE(m) (((m) & 0x3) << 1)
#define FMI_CONTROL__START_BIT (0x1UL << 0)
#define FMI_CONTROL__MODE__IDLE FMI_CONTROL__MODE(0)
#define FMI_CONTROL__MODE__READ FMI_CONTROL__MODE(1)
#define FMI_CONTROL__MODE__WRITE FMI_CONTROL__MODE(2)
#define FMI_CONTROL__MODE__SOFTWARE_RESET FMI_CONTROL__MODE(3)
#define FMI_CONTROL__BUFFER_0_LOCK_FREE FMI_CONTROL__BUFFER_0_LOCK(0)
#define FMI_CONTROL__BUFFER_0_LOCK_DMA FMI_CONTROL__BUFFER_0_LOCK(1)
#define FMI_CONTROL__BUFFER_0_LOCK_ECC FMI_CONTROL__BUFFER_0_LOCK(2)
#define FMI_CONTROL__BUFFER_0_LOCK_FMC FMI_CONTROL__BUFFER_0_LOCK(3)
#define FMI_CONTROL_BUFFER_1_LOCK_FREE FMI_CONTROL__BUFFER_1_LOCK(0)
#define FMI_CONTROL_BUFFER_1_LOCK_DMA FMI_CONTROL__BUFFER_1_LOCK(1)
#define FMI_CONTROL_BUFFER_1_LOCK_ECC FMI_CONTROL__BUFFER_1_LOCK(2)
#define FMI_CONTROL_BUFFER_1_LOCK_FMC FMI_CONTROL__BUFFER_1_LOCK(3)
// =============================================================================
// FMI_STATUS bitfields
// =============================================================================
#define FMI_STATUS__FMC_ACTIVE (0x1UL << 3)
#define FMI_STATUS__ECC_ACTIVE (0x1UL << 2)
#define FMI_STATUS__DMA_ACTIVE (0x1UL << 1)
#define FMI_STATUS__BUS_ACTIVE (0x1UL << 0)
// =============================================================================
// FMI_INT_PEND bitfields
// =============================================================================
#define FMI_INT_PEND__SEQUENCER_INTERRUPT (0x1UL << 28)
#define FMI_INT_PEND__SEED_FIFO_EMPTY (0x1UL << 27)
#define FMI_INT_PEND__SEED_FIFO_LOW (0x1UL << 26)
#define FMI_INT_PEND__SEED_FIFO_OVERFLOW (0x1UL << 25)
#define FMI_INT_PEND__ECC_RESULTS_FIFO_UNDERFLOW (0x1UL << 24)
#define FMI_INT_PEND__ECC_RESULTS_FIFO_OVERFLOW (0x1UL << 23)
#define FMI_INT_PEND__LAST_ECC_DONE (0x1UL << 22)
#define FMI_INT_PEND__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_PEND__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_PEND__ECC_DONE (0x1UL << 19)
#define FMI_INT_PEND__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_PEND__FMC_READY_BUSY(n) (((n) & 0xFF) << 10)
#define FMI_INT_PEND__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_PEND__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_PEND__FMC_NSERR (0x1UL << 7)
#define FMI_INT_PEND__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_PEND__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_PEND__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_PEND__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_PEND__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_PEND__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_PEND__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_INT_EN bitfields
// =============================================================================
#define FMI_INT_EN__SEQUENCER_INTERRUPT (0x1UL << 28)
#define FMI_INT_EN__SEED_FIFO_EMPTY (0x1UL << 27)
#define FMI_INT_EN__SEED_FIFO_LOW (0x1UL << 26)
#define FMI_INT_EN__SEED_FIFO_OVERFLOW (0x1UL << 25)
#define FMI_INT_EN__ECC_RESULTS_FIFO_UNDERFLOW (0x1UL << 24)
#define FMI_INT_EN__ECC_RESULTS_FIFO_OVERFLOW (0x1UL << 23)
#define FMI_INT_EN__LAST_ECC_DONE (0x1UL << 22)
#define FMI_INT_EN__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_EN__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_EN__ECC_DONE (0x1UL << 19)
#define FMI_INT_EN__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_EN__FMC_READY_BUSY (0x1UL << 10)
#define FMI_INT_EN__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_EN__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_EN__FMC_NSERR (0x1UL << 7)
#define FMI_INT_EN__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_EN__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_EN__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_EN__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_EN__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_EN__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_EN__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_DEBUG0 bitfields
// =============================================================================
#define FMI_DEBUG0__FMC_TASKS_PENDING(n) (((n) & 0x3) << 7)
#define FMI_DEBUG0__ECC_TASKS_PENDING(n) (((n) & 0x3) << 5)
#define FMI_DEBUG0__DMA_TASKS_PENDING(n) (((n) & 0x3) << 3)
#define FMI_DEBUG0__FMC_TARGET_BUFFER(b) (((b) & 0x1) << 2)
#define FMI_DEBUG0__ECC_TARGET_BUFFER(b) (((b) & 0x1) << 1)
#define FMI_DEBUG0__DMA_TARGET_BUFFER(b) (((b) & 0x1) << 0)
// =============================================================================
// FMI_DATA_SIZE bifields
// =============================================================================
#define FMI_DATA_SIZE__META_BYTES_PER_SECTOR(n) (((n) & 0x3F) << 25)
#define FMI_DATA_SIZE__META_BYTES_PER_PAGE(n) (((n) & 0x3F) << 19)
#define FMI_DATA_SIZE__BYTES_PER_SECTOR(n) (((n) & 0x7FF) << 8)
#define FMI_DATA_SIZE__SECTORS_PER_PAGE(n) (((n) & 0xFF) << 0)
// =============================================================================
// FMI_SEED_FIFO_LOW_LEVEL bitfields
// =============================================================================
#define FMI_SEED_FIFO_LOW_LEVEL__LEVEL(x) (((x) & 0x7) << 0)
// =============================================================================
// METADATA_FIFO_PTR bitfields
// =============================================================================
#define METADATA_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define METADATA_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define METADATA_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// SEED_FIFO_PTR bitfields
// =============================================================================
#define SEED_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x7)
#define SEED_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x7)
#define SEED_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0xF)
// =============================================================================
// FMC_ON bitfields
// =============================================================================
#define FMC_ON__SWRST (0x1UL << 8)
#define FMC_ON__ASYNC_DRIVE_DQS (0x1UL << 6)
#define FMC_ON__ASYNC_CEB_AUTO_DISABLE (0x1UL << 5)
#define FMC_ON__DDR_NAND_TYPE_TOGGLE (0x0UL << 3)
#define FMC_ON__DDR_NAND_TYPE_ONFI (0x1UL << 3)
#define FMC_ON__DDR_ENABLE (0x1UL << 2)
#define FMC_ON__CLKGATING_RDY (0x1UL << 1)
#define FMC_ON__ENABLE (0x1UL << 0)
#define FMC_ON__DISABLE (!FMC_ON__ENABLE)
// =============================================================================
// FMC_IF_CTRL bitfields
// =============================================================================
#define FMC_IF_CTRL__WPB (0x1UL << 21)
#define FMC_IF_CTRL__RBBEN (0x1UL << 20)
#define FMC_IF_CTRL__DCCYCLE(v) (((v) & 0xF) << 16)
#define FMC_IF_CTRL__REB_SETUP(v) (((v) & 0xF) << 12)
#define FMC_IF_CTRL__REB_HOLD(v) (((v) & 0xF) << 8)
#define FMC_IF_CTRL__WEB_SETUP(v) (((v) & 0xF) << 4)
#define FMC_IF_CTRL__WEB_HOLD(v) (((v) & 0xF) << 0)
#define FMC_IF_CTRL__GET_DCCYCLE(v) (((v) & 0xF0000) >> 16)
#define FMC_IF_CTRL__GET_REB_SETUP(v) (((v) & 0x0F000) >> 12)
#define FMC_IF_CTRL__GET_REB_HOLD(v) (((v) & 0x00F00) >> 8)
#define FMC_IF_CTRL__GET_WEB_SETUP(v) (((v) & 0x000F0) >> 4)
#define FMC_IF_CTRL__GET_WEB_HOLD(v) (((v) & 0x0000F) >> 0)
#define FMC_IF_CTRL__REB_SETUP_MASK (0x0000000F << 12)
#define FMC_IF_CTRL__TIMING_MAX_CLOCKS (0xFUL)
// =============================================================================
// FMC_CE_CTRL bitfields
// =============================================================================
#define FMC_CE_CTRL__CE_COUNT (8)
#define FMC_CE_CTRL__CEB(n) (0x1UL << ((n) & 0x7))
#define FMC_CE_CTRL__CEB7 FMC_CE_CTRL__CEB(7)
#define FMC_CE_CTRL__CEB6 FMC_CE_CTRL__CEB(6)
#define FMC_CE_CTRL__CEB5 FMC_CE_CTRL__CEB(5)
#define FMC_CE_CTRL__CEB4 FMC_CE_CTRL__CEB(4)
#define FMC_CE_CTRL__CEB3 FMC_CE_CTRL__CEB(3)
#define FMC_CE_CTRL__CEB2 FMC_CE_CTRL__CEB(2)
#define FMC_CE_CTRL__CEB1 FMC_CE_CTRL__CEB(1)
#define FMC_CE_CTRL__CEB0 FMC_CE_CTRL__CEB(0)
// =============================================================================
// FMC_RW_CTRL bitfields
// =============================================================================
#define FMC_RW_CTRL__NAND_TIMING_USER_TAT(x) (((x) & 0xFF) << 24)
#define FMC_RW_CTRL__CMD1_5_MODE (0x1UL << 9)
#define FMC_RW_CTRL__WAIT_NSRBB_FLD (0x1UL << 8)
#define FMC_RW_CTRL__RD_DONE_REB_CEB_HOLD (0x1UL << 7)
#define FMC_RW_CTRL__REBHOLD (0x1UL << 6)
#define FMC_RW_CTRL__WR_MODE (0x1UL << 5)
#define FMC_RW_CTRL__RD_MODE (0x1UL << 4)
#define FMC_RW_CTRL__ADDR_MODE (0x1UL << 3)
#define FMC_RW_CTRL__CMD3_MODE (0x1UL << 2)
#define FMC_RW_CTRL__CMD2_MODE (0x1UL << 1)
#define FMC_RW_CTRL__CMD1_MODE (0x1UL << 0)
// =============================================================================
// FMC_CMD bitfields
// =============================================================================
#define FMC_CMD__CMD1_5(c) (((c) & 0xFF) << 24)
#define FMC_CMD__CMD3(c) (((c) & 0xFF) << 16)
#define FMC_CMD__CMD2(c) (((c) & 0xFF) << 8)
#define FMC_CMD__CMD1(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR0 bitfields
// =============================================================================
#define FMC_ADDR0__SEQ3(a) (((a) & 0xFF) << 24)
#define FMC_ADDR0__SEQ2(a) (((a) & 0xFF) << 16)
#define FMC_ADDR0__SEQ1(a) (((a) & 0xFF) << 8)
#define FMC_ADDR0__SEQ0(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR1 bitfields
// =============================================================================
#define FMC_ADDR1__SEQ7(a) (((a) & 0xFF) << 24)
#define FMC_ADDR1__SEQ6(a) (((a) & 0xFF) << 16)
#define FMC_ADDR1__SEQ5(a) (((a) & 0xFF) << 8)
#define FMC_ADDR1__SEQ4(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDRNUM bitfields
// =============================================================================
#define FMC_ADDRNUM__NUM(n) (((n) & 0x7) << 0)
// =============================================================================
// FMC_DATANUM bitfields
// =============================================================================
#define FMC_DATANUM__NUM(n) (((n) & 0x3FF) << 0)
// =============================================================================
// FMC_TO_CTRL bitfields
// =============================================================================
#define FMC_TO_CTRL__EN (0x1UL << 12)
#define FMC_TO_CTRL__DIV(d) (((d) & 0xF) << 8)
#define FMC_TO_CTRL__VAL(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_TO_CNT bitfields
// =============================================================================
#define FMC_TO_CNT__CNT(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_INTMASK bitfields
// =============================================================================
#define FMC_INTMASK__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_INTMASK__CMD1_5DONE (0x1UL << 17)
#define FMC_INTMASK__RBBDONE7 FMC_INTMASK__RBBDONE(7)
#define FMC_INTMASK__RBBDONE6 FMC_INTMASK__RBBDONE(6)
#define FMC_INTMASK__RBBDONE5 FMC_INTMASK__RBBDONE(5)
#define FMC_INTMASK__RBBDONE4 FMC_INTMASK__RBBDONE(4)
#define FMC_INTMASK__RBBDONE3 FMC_INTMASK__RBBDONE(3)
#define FMC_INTMASK__RBBDONE2 FMC_INTMASK__RBBDONE(2)
#define FMC_INTMASK__RBBDONE1 FMC_INTMASK__RBBDONE(1)
#define FMC_INTMASK__RBBDONE0 FMC_INTMASK__RBBDONE(0)
#define FMC_INTMASK__TIMEOUT (0x1UL << 7)
#define FMC_INTMASK__NSERR (0x1UL << 6)
#define FMC_INTMASK__NSRBBDONE (0x1UL << 5)
#define FMC_INTMASK__TRANSDONE (0x1UL << 4)
#define FMC_INTMASK__ADDRESSDONE (0x1UL << 3)
#define FMC_INTMASK__CMD3DONE (0x1UL << 2)
#define FMC_INTMASK__CMD2DONE (0x1UL << 1)
#define FMC_INTMASK__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_STATUS bitfields
// =============================================================================
#define FMC_STATUS__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_STATUS__EMERGENCY2 (0x1UL << 21)
#define FMC_STATUS__EMERGENCY01 (0x1UL << 20)
#define FMC_STATUS__RDATADIRTY (0x1UL << 16)
#define FMC_STATUS__RBBDONE7 FMC_STATUS__RBBDONE(7)
#define FMC_STATUS__RBBDONE6 FMC_STATUS__RBBDONE(6)
#define FMC_STATUS__RBBDONE5 FMC_STATUS__RBBDONE(5)
#define FMC_STATUS__RBBDONE4 FMC_STATUS__RBBDONE(4)
#define FMC_STATUS__RBBDONE3 FMC_STATUS__RBBDONE(3)
#define FMC_STATUS__RBBDONE2 FMC_STATUS__RBBDONE(2)
#define FMC_STATUS__RBBDONE1 FMC_STATUS__RBBDONE(1)
#define FMC_STATUS__RBBDONE0 FMC_STATUS__RBBDONE(0)
#define FMC_STATUS__TIMEOUT (0x1UL << 7)
#define FMC_STATUS__NSERR (0x1UL << 6)
#define FMC_STATUS__NSRBBDONE (0x1UL << 5)
#define FMC_STATUS__TRANSDONE (0x1UL << 4)
#define FMC_STATUS__ADDRESSDONE (0x1UL << 3)
#define FMC_STATUS__CMD3DONE (0x1UL << 2)
#define FMC_STATUS__CMD2DONE (0x1UL << 1)
#define FMC_STATUS__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_RBB_CONFIG bitfields
// =============================================================================
#define FMC_RBB_CONFIG__POL(v) (((v) & 0xFF) << 8)
#define FMC_RBB_CONFIG__POS(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_DQS_TIMING_CTRL bitfields
// =============================================================================
#define FMC_DQS_TIMING_CTRL__USE_DLL (0x1UL << 31)
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL(x) (((x) & 0x1FF) << 16)
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL_GET(x) (((x) & 0x01FF0000) >> 16)
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_COARSE_CTRL(x) (((x) & 0x7F) << 18)
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_FINE_CTRL(x) (((x) & 0x3) << 16)
#define FMC_DQS_TIMING_CTRL__DQS_WRITE_DELAY_TIMING(x) (((x) & 0xF) << 0)
#define FMC_DQS_TIMING_CTRL__DEFAULT_VAL (0x00800000)
// =============================================================================
// FMC_TOGGLE_CTRL_1 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_1_DDR_RD_PRE_TIME(x) (((x) & 0xFF) << 24)
#define FMC_TOGGLE_CTRL_1_DDR_RD_POST_TIME(x) (((x) & 0xFF) << 16)
#define FMC_TOGGLE_CTRL_1_DDR_WR_PRE_TIME(x) (((x) & 0xFF) << 8)
#define FMC_TOGGLE_CTRL_1_DDR_WR_POST_TIME(x) (((x) & 0xFF) << 0)
#define FMC_TOGGLE_CTRL_1__TIMING_MAX_CLOCKS (0xFF)
// =============================================================================
// FMC_TOGGLE_CTRL_2 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_2_CE_SETUP_TIME(x) (((x) & 0xFF) << 24)
#define FMC_TOGGLE_CTRL_2_CE_HOLD_TIME(x) (((x) & 0xFF) << 16)
#define FMC_TOGGLE_CTRL_2_NAND_TIMING_ADL(x) (((x) & 0xFF) << 8)
#define FMC_TOGGLE_CTRL_2_NAND_TIMING_WHR(x) (((x) & 0xFF) << 0)
#define FMC_TOGGLE_CTRL_2__TIMING_MAX_CLOCKS (0xFF)
// =============================================================================
// FMC_TOGGLE_CTRL_2 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_3_ONFI_WR_CLK_STOP_EN (0x1UL << 31)
#define FMC_TOGGLE_CTRL_3_DISABLE_ONFI_READ_STATUS_CLE_ALE_HOLD (0x1UL << 30)
#define FMC_TOGGLE_CTRL_3_DISABLE_ONFI_ONFI_IDLE_CLOCK_ON (0x1UL << 29)
#define FMC_TOGGLE_CTRL_3_ONFI_TIMING_CAD (((x) & 0xF) << 0)
// =============================================================================
// ECC_CON0 bitfields
// =============================================================================
#define ECC_CON0__INFORMATION_LENGTH(n) (((n) & 0x7FF) << 16)
#define ECC_CON0__ECC_CORRECTION_MODE(m) (((m) & 0x1F) << 4)
#define ECC_CON0__START_ENC (0x1UL << 1)
#define ECC_CON0__START_DEC (0x1UL << 0)
// =============================================================================
// ECC_CON1 bitfields
// =============================================================================
#define ECC_CON1__IMPLICIT_WRITE_MARK (1UL << 31)
#define ECC_CON1__SLAVE_MODE (1UL << 29)
#define ECC_CON1__SKIP_FREE_PAGE_FLD (1UL << 25)
#define ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(n) (((n) & 0x1F) << 16)
#define ECC_CON1__ERROR_ALERT_LEVEL(n) (((n) & 0x1F) << 8)
#define ECC_CON1__INT_ENABLE(b) (((b) & 0x1) << 7)
#define ECC_CON1__INT_ENABLE__ENABLE ECC_CON1__INT_ENABLE(1)
#define ECC_CON1__INT_ENABLE__DISABLE ECC_CON1__INT_ENABLE(0)
// =============================================================================
// ECC_RESULT bitfields
// =============================================================================
#define ECC_RESULT__ERROR_ALERT (0x1UL << 21)
#define ECC_RESULT__ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_RESULT__ERROR_CNT_SHIFT (16)
#define ECC_RESULT__ERROR_CNT_MASK (0x1FUL << ECC_RESULT__ERROR_CNT_SHIFT)
#define ECC_RESULT__STUCK_BIT_EXCEEDED (0x1UL << 14)
#define ECC_RESULT__STUCK_BIT_CNT(n) (((n) & 0x3F) << 8)
#define ECC_RESULT__DECODED_BUFFER_IDX (0x1UL << 6)
#define ECC_RESULT__ALL_FF (0x1UL << 3)
#define ECC_RESULT__ALL_ZERO (0x1UL << 2)
#define ECC_RESULT__FREE_PAGE (0x1UL << 1)
#define ECC_RESULT__UNCORRECTABLE (0x1UL << 0)
#define ECC_RESULT__FIFO_RESET (0x1UL << 0) // Same as uncorrectable bit
// =============================================================================
// ECC_PND bitfields
// =============================================================================
#define ECC_PND__MAX_STUCK_BIT_CNT(n) (((n) & 0x3F) << 24)
#define ECC_PND__MAX_ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_PND__MAX_ERROR_CNT_SHIFT (16)
#define ECC_PND__MAX_ERROR_CNT_MASK (0x1FUL << ECC_PND__MAX_ERROR_CNT_SHIFT)
#define ECC_PND__DETECTOR_DONE (0x1UL << 14)
#define ECC_PND__B1_DEC_DONE (0x1UL << 13)
#define ECC_PND__B0_DEC_DONE (0x1UL << 12)
#define ECC_PND__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_PND__SOME_ALL_FF (0x1UL << 8)
#define ECC_PND__SOME_ALL_ZERO (0x1UL << 7)
#define ECC_PND__ALL_FREE_PAGE (0x1UL << 6)
#define ECC_PND__SOME_ERROR_ALERT (0x1UL << 5)
#define ECC_PND__READY_BUSY (0x1UL << 4)
#define ECC_PND__ANY_UNCORRECTABLE (0x1UL << 3)
#define ECC_PND__ENC_DONE (0x1UL << 2)
#define ECC_PND__DEC_DONE (0x1UL << 1)
#define ECC_PND__ENC_DEC_DONE (0x1UL << 0)
// =============================================================================
// ECC_MASK bitfields
// =============================================================================
#define ECC_MASK__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_MASK__SOME_ALL_FF_MASK (0x1UL << 8)
#define ECC_MASK__SOME_ALL_ZERO_MASK (0x1UL << 7)
#define ECC_MASK__SOME_ERROR_ALERT_MASK (0x1UL << 5)
#define ECC_MASK__ANY_UNCORRECTABLE_MASK (0x1UL << 3)
#define ECC_MASK__ENC_DONE_MASK (0x1UL << 2)
#define ECC_MASK__DEC_DONE_MASK (0x1UL << 1)
#define ECC_MASK__ENC_DEC_DONE_MASK (0x1UL << 0)
// =============================================================================
// ECC_HISTORY bitfields
// =============================================================================
#define ECC_HISTORY__ERROR_COUNT_CLEAR (0x1UL << 26)
#define ECC_HISTORY__ERROR_COUNT(n) (((n) & 0x7FFF) << 11)
#define ECC_HISTORY__DECODING_NUMBER_CLEAR (0x1UL << 10)
#define ECC_HISTORY__DECODING_NUMBER(n) (((n) & 0x1FF) << 0)
// =============================================================================
// RESULT_FIFO_PTR bitfields
// =============================================================================
#define ECC_RESULTS_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define ECC_RESULTS_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define ECC_RESULTS_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// COMMAND_FIFO bitfields
// =============================================================================
#define COMMAND_FIFO_SIZE (32)
#define OPERAND_FIFO_SIZE (32)
#define STORE_FIFO_SIZE (32)
#define COMMAND_FIFO__COMMAND(cmd) ((cmd) << 24)
#define COMMAND_FIFO__OPERAND(op) (((op) & 0xFFFFFF) << 0)
#define OPCODE_ADDR(n) (n)
#define OPCODE_COMMAND (0x08)
#define OPCODE_ENABLE_CE (0x09)
#define OPCODE_WAIT_FOR_READY (0x0A)
#define OPCODE_TX_PAGE (0x0B)
#define OPCODE_SEND_INTERRUPT (0x0C)
#define OPCODE_PAUSE (0x0D)
#define OPCODE_TIMED_WAIT (0x0E)
#define OPCODE_LOAD_NEXT_WORD (0x0F)
#define OPCODE_LOAD_FROM_FIFO (0x10)
#define OPCODE_MACRO (0x11)
#define OPCODE_POLL (0x12)
#define OPCODE_WAIT_FOR_INT (0x13)
#define OPCODE_STORE_TO_FIFO (0x14)
#define CMD_ADDRESS(bytes, addr) (COMMAND_FIFO__COMMAND(OPCODE_ADDR(bytes)) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFFF))
#define CMD_COMMAND(cmd) (COMMAND_FIFO__COMMAND(OPCODE_COMMAND) | \
COMMAND_FIFO__OPERAND((cmd) & 0xFF))
#define CMD_ENABLE_CHIP(mask) (COMMAND_FIFO__COMMAND(OPCODE_ENABLE_CE) | \
COMMAND_FIFO__OPERAND((mask) & 0xFF))
#define CMD_WAIT_FOR_READY(code,mask,cond) (COMMAND_FIFO__COMMAND(OPCODE_WAIT_FOR_READY) | \
COMMAND_FIFO__OPERAND((code) << 16 | (mask) << 8 | (cond) << 0))
#define CMD_TX_PAGE (COMMAND_FIFO__COMMAND(OPCODE_TX_PAGE))
#define CMD_SEND_INTERRUPT(code) (COMMAND_FIFO__COMMAND(OPCODE_SEND_INTERRUPT) | \
COMMAND_FIFO__OPERAND(code))
#define CMD_PAUSE (COMMAND_FIFO__COMMAND(OPCODE_PAUSE))
#define CMD_TIMED_WAIT(clks) (COMMAND_FIFO__COMMAND(OPCODE_TIMED_WAIT) | \
COMMAND_FIFO__OPERAND(clks))
#define CMD_LOAD_NEXT_WORD(addr) (COMMAND_FIFO__COMMAND(OPCODE_LOAD_NEXT_WORD) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_LOAD_FROM_FIFO(addr) (COMMAND_FIFO__COMMAND(OPCODE_LOAD_FROM_FIFO) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_MACRO(seq,len) (COMMAND_FIFO__COMMAND(OPCODE_MACRO) | \
COMMAND_FIFO__OPERAND(((seq) << 8) | (len)))
#define CMD_POLL(addr) (COMMAND_FIFO__COMMAND(OPCODE_POLL) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_WAIT_FOR_INT(irq,bit) (COMMAND_FIFO__COMMAND(OPCODE_WAIT_FOR_INT) | \
COMMAND_FIFO__OPERAND((irq) << 8 | (bit) << 0))
#define CMD_STORE_TO_FIFO(reg) (COMMAND_FIFO__COMMAND(OPCODE_STORE_TO_FIFO) | \
COMMAND_FIFO__OPERAND((reg) & 0xFFFFF))
// =============================================================================
// COMMAND_FIFO_PTR bitfields
// =============================================================================
#define COMMAND_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define COMMAND_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define COMMAND_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// COMMAND_FIFO_LOW bitfields
// =============================================================================
#define COMMAND_FIFO_LOW__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// COMMAND_COUNT bitfields
// =============================================================================
#define COMMAND_COUNT__MAX_COUNT (32)
// =============================================================================
// COMMAND_INT_CODE bitfields
// =============================================================================
#define COMMAND_INT_CODE__READ(regval) ((regval) & 0xFFFFFF)
#define COMMAND_INT_CODE__WAIT_FOR_READY_CODE(regval) ((regval >> 16) & 0xFF)
#define COMMAND_INT_CODE__WAIT_FOR_READY_STATUS(regval) ((regval >> 0) & 0xFF)
// =============================================================================
// OPERAND_FIFO_PTR bitfields
// =============================================================================
#define OPERAND_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define OPERAND_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define OPERAND_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// OPERAND_FIFO_LOW bitfields
// =============================================================================
#define OPERAND_FIFO_LOW__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// STORE_FIFO_PTR bitfields
// =============================================================================
#define STORE_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define STORE_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define STORE_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// STORE_FIFO_HIGH bitfields
// =============================================================================
#define STORE_FIFO_HIGH__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// SEQ_INT_PEND bitfields
// =============================================================================
#define SEQ_INT_PEND__STORE_FIFO_FULL (0x1UL << 10)
#define SEQ_INT_PEND__STORE_FIFO_HIGH (0x1UL << 9)
#define SEQ_INT_PEND__STORE_FIFO_OVERFLOW (0x1UL << 8)
#define SEQ_INT_PEND__TIMEOUT (0x1UL << 7)
#define SEQ_INT_PEND__OPERAND_FIFO_EMPTY (0x1UL << 6)
#define SEQ_INT_PEND__OPERAND_FIFO_LOW (0x1UL << 5)
#define SEQ_INT_PEND__OPERAND_FIFO_OVERFLOW (0x1UL << 4)
#define SEQ_INT_PEND__COMMAND_FIFO_EMPTY (0x1UL << 3)
#define SEQ_INT_PEND__COMMAND_FIFO_LOW (0x1UL << 2)
#define SEQ_INT_PEND__COMMAND_FIFO_OVERFLOW (0x1UL << 1)
#define SEQ_INT_PEND__SEQUENCER_SIGNAL (0x1UL << 0)
// =============================================================================
// SEQ_INT_EN bitfields
// =============================================================================
#define SEQ_INT_EN__TIMEOUT (0x1UL << 7)
#define SEQ_INT_EN__OPERAND_FIFO_EMPTY (0x1UL << 6)
#define SEQ_INT_EN__OPERAND_FIFO_LOW (0x1UL << 5)
#define SEQ_INT_EN__OPERAND_FIFO_OVERFLOW (0x1UL << 4)
#define SEQ_INT_EN__COMMAND_FIFO_EMPTY (0x1UL << 3)
#define SEQ_INT_EN__COMMAND_FIFO_LOW (0x1UL << 2)
#define SEQ_INT_EN__COMMAND_FIFO_OVERFLOW (0x1UL << 1)
#define SEQ_INT_EN__SEQUENCER_SIGNAL (0x1UL << 0)
// =============================================================================
// SEQ_MACRO_CONTROL bitfields
// =============================================================================
#define SEQ_MACRO_CONTROL__WORD_COUNT(cnt) (((cnt) & 0x3F) << 8)
#define SEQ_MACRO_CONTROL__MACRO_ADDRESS(addr) (((addr) & 0x3F) << 0)
#define SEQ_MACRO_CONTROL__GET_WORD_COUNT(regval) (((regval) >> 8) & 0x3F)
#define SEQ_MACRO_CONTROL__GET_MACRO_ADDRESS(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// SoC-Specific Tuning
// =============================================================================
#define FMI_TX_PROP_DELAY_NS (7)
#define FMI_RX_PROP_DELAY_NS (5)
#define FMI_USE_WRITE_CYCLE_BALANCING (1)
#endif // _H2FMI_8945REGS_H_
// ********************************** EOF *************************************
+840
View File
@@ -0,0 +1,840 @@
// *****************************************************************************
//
// File: H2fmi_regs.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position
//
// - consider adding definitions for extracting value from register position
//
// *****************************************************************************
//
// Copyright (C) 2010 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "WMRFeatures.h"
#if defined(H2FMI_EFI) && H2FMI_EFI
#include "SoC.h"
#else
#include <platform/soc/hwregbase.h>
#endif
#include <WMRTypes.h>
#ifndef _H2FMI_8945REGS_H_
#define _H2FMI_8945REGS_H_
// =============================================================================
// register bases and offsets
// =============================================================================
#define FMI0 ((UInt32*)FMI0_BASE_ADDR)
#define FMI1 ((UInt32*)FMI1_BASE_ADDR)
#define FMI_OFFSET (0x00000)
#define FMC_OFFSET (0x40000)
#define ECC_OFFSET (0x80000)
#define CMD_OFFSET (0xC0000)
#define FMC0 ((volatile UInt32*)((UInt32)FMI0 + FMC_OFFSET))
#define FMC1 ((volatile UInt32*)((UInt32)FMI1 + FMC_OFFSET))
#define FMI_BA(offset) ((UInt32)(FMI_OFFSET + offset))
#define FMC_BA(offset) ((UInt32)(FMC_OFFSET + offset))
#define ECC_BA(offset) ((UInt32)(ECC_OFFSET + offset))
#define CMD_BA(offset) ((UInt32)(CMD_OFFSET + offset))
#define NAND_DLL_REG(offset) ((volatile UInt32*)(NAND_DLL_BASE_ADDR + (offset)))
#define FMI_CONFIG FMI_BA(0x00)
#define FMI_CONTROL FMI_BA(0x04)
#define FMI_STATUS FMI_BA(0x08)
#define FMI_INT_PEND FMI_BA(0x0C)
#define FMI_INT_EN FMI_BA(0x10)
#define FMI_DATA_BUF FMI_BA(0x14)
#define FMI_META_FIFO FMI_BA(0x18)
#define FMI_DEBUG0 FMI_BA(0x1C)
#define FMI_HW_VERSION FMI_BA(0x30)
#define FMI_DATA_SIZE FMI_BA(0x34)
#define FMI_RAW_PAGE_SIZE FMI_BA(0x38)
#define FMI_SCRAMBLER_SEED_FIFO FMI_BA(0x3C)
#define FMI_SEED_FIFO_LOW_LEVEL FMI_BA(0x40)
#define FMI_METADATA_FIFO_PTR FMI_BA(0x44)
#define FMI_SEED_FIFO_PTR FMI_BA(0x48)
#define FMI_RANDOMIZER_VERSION FMI_BA(0x4C)
#define FMI_BUFFER_0_BASE FMI_BA(0x1000)
#define FMI_BUFFER_1_BASE FMI_BA(0x1800)
#define FMI_BUFFER_LEN (0x45F)
#define FMI_META_FIFO_BASE FMI_BA(0x2000)
#define FMI_META_FIFO_LENGTH (32)
#define FMI_SEED_FIFO_BASE FMI_BA(0x3000)
#define FMI_SEED_FIFO_LENGTH (8)
#define FMI_ECC_RESULT_FIFO_BASE FMI_BA(0x81000)
#define FMI_ECC_RESULT_FIFO_LENGTH (32)
#define FMI_ECC_PAGE_FIFO_BASE FMI_BA(0xC1000)
#define FMI_ECC_PAGE_FIFO_LENGTH (32)
#define FMC_ON FMC_BA(0x00)
#define FMC_VER FMC_BA(0x04)
#define FMC_IF_CTRL FMC_BA(0x08)
#define FMC_CE_CTRL FMC_BA(0x0C)
#define FMC_RW_CTRL FMC_BA(0x10)
#define FMC_CMD FMC_BA(0x14)
#define FMC_ADDR0 FMC_BA(0x18)
#define FMC_ADDR1 FMC_BA(0x1C)
#define FMC_ADDRNUM FMC_BA(0x20)
#define FMC_DATANUM FMC_BA(0x24)
#define FMC_UNDEF0 FMC_BA(0x28)
#define FMC_UNDEF1 FMC_BA(0x2C)
#define FMC_TO_CTRL FMC_BA(0x30)
#define FMC_TO_CNT FMC_BA(0x34)
#define FMC_UNDEF2 FMC_BA(0x38)
#define FMC_UNDEF3 FMC_BA(0x3C)
#define FMC_INTMASK FMC_BA(0x40)
#define FMC_STATUS FMC_BA(0x44)
#define FMC_NAND_STATUS FMC_BA(0x48)
#define FMC_RBB_CONFIG FMC_BA(0x4C)
#define FMC_DQS_TIMING_CTRL FMC_BA(0x70)
#define FMC_TOGGLE_CTRL_1 FMC_BA(0x74)
#define FMC_TOGGLE_CTRL_2 FMC_BA(0x78)
#define FMC_TOGGLE_CTRL_3 FMC_BA(0x7C)
#define ECC_VERSION ECC_BA(0x00)
#define ECC_CON0 ECC_BA(0x04)
#define ECC_CON1 ECC_BA(0x08)
#define ECC_RESULT ECC_BA(0x0C)
#define ECC_PND ECC_BA(0x10)
#define ECC_MASK ECC_BA(0x14)
#define ECC_HISTORY ECC_BA(0x18)
#define ECC_CORE_SW_RESET ECC_BA(0x1C)
#define ECC_PAGE_ERROR_FIFO ECC_BA(0x24)
#define ECC_PAGE_ERROR_FIFO_PTR ECC_BA(0x28)
#define ECC_RESULTS_FIFO_PTR ECC_BA(0x2C)
#define COMMAND_FIFO CMD_BA(0x00)
#define COMMAND_FIFO_PTR CMD_BA(0x04)
#define COMMAND_FIFO_LOW CMD_BA(0x08)
#define COMMAND_COUNT CMD_BA(0x0C)
#define COMMAND_INT_CODE CMD_BA(0x10)
#define OPERAND_FIFO CMD_BA(0x14)
#define OPERAND_FIFO_PTR CMD_BA(0x18)
#define OPERAND_FIFO_LOW CMD_BA(0x1C)
#define SEQ_INT_PEND CMD_BA(0x20)
#define SEQ_INT_EN CMD_BA(0x24)
#define SEQ_MACRO_CONTROL CMD_BA(0x28)
#define TIMEOUT_VALUE CMD_BA(0x2C)
#define STORE_FIFO CMD_BA(0x30)
#define STORE_FIFO_PTR CMD_BA(0x34)
#define STORE_FIFO_HIGH CMD_BA(0x38)
#define SEQUENCER_MACROS(n) CMD_BA(0x1000 + ((n) & 0xFF))
#define SEQUENCER_COMMANDS(n) CMD_BA(0x2000 + ((n) & 0x7F))
#define SEQUENCER_OPERANDS(n) CMD_BA(0x3000 + ((n) & 0x7F))
#define SEQUENCER_STORES(n) CMD_BA(0x4000 + ((n) & 0x7F))
#define NAND_DLL_CONTROL NAND_DLL_REG(0x00)
#define NAND_DLL_TIMEOUT_DELAY NAND_DLL_REG(0x04)
#define NAND_DLL_STATUS NAND_DLL_REG(0x08)
#define NAND_DLL_FORCE_VALUE NAND_DLL_REG(0x0C)
#define h2fmi_dll_wr(reg, val) (*(reg) = (val))
#define h2fmi_dll_rd(reg) (*(reg))
// =============================================================================
// FMI_CONFIG bitfields
// =============================================================================
#define FMI_CONFIG__DMA_BURST(n) (((n) & 0x7) << 0)
#define FMI_CONFIG__META_DMA_BURST_SIZE(n) (((n) & 0x7) << 9)
#define FMI_CONFIG__META_DMA_BURST_WIDTH(n) (((n) & 0x3) << 12)
#define FMI_CONFIG__ECC_CORRECTABLE_BITS(m) (((m) & 0x1f) << 3)
#define FMI_CONFIG__SCRAMBLE_SEED (0x1UL << 14)
#define FMI_CONFIG__ENABLE_WHITENING (0x1UL << 8)
#define FMI_CONFIG__DMA_BURST__32_CYCLES FMI_CONFIG__DMA_BURST(5)
#define FMI_CONFIG__DMA_BURST__16_CYCLES FMI_CONFIG__DMA_BURST(4)
#define FMI_CONFIG__DMA_BURST__8_CYCLES FMI_CONFIG__DMA_BURST(3)
#define FMI_CONFIG__DMA_BURST__4_CYCLES FMI_CONFIG__DMA_BURST(2)
#define FMI_CONFIG__DMA_BURST__2_CYCLES FMI_CONFIG__DMA_BURST(1)
#define FMI_CONFIG__DMA_BURST__1_CYCLES FMI_CONFIG__DMA_BURST(0)
#define FMI_CONFIG__META_DMA_BURST__32_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(5)
#define FMI_CONFIG__META_DMA_BURST__16_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(4)
#define FMI_CONFIG__META_DMA_BURST__8_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(3)
#define FMI_CONFIG__META_DMA_BURST__4_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(2)
#define FMI_CONFIG__META_DMA_BURST__2_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(1)
#define FMI_CONFIG__META_DMA_BURST__1_CYCLES FMI_CONFIG__META_DMA_BURST_SIZE(0)
#define FMI_CONFIG__META_DMA_BURST__4_BYTES FMI_CONFIG__META_DMA_BURST_WIDTH(2)
#define FMI_CONFIG__META_DMA_BURST__2_BYTES FMI_CONFIG__META_DMA_BURST_WIDTH(1)
#define FMI_CONFIG__META_DMA_BURST__1_BYTES FMI_CONFIG__META_DMA_BURST_WIDTH(0)
// =============================================================================
// FMI_CONTROL bitfields
// =============================================================================
#define FMI_CONTROL__PAUSE_WHEN_STORE_FIFO_FULL (0x1UL << 14)
#define FMI_CONTROL__DISABLE_STREAMING (0x1UL << 13)
#define FMI_CONTROL__SEQUENCER_TIMEOUT_ENABLE (0x1UL << 12)
#define FMI_CONTROL__RESET_SEED (0x1UL << 11)
#define FMI_CONTROL__RAW_READ_MODE (0x1UL << 10)
#define FMI_CONTROL__RESET_SEQUENCER (0x1UL << 9)
#define FMI_CONTROL__ENABLE_SEQUENCER (0x1UL << 8)
#define FMI_CONTROL__ECC_PAUSE (0x1UL << 7)
#define FMI_CONTROL__BUFFER_1_LOCK(m) (((m) & 0x3) << 5)
#define FMI_CONTROL__BUFFER_0_LOCK(m) (((m) & 0x3) << 3)
#define FMI_CONTROL__MODE(m) (((m) & 0x3) << 1)
#define FMI_CONTROL__START_BIT (0x1UL << 0)
#define FMI_CONTROL__MODE__IDLE FMI_CONTROL__MODE(0)
#define FMI_CONTROL__MODE__READ FMI_CONTROL__MODE(1)
#define FMI_CONTROL__MODE__WRITE FMI_CONTROL__MODE(2)
#define FMI_CONTROL__MODE__SOFTWARE_RESET FMI_CONTROL__MODE(3)
#define FMI_CONTROL__BUFFER_0_LOCK_FREE FMI_CONTROL__BUFFER_0_LOCK(0)
#define FMI_CONTROL__BUFFER_0_LOCK_DMA FMI_CONTROL__BUFFER_0_LOCK(1)
#define FMI_CONTROL__BUFFER_0_LOCK_ECC FMI_CONTROL__BUFFER_0_LOCK(2)
#define FMI_CONTROL__BUFFER_0_LOCK_FMC FMI_CONTROL__BUFFER_0_LOCK(3)
#define FMI_CONTROL_BUFFER_1_LOCK_FREE FMI_CONTROL__BUFFER_1_LOCK(0)
#define FMI_CONTROL_BUFFER_1_LOCK_DMA FMI_CONTROL__BUFFER_1_LOCK(1)
#define FMI_CONTROL_BUFFER_1_LOCK_ECC FMI_CONTROL__BUFFER_1_LOCK(2)
#define FMI_CONTROL_BUFFER_1_LOCK_FMC FMI_CONTROL__BUFFER_1_LOCK(3)
// =============================================================================
// FMI_STATUS bitfields
// =============================================================================
#define FMI_STATUS__FMC_ACTIVE (0x1UL << 3)
#define FMI_STATUS__ECC_ACTIVE (0x1UL << 2)
#define FMI_STATUS__DMA_ACTIVE (0x1UL << 1)
#define FMI_STATUS__BUS_ACTIVE (0x1UL << 0)
// =============================================================================
// FMI_INT_PEND bitfields
// =============================================================================
#define FMI_INT_PEND__SEQUENCER_INTERRUPT (0x1UL << 28)
#define FMI_INT_PEND__SEED_FIFO_EMPTY (0x1UL << 27)
#define FMI_INT_PEND__SEED_FIFO_LOW (0x1UL << 26)
#define FMI_INT_PEND__SEED_FIFO_OVERFLOW (0x1UL << 25)
#define FMI_INT_PEND__ECC_RESULTS_FIFO_UNDERFLOW (0x1UL << 24)
#define FMI_INT_PEND__ECC_RESULTS_FIFO_OVERFLOW (0x1UL << 23)
#define FMI_INT_PEND__LAST_ECC_DONE (0x1UL << 22)
#define FMI_INT_PEND__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_PEND__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_PEND__ECC_DONE (0x1UL << 19)
#define FMI_INT_PEND__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_PEND__FMC_READY_BUSY(n) (((n) & 0xFF) << 10)
#define FMI_INT_PEND__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_PEND__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_PEND__FMC_NSERR (0x1UL << 7)
#define FMI_INT_PEND__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_PEND__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_PEND__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_PEND__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_PEND__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_PEND__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_PEND__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_INT_EN bitfields
// =============================================================================
#define FMI_INT_EN__SEQUENCER_INTERRUPT (0x1UL << 28)
#define FMI_INT_EN__SEED_FIFO_EMPTY (0x1UL << 27)
#define FMI_INT_EN__SEED_FIFO_LOW (0x1UL << 26)
#define FMI_INT_EN__SEED_FIFO_OVERFLOW (0x1UL << 25)
#define FMI_INT_EN__ECC_RESULTS_FIFO_UNDERFLOW (0x1UL << 24)
#define FMI_INT_EN__ECC_RESULTS_FIFO_OVERFLOW (0x1UL << 23)
#define FMI_INT_EN__LAST_ECC_DONE (0x1UL << 22)
#define FMI_INT_EN__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_EN__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_EN__ECC_DONE (0x1UL << 19)
#define FMI_INT_EN__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_EN__FMC_READY_BUSY (0x1UL << 10)
#define FMI_INT_EN__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_EN__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_EN__FMC_NSERR (0x1UL << 7)
#define FMI_INT_EN__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_EN__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_EN__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_EN__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_EN__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_EN__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_EN__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_DEBUG0 bitfields
// =============================================================================
#define FMI_DEBUG0__FMC_TASKS_PENDING(n) (((n) & 0x3) << 7)
#define FMI_DEBUG0__ECC_TASKS_PENDING(n) (((n) & 0x3) << 5)
#define FMI_DEBUG0__DMA_TASKS_PENDING(n) (((n) & 0x3) << 3)
#define FMI_DEBUG0__FMC_TARGET_BUFFER(b) (((b) & 0x1) << 2)
#define FMI_DEBUG0__ECC_TARGET_BUFFER(b) (((b) & 0x1) << 1)
#define FMI_DEBUG0__DMA_TARGET_BUFFER(b) (((b) & 0x1) << 0)
// =============================================================================
// FMI_DATA_SIZE bifields
// =============================================================================
#define FMI_DATA_SIZE__META_BYTES_PER_SECTOR(n) (((n) & 0x3F) << 25)
#define FMI_DATA_SIZE__META_BYTES_PER_PAGE(n) (((n) & 0x3F) << 19)
#define FMI_DATA_SIZE__BYTES_PER_SECTOR(n) (((n) & 0x7FF) << 8)
#define FMI_DATA_SIZE__SECTORS_PER_PAGE(n) (((n) & 0xFF) << 0)
// =============================================================================
// FMI_SEED_FIFO_LOW_LEVEL bitfields
// =============================================================================
#define FMI_SEED_FIFO_LOW_LEVEL__LEVEL(x) (((x) & 0x7) << 0)
// =============================================================================
// METADATA_FIFO_PTR bitfields
// =============================================================================
#define METADATA_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define METADATA_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define METADATA_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// SEED_FIFO_PTR bitfields
// =============================================================================
#define SEED_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x7)
#define SEED_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x7)
#define SEED_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0xF)
// =============================================================================
// FMC_ON bitfields
// =============================================================================
#define FMC_ON__SWRST (0x1UL << 8)
#define FMC_ON__ASYNC_DRIVE_DQS (0x1UL << 6)
#define FMC_ON__ASYNC_CEB_AUTO_DISABLE (0x1UL << 5)
#define FMC_ON__DDR_NAND_TYPE_TOGGLE (0x0UL << 3)
#define FMC_ON__DDR_NAND_TYPE_ONFI (0x1UL << 3)
#define FMC_ON__DDR_ENABLE (0x1UL << 2)
#define FMC_ON__CLKGATING_RDY (0x1UL << 1)
#define FMC_ON__ENABLE (0x1UL << 0)
#define FMC_ON__DISABLE (!FMC_ON__ENABLE)
// =============================================================================
// FMC_IF_CTRL bitfields
// =============================================================================
#define FMC_IF_CTRL__WPB (0x1UL << 21)
#define FMC_IF_CTRL__RBBEN (0x1UL << 20)
#define FMC_IF_CTRL__DCCYCLE(v) (((v) & 0xF) << 16)
#define FMC_IF_CTRL__REB_SETUP(v) (((v) & 0xF) << 12)
#define FMC_IF_CTRL__REB_HOLD(v) (((v) & 0xF) << 8)
#define FMC_IF_CTRL__WEB_SETUP(v) (((v) & 0xF) << 4)
#define FMC_IF_CTRL__WEB_HOLD(v) (((v) & 0xF) << 0)
#define FMC_IF_CTRL__GET_DCCYCLE(v) (((v) & 0xF0000) >> 16)
#define FMC_IF_CTRL__GET_REB_SETUP(v) (((v) & 0x0F000) >> 12)
#define FMC_IF_CTRL__GET_REB_HOLD(v) (((v) & 0x00F00) >> 8)
#define FMC_IF_CTRL__GET_WEB_SETUP(v) (((v) & 0x000F0) >> 4)
#define FMC_IF_CTRL__GET_WEB_HOLD(v) (((v) & 0x0000F) >> 0)
#define FMC_IF_CTRL__REB_SETUP_MASK (0x0000000F << 12)
#define FMC_IF_CTRL__TIMING_MAX_CLOCKS (0xFUL)
// =============================================================================
// FMC_CE_CTRL bitfields
// =============================================================================
#define FMC_CE_CTRL__CE_COUNT (8)
#define FMC_CE_CTRL__CEB(n) (0x1UL << ((n) & 0x7))
#define FMC_CE_CTRL__CEB7 FMC_CE_CTRL__CEB(7)
#define FMC_CE_CTRL__CEB6 FMC_CE_CTRL__CEB(6)
#define FMC_CE_CTRL__CEB5 FMC_CE_CTRL__CEB(5)
#define FMC_CE_CTRL__CEB4 FMC_CE_CTRL__CEB(4)
#define FMC_CE_CTRL__CEB3 FMC_CE_CTRL__CEB(3)
#define FMC_CE_CTRL__CEB2 FMC_CE_CTRL__CEB(2)
#define FMC_CE_CTRL__CEB1 FMC_CE_CTRL__CEB(1)
#define FMC_CE_CTRL__CEB0 FMC_CE_CTRL__CEB(0)
// =============================================================================
// FMC_RW_CTRL bitfields
// =============================================================================
#define FMC_RW_CTRL__NAND_TIMING_USER_TAT(x) (((x) & 0xFF) << 24)
#define FMC_RW_CTRL__CMD1_5_MODE (0x1UL << 9)
#define FMC_RW_CTRL__WAIT_NSRBB_FLD (0x1UL << 8)
#define FMC_RW_CTRL__RD_DONE_REB_CEB_HOLD (0x1UL << 7)
#define FMC_RW_CTRL__REBHOLD (0x1UL << 6)
#define FMC_RW_CTRL__WR_MODE (0x1UL << 5)
#define FMC_RW_CTRL__RD_MODE (0x1UL << 4)
#define FMC_RW_CTRL__ADDR_MODE (0x1UL << 3)
#define FMC_RW_CTRL__CMD3_MODE (0x1UL << 2)
#define FMC_RW_CTRL__CMD2_MODE (0x1UL << 1)
#define FMC_RW_CTRL__CMD1_MODE (0x1UL << 0)
// =============================================================================
// FMC_CMD bitfields
// =============================================================================
#define FMC_CMD__CMD1_5(c) (((c) & 0xFF) << 24)
#define FMC_CMD__CMD3(c) (((c) & 0xFF) << 16)
#define FMC_CMD__CMD2(c) (((c) & 0xFF) << 8)
#define FMC_CMD__CMD1(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR0 bitfields
// =============================================================================
#define FMC_ADDR0__SEQ3(a) (((a) & 0xFF) << 24)
#define FMC_ADDR0__SEQ2(a) (((a) & 0xFF) << 16)
#define FMC_ADDR0__SEQ1(a) (((a) & 0xFF) << 8)
#define FMC_ADDR0__SEQ0(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR1 bitfields
// =============================================================================
#define FMC_ADDR1__SEQ7(a) (((a) & 0xFF) << 24)
#define FMC_ADDR1__SEQ6(a) (((a) & 0xFF) << 16)
#define FMC_ADDR1__SEQ5(a) (((a) & 0xFF) << 8)
#define FMC_ADDR1__SEQ4(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDRNUM bitfields
// =============================================================================
#define FMC_ADDRNUM__NUM(n) (((n) & 0x7) << 0)
// =============================================================================
// FMC_DATANUM bitfields
// =============================================================================
#define FMC_DATANUM__NUM(n) (((n) & 0x3FF) << 0)
// =============================================================================
// FMC_TO_CTRL bitfields
// =============================================================================
#define FMC_TO_CTRL__EN (0x1UL << 12)
#define FMC_TO_CTRL__DIV(d) (((d) & 0xF) << 8)
#define FMC_TO_CTRL__VAL(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_TO_CNT bitfields
// =============================================================================
#define FMC_TO_CNT__CNT(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_INTMASK bitfields
// =============================================================================
#define FMC_INTMASK__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_INTMASK__CMD1_5DONE (0x1UL << 17)
#define FMC_INTMASK__RBBDONE7 FMC_INTMASK__RBBDONE(7)
#define FMC_INTMASK__RBBDONE6 FMC_INTMASK__RBBDONE(6)
#define FMC_INTMASK__RBBDONE5 FMC_INTMASK__RBBDONE(5)
#define FMC_INTMASK__RBBDONE4 FMC_INTMASK__RBBDONE(4)
#define FMC_INTMASK__RBBDONE3 FMC_INTMASK__RBBDONE(3)
#define FMC_INTMASK__RBBDONE2 FMC_INTMASK__RBBDONE(2)
#define FMC_INTMASK__RBBDONE1 FMC_INTMASK__RBBDONE(1)
#define FMC_INTMASK__RBBDONE0 FMC_INTMASK__RBBDONE(0)
#define FMC_INTMASK__TIMEOUT (0x1UL << 7)
#define FMC_INTMASK__NSERR (0x1UL << 6)
#define FMC_INTMASK__NSRBBDONE (0x1UL << 5)
#define FMC_INTMASK__TRANSDONE (0x1UL << 4)
#define FMC_INTMASK__ADDRESSDONE (0x1UL << 3)
#define FMC_INTMASK__CMD3DONE (0x1UL << 2)
#define FMC_INTMASK__CMD2DONE (0x1UL << 1)
#define FMC_INTMASK__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_STATUS bitfields
// =============================================================================
#define FMC_STATUS__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_STATUS__EMERGENCY2 (0x1UL << 21)
#define FMC_STATUS__EMERGENCY01 (0x1UL << 20)
#define FMC_STATUS__RDATADIRTY (0x1UL << 16)
#define FMC_STATUS__RBBDONE7 FMC_STATUS__RBBDONE(7)
#define FMC_STATUS__RBBDONE6 FMC_STATUS__RBBDONE(6)
#define FMC_STATUS__RBBDONE5 FMC_STATUS__RBBDONE(5)
#define FMC_STATUS__RBBDONE4 FMC_STATUS__RBBDONE(4)
#define FMC_STATUS__RBBDONE3 FMC_STATUS__RBBDONE(3)
#define FMC_STATUS__RBBDONE2 FMC_STATUS__RBBDONE(2)
#define FMC_STATUS__RBBDONE1 FMC_STATUS__RBBDONE(1)
#define FMC_STATUS__RBBDONE0 FMC_STATUS__RBBDONE(0)
#define FMC_STATUS__TIMEOUT (0x1UL << 7)
#define FMC_STATUS__NSERR (0x1UL << 6)
#define FMC_STATUS__NSRBBDONE (0x1UL << 5)
#define FMC_STATUS__TRANSDONE (0x1UL << 4)
#define FMC_STATUS__ADDRESSDONE (0x1UL << 3)
#define FMC_STATUS__CMD3DONE (0x1UL << 2)
#define FMC_STATUS__CMD2DONE (0x1UL << 1)
#define FMC_STATUS__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_RBB_CONFIG bitfields
// =============================================================================
#define FMC_RBB_CONFIG__POL(v) (((v) & 0xFF) << 8)
#define FMC_RBB_CONFIG__POS(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_DQS_TIMING_CTRL bitfields
// =============================================================================
#define FMC_DQS_TIMING_CTRL__USE_DLL (0x1UL << 31)
#define FMC_DQS_TIMING_CTRL__DELTAV_SUSPENDS_READS (0x1UL << 30)
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL(x) (((x) & 0x1FF) << 16)
#define FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL_GET(x) (((x) & 0x01FF0000) >> 16)
#define FMC_DQS_TIMING_CTRL__DQS_WRITE_TIMING_DIR_POS (0 << 3)
#define FMC_DQS_TIMING_CTRL__DQS_WRITE_TIMING_DIR_NEG (1 << 3)
#define FMC_DQS_TIMING_CTRL__DQS_WRITE_DELAY_TIMING(x) (((x) & 0x7) << 0)
#define FMC_DQS_TIMING_CTRL__DEFAULT_VAL (0x01FF0000)
// =============================================================================
// FMC_TOGGLE_CTRL_1 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_1_DDR_RD_PRE_TIME(x) (((x) & 0xFF) << 24)
#define FMC_TOGGLE_CTRL_1_DDR_RD_POST_TIME(x) (((x) & 0xFF) << 16)
#define FMC_TOGGLE_CTRL_1_DDR_WR_PRE_TIME(x) (((x) & 0xFF) << 8)
#define FMC_TOGGLE_CTRL_1_DDR_WR_POST_TIME(x) (((x) & 0xFF) << 0)
#define FMC_TOGGLE_CTRL_1__TIMING_MAX_CLOCKS (0xFF)
// =============================================================================
// FMC_TOGGLE_CTRL_2 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_2_CE_SETUP_TIME(x) (((x) & 0xFF) << 24)
#define FMC_TOGGLE_CTRL_2_CE_HOLD_TIME(x) (((x) & 0xFF) << 16)
#define FMC_TOGGLE_CTRL_2_NAND_TIMING_ADL(x) (((x) & 0xFF) << 8)
#define FMC_TOGGLE_CTRL_2_NAND_TIMING_WHR(x) (((x) & 0xFF) << 0)
#define FMC_TOGGLE_CTRL_2__TIMING_MAX_CLOCKS (0xFF)
// =============================================================================
// FMC_TOGGLE_CTRL_2 bitfields
// =============================================================================
#define FMC_TOGGLE_CTRL_3_ONFI_WR_CLK_STOP_EN (0x1UL << 31)
#define FMC_TOGGLE_CTRL_3_DISABLE_ONFI_READ_STATUS_CLE_ALE_HOLD (0x1UL << 30)
#define FMC_TOGGLE_CTRL_3_DISABLE_ONFI_ONFI_IDLE_CLOCK_ON (0x1UL << 29)
#define FMC_TOGGLE_CTRL_3_ONFI_TIMING_CAD (((x) & 0xF) << 0)
// =============================================================================
// ECC_CON0 bitfields
// =============================================================================
#define ECC_CON0__INFORMATION_LENGTH(n) (((n) & 0x7FF) << 16)
#define ECC_CON0__ECC_CORRECTION_MODE(m) (((m) & 0x1F) << 4)
#define ECC_CON0__START_ENC (0x1UL << 1)
#define ECC_CON0__START_DEC (0x1UL << 0)
// =============================================================================
// ECC_CON1 bitfields
// =============================================================================
#define ECC_CON1__IMPLICIT_WRITE_MARK (1UL << 31)
#define ECC_CON1__SLAVE_MODE (1UL << 29)
#define ECC_CON1__SKIP_FREE_PAGE_FLD (1UL << 25)
#define ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(n) (((n) & 0x1F) << 16)
#define ECC_CON1__ERROR_ALERT_LEVEL(n) (((n) & 0x1F) << 8)
#define ECC_CON1__INT_ENABLE(b) (((b) & 0x1) << 7)
#define ECC_CON1__INT_ENABLE__ENABLE ECC_CON1__INT_ENABLE(1)
#define ECC_CON1__INT_ENABLE__DISABLE ECC_CON1__INT_ENABLE(0)
// =============================================================================
// ECC_RESULT bitfields
// =============================================================================
#define ECC_RESULT__ERROR_ALERT (0x1UL << 21)
#define ECC_RESULT__ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_RESULT__ERROR_CNT_SHIFT (16)
#define ECC_RESULT__ERROR_CNT_MASK (0x1FUL << ECC_RESULT__ERROR_CNT_SHIFT)
#define ECC_RESULT__STUCK_BIT_EXCEEDED (0x1UL << 14)
#define ECC_RESULT__STUCK_BIT_CNT(n) (((n) & 0x3F) << 8)
#define ECC_RESULT__DECODED_BUFFER_IDX (0x1UL << 6)
#define ECC_RESULT__ALL_FF (0x1UL << 3)
#define ECC_RESULT__ALL_ZERO (0x1UL << 2)
#define ECC_RESULT__FREE_PAGE (0x1UL << 1)
#define ECC_RESULT__UNCORRECTABLE (0x1UL << 0)
#define ECC_RESULT__FIFO_RESET (0x1UL << 0) // Same as uncorrectable bit
// =============================================================================
// ECC_PND bitfields
// =============================================================================
#define ECC_PND__MAX_STUCK_BIT_CNT(n) (((n) & 0x3F) << 24)
#define ECC_PND__MAX_ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_PND__MAX_ERROR_CNT_SHIFT (16)
#define ECC_PND__MAX_ERROR_CNT_MASK (0x1FUL << ECC_PND__MAX_ERROR_CNT_SHIFT)
#define ECC_PND__DETECTOR_DONE (0x1UL << 14)
#define ECC_PND__B1_DEC_DONE (0x1UL << 13)
#define ECC_PND__B0_DEC_DONE (0x1UL << 12)
#define ECC_PND__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_PND__SOME_ALL_FF (0x1UL << 8)
#define ECC_PND__SOME_ALL_ZERO (0x1UL << 7)
#define ECC_PND__ALL_FREE_PAGE (0x1UL << 6)
#define ECC_PND__SOME_ERROR_ALERT (0x1UL << 5)
#define ECC_PND__READY_BUSY (0x1UL << 4)
#define ECC_PND__ANY_UNCORRECTABLE (0x1UL << 3)
#define ECC_PND__ENC_DONE (0x1UL << 2)
#define ECC_PND__DEC_DONE (0x1UL << 1)
#define ECC_PND__ENC_DEC_DONE (0x1UL << 0)
// =============================================================================
// ECC_MASK bitfields
// =============================================================================
#define ECC_MASK__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_MASK__SOME_ALL_FF_MASK (0x1UL << 8)
#define ECC_MASK__SOME_ALL_ZERO_MASK (0x1UL << 7)
#define ECC_MASK__SOME_ERROR_ALERT_MASK (0x1UL << 5)
#define ECC_MASK__ANY_UNCORRECTABLE_MASK (0x1UL << 3)
#define ECC_MASK__ENC_DONE_MASK (0x1UL << 2)
#define ECC_MASK__DEC_DONE_MASK (0x1UL << 1)
#define ECC_MASK__ENC_DEC_DONE_MASK (0x1UL << 0)
// =============================================================================
// ECC_HISTORY bitfields
// =============================================================================
#define ECC_HISTORY__ERROR_COUNT_CLEAR (0x1UL << 26)
#define ECC_HISTORY__ERROR_COUNT(n) (((n) & 0x7FFF) << 11)
#define ECC_HISTORY__DECODING_NUMBER_CLEAR (0x1UL << 10)
#define ECC_HISTORY__DECODING_NUMBER(n) (((n) & 0x1FF) << 0)
// =============================================================================
// RESULT_FIFO_PTR bitfields
// =============================================================================
#define ECC_RESULTS_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define ECC_RESULTS_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define ECC_RESULTS_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// COMMAND_FIFO bitfields
// =============================================================================
#define COMMAND_FIFO_SIZE (32)
#define OPERAND_FIFO_SIZE (32)
#define STORE_FIFO_SIZE (32)
#define COMMAND_FIFO__COMMAND(cmd) ((cmd) << 24)
#define COMMAND_FIFO__OPERAND(op) (((op) & 0xFFFFFF) << 0)
#define OPCODE_ADDR(n) (n)
#define OPCODE_COMMAND (0x08)
#define OPCODE_ENABLE_CE (0x09)
#define OPCODE_WAIT_FOR_READY (0x0A)
#define OPCODE_TX_PAGE (0x0B)
#define OPCODE_SEND_INTERRUPT (0x0C)
#define OPCODE_PAUSE (0x0D)
#define OPCODE_TIMED_WAIT (0x0E)
#define OPCODE_LOAD_NEXT_WORD (0x0F)
#define OPCODE_LOAD_FROM_FIFO (0x10)
#define OPCODE_MACRO (0x11)
#define OPCODE_POLL (0x12)
#define OPCODE_WAIT_FOR_INT (0x13)
#define OPCODE_STORE_TO_FIFO (0x14)
#define CMD_ADDRESS(bytes, addr) (COMMAND_FIFO__COMMAND(OPCODE_ADDR(bytes)) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFFF))
#define CMD_COMMAND(cmd) (COMMAND_FIFO__COMMAND(OPCODE_COMMAND) | \
COMMAND_FIFO__OPERAND((cmd) & 0xFF))
#define CMD_ENABLE_CHIP(mask) (COMMAND_FIFO__COMMAND(OPCODE_ENABLE_CE) | \
COMMAND_FIFO__OPERAND((mask) & 0xFF))
#define CMD_WAIT_FOR_READY(code,mask,cond) (COMMAND_FIFO__COMMAND(OPCODE_WAIT_FOR_READY) | \
COMMAND_FIFO__OPERAND((code) << 16 | (mask) << 8 | (cond) << 0))
#define CMD_TX_PAGE (COMMAND_FIFO__COMMAND(OPCODE_TX_PAGE))
#define CMD_SEND_INTERRUPT(code) (COMMAND_FIFO__COMMAND(OPCODE_SEND_INTERRUPT) | \
COMMAND_FIFO__OPERAND(code))
#define CMD_PAUSE (COMMAND_FIFO__COMMAND(OPCODE_PAUSE))
#define CMD_TIMED_WAIT(clks) (COMMAND_FIFO__COMMAND(OPCODE_TIMED_WAIT) | \
COMMAND_FIFO__OPERAND(clks))
#define CMD_LOAD_NEXT_WORD(addr) (COMMAND_FIFO__COMMAND(OPCODE_LOAD_NEXT_WORD) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_LOAD_FROM_FIFO(addr) (COMMAND_FIFO__COMMAND(OPCODE_LOAD_FROM_FIFO) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_MACRO(seq,len) (COMMAND_FIFO__COMMAND(OPCODE_MACRO) | \
COMMAND_FIFO__OPERAND(((seq) << 8) | (len)))
#define CMD_POLL(addr) (COMMAND_FIFO__COMMAND(OPCODE_POLL) | \
COMMAND_FIFO__OPERAND((addr) & 0xFFFFF))
#define CMD_WAIT_FOR_INT(irq,bit) (COMMAND_FIFO__COMMAND(OPCODE_WAIT_FOR_INT) | \
COMMAND_FIFO__OPERAND((irq) << 8 | (bit) << 0))
#define CMD_STORE_TO_FIFO(reg) (COMMAND_FIFO__COMMAND(OPCODE_STORE_TO_FIFO) | \
COMMAND_FIFO__OPERAND((reg) & 0xFFFFF))
// =============================================================================
// COMMAND_FIFO_PTR bitfields
// =============================================================================
#define COMMAND_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define COMMAND_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define COMMAND_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// COMMAND_FIFO_LOW bitfields
// =============================================================================
#define COMMAND_FIFO_LOW__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// COMMAND_COUNT bitfields
// =============================================================================
#define COMMAND_COUNT__MAX_COUNT (32)
// =============================================================================
// COMMAND_INT_CODE bitfields
// =============================================================================
#define COMMAND_INT_CODE__READ(regval) ((regval) & 0xFFFFFF)
#define COMMAND_INT_CODE__WAIT_FOR_READY_CODE(regval) ((regval >> 16) & 0xFF)
#define COMMAND_INT_CODE__WAIT_FOR_READY_STATUS(regval) ((regval >> 0) & 0xFF)
// =============================================================================
// OPERAND_FIFO_PTR bitfields
// =============================================================================
#define OPERAND_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define OPERAND_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define OPERAND_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// OPERAND_FIFO_LOW bitfields
// =============================================================================
#define OPERAND_FIFO_LOW__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// STORE_FIFO_PTR bitfields
// =============================================================================
#define STORE_FIFO_PTR__READ(regval) (((regval) >> 16) & 0x1F)
#define STORE_FIFO_PTR__WRITE(regval) (((regval) >> 8) & 0x1F)
#define STORE_FIFO_PTR__LEVEL(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// STORE_FIFO_HIGH bitfields
// =============================================================================
#define STORE_FIFO_HIGH__LEVEL(x) (((x) & 0x3F) << 0)
// =============================================================================
// SEQ_INT_PEND bitfields
// =============================================================================
#define SEQ_INT_PEND__STORE_FIFO_FULL (0x1UL << 10)
#define SEQ_INT_PEND__STORE_FIFO_HIGH (0x1UL << 9)
#define SEQ_INT_PEND__STORE_FIFO_OVERFLOW (0x1UL << 8)
#define SEQ_INT_PEND__TIMEOUT (0x1UL << 7)
#define SEQ_INT_PEND__OPERAND_FIFO_EMPTY (0x1UL << 6)
#define SEQ_INT_PEND__OPERAND_FIFO_LOW (0x1UL << 5)
#define SEQ_INT_PEND__OPERAND_FIFO_OVERFLOW (0x1UL << 4)
#define SEQ_INT_PEND__COMMAND_FIFO_EMPTY (0x1UL << 3)
#define SEQ_INT_PEND__COMMAND_FIFO_LOW (0x1UL << 2)
#define SEQ_INT_PEND__COMMAND_FIFO_OVERFLOW (0x1UL << 1)
#define SEQ_INT_PEND__SEQUENCER_SIGNAL (0x1UL << 0)
// =============================================================================
// SEQ_INT_EN bitfields
// =============================================================================
#define SEQ_INT_EN__TIMEOUT (0x1UL << 7)
#define SEQ_INT_EN__OPERAND_FIFO_EMPTY (0x1UL << 6)
#define SEQ_INT_EN__OPERAND_FIFO_LOW (0x1UL << 5)
#define SEQ_INT_EN__OPERAND_FIFO_OVERFLOW (0x1UL << 4)
#define SEQ_INT_EN__COMMAND_FIFO_EMPTY (0x1UL << 3)
#define SEQ_INT_EN__COMMAND_FIFO_LOW (0x1UL << 2)
#define SEQ_INT_EN__COMMAND_FIFO_OVERFLOW (0x1UL << 1)
#define SEQ_INT_EN__SEQUENCER_SIGNAL (0x1UL << 0)
// =============================================================================
// SEQ_MACRO_CONTROL bitfields
// =============================================================================
#define SEQ_MACRO_CONTROL__WORD_COUNT(cnt) (((cnt) & 0x3F) << 8)
#define SEQ_MACRO_CONTROL__MACRO_ADDRESS(addr) (((addr) & 0x3F) << 0)
#define SEQ_MACRO_CONTROL__GET_WORD_COUNT(regval) (((regval) >> 8) & 0x3F)
#define SEQ_MACRO_CONTROL__GET_MACRO_ADDRESS(regval) (((regval) >> 0) & 0x3F)
// =============================================================================
// NAND_DLL_CONTROL bitfields
// =============================================================================
#define NAND_DLL_CONTROL__REFERENCE(x) (((x) & 0xF) << 24)
#define NAND_DLL_CONTROL__STEP_SIZE(x) (((x) & 0xFF) << 16)
#define NAND_DLL_CONTROL__START_POINT(x) (((x) & 0xFF) << 8)
#define NAND_DLL_CONTROL__HALF (1 << 7)
#define NAND_DLL_CONTROL__OVERRIDE (1 << 5)
#define NAND_DLL_CONTROL__CHANNEL_ACTIVE_START (1 << 4)
#define NAND_DLL_CONTROL__VOLTAGE_SHIFT_START (1 << 3)
#define NAND_DLL_CONTROL__TIMEOUT_START (1 << 2)
#define NAND_DLL_CONTROL__SOFTWARE_START (1 << 1)
#define NAND_DLL_CONTROL__ENABLE (1 << 0)
#define NAND_DLL_CONTROL__REFERENCE_DEFAULT (0x8)
#define NAND_DLL_CONTROL__STEP_SIZE_DEFAULT (0x01)
#define NAND_DLL_CONTROL__START_POINT_DEFAULT (0x10)
#define NAND_DLL_TRAIN_TIME_US (1)
// =============================================================================
// NAND_DLL_TIMEOUT bitfields
// =============================================================================
// =============================================================================
// NAND_DLL_STATUS bitfields
// =============================================================================
#define NAND_DLL_STATUS__LOCK_VALUE_GET(x) (((x) >> 3) & 0x3FF)
#define NAND_DLL_STATUS__COARSE_LOCK_ON_GET(x) (((x) >> 2) & 0x1)
#define NAND_DLL_STATUS__FINE_LOCK_ON_GET(x) (((x) >> 1) & 0x1)
#define NAND_DLL_STATUS__DLL_LOCKED_GET(x) (((x) >> 0) & 0x1)
// =============================================================================
// NAND_DLL_FORCE_VALUE bitfields
// =============================================================================
// =============================================================================
// SoC-Specific Tuning
// =============================================================================
#define FMI_TX_PROP_DELAY_NS (6)
#define FMI_RX_PROP_DELAY_NS (6)
#endif // _H2FMI_8945REGS_H_
// ********************************** EOF *************************************
+483
View File
@@ -0,0 +1,483 @@
// *****************************************************************************
//
// File: H2fmi_boot.c
//
// *****************************************************************************
//
// Notes:
//
// - This file contains initialization functions for iBoot and IOP
//
//
// *****************************************************************************
//
// Copyright (C) 2008-2010 Apple, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_private.h"
#include "H2fmi_ppn.h"
#if WMR_BUILDING_EFI
#include "SoC.h"
#else
#include "soc.h"
#endif // WMR_BUILDING_EFI
#include "WMROAM.h"
// =============================================================================
// implementation function declarations shared between SecureROM and iBoot
// =============================================================================
static BOOL32 h2fmi_wait_ready(h2fmi_t* fmi, UInt8 io_mask, UInt8 io_val);
BOOL32 h2fmi_is_chipid_invalid(h2fmi_chipid_t* const id)
{
const h2fmi_chipid_t Zeroes = { 0x00, 0x00, 0x00, 0x00, 0x00 };
const h2fmi_chipid_t Ones = { 0xff, 0xff, 0xff, 0xff, 0xff };
if (WMR_MEMCMP(id, Zeroes, sizeof(h2fmi_chipid_t)) &&
WMR_MEMCMP(id, Ones, sizeof(h2fmi_chipid_t)))
{
return FALSE32;
}
else
{
return TRUE32;
}
}
void h2fmi_reset(h2fmi_t* fmi)
{
// reset the specified FMI subsystem
WMR_CLOCK_RESET_DEVICE(h2fmi_get_gate(fmi));
#if FMI_VERSION > 0
h2fmi_wr(fmi, FMI_CONTROL, FMI_CONTROL__MODE__SOFTWARE_RESET);
#endif
turn_on_fmc(fmi);
restoreTimingRegs(fmi);
}
BOOL32 h2fmi_wait_done(h2fmi_t* fmi,
UInt32 reg,
UInt32 mask,
UInt32 bits)
{
BOOL32 result = TRUE32;
UInt64 check_time = H2FMI_DEFAULT_TIMEOUT_MICROS * WMR_GET_TICKS_PER_US();
UInt64 start_time = WMR_CLOCK_TICKS();
// wait for specified bits to be set
while ((h2fmi_rd(fmi, reg) & mask) != bits)
{
if (WMR_HAS_TIME_ELAPSED_TICKS(start_time, check_time))
{
h2fmi_fail(result);
break;
}
WMR_YIELD();
}
// clear specified bits
h2fmi_wr(fmi, reg, bits);
return result;
}
BOOL32 h2fmi_wait_dma_task_pending(h2fmi_t* fmi)
{
BOOL32 result = TRUE32;
UInt64 check_time = H2FMI_DEFAULT_TIMEOUT_MICROS * WMR_GET_TICKS_PER_US();
UInt64 start_time = WMR_CLOCK_TICKS();
// wait for FMI to complete transfer of sector to fifo
const uint32_t msk = FMI_DEBUG0__DMA_TASKS_PENDING(0x3);
// wait for FMI to to be ready for at least one dma task
while ((h2fmi_rd(fmi, FMI_DEBUG0) & msk) == 0)
{
if (WMR_HAS_TIME_ELAPSED_TICKS(start_time, check_time))
{
h2fmi_fail(result);
break;
}
WMR_YIELD();
}
return result;
}
void h2fmi_config_page_addr(h2fmi_t* fmi,
UInt32 page)
{
const UInt32 page_addr_size = 5;
const UInt32 page_addr_2 = (page >> 16) & 0xFF;
const UInt32 page_addr_1 = (page >> 8) & 0xFF;
const UInt32 page_addr_0 = (page >> 0) & 0xFF;
h2fmi_wr(fmi, FMC_ADDR1, (FMC_ADDR1__SEQ7(0x00) |
FMC_ADDR1__SEQ6(0x00) |
FMC_ADDR1__SEQ5(0x00) |
FMC_ADDR1__SEQ4(page_addr_2)));
h2fmi_wr(fmi, FMC_ADDR0, (FMC_ADDR0__SEQ3(page_addr_1) |
FMC_ADDR0__SEQ2(page_addr_0) |
FMC_ADDR0__SEQ1(0x00) |
FMC_ADDR0__SEQ0(0x00)));
h2fmi_wr(fmi, FMC_ADDRNUM, FMC_ADDRNUM__NUM(page_addr_size - 1));
}
void h2fmi_clean_ecc(h2fmi_t* fmi)
{
// clean status bits by setting them
#if FMI_VERSION == 0
// S5L9820X
h2fmi_wr(fmi, ECC_PND, (ECC_PND__BCH_ALL_FF |
ECC_PND__SECTOR_ERROR_ALERT |
ECC_PND__UNCORRECTABLE));
#else
// S5L8922X and later
h2fmi_wr(fmi, ECC_PND, (ECC_PND__SOME_ALL_ZERO |
ECC_PND__SOME_ALL_FF |
ECC_PND__SOME_ERROR_ALERT |
ECC_PND__ANY_UNCORRECTABLE));
#endif
}
void h2fmi_fmc_read_data(h2fmi_t* fmi,
UInt32 size,
UInt8* data)
{
register UInt32 idx;
UInt32 delay_ticks;
UInt32 if_ctrl;
// Force-clear FMC timings. We're manually hitting /RE and the I/O lines
// so we can take care of timings ourselves.
if_ctrl = h2fmi_rd(fmi, FMC_IF_CTRL);
h2fmi_set_if_ctrl(fmi, 0);
delay_ticks = WMR_GET_TICKS_PER_US() / 8; //(125ns)
// employ REBHOLD to hold nRD low so that each byte on the bus can
// be read, one at a time, from NAND_STATUS
h2fmi_wr(fmi, FMC_DATANUM, FMC_DATANUM__NUM(0));
for (idx = 0; idx < size; idx++)
{
UInt64 start;
h2fmi_wr(fmi, FMC_RW_CTRL, (FMC_RW_CTRL__REBHOLD |
FMC_RW_CTRL__RD_MODE));
// FMC requires 8 + REBSETUP cycles between asserting REBHOLD and reading FMC_NAND_STATUS.
start = WMR_CLOCK_TICKS();
while(!WMR_HAS_TIME_ELAPSED_TICKS(start, delay_ticks));
data[idx] = (UInt8)h2fmi_rd(fmi, FMC_NAND_STATUS);
// clear FMC_RW_CTRL, thereby releasing REBHOLD and completing
// current read cycle
h2fmi_wr(fmi, FMC_RW_CTRL, 0);
}
h2fmi_set_if_ctrl(fmi, if_ctrl);
}
BOOL32 h2fmi_nand_reset(h2fmi_t* fmi,
h2fmi_ce_t ce)
{
BOOL32 result = TRUE32;
// enable specified nand device
h2fmi_fmc_enable_ce(fmi, ce);
// Only for H5X - // <rdar://problem/11677742> Software workaround for Samsung reset and bad chip ID isssue
#if FMI_VERSION >= 5
WMR_SLEEP_US(H2FMI_EXTRA_CE_SETUP_TIME_US);
#endif // FMI_VERSION >= 5
// perform reset command
h2fmi_wr(fmi, FMC_CMD, FMC_CMD__CMD1(NAND_CMD__RESET));
h2fmi_wr(fmi, FMC_RW_CTRL, FMC_RW_CTRL__CMD1_MODE);
// wait until cmd sent on bus
if (!h2fmi_wait_done(fmi, FMC_STATUS,
FMC_STATUS__CMD1DONE,
FMC_STATUS__CMD1DONE))
{
h2fmi_fail(result);
}
// disable all nand devices
h2fmi_fmc_disable_ce(fmi, ce);
#if SUPPORT_PPN && H2FMI_PPN_VERIFY_SET_FEATURES
if (fmi->is_ppn)
{
h2fmi_ppn_reset_feature_shadow(fmi);
}
#endif // SUPPORT_PPN && H2FMI_PPN_VERIFY_SET_FEATURES
return result;
}
BOOL32 h2fmi_nand_read_id(h2fmi_t* fmi,
h2fmi_ce_t ce,
h2fmi_chipid_t* id,
UInt8 addr)
{
const UInt32 cmd1_addr_done = (FMC_STATUS__ADDRESSDONE |
FMC_STATUS__CMD1DONE);
BOOL32 result = TRUE32;
#if SUPPORT_TOGGLE_NAND
WMR_ASSERT(!fmi->is_toggle);
#endif
// enable specified nand device
h2fmi_fmc_enable_ce(fmi, ce);
// set up Read Id command and address cycles
h2fmi_wr(fmi, FMC_CMD, FMC_CMD__CMD1(NAND_CMD__READ_ID));
h2fmi_wr(fmi, FMC_ADDR0, FMC_ADDR0__SEQ0(addr));
h2fmi_wr(fmi, FMC_ADDRNUM, FMC_ADDRNUM__NUM(0));
h2fmi_wr(fmi, FMC_RW_CTRL, (FMC_RW_CTRL__ADDR_MODE |
FMC_RW_CTRL__CMD1_MODE));
// wait until cmd & addr completion
if (!h2fmi_wait_done(fmi, FMC_STATUS,
cmd1_addr_done,
cmd1_addr_done))
{
h2fmi_fail(result);
}
else
{
#if FMI_VERSION == 0
// read correct number of id bytes into local temporary
h2fmi_fmc_read_data(fmi, H2FMI_NAND_ID_SIZE, *id);
#else
UInt32 fmi_control = (FMI_CONTROL__MODE__READ |
FMI_CONTROL__START_BIT);
#if FMI_VERSION == 4
if (fmi->read_stream_disable)
{
fmi_control |= FMI_CONTROL__DISABLE_STREAMING;
}
#endif // FMI_VERSION == 4
h2fmi_wr(fmi, FMI_CONFIG, 0);
h2fmi_wr(fmi, FMI_DATA_SIZE, (FMI_DATA_SIZE__BYTES_PER_SECTOR( ROUNDUPTO( sizeof(h2fmi_chipid_t), sizeof(UInt32) ) ) |
FMI_DATA_SIZE__SECTORS_PER_PAGE(1)));
h2fmi_wr(fmi, FMI_CONTROL, fmi_control);
if (!h2fmi_wait_done(fmi, FMI_INT_PEND, FMI_INT_PEND__LAST_FMC_DONE, FMI_INT_PEND__LAST_FMC_DONE))
{
h2fmi_fail(result);
}
else
{
h2fmi_pio_read_sector(fmi, id, sizeof(h2fmi_chipid_t));
}
h2fmi_reset(fmi);
#endif
}
// disable all nand devices
h2fmi_fmc_disable_ce(fmi, ce);
return result;
}
BOOL32 h2fmi_pio_write_sector(h2fmi_t* fmi,
const void* buf,
UInt32 len)
{
BOOL32 result = TRUE32;
UInt32* ptr = (UInt32*)buf;
UInt32 i;
if (!h2fmi_wait_dma_task_pending(fmi))
{
// timed out
WMR_PANIC();
h2fmi_fail(result);
}
else
{
for( i = 0; i < len / sizeof(UInt32); i++ )
{
h2fmi_wr(fmi, FMI_DATA_BUF, *ptr++);
}
}
return result;
}
BOOL32 h2fmi_pio_read_sector(h2fmi_t* fmi,
void* buf,
UInt32 len)
{
BOOL32 result = TRUE32;
UInt32 *word_ptr = (UInt32*)buf;
UInt8 *byte_ptr;
int i;
// wait for FMI to be ready with data in fifo for DMA to transfer out
if (!h2fmi_wait_dma_task_pending(fmi))
{
// timed out
h2fmi_fail(result);
}
else
{
if (((UInt32)word_ptr & 0xF) == 0)
{
// Our buffers (particularly boot pages) are generally aligned.
// Do as many 32 bit operations as we can.
while (len >= sizeof(UInt32))
{
*word_ptr++ = h2fmi_rd(fmi, FMI_DATA_BUF);
len -= sizeof(UInt32);
}
}
byte_ptr = (UInt8*)word_ptr;
while (len)
{
UInt8 bytes = WMR_MIN(sizeof(UInt32), len);
UInt32 tmp = h2fmi_rd(fmi, FMI_DATA_BUF);
for (i = 0; i < bytes; i++)
{
*byte_ptr++ = (tmp >> (i*8)) & 0xFF;
}
len -= bytes;
}
}
return result;
}
UInt32 h2fmi_get_gate(h2fmi_t* fmi)
{
return h2fmi_select_by_bus(fmi, 0, 1 );
}
// =============================================================================
// static implementation function definitions used by both SecureROM and iBoot
// =============================================================================
BOOL32 h2fmi_start_nand_page_read(h2fmi_t* fmi,
UInt32 page)
{
const UInt32 cmd1_addr_cmd2_done = (FMC_STATUS__ADDRESSDONE |
FMC_STATUS__CMD2DONE |
FMC_STATUS__CMD1DONE);
BOOL32 result = TRUE32;
// configure FMC for cmd1/addr/cmd2 sequence
h2fmi_config_page_addr(fmi, page);
h2fmi_wr(fmi, FMC_CMD, (FMC_CMD__CMD2(NAND_CMD__READ_CONFIRM) |
FMC_CMD__CMD1(NAND_CMD__READ)));
// start cmd1/addr/cmd2 sequence
h2fmi_wr(fmi, FMC_RW_CTRL, (FMC_RW_CTRL__ADDR_MODE |
FMC_RW_CTRL__CMD2_MODE |
FMC_RW_CTRL__CMD1_MODE));
// wait until cmd1/addr/cmd2 sequence completed
if (!h2fmi_wait_done(fmi, FMC_STATUS,
cmd1_addr_cmd2_done,
cmd1_addr_cmd2_done))
{
h2fmi_fail(result);
}
// wait for ready using Read Status command
else if (!h2fmi_wait_ready(fmi,
NAND_STATUS__DATA_CACHE_RB,
NAND_STATUS__DATA_CACHE_RB_READY))
{
h2fmi_fail(result);
}
else
{
// reissue cmd1 and wait until completed
h2fmi_wr(fmi, FMC_CMD, FMC_CMD__CMD1(NAND_CMD__READ));
h2fmi_wr(fmi, FMC_RW_CTRL, FMC_RW_CTRL__CMD1_MODE);
if (!h2fmi_wait_done(fmi, FMC_STATUS,
FMC_STATUS__CMD1DONE,
FMC_STATUS__CMD1DONE))
{
h2fmi_fail(result);
}
}
return result;
}
static BOOL32 h2fmi_wait_ready(h2fmi_t* fmi,
UInt8 io_mask,
UInt8 io_val)
{
BOOL32 result = TRUE32;
// turn off RBBEN and configure it to use look for I/O bit 6 (0x40)
h2fmi_set_if_ctrl(fmi, (~FMC_IF_CTRL__RBBEN & h2fmi_rd(fmi, FMC_IF_CTRL)));
h2fmi_wr(fmi, FMC_RBB_CONFIG, (FMC_RBB_CONFIG__POL(io_val) |
FMC_RBB_CONFIG__POS(io_mask)));
// exec Read Status command cycle
h2fmi_wr(fmi, FMC_CMD, FMC_CMD__CMD1(NAND_CMD__READ_STATUS));
h2fmi_wr(fmi, FMC_RW_CTRL, FMC_RW_CTRL__CMD1_MODE);
// wait until command cycle completed
if (!h2fmi_wait_done(fmi, FMC_STATUS,
FMC_STATUS__CMD1DONE,
FMC_STATUS__CMD1DONE))
{
h2fmi_fail(result);
}
else
{
// clear the FMC_STATUS__NSRBBDONE bit in FMC_STATUS
h2fmi_wr(fmi, FMC_STATUS, FMC_STATUS__NSRBBDONE);
// set up read cycle with REBHOLD to wait for ready bit to be
// set on I/O lines
h2fmi_wr(fmi, FMC_DATANUM, FMC_DATANUM__NUM(0));
h2fmi_wr(fmi, FMC_RW_CTRL, (FMC_RW_CTRL__REBHOLD | FMC_RW_CTRL__RD_MODE));
// wait until NSRBB done signaled
if (!h2fmi_wait_done(fmi, FMC_STATUS,
FMC_STATUS__NSRBBDONE,
FMC_STATUS__NSRBBDONE))
{
h2fmi_fail(result);
}
// clear FMC_RW_CTRL, thereby releasing REBHOLD and completing
// current read cycle
h2fmi_wr(fmi, FMC_RW_CTRL, 0);
}
return result;
}
// ********************************** EOF **************************************
+249
View File
@@ -0,0 +1,249 @@
// *****************************************************************************
//
// File: H2fmi_debug.c
//
// *****************************************************************************
//
// Notes:
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_private.h"
// =============================================================================
// public implementation function definitions
// =============================================================================
#if (H2FMI_TRACE_REG_WRITES)
UInt32 h2fmi_trace_wr(h2fmi_t* fmi,
UInt32 reg,
UInt32 val)
{
const UInt32 offset = reg >> 2;
WMR_PRINT(MISC, "*%p = 0x%08X\n", ((UInt32)fmi->regs) + reg, val);
fmi->regs[offset] = val;
return val;
}
UInt8 h2fmi_trace_wr8(h2fmi_t* fmi,
UInt32 reg,
UInt8 val)
{
const UInt32 offset = reg;
WMR_PRINT(MISC, "*%p = 0x%02X\n", ((UInt32)fmi->regs) + reg, val);
((UInt8*)fmi->regs)[offset] = val;
return val;
}
UInt32 h2fmc_trace_wr(volatile UInt32* h2fmc_regs,
UInt32 reg,
UInt32 val)
{
const UInt32 offset = reg >> 2;
WMR_PRINT(MISC, "*%p = 0x%08X\n", ((UInt32)h2fmc_regs) + reg, val);
h2fmc_regs[offset] = val;
return val;
}
#endif // H2FMI_TRACE_REG_WRITES
#if (H2FMI_TRACE_REG_READS)
UInt32 h2fmi_trace_rd(h2fmi_t* fmi,
UInt32 reg)
{
const UInt32 offset = reg >> 2;
const UInt32 val = fmi->regs[offset];
WMR_PRINT(MISC, "*%p == 0x%08X\n", ((UInt32)fmi->regs) + reg, val);
return val;
}
UInt8 h2fmi_trace_rd8(h2fmi_t* fmi,
UInt32 reg)
{
const UInt32 offset = reg;
const UInt8 val = ((volatile UInt8*)fmi->regs)[offset];
WMR_PRINT(MISC, "*%p == 0x%02X\n", ((UInt32)fmi->regs) + reg, val);
return val;
}
#endif // H2FMI_TRACE_REG_READS
#if (H2FMI_DEBUG)
void h2fmi_spew_config(h2fmi_t* fmi)
{
WMR_PRINT(INF, "fmi->regs: %p\n", fmi->regs);
WMR_PRINT(INF, "fmi->num_of_ce: %p\n", fmi->num_of_ce);
WMR_PRINT(INF, "fmi->pages_per_block: %p\n", fmi->pages_per_block);
WMR_PRINT(INF, "fmi->sectors_per_page: %p\n", fmi->sectors_per_page);
WMR_PRINT(INF, "fmi->bytes_per_spare: %p\n", fmi->bytes_per_spare);
WMR_PRINT(INF, "fmi->blocks_per_ce: %p\n", fmi->blocks_per_ce);
WMR_PRINT(INF, "fmi->total_bytes_per_meta: %p\n", fmi->total_bytes_per_meta);
WMR_PRINT(INF, "fmi->valid_bytes_per_meta: %p\n", fmi->valid_bytes_per_meta);
WMR_PRINT(INF, "fmi->if_ctrl: %p\n", fmi->if_ctrl);
#if SUPPORT_TOGGLE_NAND
WMR_PRINT(INF, "fmi->toggle_if_ctrl: %p\n", fmi->toggle_if_ctrl);
#endif
WMR_PRINT(INF, "fmi->bytes_per_page : %p\n", fmi->bytes_per_page);
}
void h2fmi_spew_status_regs(h2fmi_t* fmi,
const char* prefix)
{
WMR_PRINT(INF, "%sFMI_INT_PEND: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_INT_PEND));
WMR_PRINT(INF, "%sFMC_STATUS: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_STATUS));
// ECC might be clocked off for PPN
if (!fmi->is_ppn)
{
WMR_PRINT(INF, "%sECC_PND: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PND));
}
else
{
WMR_PRINT(INF, "%s: omitting ecc registers for ppn device\n", prefix);
}
}
void h2fmi_spew_fmi_regs(h2fmi_t* fmi,
const char* prefix)
{
WMR_PRINT(INF, "%sFMI_CONFIG: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_CONFIG));
WMR_PRINT(INF, "%sFMI_CONTROL: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_CONTROL));
WMR_PRINT(INF, "%sFMI_STATUS: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_STATUS));
WMR_PRINT(INF, "%sFMI_INT_PEND: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_INT_PEND));
WMR_PRINT(INF, "%sFMI_INT_EN: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_INT_EN));
// can't read from fifos, since that would alter state of block
WMR_PRINT(INF, "%sFMI_DEBUG0: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_DEBUG0));
#if FMI_VERSION <= 2
WMR_PRINT(INF, "%sFMI_DEBUG1: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_DEBUG1));
WMR_PRINT(INF, "%sFMI_DEBUG2: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_DEBUG2));
#endif
#if FMI_VERSION > 0
WMR_PRINT(INF, "%sFMI_HW_VERSION: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_HW_VERSION));
#if FMI_VERSION <= 2
WMR_PRINT(INF, "%sFMI_DEBUG3: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_DEBUG3));
#endif
WMR_PRINT(INF, "%sFMI_DATA_SIZE: 0x%08X\n", prefix, h2fmi_rd(fmi, FMI_DATA_SIZE));
#endif
}
void h2fmi_spew_fmc_regs(h2fmi_t* fmi,
const char* prefix)
{
WMR_PRINT(INF, "%sFMC_ON: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_ON));
WMR_PRINT(INF, "%sFMC_VER: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_VER));
WMR_PRINT(INF, "%sFMC_IF_CTRL: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_IF_CTRL));
WMR_PRINT(INF, "%sFMC_CE_CTRL: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_CE_CTRL));
WMR_PRINT(INF, "%sFMC_RW_CTRL: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_RW_CTRL));
WMR_PRINT(INF, "%sFMC_CMD: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_CMD));
WMR_PRINT(INF, "%sFMC_ADDR0: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_ADDR0));
WMR_PRINT(INF, "%sFMC_ADDR1: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_ADDR1));
WMR_PRINT(INF, "%sFMC_ADDRNUM: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_ADDRNUM));
WMR_PRINT(INF, "%sFMC_DATANUM: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_DATANUM));
WMR_PRINT(INF, "%sFMC_TO_CTRL: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_TO_CTRL));
WMR_PRINT(INF, "%sFMC_TO_CNT: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_TO_CNT));
WMR_PRINT(INF, "%sFMC_INTMASK: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_INTMASK));
WMR_PRINT(INF, "%sFMC_STATUS: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_STATUS));
WMR_PRINT(INF, "%sFMC_NAND_STATUS: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_NAND_STATUS));
WMR_PRINT(INF, "%sFMC_RBB_CONFIG: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_RBB_CONFIG));
#if SUPPORT_TOGGLE_NAND
WMR_PRINT(INF, "%sFMC_DQS_TIMING_CTRL:0x%08X\n", prefix, h2fmi_rd(fmi, FMC_DQS_TIMING_CTRL));
WMR_PRINT(INF, "%sFMC_TOGGLE_CTRL_1: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_TOGGLE_CTRL_1));
WMR_PRINT(INF, "%sFMC_TOGGLE_CTRL_2: 0x%08X\n", prefix, h2fmi_rd(fmi, FMC_TOGGLE_CTRL_2));
#endif
}
void h2fmi_spew_ecc_regs(h2fmi_t* fmi,
const char* prefix)
{
// ECC might be clocked off for PPN
if (!fmi->is_ppn)
{
WMR_PRINT(INF, "%sECC_VERSION: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_VERSION));
WMR_PRINT(INF, "%sECC_CON0: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_CON0));
WMR_PRINT(INF, "%sECC_CON1: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_CON1));
// ECC_RESULT is a fifo head; reading from it changes state, and therefore it won't be
// included in the spew function
//WMR_PRINT(INF, "%sECC_RESULT: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_RESULT));
WMR_PRINT(INF, "%sECC_PND: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PND));
WMR_PRINT(INF, "%sECC_MASK: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_MASK));
WMR_PRINT(INF, "%sECC_HISTORY: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_HISTORY));
WMR_PRINT(INF, "%sECC_CORE_SW_RESET: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_CORE_SW_RESET));
#if FMI_VERSION <= 2
WMR_PRINT(INF, "%sECC_LOC0: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_LOC0));
WMR_PRINT(INF, "%sECC_LOC1: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_LOC1));
WMR_PRINT(INF, "%sECC_LOC2: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_LOC2));
WMR_PRINT(INF, "%sECC_LOC3: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_LOC3));
WMR_PRINT(INF, "%sECC_LOC4: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_LOC4));
WMR_PRINT(INF, "%sECC_LOC5: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_LOC5));
WMR_PRINT(INF, "%sECC_LOC6: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_LOC6));
WMR_PRINT(INF, "%sECC_PARITY0: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PARITY0));
WMR_PRINT(INF, "%sECC_PARITY1: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PARITY1));
WMR_PRINT(INF, "%sECC_PARITY2: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PARITY2));
WMR_PRINT(INF, "%sECC_PARITY3: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PARITY3));
WMR_PRINT(INF, "%sECC_PARITY4: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PARITY4));
WMR_PRINT(INF, "%sECC_PARITY5: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PARITY5));
WMR_PRINT(INF, "%sECC_PARITY6: 0x%08X\n", prefix, h2fmi_rd(fmi, ECC_PARITY6));
#endif
}
else
{
WMR_PRINT(INF, "%s: omitting ecc registers for ppn device\n", prefix);
}
}
void h2fmi_spew_regs(h2fmi_t* fmi,
const char* prefix)
{
h2fmi_spew_fmi_regs(fmi, prefix);
h2fmi_spew_fmc_regs(fmi, prefix);
h2fmi_spew_ecc_regs(fmi, prefix);
}
void h2fmi_spew_buffer(UInt8* buf,
UInt32 size)
{
UInt32 idx;
for (idx = 0; idx < size; idx++)
{
if (!idx)
{
WMR_PRINT(INF, "0x%08X: ", (UInt32)buf);
}
else if (!(idx % 16))
{
WMR_PRINT(INF, "\n0x%08X: ", ((UInt32)buf) + idx);
}
else if (!(idx % 4))
{
WMR_PRINT(INF, " ");
}
WMR_PRINT(INF, "%02X", buf[idx]);
}
WMR_PRINT(INF, "\n");
}
#endif // H2FMI_DEBUG
// ********************************** EOF **************************************
+45
View File
@@ -0,0 +1,45 @@
// *****************************************************************************
//
// File: H2fmi_dma.h
//
// *****************************************************************************
//
// Notes:
//
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_private.h"
#include "H2fmi_dma_types.h"
#ifndef _H2FMI_DMA_H_
#define _H2FMI_DMA_H_
BOOL32 h2fmi_dma_execute_cmd(UInt32 cmd, int dma_channel,
void *src, void *dst, UInt32 length,
UInt32 word_size, UInt32 burst_size,
struct dma_aes_config *config);
BOOL32 h2fmi_dma_execute_async(UInt32 cmd, Int32 dma_channel,
struct dma_segment *sgl, void *fifo, UInt32 length,
UInt32 word_size, UInt32 burst_size,
struct dma_aes_config *config);
BOOL32 h2fmi_dma_wait(int dma_channel, UInt32 timeoutUs);
void h2fmi_dma_cancel(int dma_channel);
#endif //_H2FMI_DMA_H_
// ********************************** EOF **************************************
+198
View File
@@ -0,0 +1,198 @@
// *****************************************************************************
//
// File: H2fmi_dma_iboot.c
//
// *****************************************************************************
//
// Notes:
//
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_dma.h"
#include <drivers/dma.h>
#include <platform/timer.h>
#include <sys/task.h>
#include "WMROAM.h"
#define H2FMI_DMA_POLLING_ENABLED (1)
#if !H2FMI_DMA_POLLING_ENABLED
static struct task_event dma_events[DMA_CHANNEL_COUNT];
static BOOL32 first_time = TRUE32;
static void h2fmi_dma_done_handler(void *arg)
{
UInt32 channel = (UInt32)arg;
event_signal(&dma_events[channel]);
}
#endif // !H2FMI_DMA_POLLING_ENABLED
// no timeout - rdar://6403538
BOOL32 h2fmi_dma_execute_cmd(UInt32 cmd, int dma_channel,
void *src, void *dst, UInt32 length,
UInt32 word_size, UInt32 burst_size,
struct dma_aes_config *config)
{
struct dma_segment sgl;
BOOL32 ret;
sgl.paddr = (UInt32)src;
sgl.length = length;
ret = h2fmi_dma_execute_async(cmd,
dma_channel,
&sgl,
dst,
length,
word_size,
burst_size,
config);
if( !ret )
{
return FALSE32;
}
h2fmi_dma_wait(dma_channel, 0);
return TRUE32;
}
BOOL32 h2fmi_dma_execute_async(UInt32 cmd, Int32 dma_channel,
struct dma_segment *sgl, void *fifo, UInt32 length,
UInt32 word_size, UInt32 burst_size,
struct dma_aes_config *config)
{
int ret;
#if !H2FMI_DMA_POLLING_ENABLED
if (first_time )
{
UInt32 i;
first_time = FALSE32;
for (i = 0; i < DMA_CHANNEL_COUNT; i++)
{
event_init(&dma_events[i], EVENT_FLAG_AUTO_UNSIGNAL, false);
}
}
WMR_ASSERT(!dma_events[dma_channel].signalled);
if (dma_events[dma_channel].signalled)
{
/* This dma channel already has a completion pending. Clear it now so things
* don't get out of sync, but if this happens it's because sometime in the past
* someone called h2fmi_dma_execute_async without calling either h2fmi_dma_wait or h2fmi_dma_cancel.
*/
WMR_PRINT(ERROR, "%s called when completion already pending. Recovering, but this is a bug.", __FUNCTION__);
event_unsignal(&dma_events[dma_channel]);
}
#endif // !H2FMI_DMA_POLLING_ENABLED
dma_set_aes(dma_channel, config);
ret = dma_execute_async(cmd,
dma_channel,
sgl,
fifo,
length,
word_size,
burst_size,
#if H2FMI_DMA_POLLING_ENABLED
NULL,
NULL);
#else // H2FMI_DMA_POLLING_ENABLED
h2fmi_dma_done_handler,
(void*)dma_channel);
#endif // !H2FMI_DMA_POLLING_ENABLED
if (ret != 0)
{
WMR_PRINT(ERROR, "WMR_DMA_START_ASYNC_FAILED: direction=%d, channel=%d, length=%d\n",
cmd, dma_channel, length);
return FALSE32;
}
else
{
return TRUE32;
}
}
BOOL32 h2fmi_dma_wait(int dma_channel, UInt32 timeoutUs)
{
BOOL32 ret = TRUE32;
#if H2FMI_DMA_POLLING_ENABLED
const UInt64 startUs = WMR_CLOCK_NATIVE();
dma_use_int(dma_channel, FALSE32);
while (!dma_poll(dma_channel))
{
if ((0 != timeoutUs) && WMR_HAS_TIME_ELAPSED_US(startUs, timeoutUs))
{
ret = dma_poll(dma_channel);
break;
}
WMR_YIELD();
}
dma_use_int(dma_channel, TRUE32);
#else // H2FMI_DMA_POLLING_ENABLED
if (timeoutUs )
{
ret = event_wait_timeout(&dma_events[dma_channel], timeoutUs);
}
else
{
// Wait forever if timeout is zero
event_wait(&dma_events[dma_channel]);
ret = TRUE32;
}
#endif // !H2FMI_DMA_POLLING_ENABLED
if (!ret)
{
WMR_PRINT(ERROR, "Timeout waiting for DMA: channel=%d\n", dma_channel);
WMR_PANIC("dma timeout");
}
return ret;
}
void h2fmi_dma_cancel(int dma_channel)
{
dma_cancel(dma_channel);
#if !H2FMI_DMA_POLLING_ENABLED
event_unsignal(&dma_events[dma_channel]);
#endif // !H2FMI_DMA_POLLING_ENABLED
}
// ********************************** EOF **************************************
+81
View File
@@ -0,0 +1,81 @@
// *****************************************************************************
//
// File: H2fmi_dma.h
//
// *****************************************************************************
//
// Notes:
//
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "WMRFeatures.h"
#ifndef _H2FMI_DMA_TYPES_H_
#define _H2FMI_DMA_TYPES_H_
#if H2FMI_EFI
#include "SoC.h"
// These should match iBoot include/drivers/aes.h
#define AES_CMD_ENC (0x00000000)
#define AES_CMD_DEC (0x00000001)
#define AES_CMD_DIR_MASK (0x0000000F)
#define AES_CMD_ECB (0x00000000)
#define AES_CMD_CBC (0x00000010)
#define AES_CMD_MODE_MASK (0x000000F0)
#define AES_KEY_TYPE_USER (0x00000000)
#define AES_KEY_TYPE_UID0 (0x00000100)
#define AES_KEY_TYPE_GID0 (0x00000200)
#define AES_KEY_TYPE_GID1 (0x00000201)
#define AES_KEY_TYPE_MASK (0x00000FFF)
#define AES_KEY_SIZE_128 (0x00000000)
#define AES_KEY_SIZE_192 (0x10000000)
#define AES_KEY_SIZE_256 (0x20000000)
#define AES_KEY_SIZE_MASK (0xF0000000)
// This should match iBoot include/drivers/dma.h
struct dma_aes_config {
/* AES configuration */
UInt32 command; /* AES_CMD bits from <drivers/aes.h> */
UInt32 keying; /* AES_KEY bits from <drivers/aes.h> */
void *key; /* AES key for AES_KEY_TYPE_USER */
/* IV generation */
UInt32 chunk_size; /* AES chunk size */
void (* iv_func)(void *arg, UInt32 chunk_index, void *iv_buffer);
void *iv_func_arg;
};
struct dma_segment {
UInt32 paddr;
UInt32 length;
};
typedef void (* dma_completion_function)(void *);
#else //!H2FMI_EFI
#include <drivers/aes.h>
#include <drivers/dma.h>
#include <platform/soc/hwdmachannels.h>
#endif //!H2FMI_EFI
#endif //_H2FMI_DMA_TYPES_H_
// ********************************** EOF **************************************
+303
View File
@@ -0,0 +1,303 @@
// *****************************************************************************
//
// File: H2fmi_erase.c
//
// *****************************************************************************
//
// Notes:
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_private.h"
/**
* Define the following to simulate erase status failures.
*/
//??#define SIMULATE_ERASE_FAILURES
#if defined(SIMULATE_ERASE_FAILURES)
#define ERASE_FAILURE_MAGIC_NUMBER 1301
static unsigned long ulFailureCount = 0;
#endif
// =============================================================================
// private implementation function declarations
// =============================================================================
static void h2fmi_start_nand_block_erase(h2fmi_t* fmi, UInt32 page);
static void h2fmi_config_erase_page_addr(h2fmi_t* fmi, UInt32 page);
/**
* Same as h2fmi_wait_status except also tests to ensure
* the write protect bit is off. Used for erase mode as a
* sanity check as some NAND have been known to fail with
* 'stuck' write protects.
*
* @param fmi
*
* @return CE_STATE
*/
static BOOL32 h2fmi_wait_erase_status(h2fmi_t* fmi,
UInt8 io_mask,
UInt8 io_cond,
UInt8* status)
{
UInt8 bStatus;
BOOL32 bResult = h2fmi_wait_status(fmi,io_mask,io_cond,&bStatus);
if ( bResult )
{
const UInt32 bWPDisabled = (bStatus & NAND_STATUS__WRITE_PROTECT);
WMR_ASSERT(bWPDisabled);
}
if ( NULL!=status )
{
*status = bStatus;
}
return bResult;
}
// =============================================================================
// public interface function definitions
// =============================================================================
BOOL32 h2fmi_erase_blocks(h2fmi_t* fmi,
UInt32 num_elements,
UInt16* ce,
UInt32* block,
BOOL32* status_failed)
{
enum {
st_IDLE,
st_ERASING,
st_TIMEOUT,
st_ERROR
} ceState[ H2FMI_MAX_CE_TOTAL ];
UInt8 nand_status;
UInt32 k;
UInt32 wIndex;
BOOL32 result = TRUE32;
for ( k=0; k<( sizeof(ceState)/sizeof(ceState[0]) ); k++ )
{
ceState[k] = st_IDLE;
}
// remember initial FMC_IF_CTRL setting
const UInt32 fmc_if_ctrl = h2fmi_rd(fmi, FMC_IF_CTRL);
// disable write protect
h2fmi_set_if_ctrl(fmi, FMC_IF_CTRL__WPB | fmc_if_ctrl);
fmi->failureDetails.wNumCE_Executed = fmi->failureDetails.wOverallOperationFailure = 0;
fmi->failureDetails.wFirstFailingCE = ~0;
for ( wIndex=0; wIndex<num_elements; )
{
const UInt32 wCurrentCE = ce[wIndex];
// convert block address to page address
if ( st_ERASING==ceState[wCurrentCE] )
{
/**
* Wrapped around -- must wait for this to finish before
* continuing. :(
*/
// enable specified nand device
h2fmi_fmc_enable_ce(fmi, wCurrentCE);
// Increment wIndex -- we're done with this one whether it errors out or not.
wIndex++;
// wait for the device to indicate ready
if (!h2fmi_wait_erase_status(fmi,
NAND_STATUS__DATA_CACHE_RB,
NAND_STATUS__DATA_CACHE_RB_READY,
&nand_status))
{
ceState[wCurrentCE] = st_TIMEOUT;
h2fmi_fail(result);
fmi->failureDetails.wFirstFailingCE = wCurrentCE;
/**
* Early failure -- break out of this loop as soon as we see a
* failure occur.
*/
break;
}
else
{
const UInt32 status1 = (nand_status & NAND_STATUS__CHIP_STATUS1);
ceState[wCurrentCE] = ( 0==status1 ? st_IDLE : st_ERROR );
#if defined(SIMULATE_ERASE_FAILURES)
if ( (ulFailureCount++)>=ERASE_FAILURE_MAGIC_NUMBER )
{
ulFailureCount = 0;
ceState[wCurrentCE] = st_ERROR;
WMR_PRINT(ALWAYS,"Simulated erase failure on ce %d\n",wCurrentCE);
}
#endif
if ( st_ERROR==ceState[wCurrentCE] )
{
h2fmi_fail(result);
fmi->failureDetails.wFirstFailingCE = wCurrentCE;
break;
}
}
}
else
{
/**
* Kick off as many as we can -- we know the first one will work
* given the above test (if it were in an error state we would
* have already exited the top-level for loop).
*/
for ( k=wIndex; k<num_elements; k++ )
{
const UInt32 wThisCE = ce[k];
if ( st_IDLE!=ceState[wThisCE] )
{
/**
* Break out of this loop as soon as we hit a non-idle CE.
* This will cause us to go back and wait on the most recent
* wIndex one above, as it will not be in the st_IDLE state.
*/
break;
}
else
{
const UInt32 wThisPage = block[k] * fmi->pages_per_block;
// enable specified nand device
h2fmi_fmc_enable_ce(fmi, wThisCE);
// start nand erase operation
h2fmi_start_nand_block_erase(fmi, wThisPage);
ceState[wThisCE] = st_ERASING;
fmi->failureDetails.wNumCE_Executed++;
}
}
}
}
/**
* We're out of the above loop -- for better or for worse.
* Ensure we wait until all CE's have completed.
*/
for ( k=wIndex; k<num_elements; k++ )
{
const UInt32 wThisCE = ce[k];
if ( st_ERASING==ceState[wThisCE] )
{
// enable specified nand device
h2fmi_fmc_enable_ce(fmi, wThisCE);
// wait for the device to indicate ready
if (!h2fmi_wait_erase_status(fmi,
NAND_STATUS__DATA_CACHE_RB,
NAND_STATUS__DATA_CACHE_RB_READY,
&nand_status))
{
ceState[wThisCE] = st_TIMEOUT;
h2fmi_fail(result);
if ( (UInt32)~0 == fmi->failureDetails.wFirstFailingCE )
{
fmi->failureDetails.wFirstFailingCE = wThisCE;
}
}
else
{
const UInt32 status1 = (nand_status & NAND_STATUS__CHIP_STATUS1);
ceState[wThisCE] = ( 0==status1 ? st_IDLE : st_ERROR );
#if defined(SIMULATE_ERASE_FAILURES)
if ( (ulFailureCount++)>=ERASE_FAILURE_MAGIC_NUMBER )
{
ulFailureCount = 0;
ceState[wThisCE] = st_ERROR;
WMR_PRINT(ALWAYS,"Simulated erase failure on ce %d\n",wThisCE);
}
#endif
if ( st_ERROR==ceState[wThisCE] )
{
h2fmi_fail(result);
if ( (UInt32)~0 == fmi->failureDetails.wFirstFailingCE )
{
fmi->failureDetails.wFirstFailingCE = wThisCE;
}
}
}
}
}
// return write protect to previous state
h2fmi_set_if_ctrl(fmi, fmc_if_ctrl);
// disable all nand devices
h2fmi_fmc_disable_all_ces(fmi);
// possibly return by reference whether Read Status indicated failure
if (NULL != status_failed)
{
*status_failed = ( TRUE32==result ? FALSE32 : TRUE32 );
}
return result;
}
// =============================================================================
// private implementation function definitions
// =============================================================================
static void h2fmi_start_nand_block_erase(h2fmi_t* fmi,
UInt32 page)
{
const UInt32 cmd1_addr_cmd2_done = (FMC_STATUS__ADDRESSDONE |
FMC_STATUS__CMD2DONE |
FMC_STATUS__CMD1DONE);
// configure FMC for cmd1/addr/cmd2 sequence
h2fmi_config_erase_page_addr(fmi, page);
h2fmi_wr(fmi, FMC_CMD, (FMC_CMD__CMD1(NAND_CMD__ERASE) |
FMC_CMD__CMD2(NAND_CMD__ERASE_CONFIRM)));
// start cmd1/addr/cmd2 sequence
h2fmi_wr(fmi, FMC_RW_CTRL, (FMC_RW_CTRL__ADDR_MODE |
FMC_RW_CTRL__CMD2_MODE |
FMC_RW_CTRL__CMD1_MODE));
// busy wait until cmd1/addr/cmd2 sequence completed
h2fmi_busy_wait(fmi, FMC_STATUS, cmd1_addr_cmd2_done, cmd1_addr_cmd2_done);
h2fmi_wr(fmi, FMC_STATUS, cmd1_addr_cmd2_done);
}
static void h2fmi_config_erase_page_addr(h2fmi_t* fmi,
UInt32 page)
{
const UInt32 page_addr_size = 3;
const UInt32 page_addr_2 = (page >> 16) & 0xFF;
const UInt32 page_addr_1 = (page >> 8) & 0xFF;
const UInt32 page_addr_0 = (page >> 0) & 0xFF;
h2fmi_wr(fmi, FMC_ADDR0, (FMC_ADDR0__SEQ3(0x00) |
FMC_ADDR0__SEQ2(page_addr_2) |
FMC_ADDR0__SEQ1(page_addr_1) |
FMC_ADDR0__SEQ0(page_addr_0)));
h2fmi_wr(fmi, FMC_ADDRNUM, FMC_ADDRNUM__NUM(page_addr_size - 1));
}
// ********************************** EOF **************************************
+902
View File
@@ -0,0 +1,902 @@
// *****************************************************************************
//
// File: H2fmi_iop.c
//
// *****************************************************************************
//
// Notes:
//
// *****************************************************************************
//
// Copyright (C) 2010 Apple, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_iop.h"
#include "H2fmi_private.h"
#include "H2fmi_ppn.h"
#include "fmiss.h"
#include <platform/soc/hwclocks.h>
#include <platform/soc/pmgr.h>
#include <platform/memmap.h>
#include <platform.h>
#include <drivers/dma.h>
#include <drivers/aes.h>
#include <debug.h>
// =============================================================================
// external global variable definitions
// =============================================================================
extern UInt8 nand_whitening_key[16];
// =============================================================================
// private function declarations
// =============================================================================
bool h2fmi_setup_aes(h2fmi_t* fmi, IOPFMI* cmd, hfmi_aes_iv* aes_iv_array, UInt32 aes_chain_size, UInt32 aes_key_type, UInt32* aes_key, UInt32* seeds)
{
if (cmd->flags & (kIOPFMI_FLAGS_USE_AES | kIOPFMI_FLAGS_HOMOGENIZE))
{
switch (cmd->opcode)
{
case kIOPFMI_OPCODE_WRITE_SINGLE:
case kIOPFMI_OPCODE_WRITE_MULTIPLE:
case kIOPFMI_OPCODE_PPN_WRITE:
fmi->aes_cxt.command = AES_CMD_ENC;
break;
case kIOPFMI_OPCODE_READ_SINGLE:
case kIOPFMI_OPCODE_READ_MULTIPLE:
case kIOPFMI_OPCODE_PPN_READ:
fmi->aes_cxt.command = AES_CMD_DEC;
break;
default:
ASSERT(false);
return false;
break;
}
if (cmd->flags & kIOPFMI_FLAGS_USE_AES)
{
fmi->current_aes_iv_array = (hfmi_aes_iv*)aes_iv_array;
switch (aes_key_type)
{
case kIOPFMI_AES_KEY_TYPE_USER128:
fmi->aes_cxt.keying = AES_KEY_TYPE_USER | AES_KEY_SIZE_128;
fmi->aes_cxt.key = aes_key;
WMR_PRINT(CRYPTO, "Using HW key IV: 0x%08x 0x%08x 0x%08x 0x%08x\n",
aes_key[0], aes_key[1], aes_key[2], aes_key[3]);
break;
case kIOPFMI_AES_KEY_TYPE_USER192:
fmi->aes_cxt.keying = AES_KEY_TYPE_USER | AES_KEY_SIZE_192;
fmi->aes_cxt.key = aes_key;
WMR_PRINT(CRYPTO, "Using HW key IV: 0x%08x 0x%08x 0x%08x 0x%08x 0X%08x 0x%08x\n",
aes_key[0], aes_key[1], aes_key[2], aes_key[3], aes_key[4], aes_key[5]);
break;
case kIOPFMI_AES_KEY_TYPE_USER256:
fmi->aes_cxt.keying = AES_KEY_TYPE_USER | AES_KEY_SIZE_256;
fmi->aes_cxt.key = aes_key;
WMR_PRINT(CRYPTO, "Using HW key IV: 0x%08x 0x%08x 0x%08x 0x%08x 0X%08x 0x%08x 0X%08x 0x%08x\n",
aes_key[0], aes_key[1], aes_key[2], aes_key[3], aes_key[4], aes_key[5], aes_key[6], aes_key[7]);
break;
case kIOPFMI_AES_KEY_TYPE_UID0:
fmi->aes_cxt.keying = AES_KEY_TYPE_UID0;
fmi->aes_cxt.key = NULL;
WMR_PRINT(CRYPTO, "Using HW UID0\n");
break;
case kIOPFMI_AES_KEY_TYPE_GID0:
fmi->aes_cxt.keying = AES_KEY_TYPE_GID0;
fmi->aes_cxt.key = NULL;
WMR_PRINT(CRYPTO, "Using HW GID0\n");
break;
case kIOPFMI_AES_KEY_TYPE_GID1:
fmi->aes_cxt.keying = AES_KEY_TYPE_GID1;
fmi->aes_cxt.key = NULL;
WMR_PRINT(CRYPTO, "Using HW GID1\n");
break;
default:
ASSERT(false);
return false;
break;
}
fmi->aes_cxt.chunk_size = aes_chain_size;
}
else
{
fmi->aes_cxt.keying = (AES_KEY_TYPE_USER | AES_KEY_SIZE_128);
fmi->aes_cxt.key = nand_whitening_key;
fmi->current_aes_iv_array = NULL;
fmi->aes_cxt.chunk_size = fmi->logical_page_size;
WMR_PRINT(CRYPTO, "Using constant AES for whitening\n");
}
fmi->aes_cxt.chunk_size = aes_chain_size;
fmi->aes_cxt.iv_func = h2fmi_aes_iv;
fmi->aes_cxt.iv_func_arg = fmi;
fmi->iv_seed_array = seeds;
fmi->current_aes_cxt = &fmi->aes_cxt;
}
else
{
//WMR_PRINT(CRYPTO, "Disabling AES\n");
fmi->current_aes_cxt = NULL;
fmi->current_aes_iv_array = NULL;
}
return true;
}
void h2fmi_restoreFmiRegs(h2fmi_t *fmi)
{
// Restore any register state that may have been lost
// due to power gating
#if FMI_VERSION > 2
restoreTimingRegs(fmi);
turn_on_fmc(fmi);
#endif
#if FMISS_ENABLED
if (!fmi->is_ppn)
{
fmiss_raw_init_sequences(fmi);
}
else
{
fmiss_init_sequences(fmi);
}
#endif
}
// =============================================================================
// implementation function declarations
// =============================================================================
void h2fmi_iop_set_config(h2fmi_t* fmi, IOPFMI_SetConfig* cmd)
{
// record which interface is being used
dprintf(DEBUG_SPEW, "configuring FMI%d\n", cmd->fmi);
fmi->regs = (cmd->fmi == 0) ? FMI0 : FMI1;
fmi->bus_id = cmd->fmi;
// record necessary device geometry information
fmi->bytes_per_spare = cmd->bytes_per_spare;
fmi->num_of_ce = cmd->num_of_ce;
fmi->pages_per_block = cmd->pages_per_block;
fmi->blocks_per_ce = cmd->blocks_per_ce;
fmi->total_bytes_per_meta = cmd->total_bytes_per_meta;
fmi->valid_bytes_per_meta = cmd->valid_bytes_per_meta;
fmi->bytes_per_page = cmd->bytes_per_page;
fmi->sectors_per_page = fmi->bytes_per_page / H2FMI_BYTES_PER_SECTOR;
fmi->valid_ces = cmd->valid_ces;
fmi->is_ppn = cmd->ppn;
fmi->logical_page_size = cmd->logical_page_size;
fmi->clock_speed_khz = cmd->clock_speed_khz;
// TODO: decide on appropriate infrastructure in support of
// vendor-specific superblock formats and command sequences
fmi->banks_per_ce = 1;
// calculate and store bus interface timing control
WMR_PRINT(INF, "cmd->read_sample_cycles : %d\n", cmd->read_sample_cycles);
WMR_PRINT(INF, "cmd->read_setup_cycles : %d\n", cmd->read_setup_cycles);
WMR_PRINT(INF, "cmd->read_hold_cycles : %d\n", cmd->read_hold_cycles);
WMR_PRINT(INF, "cmd->write_setup_cycles : %d\n", cmd->write_setup_cycles);
WMR_PRINT(INF, "cmd->write_hold_cycles : %d\n", cmd->write_hold_cycles);
fmi->if_ctrl = (FMC_IF_CTRL__DCCYCLE(cmd->read_sample_cycles) |
FMC_IF_CTRL__REB_SETUP(cmd->read_setup_cycles) |
FMC_IF_CTRL__REB_HOLD(cmd->read_hold_cycles) |
FMC_IF_CTRL__WEB_SETUP(cmd->write_setup_cycles) |
FMC_IF_CTRL__WEB_HOLD(cmd->write_hold_cycles));
WMR_PRINT(INF, "cmd->retire_on_invalid_refresh : %d\n", cmd->retire_on_invalid_refresh);
fmi->retire_on_invalid_refresh = cmd->retire_on_invalid_refresh;
#if SUPPORT_TOGGLE_NAND
fmi->is_toggle_system = cmd->toggle_system;
fmi->is_toggle = cmd->toggle;
if (fmi->is_toggle)
{
WMR_PRINT(INF, "cmd->ce_hold_cycles : %d\n", cmd->ce_hold_cycles);
WMR_PRINT(INF, "cmd->ce_setup_cycles : %d\n", cmd->ce_setup_cycles);
WMR_PRINT(INF, "cmd->adl_cycles : %d\n", cmd->adl_cycles);
WMR_PRINT(INF, "cmd->whr_cycles : %d\n", cmd->whr_cycles);
WMR_PRINT(INF, "cmd->read_pre_cycles : %d\n", cmd->read_pre_cycles);
WMR_PRINT(INF, "cmd->read_post_cycles : %d\n", cmd->read_post_cycles);
WMR_PRINT(INF, "cmd->write_pre_cycles : %d\n", cmd->write_pre_cycles);
WMR_PRINT(INF, "cmd->write_post_cycles : %d\n", cmd->write_post_cycles);
WMR_PRINT(INF, "cmd->enable_diff_DQS : %d\n", cmd->enable_diff_DQS);
WMR_PRINT(INF, "cmd->enable_diff_RE : %d\n", cmd->enable_diff_RE);
WMR_PRINT(INF, "cmd->enable_VREF : %d\n", cmd->enable_VREF);
fmi->dqs_ctrl = cmd->reg_dqs_delay;
fmi->timing_ctrl_1 = (FMC_TOGGLE_CTRL_1_DDR_RD_PRE_TIME(cmd->read_pre_cycles) |
FMC_TOGGLE_CTRL_1_DDR_RD_POST_TIME(cmd->read_post_cycles) |
FMC_TOGGLE_CTRL_1_DDR_WR_PRE_TIME(cmd->write_pre_cycles) |
FMC_TOGGLE_CTRL_1_DDR_WR_POST_TIME(cmd->write_post_cycles));
fmi->timing_ctrl_2 = (FMC_TOGGLE_CTRL_2_CE_SETUP_TIME(cmd->ce_setup_cycles) |
FMC_TOGGLE_CTRL_2_CE_HOLD_TIME(cmd->ce_hold_cycles) |
FMC_TOGGLE_CTRL_2_NAND_TIMING_ADL(cmd->adl_cycles) |
FMC_TOGGLE_CTRL_2_NAND_TIMING_WHR(cmd->whr_cycles));
fmi->toggle_if_ctrl = (FMC_IF_CTRL__DCCYCLE(0) |
FMC_IF_CTRL__REB_SETUP(cmd->dqs_half_cycles) |
FMC_IF_CTRL__REB_HOLD(0) |
FMC_IF_CTRL__WEB_SETUP(cmd->write_setup_cycles) |
FMC_IF_CTRL__WEB_HOLD(cmd->write_hold_cycles));
fmi->useDiffDQS = cmd->enable_diff_DQS;
fmi->useDiffRE = cmd->enable_diff_RE;
fmi->useVREF = cmd->enable_VREF;
}
#endif
h2fmi_restoreFmiRegs(fmi);
// always report config information
WMR_PRINT(INF, "fmi->regs : %p\n", fmi->regs);
WMR_PRINT(INF, "fmi->valid_ces : %p\n", fmi->valid_ces);
WMR_PRINT(INF, "fmi->num_of_ce : %p\n", fmi->num_of_ce);
WMR_PRINT(INF, "fmi->banks_per_ce : %p\n", fmi->banks_per_ce);
WMR_PRINT(INF, "fmi->pages_per_block : %p\n", fmi->pages_per_block);
WMR_PRINT(INF, "fmi->sectors_per_page : %p\n", fmi->sectors_per_page);
WMR_PRINT(INF, "fmi->bytes_per_spare : %p\n", fmi->bytes_per_spare);
WMR_PRINT(INF, "fmi->blocks_per_ce : %p\n", fmi->blocks_per_ce);
WMR_PRINT(INF, "fmi->valid_bytes_per_meta : %p\n", fmi->valid_bytes_per_meta);
WMR_PRINT(INF, "fmi->total_bytes_per_meta : %p\n", fmi->total_bytes_per_meta);
WMR_PRINT(INF, "fmi->if_ctrl : %p\n", fmi->if_ctrl);
#if SUPPORT_TOGGLE_NAND
if (fmi->is_toggle)
{
WMR_PRINT(INF, "fmi->dqs_ctrl : %p\n", fmi->dqs_ctrl);
WMR_PRINT(INF, "fmi->timing_ctrl_1 : %p\n", fmi->timing_ctrl_1);
WMR_PRINT(INF, "fmi->timing_ctrl_2 : %p\n", fmi->timing_ctrl_2);
WMR_PRINT(INF, "fmi->toggle_if_ctrl : %p\n", fmi->toggle_if_ctrl);
WMR_PRINT(INF, "fmi->is_toggle : %p\n", fmi->is_toggle);
}
#endif
WMR_PRINT(INF, "fmi->bytes_per_page : %p\n", fmi->bytes_per_page);
WMR_PRINT(INF, "fmi->is_ppn : %p\n", fmi->is_ppn);
// these steps are only taken when fmi is first configured
if (!fmi->initialized)
{
// Make certain the FMC is enabled upon init.
turn_on_fmc(fmi);
// Perform system-specific initialization.
h2fmi_init_sys(fmi);
// indicate that fmi is initialized
fmi->initialized = TRUE32;
fmi->stateMachine.currentMode = fmiNone;
fmi->wMaxOutstandingCEWriteOperations = cmd->wMaxOutstandingCEWriteOperations;
}
fmi->activeCe = ~0;
if (fmi->is_ppn && (!fmi->is_ppn_channel_init))
{
#if SUPPORT_PPN
if (!h2fmi_ppn_init_channel(fmi,
cmd->ppn_debug_flags_valid,
cmd->ppn_debug_flags,
cmd->ppn_vs_debug_flags_valid,
cmd->ppn_vs_debug_flags,
cmd->ppn_allow_saving_debug_data,
cmd->ppn_version))
{
WMR_PANIC("[FIL:ERR] Unable to initialize PPN device\n");
cmd->iopfmi.status = kIOPFMI_STATUS_FAILURE;
return;
}
fmi->is_ppn_channel_init = TRUE32;
#else
WMR_PANIC("!SUPPORT_PPN");
#endif
}
// Cache page config registers
if (fmi->is_ppn)
{
#if SUPPORT_PPN
fmi->fmi_config_reg = h2fmi_ppn_calculate_fmi_config(fmi);
#if FMI_VERSION > 0
fmi->fmi_data_size_reg = h2fmi_ppn_calculate_fmi_data_size(fmi);
#endif /* FMI_VERSION > 0*/
#else //SUPPORT_PPN
WMR_PANIC("!SUPPORT_PPN");
#endif //SUPPORT_PPN
}
else
{
// Cache ECC configuration
fmi->correctable_bits = h2fmi_calculate_ecc_bits(fmi);
fmi->fmi_config_reg = h2fmi_calculate_fmi_config(fmi);
#if FMI_VERSION > 0
fmi->fmi_data_size_reg = h2fmi_calculate_fmi_data_size(fmi);
#endif /* FMI_VERSION > 0*/
}
// record success status in command structure
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
void h2fmi_iop_read_chip_ids(h2fmi_t* fmi, IOPFMI_ReadChipIDs* cmd)
{
IOPFMI_chipid_t* ids_buf = (IOPFMI_chipid_t*)mem_static_map_cached(cmd->chip_id_buffer);
IOPFMI_status_t status = kIOPFMI_STATUS_SUCCESS;
UInt32 valid_ces;
UInt32 ce;
WMR_ASSERT(ids_buf != MAP_FAILED);
valid_ces = fmi->valid_ces;
fmi->valid_ces = 0xffff;
for (ce = 0; ce < H2FMI_MAX_CE_TOTAL; ce++)
{
h2fmi_chipid_t* chipid = (h2fmi_chipid_t*)&ids_buf[ce];
UInt8 *ptr = (UInt8 *)&ids_buf[ce];
if (!h2fmi_nand_read_id(fmi, ce, chipid, CHIPID_ADDR))
{
status = kIOPFMI_STATUS_FAILED_READ_ID;
break;
}
WMR_PRINT(INF, "Read Chip ID %02X %02X %02X %02X %02X %02X to %p\n",
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], chipid);
}
fmi->valid_ces = valid_ces;
cmd->iopfmi.status = status;
WMR_PREPARE_WRITE_BUFFER(ids_buf, H2FMI_MAX_CE_TOTAL * sizeof(IOPFMI_chipid_t));
}
void h2fmi_iop_reset_everything(h2fmi_t* fmi, IOPFMI_ResetEverything* cmd)
{
IOPFMI_status_t status = kIOPFMI_STATUS_SUCCESS;
BOOL32 ret = TRUE32;
h2fmi_reset(fmi);
h2fmi_init_sys(fmi);
ret = h2fmi_nand_reset_all(fmi);
if (!ret)
{
status = kIOPFMI_STATUS_FAILED_RESET_ALL;
}
}
void h2fmi_iop_erase_multiple(h2fmi_t* fmi, IOPFMI_EraseMultiple* cmd)
{
BOOL32 erase_failed = FALSE32;
WMR_PRINT(ERASE, "IOP received Multi-Erase command %d elements\n", cmd->number_of_elements);
if (!h2fmi_erase_blocks(fmi,
cmd->number_of_elements,
cmd->ce,
cmd->block_number,
&erase_failed))
{
cmd->iopfmi.status = kIOPFMI_STATUS_FAILED_ERASE_BLOCK;
}
else if (erase_failed)
{
cmd->iopfmi.status = kIOPFMI_STATUS_DEVICE_ERROR;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
/**
* Copy erase status back out ...
*/
cmd->failure_details.wNumCE_Executed = fmi->failureDetails.wNumCE_Executed;
cmd->failure_details.wFirstFailingCE = fmi->failureDetails.wFirstFailingCE;
}
void h2fmi_iop_erase_single(h2fmi_t* fmi, IOPFMI_EraseSingle* cmd)
{
BOOL32 erase_failed = FALSE32;
WMR_PRINT(ERASE, "IOP received Erase command CE %d Block %d\n", cmd->ce, cmd->block_number);
fmi->failureDetails.wCEStatusArray = &fmi->failureDetails.wSingleCEStatus;
fmi->failureDetails.wCEStatusArrayModulusMask = 0;
if (!h2fmi_erase_blocks(fmi,
1,
&cmd->ce,
&cmd->block_number,
&erase_failed))
{
cmd->iopfmi.status = kIOPFMI_STATUS_FAILED_ERASE_BLOCK;
}
else if (erase_failed)
{
cmd->iopfmi.status = kIOPFMI_STATUS_DEVICE_ERROR;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
/**
* Copy erase status back out ...
*/
cmd->failure_details.wNumCE_Executed = fmi->failureDetails.wNumCE_Executed;
cmd->failure_details.wSingleCEStatus = fmi->failureDetails.wSingleCEStatus;
}
void h2fmi_iop_read_single(h2fmi_t* fmi, IOPFMI_IOSingle* cmd)
{
BOOL32 gather_corrections = (0 != cmd->correction_address);
UInt8* correct_buf = (gather_corrections
? (UInt8*)mem_static_map_cached(cmd->correction_address)
: NULL);
UInt8* data_buf = (UInt8*)cmd->data_address;
UInt8* meta_buf = (UInt8*)cmd->meta_address;
hfmi_aes_iv* aes_iv_array = NULL;
WMR_ASSERT(correct_buf != MAP_FAILED);
WMR_PRINT(READ, "IOP received Read Single command CE %d Block %d\n", cmd->ce, cmd->page_number);
if (cmd->aes_iv_array)
{
aes_iv_array = (hfmi_aes_iv*)mem_static_map_cached(cmd->aes_iv_array);
WMR_ASSERT(aes_iv_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(aes_iv_array, cmd->aes_num_chains * sizeof(hfmi_aes_iv));
}
h2fmi_setup_aes(fmi, &cmd->iopfmi, aes_iv_array, cmd->aes_chain_size, cmd->aes_key_type, (UInt32*)cmd->aes_key_bytes, &cmd->page_number);
cmd->iopfmi.status = h2fmi_read_page(fmi,
cmd->ce,
cmd->page_number,
data_buf,
meta_buf,
correct_buf,
NULL);
// clean corrections buffer, if not NULL
if (gather_corrections)
{
WMR_PREPARE_WRITE_BUFFER(correct_buf,
fmi->sectors_per_page * sizeof(IOPFMI_correction_t));
}
}
void h2fmi_iop_read_multiple(h2fmi_t* fmi, IOPFMI_IOMultiple* cmd)
{
const UInt32 page_count = cmd->page_count;
BOOL32 gather_corrections = (0 != cmd->corrections_array);
UInt8* corrections_array = (gather_corrections
? (UInt8*)mem_static_map_cached(cmd->corrections_array)
: NULL);
h2fmi_ce_t* chip_enable_array = (h2fmi_ce_t*)mem_static_map_cached(cmd->chip_enable_array);
UInt32* page_number_array = (UInt32*)mem_static_map_cached(cmd->page_number_array);
hfmi_aes_iv* aes_iv_array = NULL;
WMR_ASSERT(corrections_array != MAP_FAILED);
WMR_ASSERT(chip_enable_array != MAP_FAILED);
WMR_ASSERT(page_number_array != MAP_FAILED);
if (cmd->aes_iv_array)
{
aes_iv_array = (hfmi_aes_iv*)mem_static_map_cached(cmd->aes_iv_array);
WMR_ASSERT(aes_iv_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(aes_iv_array, cmd->aes_num_chains * sizeof(hfmi_aes_iv));
}
// Invalidate control arrays, ensuring that these values are
// re-read from physical memory.
WMR_PREPARE_READ_BUFFER(chip_enable_array, page_count * sizeof(UInt32));
WMR_PREPARE_READ_BUFFER(page_number_array, page_count * sizeof(UInt32));
UInt32* data_segments_array = (UInt32*)mem_static_map_cached(cmd->data_segments_array);
UInt32* meta_segments_array = (UInt32*)mem_static_map_cached(cmd->meta_segments_array);
WMR_ASSERT(data_segments_array != MAP_FAILED);
WMR_ASSERT(meta_segments_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(data_segments_array, cmd->data_segment_array_length_in_bytes);
WMR_PREPARE_READ_BUFFER(meta_segments_array, cmd->meta_segment_array_length_in_bytes);
h2fmi_setup_aes(fmi, &cmd->iopfmi, aes_iv_array, cmd->aes_chain_size, cmd->aes_key_type, (UInt32*)cmd->aes_key_bytes, page_number_array);
WMR_PRINT(READ, "IOP received Read Multiple command NumPages %d\n", page_count);
// perform multi-read
cmd->iopfmi.status = h2fmi_read_multi(fmi,
page_count,
chip_enable_array,
page_number_array,
(void*)data_segments_array,
(void*)meta_segments_array,
corrections_array,
NULL);
// clean corrections buffer, if not NULL
if (gather_corrections)
{
WMR_PREPARE_WRITE_BUFFER(corrections_array,
page_count * fmi->sectors_per_page * sizeof(IOPFMI_correction_t));
}
/**
* Copy failure data.
*/
cmd->failure_details.wNumCE_Executed = fmi->failureDetails.wNumCE_Executed;
cmd->failure_details.wOverallOperationFailure = fmi->failureDetails.wOverallOperationFailure;
cmd->failure_details.wFirstFailingCE = fmi->failureDetails.wFirstFailingCE;
#if (defined (WMR_DEBUG) && WMR_DEBUG)
if ( (kIOPFMI_STATUS_SUCCESS != cmd->iopfmi.status) &&
(kIOPFMI_STATUS_BLANK != cmd->iopfmi.status) &&
(kIOPFMI_STATUS_FUSED != cmd->iopfmi.status))
{
unsigned k = fmi->failureDetails.wCEStatusArrayModulusMask;
WMR_PRINT(ERROR, "IOP --> err 0x%08x, %d completed on %d\n",cmd->iopfmi.status, fmi->failureDetails.wNumCE_Executed,fmi->bus_id);
while ( k>0 )
{
WMR_PRINT(ERROR, "Status[%d] = 0x%x\n",k,fmi->failureDetails.wCEStatusArray[k]);
k--;
}
}
#endif
}
void h2fmi_iop_write_single(h2fmi_t* fmi, IOPFMI_IOSingle* cmd)
{
UInt8* data_buf = (UInt8*)cmd->data_address;
UInt8* meta_buf = (UInt8*)cmd->meta_address;
BOOL32 write_failed = FALSE32;
hfmi_aes_iv* aes_iv_array = NULL;
if (cmd->aes_iv_array)
{
aes_iv_array = (hfmi_aes_iv*)mem_static_map_cached(cmd->aes_iv_array);
WMR_ASSERT(aes_iv_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(aes_iv_array, cmd->aes_num_chains * sizeof(hfmi_aes_iv));
}
WMR_PRINT(WRITE, "IOP received Write Single command CE %d Block %d\n", cmd->ce, cmd->page_number);
h2fmi_setup_aes(fmi, &cmd->iopfmi, aes_iv_array, cmd->aes_chain_size, cmd->aes_key_type, (UInt32*)cmd->aes_key_bytes, &cmd->page_number);
if (!h2fmi_write_page(fmi,
cmd->ce,
cmd->page_number,
data_buf,
meta_buf,
&write_failed))
{
cmd->iopfmi.status = kIOPFMI_STATUS_FAILED_WRITE_PAGE;
}
else if (write_failed)
{
cmd->iopfmi.status = kIOPFMI_STATUS_DEVICE_ERROR;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
}
void h2fmi_iop_write_multiple(h2fmi_t* fmi, IOPFMI_IOMultiple* cmd)
{
const UInt32 page_count = cmd->page_count;
h2fmi_ce_t* chip_enable_array = (h2fmi_ce_t*)mem_static_map_cached(cmd->chip_enable_array);
UInt32* page_number_array = (UInt32*)mem_static_map_cached(cmd->page_number_array);
BOOL32 write_failed = FALSE32;
hfmi_aes_iv* aes_iv_array = NULL;
WMR_ASSERT(chip_enable_array != MAP_FAILED);
WMR_ASSERT(page_number_array != MAP_FAILED);
if (cmd->aes_iv_array)
{
aes_iv_array = (hfmi_aes_iv*)mem_static_map_cached(cmd->aes_iv_array);
WMR_ASSERT(aes_iv_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(aes_iv_array, cmd->aes_num_chains * sizeof(hfmi_aes_iv));
}
// Invalidate control arrays, ensuring that these values are
// re-read from physical memory.
WMR_PREPARE_READ_BUFFER(chip_enable_array, page_count * sizeof(UInt32));
WMR_PREPARE_READ_BUFFER(page_number_array, page_count * sizeof(UInt32));
UInt32* data_segments_array = (UInt32*)mem_static_map_cached(cmd->data_segments_array);
UInt32* meta_segments_array = (UInt32*)mem_static_map_cached(cmd->meta_segments_array);
WMR_ASSERT(data_segments_array != MAP_FAILED);
WMR_ASSERT(meta_segments_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(data_segments_array, cmd->data_segment_array_length_in_bytes);
WMR_PREPARE_READ_BUFFER(meta_segments_array, cmd->meta_segment_array_length_in_bytes);
WMR_PRINT(WRITE, "IOP received Write Multiple command NumPages %d\n", page_count);
h2fmi_setup_aes(fmi, &cmd->iopfmi, aes_iv_array, cmd->aes_chain_size, cmd->aes_key_type, (UInt32*)cmd->aes_key_bytes, page_number_array);
// perform multi-write
if (!h2fmi_write_multi(fmi,
page_count,
chip_enable_array,
page_number_array,
(void*)data_segments_array,
(void*)meta_segments_array,
&write_failed,
cmd->vendorProtocol))
{
cmd->iopfmi.status = kIOPFMI_STATUS_FAILED_WRITE_MULTI;
}
else if (write_failed)
{
cmd->iopfmi.status = kIOPFMI_STATUS_DEVICE_ERROR;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
/**
* Copy failure data.
*/
cmd->failure_details.wNumCE_Executed = fmi->failureDetails.wNumCE_Executed;
cmd->failure_details.wFirstFailingCE = fmi->failureDetails.wFirstFailingCE;
}
void h2fmi_iop_read_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd)
{
UInt8* page_buf = (UInt8*)(cmd->buffer_address);
UInt8* data_buf = page_buf + 0;
UInt8* spare_buf = page_buf + fmi->bytes_per_page;
fmi->current_aes_cxt = NULL;
WMR_PRINT(READ, "IOP received Read Raw command CE %d Page %d\n", cmd->ce, cmd->page_number);
if (!h2fmi_read_raw_page(fmi,
cmd->ce,
cmd->page_number,
data_buf,
spare_buf))
{
cmd->iopfmi.status = kIOPFMI_STATUS_FAILED_READ_RAW;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
}
void h2fmi_iop_write_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd)
{
const UInt32 data_bytes_per_page = (fmi->sectors_per_page * H2FMI_BYTES_PER_SECTOR);
const UInt32 bytes_per_page = data_bytes_per_page + fmi->bytes_per_spare;
UInt8* page_buf = (UInt8*)cmd->buffer_address;
UInt8* data_buf = page_buf;
// deal with cache coherency issues
const UInt32 data_clean_size = bytes_per_page;
fmi->current_aes_cxt = NULL;
WMR_PRINT(WRITE, "IOP sending write raw ce %d page %d data_buf %08x size %d\n",
cmd->ce,
cmd->page_number,
data_buf,
bytes_per_page);
// Invalidate data and meta buffers, ensuring their
// contents are re-read from physical memory
WMR_PREPARE_READ_BUFFER(data_buf, data_clean_size);
cmd->iopfmi.status = h2fmi_write_raw_page(fmi,
cmd->ce,
cmd->page_number,
data_buf);
}
void h2fmi_iop_read_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd)
{
BOOL32 gather_corrections = (0 != cmd->corrections_array);
UInt8* corrections_array = (gather_corrections
? (UInt8*)mem_static_map_cached(cmd->corrections_array)
: NULL);
UInt8* page_buf = (UInt8*)cmd->buffer_address;
WMR_ASSERT(corrections_array != MAP_FAILED);
fmi->current_aes_cxt = NULL;
WMR_PRINT(READ, "IOP received Read Boot Page command CE %d Page %d\n", cmd->ce, cmd->page_number);
cmd->iopfmi.status = h2fmi_read_bootpage(fmi,
cmd->ce,
cmd->page_number,
page_buf,
corrections_array);
// clean corrections buffer, if not NULL
if (gather_corrections)
{
WMR_PREPARE_WRITE_BUFFER(corrections_array,
fmi->sectors_per_page * sizeof(IOPFMI_correction_t));
}
}
void h2fmi_iop_write_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd)
{
UInt8* page_buf = (UInt8*)mem_static_map_cached(cmd->buffer_address);
WMR_ASSERT(page_buf != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(page_buf, H2FMI_BOOT_BYTES_PER_PAGE);
fmi->current_aes_cxt = NULL;
WMR_PRINT(WRITE, "IOP received Write Boot Page command CE %d Page %d\n", cmd->ce, cmd->page_number);
cmd->iopfmi.status = h2fmi_write_bootpage(fmi,
cmd->ce,
cmd->page_number,
page_buf);
}
void h2fmi_iop_sleep(h2fmi_t* fmi)
{
dprintf(DEBUG_CRITICAL, "sleeping FMI%d\n", h2fmi_bus_index(fmi));
}
void h2fmi_iop_wake(h2fmi_t* fmi)
{
dprintf(DEBUG_CRITICAL, "waking FMI%d\n", h2fmi_bus_index(fmi));
}
void dump_fmi_state(h2fmi_t *pFMI, uint32_t index, BOOL32 withHWRegs, BOOL32 withECC)
{
/**
* Dump 'important' parts of state machine ...
*/
printf("FMI[%u] - stateMachine{mode:%d, state: %d, CEsav: %d, page_idx: %d, page_count: %d, currentCE: %d, currentPage: 0x%x, fSuccessful: %d, lastCE: %d, needsPrepare: %d, cleanPages: %d, uecc_pages: %d, cmdStartTick: 0x%llx, wVendorType: %d}\n",
index,
(int)pFMI->stateMachine.currentMode,
(int)pFMI->stateMachine.state.rd,
pFMI->stateMachine.savedCurrentCE,
pFMI->stateMachine.page_idx,
pFMI->stateMachine.page_count,
pFMI->stateMachine.currentCE,
pFMI->stateMachine.currentPage,
(int)pFMI->stateMachine.fSuccessful,
pFMI->stateMachine.lastCE,
pFMI->stateMachine.needs_prepare,
pFMI->stateMachine.clean_pages,
pFMI->stateMachine.uecc_pages,
pFMI->stateMachine.wCmdStartTicks,
pFMI->stateMachine.wVendorType);
/**
* Dump failure details.
*/
printf("FMI[%u] - failureDetails{wNumCEexec:%d, hldoff: %d, outstd: %d/%d, overall: 0x%x, firstFailingCE: 0x%x, wSingleCEStatus: 0x%x}\n",
index,
pFMI->failureDetails.wNumCE_Executed,
pFMI->stateMachine.wNumTimesHoldoffExecuted,
pFMI->stateMachine.wOutstandingCEWriteOperations,
pFMI->stateMachine.wMaxOutstandingCEWriteOperations,
pFMI->failureDetails.wOverallOperationFailure,
pFMI->failureDetails.wFirstFailingCE,
pFMI->failureDetails.wSingleCEStatus
);
if (withHWRegs)
{
/**
* Dump important FMI registers ...
*/
#if FMI_VERSION <=2
printf("FMI[%u] - fmi{bus: %d, CFG: 0x%x, CTRL: 0x%x, STAT: 0x%x, INTPND: 0x%x, INT_EN: 0x%x, DBG0: 0x%x, DBG1: 0x%x, DBG2: 0x%x}\n",
index,
pFMI->bus_id,
h2fmi_rd(pFMI,FMI_CONFIG),
h2fmi_rd(pFMI,FMI_CONTROL),
h2fmi_rd(pFMI,FMI_STATUS),
h2fmi_rd(pFMI,FMI_INT_PEND),
h2fmi_rd(pFMI,FMI_INT_EN),
h2fmi_rd(pFMI,FMI_DEBUG0),
h2fmi_rd(pFMI,FMI_DEBUG1),
h2fmi_rd(pFMI,FMI_DEBUG2)
);
#else
printf("FMI[%u] - fmi{bus: %d, CFG: 0x%x, CTRL: 0x%x, STAT: 0x%x, INTPND: 0x%x, INT_EN: 0x%x, DBG0: 0x%x, DATSIZ: 0x%x}\n",
index,
pFMI->bus_id,
h2fmi_rd(pFMI,FMI_CONFIG),
h2fmi_rd(pFMI,FMI_CONTROL),
h2fmi_rd(pFMI,FMI_STATUS),
h2fmi_rd(pFMI,FMI_INT_PEND),
h2fmi_rd(pFMI,FMI_INT_EN),
h2fmi_rd(pFMI,FMI_DEBUG0),
h2fmi_rd(pFMI,FMI_DATA_SIZE)
);
#endif
#if ((FMI_VERSION > 0) && (FMI_VERSION <= 2))
printf("FMI[%u] - fmi{DBG3: 0x%x, DATSIZ: 0x%x}\n",index,h2fmi_rd(pFMI,FMI_DEBUG3),h2fmi_rd(pFMI,FMI_DATA_SIZE));
#endif
/**
* Dump important FMC registers ...
*/
printf("FMI[%u] - fmc{ON: 0x%x, IFCTRL: 0x%x, CECTRL: 0x%x, RWCTRL: 0x%x, CMD: 0x%x, ADDR0: 0x%x, ADDR1: 0x%x, ANUM: 0x%x, DNUM: 0x%x, FSTATUS: 0x%x, NSTATUS: 0x%x, RBB_CFG: 0x%x}\n",
index,
h2fmi_rd(pFMI,FMC_ON),
h2fmi_rd(pFMI,FMC_IF_CTRL),
h2fmi_rd(pFMI,FMC_CE_CTRL),
h2fmi_rd(pFMI,FMC_RW_CTRL),
h2fmi_rd(pFMI,FMC_CMD),
h2fmi_rd(pFMI,FMC_ADDR0),
h2fmi_rd(pFMI,FMC_ADDR1),
h2fmi_rd(pFMI,FMC_ADDRNUM),
h2fmi_rd(pFMI,FMC_DATANUM),
h2fmi_rd(pFMI,FMC_STATUS),
h2fmi_rd(pFMI,FMC_NAND_STATUS),
h2fmi_rd(pFMI,FMC_RBB_CONFIG)
);
#if FMI_VERSION > 2
printf("FMI[%u] - fmc{DQST: 0x%x, NANDT1: 0x%x, NANDT2: 0x%x, NANDT3: 0x%x}\n",
index,
h2fmi_rd(pFMI,FMC_DQS_TIMING_CTRL),
h2fmi_rd(pFMI,FMC_TOGGLE_CTRL_1),
h2fmi_rd(pFMI,FMC_TOGGLE_CTRL_2),
h2fmi_rd(pFMI,FMC_TOGGLE_CTRL_3)
);
#endif // FMI_VERSION > 2
// ECC might be clocked off for PPN
if (withECC)
{
/**
* Dump important ECC registers ...
*/
printf("FMI[%u] - ecc{PND: 0x%x, MASK: 0x%x}\n",
index,
h2fmi_rd(pFMI,ECC_PND),
h2fmi_rd(pFMI,ECC_MASK)
);
}
else
{
printf("FMI[%u} - omitting ecc registers for ppn device\n", index);
}
#if FMISS_DUMP_ENABLED
// FMISS
if (0 != (FMI_CONTROL__SEQUENCER_TIMEOUT_ENABLE & h2fmi_rd(pFMI, FMI_CONTROL)))
{
fmiss_dump(pFMI);
}
#endif // FMISS_DUMP_ENABLED
}
}
+70
View File
@@ -0,0 +1,70 @@
// *****************************************************************************
//
// File: H2fmi_iop.h
//
// *****************************************************************************
//
// Notes:
//
// *****************************************************************************
//
// Copyright (C) 2010 Apple, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#ifndef _H2FMI_IOP_H
#define _H2FMI_IOP_H
// TODO: fix this by moving referenced header into common include directory
#include "../../../apps/EmbeddedIOP/function_fmi/iop_fmi_protocol.h"
#include "H2fmi_private.h"
bool h2fmi_setup_aes(h2fmi_t* fmi, IOPFMI* cmd, hfmi_aes_iv* aes_iv_array, UInt32 aes_chain_size, UInt32 aes_key_type, UInt32* aes_key, UInt32* seeds);
void h2fmi_iop_set_config(h2fmi_t* fmi, IOPFMI_SetConfig* config);
void h2fmi_iop_reset_everything(h2fmi_t* fmi, IOPFMI_ResetEverything* cmd);
void h2fmi_iop_read_chip_ids(h2fmi_t* fmi, IOPFMI_ReadChipIDs* cmd);
void h2fmi_iop_erase_single(h2fmi_t* fmi, IOPFMI_EraseSingle* cmd);
void h2fmi_iop_erase_multiple(h2fmi_t* fmi, IOPFMI_EraseMultiple* cmd);
void h2fmi_iop_read_single(h2fmi_t* fmi, IOPFMI_IOSingle* cmd);
void h2fmi_iop_write_single(h2fmi_t* fmi, IOPFMI_IOSingle* cmd);
void h2fmi_iop_read_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd);
void h2fmi_iop_write_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd);
void h2fmi_iop_read_multiple(h2fmi_t* fmi, IOPFMI_IOMultiple* cmd);
void h2fmi_iop_write_multiple(h2fmi_t* fmi, IOPFMI_IOMultiple* cmd);
void h2fmi_iop_write_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd);
void h2fmi_iop_read_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd);
void h2fmi_iop_sleep(h2fmi_t* fmi);
void h2fmi_iop_wake(h2fmi_t* fmi);
void h2fmi_ppn_iop_reset_everything(h2fmi_t *fmi, IOPFMI_ResetEverything* cmd);
void h2fmi_ppn_iop_erase_multiple(h2fmi_t *fmi, IOPFMI_IOPpn* cmd);
void h2fmi_ppn_iop_erase_single(h2fmi_t *fmi, IOPFMI_EraseSingle *cmd);
void h2fmi_ppn_iop_read_single(h2fmi_t *fmi, IOPFMI_IOSingle* cmd);
void h2fmi_ppn_iop_read_multiple(h2fmi_t *fmi, IOPFMI_IOPpn* cmd);
void h2fmi_ppn_iop_write_single(h2fmi_t *fmi, IOPFMI_IOSingle* cmd);
void h2fmi_ppn_iop_write_multiple(h2fmi_t *fmi, IOPFMI_IOPpn* cmd);
void h2fmi_ppn_iop_read_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd);
void h2fmi_ppn_iop_write_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd);
void h2fmi_ppn_iop_read_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd);
void h2fmi_ppn_iop_write_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd);
void h2fmi_ppn_iop_read_cau_bbt(h2fmi_t* fmi, IOPFMI_IOPpn* cmd);
void h2fmi_ppn_iop_update_firmware(h2fmi_t* fmi, IOPFMI_UpdateFirmware* cmd);
void h2fmi_ppn_iop_post_rst_pre_pwrstate_operations(h2fmi_t* fmi, IOPFMI_PostResetOperations *cmd);
void h2fmi_ppn_iop_set_power(h2fmi_t* fmi, IOPFMI_SetPower* cmd);
void h2fmi_ppn_iop_get_failure_info(h2fmi_t* fmi, IOPFMI_GetFailureInfo* cmd);
void h2fmi_ppn_iop_get_controller_info(h2fmi_t* fmi, IOPFMI_GetControllerInfo* cmd);
void h2fmi_ppn_iop_get_temperature(h2fmi_t *fmi, IOPFMI_GetTemperature* cmd);
void h2fmi_ppn_iop_get_die_info(h2fmi_t* fmi, IOPFMI_GetDieInfo* cmd);
void h2fmi_ppn_iop_set_feature_list(h2fmi_t *fmi, IOPFMI_SetFeatures* cmd);
void h2fmi_ppn_iop_power_state_changed(h2fmi_t* fmi);
void dump_fmi_state(h2fmi_t *pFMI, uint32_t index, BOOL32 withHWRegs, BOOL32 withECC);
#endif // _H2FMI_IOP_H
+984
View File
@@ -0,0 +1,984 @@
// *****************************************************************************
//
// File: H2fmi_misc.c
//
// *****************************************************************************
//
// Notes:
//
// - Add a global for FMC_IF_CTRL values and avoid reading it on the
// fly to get the values.
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_private.h"
#include "H2fmi_dma.h"
#if SUPPORT_PPN
#include "H2fmi_ppn.h"
#endif
#if (H2FMI_WAIT_USING_ISR)
#include <platform/soc/hwisr.h>
#include <platform/int.h>
#endif
// =============================================================================
// global variable declarations
// =============================================================================
//AES_KEY_SIZE_128
UInt8 nand_whitening_key[16] = {0x92, 0xa7, 0x42, 0xab, 0x08, 0xc9, 0x69, 0xbf, 0x00, 0x6c, 0x94, 0x12, 0xd3, 0xcc, 0x79, 0xa5};
// =============================================================================
// static implementation function declarations
// =============================================================================
#if (H2FMI_WAIT_USING_ISR)
static void h2fmi_init_isr(h2fmi_t* fmi);
static void h2fmi_isr_handler(void* arg);
#endif
// =============================================================================
// public implementation function definitions
// =============================================================================
void h2fmi_init_sys(h2fmi_t* fmi)
{
#if (H2FMI_WAIT_USING_ISR)
h2fmi_init_isr(fmi);
#endif
#if (H2FMI_WAIT_USING_ISR)
// init state machine event
event_init(&fmi->stateMachine.stateMachineDoneEvent, EVENT_FLAG_AUTO_UNSIGNAL, false);
#endif
// FMI manages ECC interaction, so make certain we aren't
// unmasking any interrupt sources
h2fmi_wr(fmi, ECC_MASK, 0x0);
fmi->h2fmi_ppn_panic_on_status_timeout = TRUE32;
}
void h2fmi_prepare_wait_status(h2fmi_t* fmi, UInt8 io_mask, UInt8 io_cond)
{
UInt32 wReadStatusCmd;
// turn off RBBEN and configure it to use look for mask value on I/O lines
h2fmi_set_if_ctrl(fmi, (~FMC_IF_CTRL__RBBEN & h2fmi_rd(fmi, FMC_IF_CTRL)));
h2fmi_wr(fmi, FMC_RBB_CONFIG, (FMC_RBB_CONFIG__POL(io_cond) |
FMC_RBB_CONFIG__POS(io_mask)));
if ( fmiWrite==fmi->stateMachine.currentMode )
{
switch ( fmi->stateMachine.wVendorType )
{
case _kVS_TOSHIBA_2P:
wReadStatusCmd = NAND_CMD__TOS_STATUS_71h;
break;
case _kVS_SAMSUNG_2P_2D:
wReadStatusCmd = ( 0==(fmi->stateMachine.page_idx&2) ? NAND_CMD__READ_SS_DIE1 : NAND_CMD__READ_SS_DIE2 );
break;
case _kVS_SAMSUNG_2D:
wReadStatusCmd = ( 0==(fmi->stateMachine.page_idx&1) ? NAND_CMD__READ_SS_DIE1 : NAND_CMD__READ_SS_DIE2 );
break;
case _kVS_NONE:
default:
wReadStatusCmd = NAND_CMD__READ_STATUS;
break;
}
}
else
{
wReadStatusCmd = NAND_CMD__READ_STATUS;
}
// exec Read Status command cycle
h2fmi_wr(fmi, FMC_CMD, FMC_CMD__CMD1(wReadStatusCmd));
h2fmi_wr(fmi, FMC_RW_CTRL, FMC_RW_CTRL__CMD1_MODE);
// busy wait until command cycle completed
h2fmi_busy_wait(fmi, FMC_STATUS, FMC_STATUS__CMD1DONE, FMC_STATUS__CMD1DONE);
h2fmi_wr(fmi, FMC_STATUS, FMC_STATUS__CMD1DONE);
// clear the FMC_STATUS__NSRBBDONE bit in FMC_STATUS
h2fmi_clear_interrupts_and_reset_masks(fmi);
// set up read cycle with REBHOLD to wait for ready bit to be
// set on I/O lines
h2fmi_wr(fmi, FMC_DATANUM, FMC_DATANUM__NUM(0));
h2fmi_wr(fmi, FMC_RW_CTRL, (FMC_RW_CTRL__REBHOLD | FMC_RW_CTRL__RD_MODE));
}
BOOL32 h2fmi_wait_status(h2fmi_t* fmi,
UInt8 io_mask,
UInt8 io_cond,
UInt8* status)
{
BOOL32 result = TRUE32;
h2fmi_prepare_wait_status(fmi, io_mask, io_cond);
#if (H2FMI_WAIT_USING_ISR)
{
// use NSRBBDone interrupt source to wait for I/O ready state
h2fmi_wr(fmi, FMC_INTMASK, FMC_INTMASK__NSRBBDONE);
h2fmi_wr(fmi, FMI_INT_EN, FMI_INT_EN__FMC_NSRBBDONE);
if (!event_wait_timeout(&fmi->isr_event, H2FMI_PAGE_TIMEOUT_MICROS))
{
h2fmi_fail(result);
}
else if (!(fmi->isr_condition & FMI_INT_PEND__FMC_NSRBBDONE))
{
h2fmi_fail(result);
}
}
#else
{
// wait until NSRBB done signaled
if (!h2fmi_wait_done(fmi, FMC_STATUS,
FMC_STATUS__NSRBBDONE,
FMC_STATUS__NSRBBDONE))
{
h2fmi_fail(result);
}
}
#endif
// if status collection desired, grab it while REBHOLD still active
if (NULL != status)
{
*status = (UInt8)h2fmi_rd(fmi, FMC_NAND_STATUS);
}
// clear FMC_RW_CTRL, thereby releasing REBHOLD and completing
// current read cycle
h2fmi_wr(fmi, FMC_RW_CTRL, 0);
return result;
}
void h2fmi_nand_read_chipid(h2fmi_t* fmi,
h2fmi_ce_t ce,
h2fmi_chipid_t* id)
{
UInt32 if_ctrl;
const UInt32 cmd1_addr_done = (FMC_STATUS__ADDRESSDONE |
FMC_STATUS__CMD1DONE);
if_ctrl = h2fmi_rd(fmi, FMC_IF_CTRL);
h2fmi_set_if_ctrl(fmi, (FMC_IF_CTRL__DCCYCLE(0) |
FMC_IF_CTRL__REB_SETUP(FMC_IF_CTRL__TIMING_MAX_CLOCKS) |
FMC_IF_CTRL__REB_HOLD(FMC_IF_CTRL__TIMING_MAX_CLOCKS) |
FMC_IF_CTRL__WEB_SETUP(FMC_IF_CTRL__TIMING_MAX_CLOCKS) |
FMC_IF_CTRL__WEB_HOLD(FMC_IF_CTRL__TIMING_MAX_CLOCKS)));
// enable specified nand device
h2fmi_fmc_enable_ce(fmi, ce);
// set up Read Id command and address cycles
h2fmi_wr(fmi, FMC_CMD, FMC_CMD__CMD1(NAND_CMD__READ_ID));
h2fmi_wr(fmi, FMC_ADDR0, FMC_ADDR0__SEQ0(0x00));
h2fmi_wr(fmi, FMC_ADDRNUM, FMC_ADDRNUM__NUM(0));
h2fmi_wr(fmi, FMC_RW_CTRL, (FMC_RW_CTRL__ADDR_MODE |
FMC_RW_CTRL__CMD1_MODE));
// wait until cmd & addr completion
h2fmi_busy_wait(fmi, FMC_STATUS, cmd1_addr_done, cmd1_addr_done);
h2fmi_wr(fmi, FMC_STATUS, cmd1_addr_done);
// read correct number of id bytes
h2fmi_fmc_read_data(fmi, H2FMI_NAND_ID_SIZE, (UInt8*)id);
// disable all nand devices
h2fmi_fmc_disable_all_ces(fmi);
h2fmi_set_if_ctrl(fmi, if_ctrl);
}
// Builds the valid_ces bitmask for all chip IDs that match id_filter
void h2fmi_build_ce_bitmask(h2fmi_t* fmi,
h2fmi_chipid_t* ids,
h2fmi_chipid_t* id_filter,
UInt8 addr)
{
UInt32 wIdx;
h2fmi_chipid_t all_zeros = {0};
// skip it if the filter is zeroes
if (!WMR_MEMCMP(all_zeros, id_filter, sizeof(h2fmi_chipid_t)))
{
return;
}
for (wIdx = 0; wIdx < H2FMI_MAX_CE_TOTAL; ++wIdx)
{
if (WMR_MEMCMP(ids[wIdx], *id_filter, H2FMI_NAND_ID_COMPARISON_SIZE) == 0)
{
// Chip ID matches
if(CHIPID_ADDR == addr)
{
_WMR_PRINT("[NAND] Found Chip ID %02X %02X %02X %02X %02X %02X on FMI%d:CE%d\n",
(UInt32)ids[wIdx][0],
(UInt32)ids[wIdx][1],
(UInt32)ids[wIdx][2],
(UInt32)ids[wIdx][3],
(UInt32)ids[wIdx][4],
(UInt32)ids[wIdx][5],
fmi->bus_id,
wIdx);
}
fmi->valid_ces |= (1UL << wIdx);
fmi->num_of_ce += 1;
}
else if(!h2fmi_is_chipid_invalid(&ids[wIdx]))
{
_WMR_PRINT("[NAND] Ignoring mismatched Chip ID %02X %02X %02X %02X %02X %02X on FMI%d:CE%d\n",
(UInt32)ids[wIdx][0],
(UInt32)ids[wIdx][1],
(UInt32)ids[wIdx][2],
(UInt32)ids[wIdx][3],
(UInt32)ids[wIdx][4],
(UInt32)ids[wIdx][5],
fmi->bus_id,
wIdx);
}
}
}
BOOL32 h2fmi_nand_read_id_all(h2fmi_t* fmi,
h2fmi_chipid_t* ids,
UInt8 addr)
{
UInt32 wIdx;
BOOL32 result = TRUE32;
WMR_MEMSET(ids, 0, (sizeof(h2fmi_chipid_t) * H2FMI_MAX_CE_TOTAL));
fmi->valid_ces = 0;
fmi->num_of_ce = 0;
for (wIdx = 0; wIdx < H2FMI_MAX_CE_TOTAL; wIdx++)
{
if (!h2fmi_nand_read_id(fmi, wIdx, &ids[wIdx], addr))
{
h2fmi_fail(result);
break;
}
}
return result;
}
BOOL32 h2fmi_reset_and_read_chipids(h2fmi_t* fmi,
h2fmi_chipid_t* ids,
UInt8 addr)
{
BOOL32 result = TRUE32;
if (!h2fmi_nand_reset_all(fmi))
{
h2fmi_fail(result);
}
else
{
result = h2fmi_nand_read_id_all(fmi, ids, addr);
}
return result;
}
BOOL32 h2fmi_nand_reset_all(h2fmi_t* fmi)
{
BOOL32 result = TRUE32;
UInt32 ce_idx;
for (ce_idx = 0; ce_idx < H2FMI_MAX_CE_TOTAL; ce_idx++)
{
// reset next device
if (!h2fmi_nand_reset(fmi, ce_idx))
{
// fail, but continue on to next device regardless
h2fmi_fail(result);
}
}
// <rdar://problem/8023322> Fix wait periods for initial reset
// wait 50 ms to allow nand to reset
WMR_SLEEP_US(H2FMI_MAX_RESET_DELAY);
#if SUPPORT_PPN
#if !H2FMI_IOP
if (fmi->is_ppn)
{
fmi->if_ctrl = H2FMI_IF_CTRL_LOW_POWER;
restoreTimingRegs(fmi);
}
#endif // !H2FMI_IOP
#endif // SUPPORT_PPN
return result;
}
#if FMI_VERSION == 0
UInt32 h2fmi_config_sectors_to_page_size(h2fmi_t* fmi)
{
UInt32 fmi_config = 0xFFFFFFFF;
// configure page size based device id table
switch (fmi->sectors_per_page)
{
case (4):
fmi_config = FMI_CONFIG__PAGE_SIZE__2K;
break;
case (8):
fmi_config = FMI_CONFIG__PAGE_SIZE__4K;
break;
case (16):
fmi_config = FMI_CONFIG__PAGE_SIZE__8K;
break;
case (1):
fmi_config = FMI_CONFIG__PAGE_SIZE__512;
break;
default:
WMR_PRINT(ERROR,
"[FIL:ERR] (512 x %d)-byte page size unsupported\n",
fmi->sectors_per_page);
}
return fmi_config;
}
#endif // S5L8920X
void h2fmi_set_raw_write_data_format(h2fmi_t* fmi, UInt32 spare_per_sector)
{
#if FMI_VERSION == 0
// Use 512 bytes per page when writing. The H2P FMI_CONFIG register doesn't give us enough
// bits in the META_PER_PAGE field to do an entire 4KB page's worth of spare so we'll
// do four 512 byte reads in a row instead.
//
// If we have no spare, use LBA_AB rather than BYPASS_ECC. Otherwise FMI will hang waiting
// for a DMA operation on the meta channel that'll never come.
h2fmi_wr(fmi, FMI_CONFIG, ((spare_per_sector ? FMI_CONFIG__LBA_MODE__BYPASS_ECC : FMI_CONFIG__LBA_MODE__LBA_TYPE_AB) |
FMI_CONFIG__META_PER_ENVELOPE(spare_per_sector) |
FMI_CONFIG__META_PER_PAGE(spare_per_sector) |
FMI_CONFIG__PAGE_SIZE__512));
#else
// With H2A and later we have arbitrary control over page and sector size. We can make our life easier
// by just setting the sector size to be sector_data_size + sector_spare_size and pusing
// everything through the data FIFO.
h2fmi_wr(fmi, FMI_CONFIG, FMI_CONFIG__ECC_CORRECTABLE_BITS( 0 ) | FMI_CONFIG__DMA_BURST__32_CYCLES);
h2fmi_wr(fmi, FMI_DATA_SIZE, (FMI_DATA_SIZE__META_BYTES_PER_SECTOR( spare_per_sector ) |
FMI_DATA_SIZE__META_BYTES_PER_PAGE( spare_per_sector ) |
FMI_DATA_SIZE__BYTES_PER_SECTOR( 1024 ) |
FMI_DATA_SIZE__SECTORS_PER_PAGE( 1 )));
#endif
}
void h2fmi_set_bootpage_data_format(h2fmi_t* fmi)
{
#if FMI_VERSION == 0
h2fmi_wr(fmi, FMI_CONFIG, (FMI_CONFIG__LBA_MODE__NORMAL |
FMI_CONFIG__META_PER_ENVELOPE(0) |
FMI_CONFIG__META_PER_PAGE(0) |
FMI_CONFIG__PAGE_SIZE__512 |
FMI_CONFIG__ECC_MODE__16BIT |
FMI_CONFIG__DMA_BURST__32_CYCLES));
#elif FMI_VERSION <= 2
h2fmi_wr(fmi, FMI_CONFIG, FMI_CONFIG__ECC_CORRECTABLE_BITS( MAX_ECC_CORRECTION ));
h2fmi_wr(fmi, FMI_DATA_SIZE, (FMI_DATA_SIZE__META_BYTES_PER_SECTOR(0) |
FMI_DATA_SIZE__META_BYTES_PER_PAGE(0) |
FMI_DATA_SIZE__BYTES_PER_SECTOR(512) |
FMI_DATA_SIZE__SECTORS_PER_PAGE(1)));
#elif FMI_VERSION <= 3
h2fmi_wr(fmi, FMI_CONFIG, FMI_CONFIG__ECC_CORRECTABLE_BITS( MAX_ECC_CORRECTION ));
h2fmi_wr(fmi, FMI_DATA_SIZE, (FMI_DATA_SIZE__META_BYTES_PER_SECTOR(0) |
FMI_DATA_SIZE__META_BYTES_PER_PAGE(0) |
FMI_DATA_SIZE__BYTES_PER_SECTOR(512) |
FMI_DATA_SIZE__SECTORS_PER_PAGE(1)));
// Do not use written-mark
h2fmi_wr(fmi, ECC_CON1, (ECC_CON1__ERROR_ALERT_LEVEL(0) |
ECC_CON1__INT_ENABLE(0) |
ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(MAX_ECC_CORRECTION)));
#else
// Use randomizer
h2fmi_wr(fmi, FMI_CONFIG, FMI_CONFIG__ECC_CORRECTABLE_BITS( MAX_ECC_CORRECTION ) |
FMI_CONFIG__SCRAMBLE_SEED |
FMI_CONFIG__ENABLE_WHITENING);
h2fmi_wr(fmi, FMI_DATA_SIZE, (FMI_DATA_SIZE__META_BYTES_PER_SECTOR(0) |
FMI_DATA_SIZE__META_BYTES_PER_PAGE(0) |
FMI_DATA_SIZE__BYTES_PER_SECTOR(512) |
FMI_DATA_SIZE__SECTORS_PER_PAGE(1)));
// Fewer stuck bits are allowed
h2fmi_wr(fmi, ECC_CON1, (ECC_CON1__ERROR_ALERT_LEVEL(0) |
ECC_CON1__INT_ENABLE(0) |
ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(2)));
#endif
}
void h2fmi_set_page_format(h2fmi_t* fmi)
{
h2fmi_wr(fmi, FMI_CONFIG, fmi->fmi_config_reg);
# if FMI_VERSION > 0
h2fmi_wr(fmi, FMI_DATA_SIZE, fmi->fmi_data_size_reg);
#endif
}
typedef struct
{
UInt32 eccBytesPerSector;
UInt32 eccCorrectableBits;
} h2fmi_spare_layout;
#if FMI_VERSION > 0
// H2A, H3P
static const h2fmi_spare_layout _h2fmi_spare_layout [] =
{
{ 53, 30 },
{ 51, 29 },
{ 44, 25 },
{ 28, 16 },
{ 27, 15 },
{ 0, 0 }
};
#else
// H2P
static const h2fmi_spare_layout _h2fmi_spare_layout [] =
{
{ 26, 16 },
{ 13, 8 },
{ 0, 0 }
};
#endif
UInt32 h2fmi_calculate_ecc_bits(h2fmi_t* fmi)
{
UInt32 eccMode = 0;
const h2fmi_spare_layout* layout = _h2fmi_spare_layout;
const UInt32 bytesForEccPerSector = ((fmi->bytes_per_spare - fmi->valid_bytes_per_meta) /
(fmi->bytes_per_page / H2FMI_BYTES_PER_SECTOR));
for( ; layout->eccBytesPerSector != 0; layout++ )
{
if( layout->eccBytesPerSector <= bytesForEccPerSector )
{
eccMode = layout->eccCorrectableBits;
break;
}
}
WMR_ASSERT(eccMode != 0);
return eccMode;
}
UInt32 h2fmi_calculate_ecc_output_bytes(h2fmi_t* fmi)
{
const h2fmi_spare_layout* layout = _h2fmi_spare_layout;
const UInt32 bytesForEccPerSector = ((fmi->bytes_per_spare - fmi->valid_bytes_per_meta) /
(fmi->bytes_per_page / H2FMI_BYTES_PER_SECTOR));
for( ; layout->eccBytesPerSector != 0; layout++ )
{
if( layout->eccBytesPerSector <= bytesForEccPerSector )
{
return layout->eccBytesPerSector;
}
}
return 0;
}
UInt32 h2fmi_calculate_fmi_config(h2fmi_t* fmi)
{
UInt32 ret;
#if FMI_VERSION == 0
UInt32 eccMode;
eccMode = (fmi->correctable_bits == 16) ? FMI_CONFIG__ECC_MODE__16BIT :
FMI_CONFIG__ECC_MODE__8BIT;
ret = (FMI_CONFIG__LBA_MODE__NORMAL |
FMI_CONFIG__META_PER_ENVELOPE(fmi->valid_bytes_per_meta) |
FMI_CONFIG__META_PER_PAGE(fmi->valid_bytes_per_meta) |
h2fmi_config_sectors_to_page_size(fmi) |
FMI_CONFIG__DMA_BURST__8_CYCLES |
eccMode);
#else
ret = (FMI_CONFIG__ECC_CORRECTABLE_BITS( fmi->correctable_bits ) |
FMI_CONFIG__DMA_BURST__32_CYCLES);
#endif
return ret;
}
#if FMI_VERSION > 0
UInt32 h2fmi_calculate_fmi_data_size(h2fmi_t* fmi)
{
UInt32 ret;
ret = (FMI_DATA_SIZE__META_BYTES_PER_SECTOR( fmi->valid_bytes_per_meta ) |
FMI_DATA_SIZE__META_BYTES_PER_PAGE( fmi->valid_bytes_per_meta ) |
FMI_DATA_SIZE__BYTES_PER_SECTOR( H2FMI_BYTES_PER_SECTOR ) |
FMI_DATA_SIZE__SECTORS_PER_PAGE( fmi->sectors_per_page ));
return ret;
}
#endif
// =============================================================================
// isr-only static implementation function definitions
// =============================================================================
#if (H2FMI_WAIT_USING_ISR)
static void h2fmi_init_isr(h2fmi_t* fmi)
{
WMR_PRINT(IRQ, "initializing interrupts for FMI%d\n",
h2fmi_bus_index(fmi));
// lookup fmi interrupt vector to use based upon fmi block
UInt32 vector = h2fmi_select_by_bus(fmi, INT_FMI0, INT_FMI1);
// init isr event and condition
event_init(&fmi->isr_event, EVENT_FLAG_AUTO_UNSIGNAL, false);
fmi->isr_condition = 0;
#if FMISS_ENABLED
fmi->isr_handler = NULL;
#endif // FMISS_ENABLED
// clear out any preexisting interrupts and mask sources
h2fmi_clear_interrupts_and_reset_masks(fmi);
// install interrupt handler
set_int_type(vector, INT_TYPE_IRQ | INT_TYPE_LEVEL);
install_int_handler(vector, h2fmi_isr_handler, (void*)fmi);
unmask_int(vector);
}
static void h2fmi_default_isr_handler(h2fmi_t* fmi)
{
// capture condition triggering isr
fmi->isr_condition = h2fmi_rd(fmi, FMI_INT_PEND);
// clear all interrupts and mask sources
h2fmi_clear_interrupts_and_reset_masks(fmi);
// signal isr event
event_signal(&fmi->isr_event);
}
typedef void (*h2fmi_dispatch_handler)(h2fmi_t* fmi);
static const h2fmi_dispatch_handler h2fmi_isr_dispatchTable[] = {
h2fmi_default_isr_handler, // fmiNone
h2fmi_handle_read_ISR_state_machine, // fmiRead
h2fmi_handle_write_ISR_state_machine // fmiWrite
};
static void h2fmi_isr_handler(void* arg)
{
h2fmi_t* fmi = (h2fmi_t*)arg;
#if FMISS_ENABLED
if (NULL != fmi->isr_handler)
{
fmi->isr_handler(fmi);
}
else
#endif // FMISS_ENABLED
{
WMR_ASSERT( fmi->stateMachine.currentMode <= fmiWrite );
h2fmi_isr_dispatchTable[ fmi->stateMachine.currentMode ]( fmi );
}
}
#endif
void h2fmi_clear_interrupts_and_reset_masks(h2fmi_t* fmi)
{
// mask further interrupts
h2fmi_wr(fmi, FMC_INTMASK, 0x0);
h2fmi_wr(fmi, FMI_INT_EN, 0x0);
// clear interrupt source flags
h2fmi_wr(fmi, FMC_STATUS, (FMC_STATUS__EMERGENCY2 |
FMC_STATUS__EMERGENCY01 |
FMC_STATUS__RDATADIRTY |
FMC_STATUS__RBBDONE7 |
FMC_STATUS__RBBDONE6 |
FMC_STATUS__RBBDONE5 |
FMC_STATUS__RBBDONE4 |
FMC_STATUS__RBBDONE3 |
FMC_STATUS__RBBDONE2 |
FMC_STATUS__RBBDONE1 |
FMC_STATUS__RBBDONE0 |
FMC_STATUS__TIMEOUT |
FMC_STATUS__NSERR |
FMC_STATUS__NSRBBDONE |
FMC_STATUS__TRANSDONE |
FMC_STATUS__ADDRESSDONE |
FMC_STATUS__CMD3DONE |
FMC_STATUS__CMD2DONE |
FMC_STATUS__CMD1DONE));
h2fmi_wr(fmi, FMI_INT_PEND, (FMI_INT_PEND__META_FIFO_OVERFLOW |
FMI_INT_PEND__META_FIFO_UNDERFLOW |
FMI_INT_PEND__LAST_FMC_DONE |
FMI_INT_PEND__TRANSACTION_COMPLETE));
}
/**
* Maps the absolute CE to the required register bit # and
* provides which bus number that CE is on.
*
* Note that CE's are absolute on our system -- CE0 is ALWAYS
* from FMC0, regardless of which bus we are dealing with. CE8
* is ALWAYS bit zero of FMC1 as well.
*
* @param ce - desired absolute CE #
* @param p_wTargetBus pointer to store translated bus number.
* @param p_targetCE - pointer to store translated CE bit.
*/
static inline void h2fmi_calc_bus_ce(h2fmi_ce_t ce,
UInt32* p_wTargetBus,
h2fmi_ce_t* p_targetCE)
{
*p_wTargetBus = ( ce >> H2FMI_MAX_CE_PER_BUS_POW2 );
*p_targetCE = ( ce & (H2FMI_MAX_CE_PER_BUS - 1) );
}
/**
* Enable the specified CE while ensuring that only one CE is
* enabled at a time on the given bus.
*
* @param fmi - context
* @param ce - Absolute CE #
*/
void h2fmi_fmc_enable_ce(h2fmi_t* fmi, h2fmi_ce_t ce)
{
h2fmi_ce_t targetCE;
UInt32 wTargetBus;
h2fmi_calc_bus_ce(ce, &wTargetBus, &targetCE);
if(wTargetBus == fmi->bus_id)
{
h2fmi_wr(fmi, FMC_CE_CTRL, FMC_CE_CTRL__CEB(targetCE));
}
else
{
h2fmi_fmc_disable_all_ces(fmi);
}
}
/**
* Disable ONLY the specified CE (using read/modify/write).
*
* @param ce - Absolute CE #
*/
void h2fmi_fmc_disable_ce(h2fmi_t* fmi, h2fmi_ce_t ce)
{
h2fmi_ce_t targetCE;
UInt32 wTargetBus;
h2fmi_calc_bus_ce(ce, &wTargetBus, &targetCE);
if(wTargetBus == fmi->bus_id)
{
UInt32 val = h2fmi_rd(fmi, FMC_CE_CTRL);
h2fmi_wr(fmi, FMC_CE_CTRL, val & ~FMC_CE_CTRL__CEB(targetCE));
}
}
void h2fmi_fmc_disable_all_ces(h2fmi_t* fmi)
{
h2fmi_wr(fmi, FMC_CE_CTRL, 0);
}
void h2fmi_prepare_for_ready_busy_interrupt(h2fmi_t* fmi)
{
h2fmi_prepare_wait_status(fmi,
NAND_STATUS__DATA_CACHE_RB,
NAND_STATUS__DATA_CACHE_RB_READY);
// use NSRBBDone interrupt source to wait for I/O ready state
h2fmi_wr(fmi, FMC_INTMASK, FMC_INTMASK__NSRBBDONE);
h2fmi_wr(fmi, FMI_INT_EN, FMI_INT_EN__FMC_NSRBBDONE);
}
void h2fmi_set_page_format_and_ECC_level(h2fmi_t* fmi, UInt32 wErrorAlertLevel)
{
// configure FMI with page format
h2fmi_set_page_format(fmi);
#if FMI_VERSION == 0
h2fmi_wr(fmi, ECC_CON1, (ECC_CON1__ERROR_ALERT_LEVEL(wErrorAlertLevel) |
ECC_CON1__INT_ENABLE(0)));
#elif FMI_VERSION <= 2
h2fmi_wr(fmi, ECC_CON1, (ECC_CON1__ERROR_ALERT_LEVEL(wErrorAlertLevel) |
ECC_CON1__INT_ENABLE(0) |
ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(fmi->correctable_bits)));
#else
h2fmi_wr(fmi, ECC_CON1, (ECC_CON1__ERROR_ALERT_LEVEL(wErrorAlertLevel) |
ECC_CON1__INT_ENABLE(0) |
ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(fmi->correctable_bits) |
ECC_CON1__IMPLICIT_WRITE_MARK));
#endif
}
/**
* Checks the current state of the (previously selected) CE,
* looking to see if it is ready or busy. Uses the
* stateMachine's "waitStartTick" and "wPageTimeoutTicks" to
* determine if the wait has timed out. Note that both of these
* fields must be initialized before calling this function.
*
* @param fmi
*
* @return CE_STATE
*/
CE_STATE h2fmi_get_current_CE_state( h2fmi_t* fmi )
{
CE_STATE ceState = CE_BUSY;
if (!(h2fmi_rd(fmi, FMI_INT_PEND) & FMI_INT_PEND__FMC_NSRBBDONE))
{
BOOL32 fTimeout = WMR_HAS_TIME_ELAPSED_TICKS( fmi->stateMachine.waitStartTicks, fmi->stateMachine.wPageTimeoutTicks );
if ( fTimeout )
{
ceState = CE_TIMEOUT;
}
}
else
{
ceState = CE_IDLE;
}
return ceState ;
}
#if ( H2FMI_INSTRUMENT_BUS_1 )
/**
* Sets the specified CE on FMI1.
*
* @param iBit - CE, zero is the first.
*/
void h2fmi_instrument_bit_set(int iBit)
{
iBit &= 0x03;
volatile UInt32* wFMCValue = ( 0 == (iBit & 0x02) ? FMI0 : FMI1 );
iBit = ( 0 == (iBit & 0x01) ? 2 : 3 );
UInt32 wCurrentValue = h2fmc_rd(wFMCValue, FMC_CE_CTRL);
wCurrentValue &= ~( 1 << iBit );
h2fmc_wr(wFMCValue, FMC_CE_CTRL, wCurrentValue );
}
/**
* Clears the specified CE on FMI1.
*
* @param iBit - CE, zero is the first.
*/
void h2fmi_instrument_bit_clear(int iBit)
{
iBit &= 0x03;
volatile UInt32* wFMCValue = ( 0 == (iBit & 0x02) ? FMI0 : FMI1 );
iBit = ( 0 == (iBit & 0x01) ? 2 : 3 );
UInt32 wCurrentValue = h2fmc_rd(wFMCValue, FMC_CE_CTRL);
wCurrentValue |= ( 1 << iBit );
h2fmc_wr(wFMCValue, FMC_CE_CTRL, wCurrentValue );
}
#endif
static void h2fmi_rx_prep(h2fmi_t* fmi)
{
h2fmi_set_page_format_and_ECC_level(fmi, 15);
}
static void h2fmi_tx_prep(h2fmi_t* fmi)
{
// undocumented silicon "feature": on write, program error alert
// level greater than bit correction capability to avoid spurious
// ECC error
// regardless, I was advised to disable interrupt to FMI from ECC
h2fmi_set_page_format_and_ECC_level(fmi, fmi->correctable_bits + 1);
// clean up any ECC block state before starting transfer
h2fmi_clean_ecc(fmi);
#if (H2FMI_WAIT_USING_ISR)
// enable appropriate interrupt source
h2fmi_wr(fmi, FMI_INT_EN, FMI_INT_EN__LAST_FMC_DONE);
#endif
}
BOOL32 h2fmi_common_idle_handler( h2fmi_t* fmi )
{
/**
* Called initially from client in non-interrupt context to let
* us set everything up and start the process.
*/
BOOL32 bSuccessful = TRUE32;
fmi->failureDetails.wNumCE_Executed = 0;
fmi->failureDetails.wOverallOperationFailure = 0;
fmi->failureDetails.wFirstFailingCE = ~0;
fmi->stateMachine.wPageTimeoutTicks = H2FMI_PAGE_TIMEOUT_MICROS * WMR_GET_TICKS_PER_US();
fmi->stateMachine.wQuarterPageTimeoutTicks = fmi->stateMachine.wPageTimeoutTicks / 4;
if ( fmiRead == fmi->stateMachine.currentMode)
{
h2fmi_rx_prep(fmi);
}
else
{
h2fmi_tx_prep(fmi);
}
return bSuccessful;
}
BOOL32 h2fmi_start_dma( h2fmi_t* fmi )
{
BOOL32 bSuccessful = TRUE32;
bSuccessful = h2fmi_dma_execute_async(
( fmiRead == fmi->stateMachine.currentMode ? DMA_CMD_DIR_RX : DMA_CMD_DIR_TX ),
h2fmi_dma_data_chan(fmi),
fmi->stateMachine.data_segment_array,
h2fmi_dma_data_fifo(fmi),
fmi->bytes_per_page * fmi->stateMachine.page_count,
sizeof(UInt32),
8,
fmi->current_aes_cxt);
if (bSuccessful)
{
// use CDMA to feed meta buffer to FMI
bSuccessful = h2fmi_dma_execute_async(
( fmiRead == fmi->stateMachine.currentMode ? DMA_CMD_DIR_RX : DMA_CMD_DIR_TX ),
h2fmi_dma_meta_chan(fmi),
fmi->stateMachine.meta_segment_array,
h2fmi_dma_meta_fifo(fmi),
fmi->valid_bytes_per_meta * fmi->stateMachine.page_count,
sizeof(UInt8),
1,
NULL);
}
return bSuccessful;
}
#define LFSR32(seed) ((seed) & 1) ? ((seed) >> 1) ^ 0x80000061 : ((seed) >> 1)
void h2fmi_aes_iv(void* arg, UInt32 chunk_index, void* iv_buffer)
{
const h2fmi_t* fmi = (h2fmi_t*)arg;
if (fmi->current_aes_iv_array)
{
const UInt8* chunk_iv = fmi->current_aes_iv_array[chunk_index].aes_iv_bytes;
WMR_MEMCPY(iv_buffer, chunk_iv, 16);
WMR_PRINT(CRYPTO, "IV: 0x%08x 0x%08x 0x%08x 0x%08x\n",
((UInt32*)chunk_iv)[0],
((UInt32*)chunk_iv)[1],
((UInt32*)chunk_iv)[2],
((UInt32*)chunk_iv)[3]);
}
else
{
const UInt32 pPage = fmi->iv_seed_array[chunk_index];
UInt32* iv = (UInt32*)iv_buffer;
WMR_PRINT(CRYPTO, "Whitening chunk %d\n", chunk_index);
iv[0] = LFSR32(pPage);
iv[1] = LFSR32(iv[0]);
iv[2] = LFSR32(iv[1]);
iv[3] = LFSR32(iv[2]);
}
}
void h2fmi_set_if_ctrl(h2fmi_t* fmi, UInt32 if_ctrl)
{
#if FMI_VERSION == 4
// there are currently limitations on timings that can be used in H4G,
// some of which can be over come by disabling streaming (<rdar://problem/9033500>)
#if SUPPORT_TOGGLE_NAND
if (fmi->is_toggle)
{
const UInt32 reb_setup = FMC_IF_CTRL__GET_REB_SETUP(if_ctrl);
fmi->read_stream_disable = (3 < reb_setup) ? TRUE32 : FALSE32;
}
else
#endif // SUPPORT_TOGGLE_NAND
{
fmi->read_stream_disable = TRUE32;
}
#endif // FMI_VERSION == 4
#if FMI_VERSION >= 5
#if SUPPORT_TOGGLE_NAND
if (fmi->is_toggle)
{
fmi->read_tx_page_delay = 0;
}
else
#endif // SUPPORT_TOGGLE_NAND
{
const UInt32 dccycle = FMC_IF_CTRL__GET_DCCYCLE(if_ctrl);
const UInt32 reb_hold = FMC_IF_CTRL__GET_REB_HOLD(if_ctrl);
// <rdar://problem/10987609> Timeout during flash data transfer in SDR mode with slow timings
fmi->read_tx_page_delay = (reb_hold > (dccycle + 4) ? reb_hold - (dccycle + 4) : 0);
}
#endif // FMI_VERSION >= 5
h2fmi_wr(fmi, FMC_IF_CTRL, if_ctrl);
}
void restoreTimingRegs(h2fmi_t* fmi)
{
#if SUPPORT_TOGGLE_NAND
if (fmi->is_toggle)
{
h2fmi_wr(fmi, FMC_DQS_TIMING_CTRL, fmi->dqs_ctrl);
h2fmi_wr(fmi, FMC_TOGGLE_CTRL_1, fmi->timing_ctrl_1);
h2fmi_wr(fmi, FMC_TOGGLE_CTRL_2, fmi->timing_ctrl_2);
h2fmi_set_if_ctrl(fmi, fmi->toggle_if_ctrl);
}
else
{
#endif
h2fmi_set_if_ctrl(fmi, fmi->if_ctrl);
#if SUPPORT_TOGGLE_NAND
}
#endif
}
// ********************************** EOF **************************************
File diff suppressed because it is too large. Load diff
+512
View File
@@ -0,0 +1,512 @@
// *****************************************************************************
//
// File: H2fmi_ppn.h
//
// Copyright (C) 2009 Apple Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#ifndef _H2FMI_PPN_H_
#define _H2FMI_PPN_H_
#include "H2fmi_private.h"
#include "H2fmi_timing.h"
#include "PPN_FIL.h"
#if defined(APPLICATION_IBOOT)
#include "nandid.h"
#elif WMR_BUILDING_EFI
#include "NandSpec.h"
#endif
#define H2FMI_PPN_VERIFY_SET_FEATURES (0)
#define PPN_MAX_FEATURE_COUNT (32)
#define NAND_CMD__MULTIPAGE_READ ((UInt8)0x07)
#define NAND_CMD__MULTIPAGE_READ_LAST ((UInt8)0x0A)
#define NAND_CMD__MULTIPAGE_READ_CONFIRM ((UInt8)0x37)
#define NAND_CMD__MULTIPAGE_PROGRAM ((UInt8)0x87)
#define NAND_CMD__MULTIPAGE_PROGRAM_LAST ((UInt8)0x8A)
#define NAND_CMD__MULTIPAGE_PROGRAM_CONFIRM ((UInt8)0x17)
#define NAND_CMD__MULTIPAGE_PREP ((UInt8)0xB0)
#define NAND_CMD__MULTIPAGE_PREP__CONFIRM ((UInt8)0xB8)
#define NAND_CMD__MULTIBLOCK_ERASE ((UInt8)0x67)
#define NAND_CMD__MULTIBLOCK_ERASE_LAST ((UInt8)0x6A)
#define NAND_CMD__MULTIBLOCK_ERASE_CONFIRM ((UInt8)0xD7)
#define NAND_CMD__LOW_POWER_READ_STATUS ((UInt8)0x70)
#define NAND_CMD__GET_NEXT_OPERATION_STATUS ((UInt8)0x77)
#define NAND_CMD__OPERATION_STATUS ((UInt8)0x7D)
#define NAND_CMD__READ_SERIAL_OUTPUT ((UInt8)0x7A)
#define NAND_CMD__CONTROLLER_STATUS ((UInt8)0x79)
#define NAND_CMD__READ_DEVICE_PARAMETERS ((UInt8)0x92)
#define NAND_CMD__READ_DEVICE_PARAMETERS_CONFIRM ((UInt8)0x97)
#define NAND_CMD__SET_FEATURES ((UInt8)0xEF)
#define NAND_CMD__GET_FEATURES ((UInt8)0xEE)
#define NAND_CMD__SET_GET_FEATURES_CONFIRM ((UInt8)0xE7)
#define NAND_CMD__SET_DEBUG_DATA ((UInt8)0xE9)
#define NAND_CMD__GET_DEBUG_DATA ((UInt8)0xE8)
#define NAND_CMD__UPDATE_FW ((UInt8)0xED)
#define NAND_CMD__PPN_STATUS_CONFIRM ((UInt8)0xED)
#define NAND_CMD__RESET ((UInt8)0xFF)
#define PPN_FEATURE__POWER_STATE ((UInt16)0x0180)
#define PPN_FEATURE__SCRATCH_PAD ((UInt16)0x0380)
#define PPN_FEATURE__ALLOW_SAVING_DEBUG_DATA ((UInt16)0x0480)
#define PPN_FEATURE__IDLE_COUNTER ((UInt16)0x0580)
#define PPN_FEATURE__FW_UPDATE ((UInt16)0x1080)
#define PPN_FEATURE__FWA_UPDATE ((UInt16)0x1180)
#define PPN_FEATURE__DRIVE_STRENGTH ((UInt16)0x2080)
#define PPN_FEATURE__DEVICE_TIMING ((UInt16)0x2180)
#define PPN_FEATURE__PROGRAM_FAILED_PAGES ((UInt16)0x3080)
#define PPN_FEATURE__PROGRAM_RETIRED_PAGES ((UInt16)0x3180)
#define PPN_FEATURE__PROGRAM_IGNORED_PAGES ((UInt16)0x3280)
#define PPN_FEATURE__CLEAR_PROGRAM_ERROR_LISTS ((UInt16)0x3380)
#define PPN_FEATURE__DQS_COMPLEMENT_ENABLE ((UInt16)0x4080)
#define PPN_FEATURE__RE_COMPLEMENT_ENABLE ((UInt16)0x4180)
#define PPN_FEATURE__VREF_ENABLE ((UInt16)0x4280)
#define PPN_FEATURE__NUM_DIE_PROGRAM_PARALLEL ((UInt16)0x5080)
#define PPN_FEATURE__NUM_DIE_READ_PARALLEL ((UInt16)0x5180)
#define PPN_FEATURE__NUM_DIE_ERASE_PARALLEL ((UInt16)0x5280)
#define PPN_FEATURE__PHYSICAL_PAGE_SIZE ((UInt16)0x8080)
#define PPN_FEATURE__ECC_CHUNK_SIZE ((UInt16)0x8180)
#define PPN_FEATURE__ECC_CODE_SIZE ((UInt16)0x8280)
#define PPN_FEATURE__FW_VERSION ((UInt16)0x9080)
#define PPN_FEATURE__PACKAGE_ASSEMBLY_CODE ((UInt16)0xA080)
#define PPN_FEATURE__CONTROLLER_UNIQUE_ID ((UInt16)0xA180)
#define PPN_FEATURE__CONTROLLER_HW_ID ((UInt16)0xA181)
#define PPN_FEATURE__NAND_DIE_UNIQUE_ID ((UInt16)0x0082)
#define PPN_FEATURE__NAND_DIE_CHIP_ID ((UInt16)0x0083)
#define PPN_FEATURE__BAD_BLOCK_BITMAP_ARRAY ((UInt16)0x0084)
#define PPN_FEATURE__NAND_MARKETING_NAME ((UInt16)0x0085)
#define PPN_FEATURE__ENABLE_BITFLIPS_DATA_COLLECTION ((UInt16)0x0090)
#define PPN_FEATURE__ENABLE_HEALTH_MONITORING ((UInt16)0x1090)
#define PPN_FEATURE__GET_HEALTH_MONTIORING_GRADES ((UInt16)0x1190)
#define PPN_FEATURE__GET_DEVICE_TEMPERATURE ((UInt16)0x2090)
#define PPN_FEATURE__SET_DEBUG_DATA_GENERIC_CONFIG ((UInt16)0x00A0)
#define PPN_FEATURE__SET_DEBUG_DATA_VENDOR_SPECIFIC ((UInt16)0x01A0)
#define PPN_FEATURE__DELETE_DEBUG_DATA ((UInt16)0x08A0)
// another copy lives in iop_fmi_protocol.h (changes should be made to both places)
#define PPN_FEATURE__POWER_STATE__LOW_POWER (0x1)
#define PPN_FEATURE__POWER_STATE__ASYNC (0x2)
#define PPN_FEATURE__POWER_STATE__STANDBY (0x4)
#define PPN_FEATURE__POWER_STATE__DDR (0xA)
// Power State transition unique identifiers and accessors
// another copy lives in iop_fmi_protocol.h (changes should be made to both places)
#define PPN_PS_TRANS_LOW_POWER_TO_ASYNC PS_TRANS_SET(PPN_FEATURE__POWER_STATE__LOW_POWER, PPN_FEATURE__POWER_STATE__ASYNC)
#define PPN_PS_TRANS_STDBY_TO_ASYNC PS_TRANS_SET(PPN_FEATURE__POWER_STATE__STDBY, PPN_FEATURE__POWER_STATE__ASYNC)
#define PPN_PS_TRANS_ASYNC_TO_LOW_POWER PS_TRANS_SET(PPN_FEATURE__POWER_STATE__ASYNC, PPN_FEATURE__POWER_STATE__LOW_POWER)
#define PPN_PS_TRANS_DDR_TO_LOW_POWER PS_TRANS_SET(PPN_FEATURE__POWER_STATE__DDR, PPN_FEATURE__POWER_STATE__LOW_POWER)
#define PPN_PS_TRANS_ASYNC_TO_STDBY PS_TRANS_SET(PPN_FEATURE__POWER_STATE__ASYNC, PPN_FEATURE__POWER_STATE__STDBY)
#define PPN_PS_TRANS_DDR_TO_STDBY PS_TRANS_SET(PPN_FEATURE__POWER_STATE__DDR, PPN_FEATURE__POWER_STATE__STDBY)
#define PPN_PS_TRANS_LOW_POWER_TO_DDR PS_TRANS_SET(PPN_FEATURE__POWER_STATE__LOW_POWER, PPN_FEATURE__POWER_STATE__DDR)
#define PPN_PS_TRANS_STDBY_TO_DDR PS_TRANS_SET(PPN_FEATURE__POWER_STATE__STDBY, PPN_FEATURE__POWER_STATE__DDR)
#define PS_TRANS_SET(from, to) ((((UInt32)(from)) << 16) | ((UInt32)(to)))
#define PS_TRANS_GET_FROM(ps) ((ps) >> 16)
#define PS_TRANS_GET_TO(ps) ((ps) & 0xFFFF)
#define PPN_FEATURE_LENGTH_ENABLE_BITFLIPS_DATA_COLLECTION 4
#define PPN_FEATURE_LENGTH_DIE_CHIP_ID 8
#define PPN_FEATURE_LENGTH_TEMPERATURE 2
#define PPN_FEATURE_LENGTH_DEFAULT 4
#define PPN_FEATURE__ALLOW_SAVING_DEBUG_DATA_ENABLE (1)
#define PPN_FEATURE__ALLOW_SAVING_DEBUG_DATA_DISABLE (0)
#define PPN_FEATURE__DEBUG_DATA_CONFIGURATION_GEB (1 << 0)
#define PPN_FEATURE__DEBUG_DATA_CONFIGURATION_READ (1 << 1)
#define PPN_FEATURE__DEBUG_DATA_CONFIGURATION_PROGRAM (1 << 2)
#define PPN_FEATURE__DEBUG_DATA_CONFIGURATION_ERASE (1 << 3)
#define PPN_OPERATION_STATUS__ERROR (1 << 0)
#define PPN_OPERATION_STATUS__REFRESH (1 << 1)
#define PPN_OPERATION_STATUS__RETIRE (1 << 2)
#define PPN_OPERATION_STATUS__CLEAN (1 << 3)
#define PPN_OPERATION_STATUS__GENERAL_ERROR (1 << 4)
#define PPN_OPERATION_STATUS__READY (1 << 6)
#define PPN_FEAT_OPERATION_STATUS__ERROR (1 << 0)
#define PPN_FEAT_OPERATION_STATUS__FW_UPDATE_ERROR (1 << 1)
#define PPN_FEAT_OPERATION_STATUS__NOT_SUPPORTED (1 << 2)
#define PPN_FEAT_OPERATION_STATUS__NOT_SUPPORTED_BY_CH (1 << 3)
#define PPN_FEAT_OPERATION_STATUS__GENERAL_ERROR (1 << 4)
#define PPN_FEAT_OPERATION_STATUS__READY (1 << 6)
#define PPN_FEAT_OPERATION_STATUS__SUCCESS (PPN_FEAT_OPERATION_STATUS__READY)
#define PPN_FEAT_OPERATION_STATUS__FAILURE (PPN_FEAT_OPERATION_STATUS__READY | PPN_FEAT_OPERATION_STATUS__ERROR)
#define PPN_FEAT_OPERATION_STATUS__FW_UPDATE_FAILURE (PPN_FEAT_OPERATION_STATUS__READY | PPN_FEAT_OPERATION_STATUS__FW_UPDATE_ERROR | PPN_FEAT_OPERATION_STATUS__ERROR)
#define PPN_FEAT_OPERATION_STATUS__UNSUPPORTED (PPN_FEAT_OPERATION_STATUS__READY | PPN_FEAT_OPERATION_STATUS__ERROR | PPN_FEAT_OPERATION_STATUS__NOT_SUPPORTED)
#define PPN_FEAT_OPERATION_STATUS__UNSUPPORTED_BY_CH (PPN_FEAT_OPERATION_STATUS__READY | PPN_FEAT_OPERATION_STATUS__ERROR | PPN_FEAT_OPERATION_STATUS__NOT_SUPPORTED_BY_CH)
#define PPN_FEAT_OPERATION_STATUS__SUCCESS_WITH_GEB (PPN_FEAT_OPERATION_STATUS__READY | PPN_FEAT_OPERATION_STATUS__GENERAL_ERROR)
#define PPN_FEAT_OPERATION_STATUS__FAILURE_WITH_GEB (PPN_FEAT_OPERATION_STATUS__READY | PPN_FEAT_OPERATION_STATUS__ERROR | PPN_FEAT_OPERATION_STATUS__GENERAL_ERROR)
#define PPN_CONTROLLER_STATUS__PENDING_ERRORS (1 << 0)
#define PPN_CONTROLLER_STATUS__READY_FOR_OPERATIONS (1 << 1)
#define PPN_CONTROLLER_STATUS__OPERATION_STATUS_AVAILABLE (1 << 2)
#define PPN_CONTROLLER_STATUS__GENERAL_ERROR (1 << 4)
#define PPN_CONTROLLER_STATUS__QUEUE_EMPTY (1 << 5)
#define PPN_CONTROLLER_STATUS__READY (1 << 6)
#define PPN_LOW_POWER_STATUS__FAIL (1 << 0)
#define PPN_LOW_POWER_STATUS__READY (1 << 6)
#define PPN_LOW_POWER_STATUS__WRITE_PROTECT_BAR (1 << 7)
#define PPN_GET_DEBUG_DATA__GET_FAILURE_TYPE 0xFFFFFFul
#define PPN_tGDD_1_5_US (20*1000)
#define PPN_tGDD_1_0_US (10*1000)
#define PPN_SET_DEBUG_DATA__FORCE_ADDRESS (0xF0FFFF)
#define PPN_SET_DEBUG_DATA__EMB_SWEEP_ADDRESS (0x540000)
#define PPN_GEB_TYPE__EMB_SWEEP_GEB_TYPE (0x07C0)
#define PPN_DELETE_DEBUG_DATA__ENABLE (1)
#define PPN_ERROR_LIST_SIZE (512)
#define PPN_DEVICE_ID_LEN (6)
#define PPN_NAND_MARKETING_NAME_LENGTH (10)
#define PPN_PERFECT_PAGE_SIZE (4112)
#define PPN_PERFECT_FMI_SECTORS_PER_PERFECT_PAGE ((UInt32)(PPN_PERFECT_PAGE_SIZE / H2FMI_BYTES_PER_SECTOR)) // rounds down
#define PPN_PERFECT_FMI_SECTOR_SIZE (PPN_PERFECT_PAGE_SIZE / PPN_PERFECT_FMI_SECTORS_PER_PERFECT_PAGE)
#define PPN_TIMING_MIN_TRHW_NS (100)
#define PPN_TIMING_MIN_TWHR_NS (60)
#define PPN_FW_START_SIGNATURE (0x72617453)
#define PPN_FW_END_SIGNATURE (0x00646E45)
#define PPN_1_5_ROW_ADDR_BYTES (4)
#define PPN_1_5_FAILURE_INFO_EXPCT_LEN (14)
#define PPN_1_0_FAILURE_INFO_EXPCT_LEN (12)
typedef enum
{
ppnFwTypeFw,
ppnFwTypeFwa
} h2fmi_ppn_fw_type;
//update PPN_1_0_FAILURE_INFO_EXPCT_LEN if this struct is updated
typedef struct _h2fmi_ppn_failure_info_ppn1_0_t
{
UInt16 type;
UInt8 startPage[3];
UInt8 pageCount[3];
UInt8 checksum;
UInt8 reserved1;
UInt8 reserved2;
UInt8 reserved3;
} h2fmi_ppn_failure_info_ppn1_0_t;
//update PPN_1_5_FAILURE_INFO_EXPCT_LEN if this struct is updated
typedef struct _h2fmi_ppn_failure_info_ppn1_5_t
{
UInt16 type;
UInt8 startPage[4];
UInt8 pageCount[3];
UInt8 checksum;
UInt8 reserved1;
UInt8 reserved2;
UInt8 reserved3;
} h2fmi_ppn_failure_info_ppn1_5_t;
typedef union _h2fmi_ppn_failure_info_t
{
h2fmi_ppn_failure_info_ppn1_5_t failure_info_1_5;
h2fmi_ppn_failure_info_ppn1_0_t failure_info_1_0;
} h2fmi_ppn_failure_info_t;
#define FAIL_INFO_GET_START_PAGE(bytesPerRowAddr, failInfo) (((bytesPerRowAddr) == PPN_1_5_ROW_ADDR_BYTES) ? \
(((failInfo).failure_info_1_5.startPage[0]) | \
((failInfo).failure_info_1_5.startPage[1] << 8) | \
((failInfo).failure_info_1_5.startPage[2] << 16) | \
((failInfo).failure_info_1_5.startPage[3] << 24)) : \
(((failInfo).failure_info_1_0.startPage[0]) |\
((failInfo).failure_info_1_0.startPage[1] << 8) |\
((failInfo).failure_info_1_0.startPage[2] << 16)))
#define FAIL_INFO_GET_PAGE_COUNT(bytesPerRowAddr, failInfo) (((bytesPerRowAddr) == PPN_1_5_ROW_ADDR_BYTES) ? \
(((failInfo).failure_info_1_5.pageCount[0]) | \
((failInfo).failure_info_1_5.pageCount[1] << 8) | \
((failInfo).failure_info_1_5.pageCount[2] << 16)) : \
(((failInfo).failure_info_1_0.pageCount[0]) | \
((failInfo).failure_info_1_0.pageCount[1] << 8) | \
((failInfo).failure_info_1_0.pageCount[2] << 16)))
#define FAIL_INFO_GET_TYPE(bytesPerRowAddr, failInfo) (((bytesPerRowAddr) == PPN_1_5_ROW_ADDR_BYTES) ? \
((failInfo).failure_info_1_5.type) : \
((failInfo).failure_info_1_0.type))
typedef enum
{
powerStateOff,
powerStateReadyForReset,
powerStateLowPower,
powerStateNormal,
powerStateStandby
} PPN_POWER_STATE;
typedef struct _h2fmi_ppn_device_params_t
{
char header[16];
UInt32 caus_per_channel;
UInt32 cau_bits;
UInt32 blocks_per_cau;
UInt32 block_bits;
UInt32 pages_per_block;
UInt32 pages_per_block_slc;
UInt32 page_address_bits;
UInt32 address_bits_bits_per_cell;
UInt32 default_bits_per_cell;
UInt32 page_size;
UInt32 dies_per_channel;
UInt32 block_pairing_scheme;
UInt32 bytes_per_row_address;
UInt8 reserved[92];
UInt8 tRC;
UInt8 tREA;
UInt8 tREH;
UInt8 tRHOH;
UInt8 tRHZ;
UInt8 tRLOH;
UInt8 tRP;
UInt8 reserved2;
UInt8 tWC;
UInt8 tWH;
UInt8 tWP;
UInt8 reserved3[53];
UInt32 read_queue_size;
UInt32 program_queue_size;
UInt32 erase_queue_size;
UInt32 prep_function_buffer_size;
UInt32 tRST_ms;
UInt32 tPURST_ms;
UInt32 tSCE_ms;
UInt32 tCERDY_us;
UInt8 reserved4[4];
UInt32 cau_per_channel2;
UInt32 dies_per_channel2;
UInt8 reserved5[4];
UInt8 ddr_tRC;
UInt8 ddr_tREH;
UInt8 ddr_tRP;
UInt8 reserved6;
UInt32 tDQSL_ps;
UInt32 tDQSH_ps;
UInt32 tDSC_ps;
UInt32 tDQSRE_ps;
UInt32 tDQSQ_ps;
UInt32 tDVW_ps;
UInt8 max_interface_speed;
UInt8 reserved7[211];
} h2fmi_ppn_device_params_t;
typedef struct _h2fmi_ppn_t
{
h2fmi_ppn_device_params_t device_params;
UInt32 spec_version;
#if !defined(APPLICATION_EMBEDDEDIOP)
NandGeometry geometry;
NandBoardSupport boardSupport;
NandPpn nandPpn;
#endif /* !APPLICATION_EMBEDDEDIOP */
UInt8 bytes_per_row_address;
UInt8 bytes_per_full_address;
BOOL32 general_error;
UInt32 general_error_ce;
UInt32 debug_flags;
BOOL32 debug_flags_valid;
UInt32 vs_debug_flags;
BOOL32 vs_debug_flags_valid;
UInt32 allow_saving_debug_data;
PageAddressType *prep_buffer[PPN_MAX_CES_PER_BUS];
#if FMI_ECC_DEBUG
UInt32 ecc_sectors_read;
#endif // FMI_ECC_DEBUG
} h2fmi_ppn_t;
typedef struct _ppn_feature_entry_t
{
UInt32 version;
UInt16 feature;
UInt32 value;
UInt32 bytes;
} ppn_feature_entry_t;
void h2fmiPpnPerformCommandList(PPNCommandStruct **commands, UInt32 num_commands);
Int32 h2fmiPpnReadNoEcc(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabDataBuf,
UInt8 *pabSpareBuf);
Int32 h2fmiPpnReadSequentialPages(UInt32 *padwPpn,
UInt8 *pabDataBuf,
UInt8 *pabMetaBuf,
UInt16 wNumOfPagesToRead,
UInt8 *pbMaxCorrectedBits,
UInt8 *pdwaSectorStats,
BOOL32 bDisableWhitening);
Int32 h2fmiPpnReadScatteredPages(UInt16 *pawCEs,
UInt32 *padwPpn,
UInt8 *pabDataBuf,
UInt8 *pabMetaBuf,
UInt16 wNumOfPagesToRead,
UInt8 *pbMaxCorrectedBits,
UInt8 *pdwaSectorStats,
BOOL32 bDisableWhitening);
Int32 h2fmiPpnReadSinglePage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8* pabDataBuf,
UInt8* pabMetaBuf,
UInt8* pbMaxCorrectedBits,
UInt8* pdwaSectorStats,
BOOL32 bDisableWhitening);
Int32 h2fmiPpnReadBootpage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabData);
Int32 h2fmiPpnReadSinglePageMaxECC(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabDataBuf);
Int32 h2fmiPpnEraseSingleBlock(UInt16 wVirtualCE,
UInt32 wPbn);
Int32 h2fmiPpnWriteScatteredPages(UInt16 *pawBanks,
UInt32 *padwPpn,
UInt8 *pabDataBuf,
UInt8 *pabMetaBuf,
UInt16 wNumOfPagesToWrite,
UInt16 *pawFailingCE,
BOOL32 bDisableWhitening,
UInt32 *pwFailingPageNum);
Int32 h2fmiPpnWriteSinglePage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabDataBuf,
UInt8 *pabMetaBuf,
BOOL32 disableWhitening);
Int32 h2fmiPpnWriteSinglePageMaxECC(UInt16 wBank,
UInt32 nPpn,
UInt8 *pdBuf);
Int32 h2fmiPpnWriteBootpage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabData);
Int32 h2fmiPpnReadCauBbt(UInt16 wCS, UInt32 wCAU, UInt8 *pData);
Int32 h2fmiPpnUpdateFw(UInt16 wVirtualCE,
UInt8 *fw,
UInt32 fw_length,
UInt8 *fwa,
UInt32 fwa_length);
Int32 h2fmiPpnGetFirmwareVersion(UInt16 virtualCE,
UInt8 *buffer);
BOOL32 h2fmiPpnValidateFirmwareVersions(UInt8 *buffer, UInt32 ce_count);
Int32 h2fmiPpnGetControllerHwId(UInt16 virtualCE, UInt8 *buffer);
Int32 h2fmiPpnGetManufacturerId(UInt16 virtualCE, UInt8 *buffer);
BOOL32 h2fmiPpnValidateManufacturerIds(UInt8 *expected, UInt32 ce_count);
Int32 h2fmiPpnGetControllerInfo(UInt16 virtualCE, UInt8 *mfg_id, UInt8 *fw_version);
Int32 h2fmiVthSweepSetup(UInt8 virCE, UInt32 blk, h2fmi_ppn_failure_info_t *failInfo, UInt32 *totalDataToRead);
Int32 h2fmiDmaDebugData(UInt8 virCE, UInt32 page, UInt32 pageCount, struct dma_segment *sgl, BOOL32 waitFortGDD);
void h2fmi_ppn_dma_debug_data_payload(h2fmi_t *fmi, h2fmi_ce_t ce, UInt32 page, UInt32 pageCount, struct dma_segment *sgl, BOOL32 waitFortGDD);
UInt32 h2fmi_ppn_get_general_error_info(h2fmi_t *fmi, h2fmi_ce_t ce, h2fmi_ppn_failure_info_t *buffer, UInt32 *dataLength, struct dma_segment *sgl);
Int32 h2fmi_ppn_configure_debug_data(h2fmi_t *fmi, h2fmi_ce_t ce);
#if SUPPORT_TOGGLE_NAND
BOOL32 h2fmi_ppn15_get_temperature(h2fmi_t *fmi, h2fmi_ce_t ce, Int16 *temperature);
BOOL32 h2fmi_ppn15_enable_optional_signals(h2fmi_t *fmi, h2fmi_ce_t ce);
#endif
Int32 h2fmi_ppn_write_bootpage(h2fmi_t *fmi,
UInt16 ce,
UInt32 dwPpn,
const UInt8 *pabData);
Int32 h2fmi_ppn_read_multi(h2fmi_t *fmi,
PPNCommandStruct *ppnCommand,
struct dma_segment *data_segment_array,
struct dma_segment *meta_segment_array);
Int32 h2fmi_ppn_write_multi(h2fmi_t *fmi,
PPNCommandStruct *ppnCommand,
struct dma_segment *data_segment_array,
struct dma_segment *meta_segment_array);
Int32 h2fmi_ppn_read_bootpage(h2fmi_t *fmi,
UInt16 ce,
UInt32 page,
UInt8 *data,
UInt8 *max_corrected);
Int32 h2fmi_ppn_erase_blocks(h2fmi_t *fmi, PPNCommandStruct *ppnCommand);
Int32 h2fmi_ppn_read_cau_bbt(h2fmi_t *fmi,
PPNCommandStruct *ppnCommand,
UInt8 *buffer);
Int32 h2fmi_ppn_fw_update(h2fmi_t *fmi, h2fmi_ce_t ce, struct dma_segment *sgl, UInt32 fw_size, h2fmi_ppn_fw_type fw_type);
BOOL32 h2fmi_ppn_get_fw_version(h2fmi_t *fmi, h2fmi_ce_t ce, UInt8 *buffer);
BOOL32 h2fmi_ppn_get_package_assembly_code(h2fmi_t *fmi, h2fmi_ce_t ce, UInt8 *buffer);
BOOL32 h2fmi_ppn_get_controller_unique_id(h2fmi_t *fmi, h2fmi_ce_t ce, UInt8 *buffer);
BOOL32 h2fmi_ppn_get_controller_hw_id(h2fmi_t *fmi, h2fmi_ce_t ce, UInt8 *buffer);
BOOL32 h2fmi_ppn_get_controller_status(h2fmi_t *fmi, UInt8 *controller_status);
BOOL32 h2fmi_ppn_get_manufacturer_id(h2fmi_t *fmi, h2fmi_ce_t ce, UInt8 *buffer);
BOOL32 h2fmi_ppn_get_die_chip_id(h2fmi_t *fmi, h2fmi_ce_t ce, UInt32 die, UInt8 *buffer);
BOOL32 h2fmi_ppn_get_marketing_name(h2fmi_t *fmi, h2fmi_ce_t ce, UInt8 *buffer);
BOOL32 h2fmi_ppn_set_debug_data(h2fmi_t *fmi, h2fmi_ce_t ce, UInt32 type, UInt8 *buffer, UInt32 len);
void h2fmi_ppn_poweron(h2fmi_t *fmi);
void h2fmi_ppn_poweroff(h2fmi_t *fmi);
void h2fmi_ppn_set_power_low_power(h2fmi_t *fmi);
void h2fmi_ppn_set_power_standby(h2fmi_t *fmi);
BOOL32 h2fmi_ppn_init_channel(h2fmi_t *fmi, BOOL32 debug_flags_valid, UInt32 debug_flags, BOOL32 vs_debug_flags_valid, UInt32 vs_debug_flags, BOOL32 allow_saving_debug_data, UInt32 spec_version);
BOOL32 h2fmi_ppn_set_channel_power_state(h2fmi_t *fmi, UInt32 ps_tran);
BOOL32 h2fmi_ppn_post_rst_pre_pwrstate_operations(h2fmi_t* fmi);
BOOL32 h2fmi_ppn_get_device_params(h2fmi_t *fmi, h2fmi_ce_t ce, h2fmi_ppn_device_params_t *params);
BOOL32 h2fmi_ppn_get_next_operation_status(h2fmi_t *fmi, UInt8 *operation_status);
UInt32 h2fmi_ppn_get_device_info(UInt32 dwParamType);
UInt32 h2fmi_ppn_calculate_fmi_config(h2fmi_t *fmi);
UInt32 h2fmi_ppn_calculate_fmi_data_size(h2fmi_t *fmi);
UInt8 h2fmi_ppn_get_idle_counter(h2fmi_t *fmi, h2fmi_ce_t ce);
void h2fmi_ppn_force_geb_address(h2fmi_t *fmi, h2fmi_ce_t ce, PageAddressType addr);
void h2fmi_ppn_set_feature_list(h2fmi_t *fmi, ppn_feature_entry_t *list, UInt32 size);
BOOL32 h2fmi_ppn_get_uid(h2fmi_t *fmi, UInt8 ce, UInt8 die, UInt8 *buf);
Int32 h2fmi_ppn_set_features(h2fmi_t *fmi, UInt32 ce, UInt16 feature, UInt8 *data, UInt32 len, BOOL32 optFeature, UInt8 *status);
BOOL32 h2fmi_ppn_get_feature(h2fmi_t *fmi, h2fmi_ce_t ce, UInt32 feature, UInt8 *buffer, UInt32 len, UInt8 *status);
void h2fmi_ppn_process_error_list(h2fmi_t *fmi, PPNCommandStruct *ppnCommand, UInt8 ceIndex, UInt32 *list, UInt8 status);
#if !defined(APPLICATION_EMBEDDEDIOP)
void h2fmi_ppn_fill_nandinfo(h2fmi_t *fmi, NandInfo *nandInfo, NandRequiredTimings *requiredTiming);
#endif /* !APPLICATIONS_EMBEDDEDIOP */
void fmiss_init_sequences(h2fmi_t *fmi);
Int32 fmiss_ppn_read_multi(h2fmi_t *fmi, PPNCommandStruct *ppnCommand, struct dma_segment *data_segment_array, struct dma_segment *meta_segment_array);
Int32 fmiss_ppn_write_multi(h2fmi_t *fmi, PPNCommandStruct *ppnCommand, struct dma_segment *data_segment_array, struct dma_segment *meta_segment_array);
#if H2FMI_PPN_VERIFY_SET_FEATURES
void h2fmi_ppn_verify_feature_shadow(h2fmi_t *fmi);
void h2fmi_ppn_reset_feature_shadow(h2fmi_t *fmi);
#endif // H2FMI_PPN_VERIFY_SET_FEATURES
#endif /* _H2FMI_PPN_H_ */
+997
View File
@@ -0,0 +1,997 @@
// *****************************************************************************
//
// File: H2fmi_ppn_fil.c
//
// Copyright (C) 2010 Apple Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 "WMROAM.h"
#include <FIL.h>
#include <FILTypes.h>
#include "H2fmi_private.h"
#include "H2fmi.h"
#include "H2fmi_ppn.h"
#if SUPPORT_PPN
extern UInt32 *g_pScratchBuf;
extern h2fmi_t g_fmi0;
extern h2fmi_t g_fmi1;
#if (defined(AND_COLLECT_FIL_STATISTICS) && AND_COLLECT_FIL_STATISTICS)
#define AND_FIL_STAT(x) (x)
extern FILStatistics stFILStatistics;
#else
#define AND_FIL_STAT(x)
#endif /* AND_COLLECT_FIL_STATISTICS */
void h2fmi_ppn_recover_nand(void);
static Int32 h2fmiPpnReadMulti(h2fmi_t *fmi, PPNCommandStruct *ppnCommand);
static Int32 h2fmiPpnReadMultiWithSingles(h2fmi_t *fmi, PPNCommandStruct *ppnCommand);
static PPNCommandStruct *topLevelSingle = NULL;
static PPNCommandStruct *lowLevelSingle = NULL;
static struct dma_segment *dataSegments = NULL;
static struct dma_segment *metaSegments = NULL;
#if (defined(AND_SUPPORT_BLOCK_STORAGE) && AND_SUPPORT_BLOCK_STORAGE)
static Int32 h2fmiPpnWriteMulti(h2fmi_t *fmi, PPNCommandStruct *ppnCommand);
#endif
BOOL32 h2fmi_ppn_fil_init(void)
{
if (NULL == lowLevelSingle)
{
lowLevelSingle = WMR_MALLOC(sizeof(*lowLevelSingle));
if (NULL == lowLevelSingle)
{
return FALSE32;
}
}
if (NULL == topLevelSingle)
{
topLevelSingle = WMR_MALLOC(sizeof(*topLevelSingle));
if (NULL == topLevelSingle)
{
return FALSE32;
}
}
if (NULL == dataSegments)
{
dataSegments = WMR_MALLOC(PPN_MAX_PAGES * sizeof(struct dma_segment));
if (NULL == dataSegments)
{
return FALSE32;
}
}
if (NULL == metaSegments)
{
metaSegments = WMR_MALLOC(PPN_MAX_PAGES * sizeof(struct dma_segment));
if (NULL == metaSegments)
{
return FALSE32;
}
}
return TRUE32;
}
void h2fmiPpnPerformCommandList(PPNCommandStruct **commands, UInt32 num_commands)
{
UInt32 i;
for (i = 0; i < num_commands; i++)
{
PPNCommandStruct *command = commands[i];
h2fmi_t *fmi = (command->context.bus_num == 1) ? &g_fmi1 : &g_fmi0;
Int32 status;
if (command->num_pages == 0)
{
continue;
}
switch(command->command)
{
case PPN_COMMAND_READ:
#if (defined(H2FMI_ALLOW_MULTIS) && H2FMI_ALLOW_MULTIS)
if (!(command->options & PPN_OPTIONS_REPORT_HEALTH))
{
status = h2fmiPpnReadMulti(fmi, command);
}
else
#endif
{
status = h2fmiPpnReadMultiWithSingles(fmi, command);
}
break;
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
#if (defined(AND_SUPPORT_BLOCK_STORAGE) && AND_SUPPORT_BLOCK_STORAGE)
case PPN_COMMAND_PROGRAM:
status = h2fmiPpnWriteMulti(fmi, command);
break;
#endif
case PPN_COMMAND_ERASE:
status = h2fmi_ppn_erase_blocks(fmi, command);
break;
#endif // !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
case PPN_COMMAND_CAUBBT:
status = h2fmi_ppn_read_cau_bbt(fmi, command, command->mem_buffers[0].data);
break;
default:
WMR_PANIC("Invalid PPN FIL command: %d", command->command);
break;
}
switch(status)
{
case _kIOPFMI_STATUS_PPN_GENERAL_ERROR:
WMR_PRINT(ERROR, "Command type 0x%08x failed due to PPN Controller General Error on bus %lu ce %lu\n",
command->command, fmi->bus_id, fmi->ppn->general_error_ce);
h2fmi_ppn_recover_nand();
break;
case _kIOPFMI_STATUS_READY_BUSY_TIMEOUT:
WMR_PRINT(ERROR, "Command type 0x%08x failed due to PPN controller status timeout on bus %lu\n",
command->command, fmi->bus_id);
h2fmi_ppn_recover_nand();
break;
}
}
}
Int32 h2fmiPpnReadMulti(h2fmi_t *fmi,
PPNCommandStruct *ppnCommand)
{
const UInt32 numPages = ppnCommand->num_pages;
UInt32 page;
Int32 ret;
UInt8 *metaBounceBuffer;
UInt8 *metaSrc;
WMR_ASSERT(metaSegments != NULL);
WMR_ASSERT(dataSegments != NULL);
WMR_MEMSET(dataSegments, 0, PPN_MAX_PAGES * sizeof(struct dma_segment));
WMR_MEMSET(metaSegments, 0, PPN_MAX_PAGES * sizeof(struct dma_segment));
metaBounceBuffer = (UInt8 *)g_pScratchBuf;
WMR_MEMSET(metaBounceBuffer, 0xAB, ppnCommand->lbas * fmi->valid_bytes_per_meta);
metaSegments[0].paddr = (UInt32)metaBounceBuffer;
metaSegments[0].length = ppnCommand->lbas * fmi->valid_bytes_per_meta;
WMR_PREPARE_READ_BUFFER(metaBounceBuffer, ppnCommand->lbas * fmi->valid_bytes_per_meta);
for (page = 0; page < numPages; page++)
{
const PPNCommandEntry *entry = &ppnCommand->entry[page];
const PPNMemoryIndex *memIndex = &ppnCommand->mem_index[page];
const PPNMemoryEntry *memoryEntry = &ppnCommand->mem_buffers[memIndex->idx];
UInt8 *dataPtr;
UInt32 dataLength;
dataPtr = (UInt8 *)memoryEntry->data + (memIndex->offset * fmi->logical_page_size);
dataLength = entry->lbas * fmi->logical_page_size;
WMR_PREPARE_READ_BUFFER(dataPtr, dataLength);
dataSegments[page].paddr = (UInt32)dataPtr;
dataSegments[page].length = dataLength;
}
#if FMISS_ENABLED
ret = fmiss_ppn_read_multi(fmi, ppnCommand, dataSegments, metaSegments);
#else
ret = h2fmi_ppn_read_multi(fmi, ppnCommand, dataSegments, metaSegments);
#endif
WMR_COMPLETE_READ_BUFFER(metaBounceBuffer, ppnCommand->lbas * fmi->valid_bytes_per_meta);
metaSrc = metaBounceBuffer;
for (page = 0; page < ppnCommand->num_pages; page++)
{
const PPNCommandEntry *entry = &ppnCommand->entry[page];
const PPNMemoryIndex *memIndex = &ppnCommand->mem_index[page];
const PPNMemoryEntry *memoryEntry = &ppnCommand->mem_buffers[memIndex->idx];
WMR_COMPLETE_READ_BUFFER((void *)dataSegments[page].paddr, dataSegments[page].length);
if (memoryEntry->meta)
{
UInt8 *metaDest;
metaDest = (UInt8 *)memoryEntry->meta + (memIndex->offset * fmi->total_bytes_per_meta);
WMR_MEMCPY(metaDest,
metaSrc,
entry->lbas * fmi->valid_bytes_per_meta);
metaSrc += entry->lbas * fmi->valid_bytes_per_meta;
}
}
return ret;
}
static Int32 h2fmiPpnReadMultiWithSingles(h2fmi_t *fmi,
PPNCommandStruct *ppnCommand)
{
UInt32 i;
UInt8 *metaBounceBuffer;
Int32 status = _kIOPFMI_STATUS_SUCCESS;
metaBounceBuffer = (UInt8 *)g_pScratchBuf;
ppnCommand->page_status_summary = 0;
for (i = 0; (i < ppnCommand->num_pages) && (status == _kIOPFMI_STATUS_SUCCESS); i++)
{
const PPNCommandEntry *entry = &ppnCommand->entry[i];
const PPNCommandCeInfo *ceInfo = &ppnCommand->ceInfo[entry->ceIdx];
const PPNMemoryIndex *memIndex = &ppnCommand->mem_index[i];
const PPNMemoryEntry *memEntry = &ppnCommand->mem_buffers[memIndex->idx];
struct dma_segment dataSegment;
struct dma_segment metaSegment;
UInt8 *dataPtr;
UInt8 *metaPtr = NULL;
WMR_MEMSET(lowLevelSingle, 0, sizeof(*lowLevelSingle));
lowLevelSingle->context = ppnCommand->context;
lowLevelSingle->command = PPN_COMMAND_READ;
lowLevelSingle->options = ppnCommand->options;
lowLevelSingle->entry[0].addr = entry->addr;
lowLevelSingle->entry[0].ceIdx = 0;
lowLevelSingle->entry[0].lbas = entry->lbas;
lowLevelSingle->ceInfo[0].pages = 1;
lowLevelSingle->ceInfo[0].ce = ceInfo->ce;
lowLevelSingle->mem_index[0] = *memIndex;
dataPtr = (UInt8 *)memEntry->data + (memIndex->offset * fmi->logical_page_size);
if (memEntry->meta)
{
metaPtr = (UInt8 *)memEntry->meta + (memIndex->offset * fmi->total_bytes_per_meta);
}
WMR_PREPARE_READ_BUFFER(dataPtr, entry->lbas * fmi->logical_page_size);
WMR_PREPARE_READ_BUFFER(metaBounceBuffer, entry->lbas * fmi->total_bytes_per_meta);
dataSegment.paddr = (UInt32)dataPtr;
dataSegment.length = entry->lbas * fmi->logical_page_size;
metaSegment.paddr = (UInt32)metaBounceBuffer;
metaSegment.length = entry->lbas * fmi->valid_bytes_per_meta;
lowLevelSingle->num_pages = 1;
lowLevelSingle->lbas = entry->lbas;
#if FMISS_ENABLED
status = fmiss_ppn_read_multi(fmi, lowLevelSingle, &dataSegment, &metaSegment);
#else
status = h2fmi_ppn_read_multi(fmi, lowLevelSingle, &dataSegment, &metaSegment);
#endif
WMR_COMPLETE_READ_BUFFER(metaBounceBuffer, entry->lbas * fmi->total_bytes_per_meta);
WMR_COMPLETE_READ_BUFFER(dataPtr, entry->lbas * fmi->logical_page_size);
if ( NULL != metaPtr )
{
WMR_MEMCPY(metaPtr, metaBounceBuffer, entry->lbas * fmi->total_bytes_per_meta);
}
ppnCommand->entry[i].status = lowLevelSingle->entry[0].status;
ppnCommand->page_status_summary |= lowLevelSingle->page_status_summary;
}
return status;
}
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
#if (defined(AND_SUPPORT_BLOCK_STORAGE) && AND_SUPPORT_BLOCK_STORAGE)
static Int32 h2fmiPpnWriteMulti(h2fmi_t *fmi,
PPNCommandStruct *ppnCommand)
{
UInt32 i;
UInt8 *metaBounceBuffer;
Int32 status;
status = _kIOPFMI_STATUS_SUCCESS;
metaBounceBuffer = (UInt8 *)g_pScratchBuf;
ppnCommand->page_status_summary = 0;
for (i = 0; (i < ppnCommand->num_pages) && (status == _kIOPFMI_STATUS_SUCCESS); i++)
{
const PPNCommandEntry *entry = &ppnCommand->entry[i];
const PPNCommandCeInfo *ceInfo = &ppnCommand->ceInfo[entry->ceIdx];
const PPNMemoryIndex *memIndex = &ppnCommand->mem_index[i];
const PPNMemoryEntry *memEntry = &ppnCommand->mem_buffers[memIndex->idx];
struct dma_segment dataSegment;
struct dma_segment metaSegment;
UInt8 *dataPtr;
UInt8 *metaPtr = NULL;
WMR_MEMSET(lowLevelSingle, 0, sizeof(*lowLevelSingle));
lowLevelSingle->context = ppnCommand->context;
lowLevelSingle->command = PPN_COMMAND_PROGRAM;
lowLevelSingle->options = ppnCommand->options;
lowLevelSingle->entry[0].addr = entry->addr;
lowLevelSingle->entry[0].ceIdx = 0;
lowLevelSingle->entry[0].lbas = entry->lbas;
lowLevelSingle->ceInfo[0].pages = 1;
lowLevelSingle->ceInfo[0].ce = ceInfo->ce;
lowLevelSingle->mem_index[0] = *memIndex;
dataPtr = (UInt8 *)memEntry->data + (memIndex->offset * fmi->logical_page_size);
if (memEntry->meta)
{
metaPtr = (UInt8 *)memEntry->meta + (memIndex->offset * fmi->total_bytes_per_meta);
WMR_MEMCPY(metaBounceBuffer, metaPtr, entry->lbas * fmi->total_bytes_per_meta);
}
else
{
WMR_MEMSET(metaBounceBuffer, 0xA5, entry->lbas * fmi->total_bytes_per_meta);
}
WMR_PREPARE_WRITE_BUFFER(dataPtr, entry->lbas * fmi->logical_page_size);
WMR_PREPARE_WRITE_BUFFER(metaBounceBuffer, entry->lbas * fmi->total_bytes_per_meta);
dataSegment.paddr = (UInt32)dataPtr;
dataSegment.length = entry->lbas * fmi->logical_page_size;
metaSegment.paddr = (UInt32)metaBounceBuffer;
metaSegment.length = entry->lbas * fmi->valid_bytes_per_meta;
lowLevelSingle->num_pages = 1;
lowLevelSingle->lbas = entry->lbas;
#if FMISS_ENABLED
status = fmiss_ppn_write_multi(fmi, lowLevelSingle, &dataSegment, &metaSegment);
#else
status = h2fmi_ppn_write_multi(fmi, lowLevelSingle, &dataSegment, &metaSegment);
#endif
ppnCommand->entry[i].status = lowLevelSingle->entry[0].status;
ppnCommand->page_status_summary |= lowLevelSingle->page_status_summary;
}
return status;
}
#endif
#endif // !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
Int32 h2fmiPpnReadSinglePage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8* pabDataBuf,
UInt8* pabMetaBuf,
UInt8* pbMaxCorrectedBits,
UInt8* pdwaSectorStats,
BOOL32 bDisableWhitening)
{
PPNCommandStruct *ppnCommand;
h2fmi_t *fmi = h2fmiTranslateVirtualCEToBus(wVirtualCE);
UInt16 ce = h2fmiTranslateVirtualCEToCe(wVirtualCE);
Int32 ret;
WMR_ASSERT(NULL != fmi);
ppnCommand = topLevelSingle;
WMR_MEMSET(ppnCommand, 0, sizeof(PPNCommandStruct));
if (pbMaxCorrectedBits)
{
*pbMaxCorrectedBits = 0;
}
ppnCommand->context.device_info = NULL;
ppnCommand->context.handle = NULL;
ppnCommand->context.bus_num = fmi->bus_id;
ppnCommand->command = PPN_COMMAND_READ;
ppnCommand->options = 0;
ppnCommand->entry[0].ceIdx = 0;
ppnCommand->entry[0].addr.length = fmi->bytes_per_page + fmi->total_bytes_per_meta;
ppnCommand->entry[0].addr.column = 0;
ppnCommand->entry[0].addr.row = dwPpn;
ppnCommand->ceInfo[0].pages = 1;
ppnCommand->ceInfo[0].ce = ce;
ppnCommand->mem_index[0].offset = 0;
ppnCommand->mem_index[0].idx = 0;
ppnCommand->entry[0].lbas = fmi->bytes_per_page / fmi->logical_page_size;
ppnCommand->mem_buffers[0].data = pabDataBuf;
ppnCommand->mem_buffers[0].meta = pabMetaBuf;
ppnCommand->mem_buffers[0].num_of_lbas = 1;
ppnCommand->num_pages = 1;
ppnCommand->lbas = fmi->bytes_per_page / fmi->logical_page_size;
if(pdwaSectorStats != NULL)
{
ppnCommand->options = PPN_OPTIONS_REPORT_HEALTH;
}
h2fmiPpnPerformCommandList(&ppnCommand, 1);
if(pdwaSectorStats != NULL)
{
WMR_MEMCPY(pdwaSectorStats, pabDataBuf, fmi->sectors_per_page);
}
switch (ppnCommand->page_status_summary)
{
case 0x40:
ret = FIL_SUCCESS;
break;
case 0x42:
ret = FIL_SUCCESS;
WMR_PRINT(ERROR, "Single Page PPN Read saw refresh - read status: 0x%02X, CE: %d, Page: 0x%08X\n",
ppnCommand->page_status_summary, wVirtualCE, dwPpn);
break;
case 0x44:
case 0x43:
case 0x45:
ret = FIL_U_ECC_ERROR;
break;
case 0x49:
ret = FIL_SUCCESS_CLEAN;
break;
default:
WMR_PRINT(ALWAYS, "Single Page PPN Read failed - overall NAND status 0x%02x\n",
ppnCommand->page_status_summary);
ret = FIL_CRITICAL_ERROR;
break;
}
return ret;
}
Int32 h2fmiPpnReadBootpage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabData)
{
Int32 nRet = FIL_SUCCESS;
UInt32 status;
h2fmi_t* fmi = h2fmiTranslateVirtualCEToBus(wVirtualCE);
h2fmi_ce_t ce = h2fmiTranslateVirtualCEToCe(wVirtualCE);
WMR_ASSERT(NULL != fmi);
WMR_ASSERT(WMR_CHECK_BUFFER(pabData, H2FMI_BOOT_BYTES_PER_PAGE));
WMR_PREPARE_READ_BUFFER(pabData, H2FMI_BOOT_BYTES_PER_PAGE);
status = h2fmi_ppn_read_bootpage(fmi, ce, dwPpn, pabData, NULL);
switch (status)
{
case _kIOPFMI_STATUS_BLANK:
WMR_PRINT(READ, "[FIL:LOG] Clean Page\n");
AND_FIL_STAT(stFILStatistics.ddwReadCleanCnt++);
nRet = FIL_SUCCESS_CLEAN;
break;
case _kIOPFMI_STATUS_SUCCESS:
WMR_PRINT(READ, "[FIL:LOG] Good page\n");
nRet = FIL_SUCCESS;
break;
case _kIOPFMI_STATUS_AT_LEAST_ONE_UECC:
WMR_PRINT(ERROR, "UECC ce: %d p:0x%08x\n", (UInt32) wVirtualCE, dwPpn);
AND_FIL_STAT(stFILStatistics.ddwReadECCErrorCnt++);
nRet = FIL_U_ECC_ERROR;
break;
case _kIOPFMI_STATUS_PPN_GENERAL_ERROR:
WMR_PRINT(ERROR, "GEB ce: %d p:0x%08x\n", (UInt32) wVirtualCE, dwPpn);
nRet = FIL_CRITICAL_ERROR;
h2fmi_ppn_recover_nand();
break;
default:
WMR_PRINT(ERROR, "Error status: 0x%08x ce: %d p:0x%08x\n", status, (UInt32) wVirtualCE, dwPpn);
AND_FIL_STAT(stFILStatistics.ddwReadHWErrorCnt++);
nRet = FIL_CRITICAL_ERROR;
h2fmi_ppn_recover_nand();
break;
}
AND_FIL_STAT(stFILStatistics.ddwPagesReadCnt++);
WMR_COMPLETE_READ_BUFFER(pabData, H2FMI_BOOT_BYTES_PER_PAGE);
return nRet;
}
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM || !H2FMI_READONLY
Int32 h2fmiPpnWriteSinglePage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabDataBuf,
UInt8 *pabMetaBuf,
BOOL32 disableWhitening)
{
PPNCommandStruct *ppnCommand;
Int32 result;
h2fmi_t *fmi = h2fmiTranslateVirtualCEToBus(wVirtualCE);
UInt16 ce = h2fmiTranslateVirtualCEToCe(wVirtualCE);
WMR_ASSERT(NULL != fmi);
ppnCommand = topLevelSingle;
WMR_ASSERT(ppnCommand != NULL);
WMR_MEMSET(ppnCommand, 0, sizeof(PPNCommandStruct));
ppnCommand->context.device_info = NULL;
ppnCommand->context.handle = NULL;
ppnCommand->context.bus_num = fmi->bus_id;
ppnCommand->command = PPN_COMMAND_PROGRAM;
ppnCommand->options = 0;
ppnCommand->entry[0].ceIdx = 0;
ppnCommand->entry[0].addr.row = dwPpn;
ppnCommand->ceInfo[0].pages = 1;
ppnCommand->ceInfo[0].ce = ce;
ppnCommand->mem_index[0].offset = 0;
ppnCommand->mem_index[0].idx = 0;
ppnCommand->entry[0].lbas = (fmi->sectors_per_page * H2FMI_BYTES_PER_SECTOR) / fmi->logical_page_size;
ppnCommand->mem_buffers[0].data = pabDataBuf;
ppnCommand->mem_buffers[0].meta = pabMetaBuf;
ppnCommand->mem_buffers[0].num_of_lbas = 1;
ppnCommand->num_pages = 1;
h2fmiPpnPerformCommandList(&ppnCommand, 1);
if (ppnCommand->page_status_summary & PPN_CONTROLLER_STATUS__PENDING_ERRORS)
{
result = FIL_WRITE_FAIL_ERROR;
}
else if (ppnCommand->page_status_summary & PPN_CONTROLLER_STATUS__GENERAL_ERROR)
{
result = FIL_CRITICAL_ERROR;
}
else
{
result = FIL_SUCCESS;
}
return result;
}
#endif // !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM || !H2FMI_READONLY
Int32 h2fmiPpnWriteBootpage(UInt16 wVirtualCE,
UInt32 dwPpn,
UInt8 *pabData)
{
Int32 nRet;
UInt32 status;
h2fmi_t* fmi = h2fmiTranslateVirtualCEToBus(wVirtualCE);
h2fmi_ce_t ce = h2fmiTranslateVirtualCEToCe(wVirtualCE);
WMR_ASSERT(NULL != fmi);
WMR_ASSERT(WMR_CHECK_BUFFER(pabData, H2FMI_BOOT_BYTES_PER_PAGE));
WMR_PREPARE_READ_BUFFER(pabData, H2FMI_BOOT_BYTES_PER_PAGE);
status = h2fmi_ppn_write_bootpage(fmi, ce, dwPpn, pabData);
switch (status)
{
case _kIOPFMI_STATUS_PGM_ERROR:
WMR_PRINT(ERROR, "[FIL:LOG] Error programming boot page\n");
AND_FIL_STAT(stFILStatistics.ddwWriteNANDErrCnt++);
nRet = FIL_WRITE_FAIL_ERROR;
break;
case _kIOPFMI_STATUS_SUCCESS:
WMR_PRINT(READ, "[FIL:LOG] Wrote Good Boot page\n");
nRet = FIL_SUCCESS;
break;
case _kIOPFMI_STATUS_PPN_GENERAL_ERROR:
WMR_PRINT(ERROR, "[FIL:ERR] General Error writing bootpage\n");
nRet = FIL_CRITICAL_ERROR;
h2fmi_ppn_recover_nand();
break;
default:
WMR_PRINT(ERROR, "[FIL:ERR] Hardware error: 0x%08x\n", status);
AND_FIL_STAT(stFILStatistics.ddwWriteHWErrCnt++);
nRet = FIL_CRITICAL_ERROR;
h2fmi_ppn_recover_nand();
break;
}
AND_FIL_STAT(stFILStatistics.ddwPagesWrittenCnt++);
WMR_COMPLETE_READ_BUFFER(pabData, H2FMI_BOOT_BYTES_PER_PAGE);
return nRet;
}
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
Int32 h2fmiPpnEraseSingleBlock(UInt16 wVirtualCE,
UInt32 wPbn)
{
PPNCommandStruct *ppnCommand;
h2fmi_t* fmi = h2fmiTranslateVirtualCEToBus(wVirtualCE);
UInt16 ce = h2fmiTranslateVirtualCEToCe(wVirtualCE);
UInt32 wPpn = (wPbn << fmi->ppn->device_params.page_address_bits);
Int32 ret;
WMR_ASSERT(NULL != fmi);
ppnCommand = topLevelSingle;
WMR_ASSERT(ppnCommand != NULL);
WMR_MEMSET(ppnCommand, 0, sizeof(PPNCommandStruct));
ppnCommand->context.device_info = NULL;
ppnCommand->context.handle = NULL;
ppnCommand->context.bus_num = fmi->bus_id;
ppnCommand->command = PPN_COMMAND_ERASE;
ppnCommand->options = 0;
ppnCommand->entry[0].ceIdx = 0;
ppnCommand->entry[0].addr.row = wPpn;
ppnCommand->ceInfo[0].pages = 1;
ppnCommand->ceInfo[0].ce = ce;
ppnCommand->num_pages = 1;
h2fmiPpnPerformCommandList(&ppnCommand, 1);
switch(ppnCommand->page_status_summary)
{
case 0x40:
ret = FIL_SUCCESS;
break;
case 0x45:
ret = FIL_WRITE_FAIL_ERROR;
break;
default:
ret = FIL_CRITICAL_ERROR;
break;
}
return ret;
}
#endif // !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
Int32 h2fmiPpnGetFirmwareVersion(UInt16 virtualCe, UInt8 *buffer)
{
h2fmi_t *fmi;
h2fmi_ce_t ce;
BOOL32 ret = FALSE32;
fmi = h2fmiTranslateVirtualCEToBus(virtualCe);
ce = h2fmiTranslateVirtualCEToCe(virtualCe);
if (NULL != fmi)
{
ret = h2fmi_ppn_get_fw_version(fmi, ce, buffer);
}
return (ret ? FIL_SUCCESS : FIL_CRITICAL_ERROR);
}
BOOL32 h2fmiPpnValidateFirmwareVersions(UInt8 *expected, UInt32 ce_count)
{
UInt8 buffer[NAND_DEV_PARAM_LEN_PPN];
UInt32 virtualCe;
Int32 ret;
BOOL32 mismatch = FALSE32;
for(virtualCe = 0; virtualCe < ce_count; virtualCe++)
{
ret = h2fmiPpnGetFirmwareVersion(virtualCe, buffer);
if (ret == FIL_SUCCESS)
{
if (WMR_MEMCMP(buffer, expected, NAND_DEV_PARAM_LEN_PPN) != 0)
{
WMR_PRINT(ERROR, "Bank %d reports incorrect PPN firmware version: expected \"%16s\", got \"%16s\"\n",
virtualCe, expected, buffer);
mismatch = TRUE32;
}
}
else
{
WMR_PRINT(ERROR, "Failed to retrieve PPN firmware version from bank %d\n", virtualCe);
mismatch = TRUE32;
}
}
return mismatch ? FALSE32 : TRUE32;
}
Int32 h2fmiPpnGetControllerHwId(UInt16 virtualCe, UInt8 *buffer)
{
h2fmi_t *fmi;
h2fmi_ce_t ce;
BOOL32 ret = FALSE32;
fmi = h2fmiTranslateVirtualCEToBus(virtualCe);
ce = h2fmiTranslateVirtualCEToCe(virtualCe);
if (fmi)
{
ret = h2fmi_ppn_get_controller_hw_id(fmi, ce, buffer);
}
return (ret ? FIL_SUCCESS : FIL_CRITICAL_ERROR);
}
Int32 h2fmiPpnGetManufacturerId(UInt16 virtualCe, UInt8 *buffer)
{
h2fmi_t *fmi;
h2fmi_ce_t ce;
BOOL32 ret = FALSE32;
fmi = h2fmiTranslateVirtualCEToBus(virtualCe);
ce = h2fmiTranslateVirtualCEToCe(virtualCe);
if (fmi)
{
ret = h2fmi_ppn_get_manufacturer_id(fmi, ce, buffer);
}
return (ret ? FIL_SUCCESS : FIL_CRITICAL_ERROR);
}
BOOL32 h2fmiPpnValidateManufacturerIds(UInt8 *expected, UInt32 ce_count)
{
UInt8 buffer[NAND_DEV_PARAM_LEN_PPN];
UInt32 virtualCe;
Int32 ret;
BOOL32 mismatch = FALSE32;
for(virtualCe = 0; virtualCe < ce_count; virtualCe++)
{
ret = h2fmiPpnGetManufacturerId(virtualCe, buffer);
if (ret == FIL_SUCCESS)
{
if (WMR_MEMCMP(buffer, expected, PPN_DEVICE_ID_LEN) != 0)
{
WMR_PRINT(ERROR, "Bank %d reports incorrect PPN manufacturer id: expected %02X %02X %02X %02X %02X %02X, got %02X %02X %02X %02X %02X %02X\n",
virtualCe,
expected[0], expected[1], expected[2], expected[3], expected[4], expected[5],
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
mismatch = TRUE32;
}
}
else
{
WMR_PRINT(ERROR, "Failed to retrieve PPN manufacturer id from bank %d\n", virtualCe);
mismatch = TRUE32;
}
}
return mismatch ? FALSE32 : TRUE32;
}
Int32 h2fmiPpnGetControllerInfo(UInt16 virtualCe, UInt8 *mfg_id, UInt8 *fw_version)
{
Int32 ret = FIL_SUCCESS;
if (FIL_SUCCESS == h2fmiPpnGetManufacturerId(0, mfg_id))
{
WMR_PRINT(INIT, "PPN Manufacturer ID: %02X %02X %02X %02X %02X %02X\n",
mfg_id[0], mfg_id[1], mfg_id[2], mfg_id[3], mfg_id[4], mfg_id[5]);
}
else
{
WMR_PRINT(ERROR, "Retrieving PPN Manufacturer ID failed!\n");
ret = FIL_CRITICAL_ERROR;
}
if (FIL_SUCCESS == h2fmiPpnGetFirmwareVersion(0, fw_version))
{
WMR_PRINT(INIT, "PPN Controller Version: %16.16s\n", fw_version);
}
else
{
WMR_PRINT(ERROR, "Retrieving PPN Controller Version failed!\n");
ret = FIL_CRITICAL_ERROR;
}
return ret;
}
#define MAX_ATTEMPTS (3)
Int32 h2fmiPpnUpdateFw(UInt16 wVirtualCE, UInt8 *fw, UInt32 fw_length, UInt8 *fwa, UInt32 fwa_length)
{
h2fmi_t *fmi;
h2fmi_ce_t ce;
struct dma_segment sgl;
int i;
Int32 status;
Int32 ret_val = FIL_CRITICAL_ERROR;
fmi = h2fmiTranslateVirtualCEToBus(wVirtualCE);
ce = h2fmiTranslateVirtualCEToCe(wVirtualCE);
if (NULL == fmi)
{
return FIL_UNSUPPORTED_ERROR;
}
for( i = 0; (i < MAX_ATTEMPTS) && (ret_val != FIL_SUCCESS); i++)
{
if (NULL != fw)
{
WMR_PRINT(ALWAYS, "Updating fw on fmi %d, ce %d\n", fmi->bus_id, ce);
sgl.paddr = (UInt32)fw;
sgl.length = fw_length;
status = h2fmi_ppn_fw_update(fmi, ce, &sgl, fw_length, ppnFwTypeFw);
if (status == FIL_SUCCESS)
{
ret_val = FIL_SUCCESS;
}
else if (status == FIL_UNSUPPORTED_ERROR)
{
return status;
}
else
{
ret_val = status;
WMR_PRINT(ERROR, "Firmware Update Failed: attempt %d/%d\n", i+1, MAX_ATTEMPTS);
continue;
}
}
if (NULL != fwa)
{
WMR_PRINT(ALWAYS, "Updating fw args on fmi %d, ce %d\n", fmi->bus_id, ce);
sgl.paddr = (UInt32)fwa;
sgl.length = fwa_length;
status = h2fmi_ppn_fw_update(fmi, ce, &sgl, fwa_length, ppnFwTypeFwa);
if (status == FIL_SUCCESS)
{
ret_val = FIL_SUCCESS;
}
else if (status == FIL_UNSUPPORTED_ERROR)
{
return status;
}
else
{
ret_val = status;
WMR_PRINT(ERROR, "Firmware Arguments Update Failed: attempt %d/%d\n", i+1, MAX_ATTEMPTS);
continue;
}
}
}
return ret_val;
}
void h2fmi_ppn_recover_nand(void)
{
h2fmi_nand_reset_all(&g_fmi0);
if(g_fmi1.num_of_ce)
{
h2fmi_nand_reset_all(&g_fmi1);
}
#if SUPPORT_TOGGLE_NAND
if (g_fmi0.is_toggle_system)
{
g_fmi0.is_toggle = FALSE32;
h2fmi_reset(&g_fmi0);
if (g_fmi1.num_of_ce)
{
WMR_ASSERT(g_fmi1.is_toggle_system);
g_fmi1.is_toggle = FALSE32;
h2fmi_reset(&g_fmi1);
}
}
#endif
h2fmi_ppn_post_rst_pre_pwrstate_operations(&g_fmi0);
if (g_fmi1.num_of_ce)
{
h2fmi_ppn_post_rst_pre_pwrstate_operations(&g_fmi1);
}
h2fmi_ppn_set_channel_power_state(&g_fmi0,
#if SUPPORT_TOGGLE_NAND
(g_fmi0.is_toggle_system) ? PPN_PS_TRANS_LOW_POWER_TO_DDR :
#endif
PPN_PS_TRANS_LOW_POWER_TO_ASYNC);
if (g_fmi1.num_of_ce)
{
h2fmi_ppn_set_channel_power_state(&g_fmi1,
#if SUPPORT_TOGGLE_NAND
(g_fmi1.is_toggle_system) ? PPN_PS_TRANS_LOW_POWER_TO_DDR :
#endif
PPN_PS_TRANS_LOW_POWER_TO_ASYNC);
}
#if SUPPORT_TOGGLE_NAND
if (g_fmi0.is_toggle_system)
{
g_fmi0.is_toggle = TRUE32;
h2fmi_reset(&g_fmi0);
if(g_fmi1.num_of_ce)
{
WMR_ASSERT(g_fmi1.is_toggle_system);
g_fmi1.is_toggle = TRUE32;
h2fmi_reset(&g_fmi1);
}
}
#endif
g_fmi0.ppn->general_error = FALSE32;
g_fmi1.ppn->general_error = FALSE32;
#if H2FMI_PPN_VERIFY_SET_FEATURES
if(g_fmi0.num_of_ce)
{
h2fmi_ppn_verify_feature_shadow(&g_fmi0);
}
if(g_fmi1.num_of_ce)
{
h2fmi_ppn_verify_feature_shadow(&g_fmi1);
}
#endif // H2FMI_PPN_VERIFY_SET_FEATURES
}
Int32 h2fmiDmaDebugData(UInt8 virCE, UInt32 page, UInt32 pageCount, struct dma_segment *sgl, BOOL32 waitFortGDD)
{
h2fmi_t *fmi;
h2fmi_ce_t ce;
WMR_ASSERT(sgl != NULL);
fmi = h2fmiTranslateVirtualCEToBus(virCE);
ce = h2fmiTranslateVirtualCEToCe(virCE);
if (!fmi)
{
return FIL_UNSUPPORTED_ERROR;
}
h2fmi_ppn_dma_debug_data_payload(fmi, ce, page, pageCount, sgl, waitFortGDD);
return FIL_SUCCESS;
}
Int32 h2fmiVthSweepSetup(UInt8 virCE, UInt32 blk, h2fmi_ppn_failure_info_t *failInfo, UInt32 *totalDataToRead)
{
h2fmi_t *fmi;
h2fmi_ce_t ce;
UInt32 rowAddr;
LowFuncTbl *fil = FIL_GetFuncTbl();
const UInt32 block_shift = fil->GetDeviceInfo(AND_DEVINFO_BITS_PER_PAGE_ADDRESS);
if (!failInfo || !totalDataToRead)
{
return FIL_CRITICAL_ERROR;
}
fmi = h2fmiTranslateVirtualCEToBus(virCE);
ce = h2fmiTranslateVirtualCEToCe(virCE);
if (!fmi)
{
return FIL_UNSUPPORTED_ERROR;
}
rowAddr = blk << block_shift;
h2fmi_ppn_set_debug_data(fmi, ce, PPN_SET_DEBUG_DATA__EMB_SWEEP_ADDRESS, (UInt8*)&rowAddr, sizeof(rowAddr));
if (!fmi->ppn->general_error)
{
WMR_PRINT(ERROR, "No GEB during Vth Setup!\n");
return FIL_CRITICAL_ERROR;
}
if (h2fmi_ppn_get_general_error_info(fmi, ce, failInfo, totalDataToRead, NULL))
{
return FIL_SUCCESS;
}
else
{
return FIL_CRITICAL_ERROR;
}
}
#endif //SUPPORT_PPN
+603
View File
@@ -0,0 +1,603 @@
#include "H2fmi_iop.h"
#include "H2fmi_private.h"
#include "H2fmi_ppn.h"
#include <platform/memmap.h>
#include <platform.h>
#include <drivers/dma.h>
#include <drivers/aes.h>
#include <debug.h>
#include "PPN_FIL.h"
#if SUPPORT_PPN
void h2fmi_ppn_iop_reset_everything(h2fmi_t* fmi, IOPFMI_ResetEverything* cmd)
{
h2fmi_restoreFmiRegs(fmi);
h2fmi_iop_reset_everything(fmi, cmd);
fmi->ppn->general_error = FALSE32;
}
void h2fmi_ppn_iop_erase_multiple(h2fmi_t *fmi, IOPFMI_IOPpn* cmd)
{
PPNCommandStruct *ppnCommand;
ppnCommand = (PPNCommandStruct *)mem_static_map_cached(cmd->ppn_fil_command);
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
WMR_ASSERT(ppnCommand != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(ppnCommand, cmd->ppn_fil_size);
h2fmi_ppn_erase_blocks(fmi, ppnCommand);
WMR_PREPARE_WRITE_BUFFER(ppnCommand, cmd->ppn_fil_size);
cmd->geb_ce = fmi->ppn->general_error_ce;
//WMR_PRINT(ALWAYS, "Erase Multiple: status 0x%02x\n", ppnCommand->page_status_summary);
}
static PPNCommandStruct singlePpnCommands[kIOPFMI_MAX_NUM_OF_CHANNELS];
void h2fmi_ppn_iop_erase_single(h2fmi_t *fmi, IOPFMI_EraseSingle* cmd)
{
PPNCommandStruct *ppnCommand;
const UInt32 pageAddr = cmd->block_number << fmi->ppn->device_params.page_address_bits;
Int32 status;
// We shouldn't use this command going forward - it's a legacy command supported
// for boot-from-NAND code only.
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
ppnCommand = &singlePpnCommands[fmi->bus_id];
WMR_MEMSET(ppnCommand, 0, sizeof(PPNCommandStruct));
ppnCommand->context.device_info = NULL;
ppnCommand->context.handle = NULL;
ppnCommand->context.bus_num = fmi->bus_id;
ppnCommand->command = PPN_COMMAND_ERASE;
ppnCommand->options = 0;
ppnCommand->entry[0].ceIdx = 0;
ppnCommand->entry[0].addr.row = pageAddr;
ppnCommand->mem_index[0].offset = 0;
ppnCommand->mem_index[0].idx = 0;
ppnCommand->entry[0].lbas = 0;
ppnCommand->ceInfo[0].pages = 1;
ppnCommand->ceInfo[0].ce = cmd->ce;
ppnCommand->num_pages = 1;
status = h2fmi_ppn_erase_blocks(fmi, ppnCommand);
if (status != kIOPFMI_STATUS_SUCCESS)
{
cmd->iopfmi.status = status;
}
else if (ppnCommand->page_status_summary == 0x40)
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_ERASE_ERROR;
}
}
void h2fmi_ppn_iop_read_single(h2fmi_t *fmi, IOPFMI_IOSingle* cmd)
{
PPNCommandStruct *ppnCommand;
const UInt32 pageAddr = cmd->page_number;
UInt8 *dataBuf = (UInt8 *)mem_static_map_physical(cmd->data_address);
UInt8 *metaBuf = (UInt8 *)mem_static_map_physical(cmd->meta_address);
struct dma_segment dataSegment;
struct dma_segment metaSegment;
WMR_ASSERT(dataBuf != MAP_FAILED);
WMR_ASSERT(metaBuf != MAP_FAILED);
// We shouldn't use this command going forward - it's a legacy command supported
// for boot-from-NAND code only.
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
fmi->current_aes_cxt = NULL;
ppnCommand = &singlePpnCommands[fmi->bus_id];
WMR_MEMSET(ppnCommand, 0, sizeof(PPNCommandStruct));
ppnCommand->context.device_info = NULL;
ppnCommand->context.handle = NULL;
ppnCommand->context.bus_num = fmi->bus_id;
ppnCommand->command = PPN_COMMAND_READ;
ppnCommand->options = 0;
ppnCommand->entry[0].ceIdx = 0;
ppnCommand->entry[0].addr.length = fmi->bytes_per_page + fmi->valid_bytes_per_meta;
ppnCommand->entry[0].addr.column = 0;
ppnCommand->entry[0].addr.row = pageAddr;
ppnCommand->mem_index[0].offset = 0;
ppnCommand->mem_index[0].idx = 0;
ppnCommand->entry[0].lbas = fmi->bytes_per_page / fmi->logical_page_size;
ppnCommand->ceInfo[0].pages = 1;
ppnCommand->ceInfo[0].ce = cmd->ce;
ppnCommand->num_pages = 1;
ppnCommand->lbas = fmi->bytes_per_page / fmi->logical_page_size;
dataSegment.paddr = (UInt32)dataBuf;
dataSegment.length = fmi->bytes_per_page;
metaSegment.paddr = (UInt32)metaBuf;
metaSegment.length = ppnCommand->lbas * fmi->valid_bytes_per_meta;
#if FMISS_ENABLED
cmd->iopfmi.status = fmiss_ppn_read_multi(fmi, ppnCommand, &dataSegment, &metaSegment);
#else
cmd->iopfmi.status = h2fmi_ppn_read_multi(fmi, ppnCommand, &dataSegment, &metaSegment);
#endif
}
void h2fmi_ppn_iop_read_multiple(h2fmi_t *fmi, IOPFMI_IOPpn* cmd)
{
PPNCommandStruct *ppnCommand;
UInt32 *data_segments_array;
UInt32 *meta_segments_array;
hfmi_aes_iv *aes_iv_array = NULL;
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
ppnCommand = (PPNCommandStruct *)mem_static_map_cached(cmd->ppn_fil_command);
data_segments_array = (UInt32 *)mem_static_map_cached(cmd->data_segments_array);
meta_segments_array = (UInt32 *)mem_static_map_cached(cmd->meta_segments_array);
WMR_ASSERT(ppnCommand != MAP_FAILED);
WMR_ASSERT(data_segments_array != MAP_FAILED);
WMR_ASSERT(meta_segments_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(ppnCommand, cmd->ppn_fil_size);
WMR_PREPARE_READ_BUFFER(data_segments_array, cmd->data_segments_array_length);
WMR_PREPARE_READ_BUFFER(meta_segments_array, cmd->meta_segments_array_length);
if (cmd->aes_iv_array)
{
aes_iv_array = (hfmi_aes_iv *)mem_static_map_cached(cmd->aes_iv_array);
WMR_ASSERT(aes_iv_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(aes_iv_array, cmd->aes_num_chains * sizeof(hfmi_aes_iv));
}
h2fmi_setup_aes(fmi, &cmd->iopfmi, aes_iv_array, cmd->aes_chain_size, cmd->aes_key_type, (UInt32 *)cmd->aes_key_bytes, NULL);
#if FMISS_ENABLED
cmd->iopfmi.status = fmiss_ppn_read_multi(fmi,
ppnCommand,
(void *)data_segments_array,
(void *)meta_segments_array);
#else
cmd->iopfmi.status = h2fmi_ppn_read_multi(fmi,
ppnCommand,
(void *)data_segments_array,
(void *)meta_segments_array);
#endif
cmd->geb_ce = fmi->ppn->general_error_ce;
WMR_PREPARE_WRITE_BUFFER(ppnCommand, cmd->ppn_fil_size);
}
void h2fmi_ppn_iop_write_single(h2fmi_t *fmi, IOPFMI_IOSingle* cmd)
{
PPNCommandStruct *ppnCommand;
const UInt32 pageAddr = cmd->page_number;
UInt8 *dataBuf = (UInt8 *)mem_static_map_physical(cmd->data_address);
UInt8 *metaBuf = (UInt8 *)mem_static_map_physical(cmd->meta_address);
struct dma_segment dataSegment;
struct dma_segment metaSegment;
WMR_ASSERT(dataBuf != MAP_FAILED);
WMR_ASSERT(metaBuf != MAP_FAILED);
// We shouldn't use this command going forward - it's a legacy command supported
// for boot-from-NAND code only.
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
fmi->current_aes_cxt = NULL;
ppnCommand = &singlePpnCommands[fmi->bus_id];
WMR_MEMSET(ppnCommand, 0, sizeof(PPNCommandStruct));
ppnCommand->context.device_info = NULL;
ppnCommand->context.handle = NULL;
ppnCommand->context.bus_num = fmi->bus_id;
ppnCommand->command = PPN_COMMAND_PROGRAM;
ppnCommand->options = 0;
ppnCommand->entry[0].ceIdx = 0;
ppnCommand->entry[0].addr.row = pageAddr;
ppnCommand->mem_index[0].offset = 0;
ppnCommand->mem_index[0].idx = 0;
ppnCommand->entry[0].lbas = fmi->bytes_per_page / fmi->logical_page_size;
ppnCommand->ceInfo[0].pages = 1;
ppnCommand->ceInfo[0].ce = cmd->ce;
ppnCommand->num_pages = 1;
ppnCommand->lbas = fmi->bytes_per_page / fmi->logical_page_size;
dataSegment.paddr = (UInt32)dataBuf;
dataSegment.length = fmi->bytes_per_page;
metaSegment.paddr = (UInt32)metaBuf;
metaSegment.length = ppnCommand->lbas * fmi->valid_bytes_per_meta;
#if FMISS_ENABLED
cmd->iopfmi.status = fmiss_ppn_write_multi(fmi, ppnCommand, &dataSegment, &metaSegment);
#else
cmd->iopfmi.status = h2fmi_ppn_write_multi(fmi, ppnCommand, &dataSegment, &metaSegment);
#endif
}
void h2fmi_ppn_iop_write_multiple(h2fmi_t *fmi, IOPFMI_IOPpn* cmd)
{
PPNCommandStruct *ppnCommand;
UInt32 *data_segments_array;
UInt32 *meta_segments_array;
hfmi_aes_iv *aes_iv_array = NULL;
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
ppnCommand = (PPNCommandStruct *)mem_static_map_cached(cmd->ppn_fil_command);
data_segments_array = (UInt32 *)mem_static_map_cached(cmd->data_segments_array);
meta_segments_array = (UInt32 *)mem_static_map_cached(cmd->meta_segments_array);
WMR_ASSERT(ppnCommand != MAP_FAILED);
WMR_ASSERT(data_segments_array != MAP_FAILED);
WMR_ASSERT(meta_segments_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(ppnCommand, cmd->ppn_fil_size);
WMR_PREPARE_READ_BUFFER(data_segments_array, cmd->data_segments_array_length);
WMR_PREPARE_READ_BUFFER(meta_segments_array, cmd->meta_segments_array_length);
if (cmd->aes_iv_array)
{
aes_iv_array = (hfmi_aes_iv *)mem_static_map_cached(cmd->aes_iv_array);
WMR_ASSERT(aes_iv_array != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(aes_iv_array, cmd->aes_num_chains * sizeof(hfmi_aes_iv));
}
h2fmi_setup_aes(fmi, &cmd->iopfmi, aes_iv_array, cmd->aes_chain_size, cmd->aes_key_type, (UInt32 *)cmd->aes_key_bytes, NULL);
#if FMISS_ENABLED
cmd->iopfmi.status = fmiss_ppn_write_multi(fmi,
ppnCommand,
(void *)data_segments_array,
(void *)meta_segments_array);
#else
cmd->iopfmi.status = h2fmi_ppn_write_multi(fmi,
ppnCommand,
(void *)data_segments_array,
(void *)meta_segments_array);
#endif
cmd->geb_ce = fmi->ppn->general_error_ce;
WMR_PREPARE_WRITE_BUFFER(ppnCommand, cmd->ppn_fil_size);
}
void h2fmi_ppn_iop_read_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd)
{
UInt8 *page_buf = (UInt8 *)cmd->buffer_address;
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
WMR_MEMSET(page_buf, 0xFF, fmi->bytes_per_page + fmi->bytes_per_spare);
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
void h2fmi_ppn_iop_write_raw(h2fmi_t* fmi, IOPFMI_IORaw* cmd)
{
panic("Write Raw means nothing on PPN");
}
void h2fmi_ppn_iop_read_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd)
{
const BOOL32 gather_corrections = (0 != cmd->corrections_array);
UInt8 *corrections_array = (gather_corrections
? (UInt8 *)mem_static_map_cached(cmd->corrections_array)
: NULL);
UInt8 *page_buf = (UInt8 *)mem_static_map_cached(cmd->buffer_address);
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
WMR_ASSERT(corrections_array != MAP_FAILED);
fmi->current_aes_cxt = NULL;
cmd->iopfmi.status = h2fmi_ppn_read_bootpage(fmi,
cmd->ce,
cmd->page_number,
page_buf,
corrections_array);
WMR_PREPARE_WRITE_BUFFER(page_buf, H2FMI_BOOT_BYTES_PER_PAGE);
if (gather_corrections)
{
WMR_PREPARE_WRITE_BUFFER(corrections_array,
fmi->sectors_per_page * sizeof(IOPFMI_correction_t));
}
}
void h2fmi_ppn_iop_write_bootpage(h2fmi_t* fmi, IOPFMI_IOBootPage* cmd)
{
UInt8 *page_buf;
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
page_buf = (UInt8 *)mem_static_map_physical(cmd->buffer_address);
WMR_ASSERT(page_buf != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(page_buf, H2FMI_BOOT_BYTES_PER_PAGE);
fmi->current_aes_cxt = NULL;
cmd->iopfmi.status = h2fmi_ppn_write_bootpage(fmi,
cmd->ce,
cmd->page_number,
page_buf);
}
void h2fmi_ppn_iop_read_cau_bbt(h2fmi_t *fmi, IOPFMI_IOPpn* cmd)
{
PPNCommandStruct *ppnCommand;
struct dma_segment *sgl;
UInt8 *buf;
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
ppnCommand = (PPNCommandStruct *)mem_static_map_cached(cmd->ppn_fil_command);
sgl = (struct dma_segment *)mem_static_map_cached(cmd->data_segments_array);
WMR_ASSERT(ppnCommand != MAP_FAILED);
WMR_ASSERT(sgl != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(ppnCommand, cmd->ppn_fil_size);
WMR_PREPARE_READ_BUFFER(sgl, cmd->data_segments_array_length);
buf = (UInt8 *)mem_static_map_cached(sgl[0].paddr);
WMR_ASSERT(buf != MAP_FAILED);
cmd->iopfmi.status = h2fmi_ppn_read_cau_bbt(fmi, ppnCommand, buf);
cmd->geb_ce = fmi->ppn->general_error_ce;
WMR_PREPARE_WRITE_BUFFER(buf, fmi->ppn->device_params.blocks_per_cau / 8);
WMR_PREPARE_WRITE_BUFFER(ppnCommand, cmd->ppn_fil_size);
}
void h2fmi_ppn_iop_get_temperature(h2fmi_t *fmi, IOPFMI_GetTemperature* cmd)
{
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
#if SUPPORT_TOGGLE_NAND
if (h2fmi_ppn15_get_temperature(fmi, 0, &(cmd->temperature_celsius)))
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_FAILURE;
}
#else
cmd->iopfmi.status = kIOPFMI_STATUS_FAILURE;
#endif
}
void h2fmi_ppn_iop_get_controller_info(h2fmi_t *fmi, IOPFMI_GetControllerInfo* cmd)
{
h2fmi_ppn_device_params_t *params = &fmi->ppn->device_params;
BOOL32 result;
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
h2fmi_ppn_get_fw_version(fmi, cmd->ce, cmd->fw_version);
h2fmi_ppn_get_package_assembly_code(fmi, cmd->ce, cmd->package_assembly_code);
h2fmi_ppn_get_controller_unique_id(fmi, cmd->ce, cmd->controller_unique_id);
h2fmi_ppn_get_controller_hw_id(fmi, cmd->ce, cmd->controller_hw_id);
h2fmi_ppn_get_manufacturer_id(fmi, cmd->ce, cmd->manufacturer_id);
result = h2fmi_ppn_get_device_params(fmi, cmd->ce, params);
WMR_ASSERT(result);
if (fmi->ppn->spec_version >= PPN_VERSION_1_5_0)
{
h2fmi_ppn_get_marketing_name(fmi, cmd->ce, cmd->marketing_name);
}
cmd->caus = params->caus_per_channel;
cmd->cau_bits = params->cau_bits;
cmd->blocks_per_cau = params->blocks_per_cau;
cmd->block_bits = params->block_bits;
cmd->pages_per_block_mlc = params->pages_per_block;
cmd->pages_per_block_slc = params->pages_per_block_slc;
cmd->page_address_bits = params->page_address_bits;
cmd->bits_per_cell_bits = params->address_bits_bits_per_cell;
cmd->default_bits_per_cell = params->default_bits_per_cell;
cmd->page_size = params->page_size;
cmd->dies = params->dies_per_channel;
cmd->tRC = params->tRC;
cmd->tREA = params->tREA;
cmd->tREH = params->tREH;
cmd->tRHOH = params->tRHOH;
cmd->tRHZ = params->tRHZ;
cmd->tRLOH = params->tRLOH;
cmd->tRP = params->tRP;
cmd->tWC = params->tWC;
cmd->tWH = params->tWH;
cmd->tWP = params->tWP;
cmd->read_queue_size = params->read_queue_size;
cmd->program_queue_size = params->program_queue_size;
cmd->erase_queue_size = params->erase_queue_size;
cmd->prep_function_buffer_size = params->prep_function_buffer_size;
cmd->tRST = params->tRST_ms;
cmd->tPURST = params->tPURST_ms;
cmd->tSCE = params->tSCE_ms;
cmd->tCERDY = params->tCERDY_us;
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
void h2fmi_ppn_iop_get_die_info(h2fmi_t *fmi, IOPFMI_GetDieInfo *cmd)
{
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
h2fmi_ppn_get_uid(fmi, cmd->ce, cmd->die, cmd->unique_id);
h2fmi_ppn_get_die_chip_id(fmi, cmd->ce, cmd->die, cmd->chip_id);
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
void h2fmi_ppn_iop_update_firmware(h2fmi_t *fmi, IOPFMI_UpdateFirmware* cmd)
{
UInt32 *sgl;
UInt8 fwVerBuffer[NAND_DEV_PARAM_LEN_PPN];
h2fmi_ce_t ce;
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
sgl = (UInt32 *)mem_static_map_cached(cmd->sgl);
WMR_ASSERT(sgl != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(sgl, cmd->sgl_length_in_bytes);
for (ce = 0; ce < H2FMI_MAX_CE_TOTAL; ce++)
{
if (h2fmi_ppn_get_fw_version(fmi, ce, fwVerBuffer) == TRUE32)
{
cmd->iopfmi.status = h2fmi_ppn_fw_update(fmi, ce, (void *)sgl, cmd->fw_size, ppnFwTypeFw);
}
}
}
void h2fmi_ppn_iop_post_rst_pre_pwrstate_operations(h2fmi_t* fmi, IOPFMI_PostResetOperations *cmd)
{
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
if (h2fmi_ppn_post_rst_pre_pwrstate_operations(fmi))
{
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
else
{
cmd->iopfmi.status = kIOPFMI_STATUS_FAILURE;
}
}
void h2fmi_ppn_iop_set_power(h2fmi_t *fmi, IOPFMI_SetPower* cmd)
{
if (fmi->ppn->general_error)
{
cmd->iopfmi.status = kIOPFMI_STATUS_IOP_NOT_READY;
return;
}
h2fmi_ppn_set_channel_power_state(fmi, cmd->power_state_trans);
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
void h2fmi_ppn_iop_get_failure_info(h2fmi_t *fmi, IOPFMI_GetFailureInfo* cmd)
{
h2fmi_ppn_failure_info_t failureInfo;
struct dma_segment *sgl = NULL;
WMR_ASSERT(fmi->ppn->general_error);
if (cmd->sgl)
{
sgl = (struct dma_segment *)mem_static_map_cached(cmd->sgl);
WMR_ASSERT(sgl != MAP_FAILED);
WMR_PREPARE_READ_BUFFER(sgl, cmd->sgl_length);
}
h2fmi_ppn_get_general_error_info(fmi, cmd->ce, &failureInfo, &cmd->rma_buffer_length, sgl);
if(fmi->ppn->bytes_per_row_address == PPN_1_5_ROW_ADDR_BYTES)
{
cmd->type = failureInfo.failure_info_1_5.type;
}
else
{
cmd->type = failureInfo.failure_info_1_0.type;
}
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
void h2fmi_ppn_iop_set_feature_list(h2fmi_t *fmi, IOPFMI_SetFeatures* cmd)
{
void *list = mem_static_map_cached(cmd->list);
UInt32 size = cmd->size;
h2fmi_ppn_set_feature_list(fmi, list, size / sizeof(ppn_feature_entry_t));
cmd->iopfmi.status = kIOPFMI_STATUS_SUCCESS;
}
void h2fmi_ppn_iop_power_state_changed(h2fmi_t* fmi)
{
#if H2FMI_PPN_VERIFY_SET_FEATURES
h2fmi_ppn_verify_feature_shadow(fmi);
#endif // H2FMI_PPN_VERIFY_SET_FEATURES
}
#endif //SUPPORT_PPN
+718
View File
@@ -0,0 +1,718 @@
// *****************************************************************************
//
// File: H2fmi_private.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position; add definitions for extracting value from register
// position
//
// *****************************************************************************
//
// Copyright (C) 2008-2010 Apple, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#ifndef _H2FMI_PRIVATE_H_
#define _H2FMI_PRIVATE_H_
#include "WMRFeatures.h"
#include "WMROAM.h"
#if (H2FMI_WAIT_USING_ISR)
#include <sys/task.h>
#endif //H2FMI_WAIT_USING_ISR
#if H2FMI_EFI
#include "SoC.h"
#else //!H2FMI_EFI
#include <platform/soc/hwregbase.h>
#endif
#if FMI_VERSION == 0
#include "H2fmi_8920regs.h"
#elif FMI_VERSION <= 2
#include "H2fmi_8922regs.h"
#elif FMI_VERSION <= 3
#include "H2fmi_8940regs.h"
#elif FMI_VERSION <= 4
#include "H2fmi_8945regs.h"
#elif FMI_VERSION <= 5
#include "H2fmi_8950regs.h"
#endif
#if FMI_VERSION > 0
#define SUPPORT_PPN (1)
#endif
#if FMI_VERSION > 2
#define SUPPORT_TOGGLE_NAND (1)
#endif
#if FMI_VERSION >= 5
#define SUPPORT_NAND_DLL (1)
#endif
#include "H2fmi_dma_types.h"
// =============================================================================
// preprocessor constants
// =============================================================================
#define H2FMI_EARLY_EXIT_ARBITRARY_LOOP_CONST 1000
#define H2FMI_MAX_RESET_DELAY (50 * 1000)
#define H2FMI_MAX_CE_PER_BUS_POW2 (3UL)
#define H2FMI_MAX_CE_PER_BUS (1UL << H2FMI_MAX_CE_PER_BUS_POW2)
#define H2FMI_MAX_NUM_BUS (2UL)
#define H2FMI_MAX_CE_TOTAL (H2FMI_MAX_CE_PER_BUS * H2FMI_MAX_NUM_BUS)
#define H2FMI_MAX_BANKS_PER_CE (4)
#define H2FMI_MAX_BANKS_TOTAL (H2FMI_MAX_CE_TOTAL * H2FMI_MAX_BANKS_PER_CE)
#if FMI_VERSION == 0
#define H2FMI_BYTES_PER_SECTOR (512UL)
#define H2FMI_MAX_META_PER_ENVELOPE (32)
#define H2FMI_MAX_META_PER_LBA (32)
#define H2FMI_MAX_LBA_PER_PAGE (1)
#else
#define H2FMI_BYTES_PER_SECTOR (1024UL)
#define H2FMI_MAX_META_PER_ENVELOPE (63)
#define H2FMI_MAX_META_PER_LBA (16)
#define H2FMI_MAX_LBA_PER_PAGE (4)
#endif
#define H2FMI_WORDS_PER_SECTOR (H2FMI_BYTES_PER_SECTOR / sizeof(UInt32))
#define H2FMI_BOOT_SECTORS_PER_PAGE (3UL)
#define H2FMI_BYTES_PER_BOOT_SECTOR (512)
#define H2FMI_BOOT_BYTES_PER_PAGE (H2FMI_BYTES_PER_BOOT_SECTOR * H2FMI_BOOT_SECTORS_PER_PAGE)
#define H2FMI_MAX_SGL_SEGMENTS_PER_RAW (20)
#define H2FMI_DEFAULT_TIMEOUT_MICROS ((100 * 1000))
#define H2FMI_PAGE_TIMEOUT_MICROS ((2 * 1000 * 1000))
#define H2FMI_NAND_ID_SIZE (8)
#define H2FMI_NAND_ID_COMPARISON_SIZE (4)
#define UNIQUE_ID_LEN (16)
#if FMI_VERSION == 0
#define MAX_ECC_CORRECTION (16)
#else
#define MAX_ECC_CORRECTION (30)
#endif
#define H2FMI_ALLOWED_STUCK_BITS_IN_FP (2)
// conservative bus timings used for boot and Read Id during init
#define H2FMI_INIT_READ_CYCLE_NANOS (200)
#define H2FMI_INIT_READ_SETUP_NANOS (200)
#define H2FMI_INIT_READ_HOLD_NANOS (200)
#define H2FMI_INIT_READ_DELAY_NANOS (0)
#define H2FMI_INIT_WRITE_CYCLE_NANOS (200)
#define H2FMI_INIT_WRITE_SETUP_NANOS (200)
#define H2FMI_INIT_WRITE_HOLD_NANOS (200)
#define H2FMI_INIT_SOC_TO_NAND_RISE_NANOS (10)
#define H2FMI_INIT_SOC_TO_NAND_FALL_NANOS (10)
#define H2FMI_INIT_NAND_TO_SOC_RISE_NANOS (10)
#define H2FMI_INIT_NAND_TO_SOC_FALL_NANOS (10)
#define METADATA_LOOKUP_SIZE (256)
#define METADATA_MULTIPLY (1664525)
#define METADATA_INCREMENT (1013904223)
#define METADATA_ITERATIONS_TABLE (763)
#define METADATA_ITERATIONS_CRYPT (3)
#if (FMI_VERSION <= 2) || ((FMI_VERSION == 3) && (FMI_VERSION_MINOR == 0))
#define H2FMI_DMA_BURST_CYCLES (32)
#else // ((FMI_VERSION == 3) && (FMI_VERSION_MINOR != 0)) || (FMI_VERSION >= 4)
#define H2FMI_DMA_BURST_CYCLES (8)
#endif // ((FMI_VERSION == 3) && (FMI_VERSION_MINOR != 0)) || (FMI_VERSION >= 4)
#if FMI_VERSION >= 3
#define FMISS_ENABLED (1)
#endif
#if FMI_VERSION >= 5
#define H2FMI_EXTRA_CE_SETUP_TIME_US (10)
#endif // FMI_VERSION >= 5
#define H2FMI_IF_CTRL_LOW_POWER \
(FMC_IF_CTRL__DCCYCLE(0) | \
FMC_IF_CTRL__REB_SETUP(FMC_IF_CTRL__TIMING_MAX_CLOCKS) | \
FMC_IF_CTRL__REB_HOLD(FMC_IF_CTRL__TIMING_MAX_CLOCKS) | \
FMC_IF_CTRL__WEB_SETUP(FMC_IF_CTRL__TIMING_MAX_CLOCKS) | \
FMC_IF_CTRL__WEB_HOLD(FMC_IF_CTRL__TIMING_MAX_CLOCKS))
// =============================================================================
// type declarations
// =============================================================================
typedef UInt16 h2fmi_ce_t;
typedef UInt8 h2fmi_chipid_t[H2FMI_NAND_ID_SIZE];
typedef enum
{
writeIdle = 0,
writeSetup,
writeWaitForCE,
writeXferData,
writeEndingWrite,
writeEndingWriteWaitCE,
writeDone,
writeWaitingForNumCELimit
} WRITE_STATE;
typedef enum
{
readIdle = 0,
readSetup = 1,
readStartWait = 2,
readXferData = 3,
readWaitECCDone = 4,
readDone = 5,
} READ_STATE;
typedef enum
{
fmiNone = 0,
fmiRead = 1,
fmiWrite = 2
} FMI_MODE;
#define INVALID_CE_INDEX ( (UInt32)~0 )
typedef struct tagFMI_ISR_STATE_MACHINE
{
FMI_MODE currentMode;
union
{
WRITE_STATE wr;
READ_STATE rd;
} state;
UInt32 dirty_ce_mask;
UInt32 page_idx;
UInt32 page_count;
UInt32 currentCE;
UInt32 savedCurrentCE;
UInt32 wMaxOutstandingCEWriteOperations;
UInt32 wOutstandingCEWriteOperations;
struct
{
UInt32 head,tail,count;
UInt32 previousCEIndex[ H2FMI_MAX_CE_PER_BUS ];
} ceCommitQueue;
UInt32 lastPageIndex[ H2FMI_MAX_CE_TOTAL ];
UInt32 currentWriteDie;
UInt32 wVendorType;
UInt32 currentPage;
UInt32 wNumTimesHoldoffExecuted;
h2fmi_ce_t* chip_enable_array;
UInt32* page_number_array;
struct dma_segment* data_segment_array;
struct dma_segment* meta_segment_array;
UInt64 wCmdStartTicks;
UInt64 waitStartTicks;
UInt64 wPageTimeoutTicks;
UInt64 wQuarterPageTimeoutTicks;
BOOL32 fSuccessful;
BOOL32 needs_prepare;
UInt32 lastCE;
UInt8* max_corrected_array;
UInt32 clean_pages;
UInt32 fused_pages;
UInt32 uecc_pages;
UInt8* sector_stats;
#if (H2FMI_WAIT_USING_ISR)
struct task_event stateMachineDoneEvent;
#endif
} FMI_ISR_STATE_MACHINE, * PFMI_ISR_STATE_MACHINE;
struct _hfmi_aes_iv
{
UInt8 aes_iv_bytes[16];
};
typedef struct _hfmi_aes_iv hfmi_aes_iv;
#define _kIOPFMI_STATUS_UNKNOWN ((UInt32) 0)
#define _kIOPFMI_STATUS_SUCCESS ((UInt32) 1)
#define _kIOPFMI_STATUS_BLANK ((UInt32) 2)
#define _kIOPFMI_STATUS_PARAM_INVALID ((UInt32) 0x80000004)
#define _kIOPFMI_STATUS_FMC_DONE_TIMEOUT ((UInt32) 0x8000001C)
#define _kIOPFMI_STATUS_READY_BUSY_TIMEOUT ((UInt32) 0x8000001D)
#define _kIOPFMI_STATUS_ECC_CLEANUP ((UInt32) 0x8000001E)
#define _kIOPFMI_STATUS_ECC_DONE_TIMEOUT ((UInt32) 0x8000001F)
#define _kIOPFMI_STATUS_PPN_GENERAL_ERROR ((UInt32) 0x80000020)
/**
* Special status -- status code from NAND is in lower 16-bits.
*/
#define _kIOPFMI_STATUS_PGM_ERROR ((UInt32) 0x80200000)
#define _kIOPFMI_STATUS_ERASE_ERROR ((UInt32) 0x80210000)
#define _kIOPFMI_STATUS_DMA_DONE_TIMEOUT ((UInt32) 0x80000022)
#define _kIOPFMI_STATUS_NOT_ALL_CLEAN ((UInt32) 0x80000023)
#define _kIOPFMI_STATUS_AT_LEAST_ONE_UECC ((UInt32) 0x80000024)
#define _kIOPFMI_STATUS_FUSED ((UInt32) 0x80000025)
/**
* Vendor-specific codes ...
*/
#define _kVS_NONE 0
#define _kVS_HYNIX_2P 1
#define _kVS_TOSHIBA_2P 2
#define _kVS_MICRON_2P 3
#define _kVS_SAMSUNG_2D 4
#define _kVS_SAMSUNG_2P_2D 5
typedef struct _h2fmi_t
{
UInt32 bus_id;
UInt32* regs;
UInt32 clock_speed_khz;
UInt32 num_of_ce;
UInt32 valid_ces;
BOOL32 is_ppn;
BOOL32 is_ppn_channel_init;
UInt32 pages_per_block;
UInt32 sectors_per_page;
UInt32 bytes_per_spare;
UInt32 blocks_per_ce;
UInt32 banks_per_ce;
UInt32 total_bytes_per_meta;
UInt32 valid_bytes_per_meta;
UInt32 bytes_per_page;
UInt32 logical_page_size;
UInt32 dies_per_cs;
UInt32 if_ctrl;
#if !H2FMI_IOP
UInt32 if_ctrl_normal;
#endif // !H2FMI_IOP
UInt32 fmi_config_reg;
UInt32 fmi_data_size_reg;
#if FMI_VERSION == 4
BOOL32 read_stream_disable;
#endif // FMI_VERSION == 4
#if FMI_VERSION >= 5
UInt32 read_tx_page_delay;
#endif // FMI_VERSION >= 5
BOOL32 retire_on_invalid_refresh;
UInt8 correctable_bits;
#if SUPPORT_TOGGLE_NAND
BOOL32 is_toggle_system; // primary mode of operation (DDR or SDR)
BOOL32 is_toggle; // current state of FMI (DDR or SDR)
UInt32 toggle_if_ctrl;
UInt32 dqs_ctrl;
UInt32 timing_ctrl_1;
UInt32 timing_ctrl_2;
UInt32 useDiffDQS;
UInt32 useDiffRE;
UInt32 useVREF;
#endif // SUPPORT_TOGGLE_NAND
UInt8 refresh_threshold_bits;
UInt32 isr_condition;
struct dma_aes_config aes_cxt;
struct dma_aes_config* current_aes_cxt;
hfmi_aes_iv* current_aes_iv_array;
UInt32* iv_seed_array;
#if (H2FMI_WAIT_USING_ISR)
struct task_event isr_event;
#endif
FMI_ISR_STATE_MACHINE stateMachine;
struct
{
UInt32 wNumCE_Executed;
UInt32 wOverallOperationFailure;
UInt32 wSingleCEStatus;
UInt32* wCEStatusArray;
UInt32 wCEStatusArrayModulusMask;
UInt32 wFirstFailingCE;
} failureDetails;
UInt32 wMaxOutstandingCEWriteOperations;
BOOL32 h2fmi_ppn_panic_on_status_timeout;
BOOL32 initialized;
struct _h2fmi_ppn_t *ppn;
h2fmi_ce_t activeCe;
UInt8 ceMap[H2FMI_MAX_CE_PER_BUS];
#if FMISS_ENABLED
void *fmiss_cxt;
void (*isr_handler)(void *arg);
#endif // FMISS_ENABLED
UInt32 * error_list;
} h2fmi_t;
struct _h2fmi_virt_to_phys_map_t
{
UInt32 bus;
h2fmi_ce_t ce;
};
typedef struct _h2fmi_virt_to_phys_map_t h2fmi_virt_to_phys_map_t;
// =============================================================================
// general fail macro
// =============================================================================
#define h2fmi_fail(b) \
do { \
WMR_PRINT(ERROR, \
"[FIL:ERR] FAIL -> %s@%d\n", \
"", __LINE__); \
b = FALSE32; \
} while (0)
// =============================================================================
// fmi bus selection macros
//
// Note: this doesn't scale nicely past two buses
// =============================================================================
#define h2fmi_select_by_bus(fmi, sel0, sel1) ((fmi->regs == FMI0) ? sel0 : sel1)
#define h2fmi_bus_index(fmi) h2fmi_select_by_bus(fmi, 0, 1)
// =============================================================================
// dma-related macros
// =============================================================================
#define h2fmi_dma_data_chan(fmi) h2fmi_select_by_bus(fmi, DMA_FMI0DATA, DMA_FMI1DATA)
#define h2fmi_dma_meta_chan(fmi) h2fmi_select_by_bus(fmi, DMA_FMI0CHECK, DMA_FMI1CHECK)
#define h2fmi_dma_meta_fifo(fmi) ((void*)(((UInt32)fmi->regs) + FMI_META_FIFO))
#define h2fmi_dma_data_fifo(fmi) ((void*)(((UInt32)fmi->regs) + FMI_DATA_BUF))
// =============================================================================
// busy wait macro
//
// this should only be used for very short waits that should never halt
// during code sequences where performance matters
// =============================================================================
#define h2fmi_busy_wait(fmi, reg, mask, cond) \
do { \
UInt32 val; \
do { \
val = h2fmi_rd(fmi, reg); \
} while ((val & (mask)) != (cond)); \
} while (0)
// =============================================================================
// register access macros
// =============================================================================
#if (H2FMI_TRACE_REG_WRITES)
UInt32 h2fmi_trace_wr(h2fmi_t* fmi, UInt32 reg, UInt32 val);
UInt8 h2fmi_trace_wr8(h2fmi_t* fmi, UInt32 reg, UInt8 val);
UInt32 h2fmc_trace_wr(volatile UInt32* h2fmc_regs, UInt32 reg, UInt32 val);
#define h2fmi_wr(fmi, reg, val) h2fmi_trace_wr(fmi, reg, val)
#define h2fmi_wr8(fmi, reg, val) h2fmi_trace_wr8(fmi, reg, val)
#if H2FMI_INSTRUMENT_BUS_1
#define h2fmc_wr(fmc_regs, reg, val) h2fmc_trace_wr(fmc_regs, reg, val)
#endif // H2FMI_INSTRUMENT_BUS_1
#else
#define h2fmi_wr(fmi, reg, val) (*((fmi)->regs + ((reg) >> 2)) = (val))
#define h2fmi_wr8(fmi, reg, val) (((volatile UInt8*)fmi->regs)[(UInt32)reg] = (UInt8)val)
#if H2FMI_INSTRUMENT_BUS_1
#define h2fmc_wr(fmc_regs, reg, val) (fmc_regs[((UInt32)reg) >> 2] = (UInt32)val)
#endif // H2FMI_INSTRUMENT_BUS_1
#endif
#if (H2FMI_TRACE_REG_READS)
UInt32 h2fmi_trace_rd(h2fmi_t* fmi, UInt32 reg);
UInt8 h2fmi_trace_rd8(h2fmi_t* fmi, UInt32 reg);
#define h2fmi_rd(fmi, reg) h2fmi_trace_rd(fmi, reg)
#define h2fmi_rd8(fmi, reg) h2fmi_trace_rd8(fmi, reg)
#if H2FMI_INSTRUMENT_BUS_1
#define h2fmc_rd(fmc_regs, reg) h2fmc_trace_rd(fmc_regs, reg)
#endif // H2FMI_INSTRUMENT_BUS_1
#else
#define h2fmi_rd(fmi, reg) (*(volatile UInt32*)((UInt8*)((fmi)->regs) + (reg)))
#define h2fmi_rd8(fmi, reg) (((volatile UInt8*)fmi->regs)[(UInt32)reg])
#if H2FMI_INSTRUMENT_BUS_1
#define h2fmc_rd(fmc_regs, reg) (fmc_regs[((UInt32)reg) >> 2])
#endif // H2FMI_INSTRUMENT_BUS_1
#endif
// =============================================================================
// nand device command bytes
// =============================================================================
#define NAND_CMD__RESET ((UInt8)0xFF)
#define NAND_CMD__READ_ID ((UInt8)0x90)
#define NAND_CMD__READ_STATUS ((UInt8)0x70)
#define NAND_CMD__READ_SS_DIE1 ((UInt8)0xF1)
#define NAND_CMD__READ_SS_DIE2 ((UInt8)0xF2)
#define NAND_CMD__READ_MICRON_DIE_STATUS ((UInt8)0x78)
#define NAND_CMD__READ ((UInt8)0x00)
#define NAND_CMD__READ_CONFIRM ((UInt8)0x30)
#define NAND_CMD__ERASE ((UInt8)0x60)
#define NAND_CMD__ERASE_CONFIRM ((UInt8)0xD0)
#define NAND_CMD__WRITE ((UInt8)0x80)
#define NAND_CMD__WRITE2_HYNIX ((UInt8)0x81)
#define NAND_CMD__WRITE2_SAMSUNG ((UInt8)0x81)
#define NAND_CMD__WRITE_CONFIRM ((UInt8)0x10)
#define NAND_CMD__DUMMY_CONFIRM_HYNIX ((UInt8)0x11)
#define NAND_CMD__DUMMY_CONFIRM_MICRON ((UInt8)0x11)
#define NAND_CMD__DUMMY_CONFIRM_TOSHIBA ((UInt8)0x11)
#define NAND_CMD__DUMMY_CONFIRM_SAMSUNG ((UInt8)0x11)
#define NAND_CMD__CONFIRM_TOSHIBA ((UInt8)0x15)
#define NAND_CMD__TOS_STATUS_71h ((UInt8)0x71)
#define CHIPID_ADDR (0x00)
#define MfgID_ADDR (0x30)
//Mask corresponding to max of ChipId size and MfgID size
#define MAX_ID_SIZE_MASK (0x0000FFFFFFFFFFFF)
// =============================================================================
// nand operations timeout specifications
// =============================================================================
#define TIMEOUT_MICROSEC_READ ((UInt32)1000)
#define TIMEOUT_MICROSEC_WRITE ((UInt32)5000)
#define TIMEOUT_MICROSEC_ERASE ((UInt32)15000)
// =============================================================================
// nand operations status specifications
// =============================================================================
#define NAND_STATUS__CHIP_STATUS1 ((UInt8)1 << 0)
#define NAND_STATUS__CHIP_STATUS1_FAIL ((UInt8)1 << 0)
#define NAND_STATUS__CHIP_STATUS1_PASS ((UInt8)0 << 0)
#define NAND_STATUS__TOS_CHIP_STATUS_MASK ((UInt8)0x1f)
#define NAND_STATUS__TOS_CHIP_STATUS_D0 ((UInt8)0x0a)
#define NAND_STATUS__TOS_CHIP_STATUS_D1 ((UInt8)0x014)
#define NAND_STATUS__SS_CHIP_STATUS_P0 ((UInt8)0x2)
#define NAND_STATUS__CHIP_STATUS2 ((UInt8)1 << 1)
#define NAND_STATUS__CHIP_STATUS2_FAIL ((UInt8)1 << 1)
#define NAND_STATUS__CHIP_STATUS2_PASS ((UInt8)0 << 1)
// bits 2-4 are not used
#define NAND_STATUS__PAGE_BUFFER_RB ((UInt8)1 << 5)
#define NAND_STATUS__PAGE_BUFFER_RB_READY ((UInt8)1 << 5)
#define NAND_STATUS__PAGE_BUFFER_RB_BUSY ((UInt8)0 << 5)
#define NAND_STATUS__DATA_CACHE_RB ((UInt8)1 << 6)
#define NAND_STATUS__DATA_CACHE_RB_READY ((UInt8)1 << 6)
#define NAND_STATUS__DATA_CACHE_RB_BUSY ((UInt8)0 << 6)
#define NAND_STATUS__WRITE_PROTECT ((UInt8)1 << 7)
#define NAND_STATUS__WRITE_PROTECT_NOT_PROTECTED ((UInt8)1 << 7)
#define NAND_STATUS__WRITE_PROTECT_PROTECTED ((UInt8)0 << 7)
// =============================================================================
// implementation function declarations shared between SecureROM and iBoot
// =============================================================================
void h2fmi_reset(h2fmi_t* fmi);
BOOL32 h2fmi_is_chipid_invalid(h2fmi_chipid_t* const id);
BOOL32 h2fmi_wait_done(h2fmi_t* fmi, UInt32 reg, UInt32 mask, UInt32 bits);
BOOL32 h2fmi_wait_dma_task_pending(h2fmi_t* fmi);
void h2fmi_clean_ecc(h2fmi_t* fmi);
void h2fmi_fmc_read_data(h2fmi_t* fmi, UInt32 size, UInt8* data);
BOOL32 h2fmi_nand_reset(h2fmi_t* fmi, h2fmi_ce_t ce);
BOOL32 h2fmi_nand_read_id(h2fmi_t* fmi, h2fmi_ce_t ce, h2fmi_chipid_t* id, UInt8 addr);
BOOL32 h2fmi_pio_write_sector(h2fmi_t* fmi, const void* buf, UInt32 len);
BOOL32 h2fmi_pio_read_sector(h2fmi_t* fmi, void* buf, UInt32 len);
// =============================================================================
// implementation function declarations not used by SecureROM
// =============================================================================
UInt32 h2fmi_get_gate(h2fmi_t* fmi);
void h2fmi_init_sys(h2fmi_t* fmi);
#if (!H2FMI_READONLY || AND_SUPPORT_NVRAM)
BOOL32 h2fmi_erase_blocks(h2fmi_t* fmi, UInt32 num_elements, UInt16* ce, UInt32* block, BOOL32* status_failed);
UInt32 h2fmi_write_bootpage(h2fmi_t* fmi, UInt32 ce, UInt32 page, UInt8* data_buf);
#endif //!H2FMI_READONLY
#if (!H2FMI_READONLY)
BOOL32 h2fmi_write_page(h2fmi_t* fmi, UInt16 ce, UInt32 page, UInt8* data_buf, UInt8* meta_buf, BOOL32* status_failed);
UInt32 h2fmi_write_raw_page(h2fmi_t* fmi, UInt32 ce, UInt32 page, UInt8* data_buf);
#endif //!H2FMI_READONLY
UInt32 h2fmi_read_page(h2fmi_t* fmi, h2fmi_ce_t ce, UInt32 page, UInt8* data_buf, UInt8* meta_buf, UInt8* max_corrected, UInt8* sector_stats);
BOOL32 h2fmi_read_multi(h2fmi_t* fmi, UInt32 page_count, h2fmi_ce_t* chip_enable_array, UInt32* page_number_array, struct dma_segment* data_segment_array, struct dma_segment* meta_segment_array, UInt8* max_corrected_array, UInt8* sector_stats);
#if (defined(ENABLE_VENDOR_UNIQUE_QUERIES) && ENABLE_VENDOR_UNIQUE_QUERIES)
BOOL32 h2fmiGenericNandReadSequence(h2fmi_t *whichFmi, UInt8 phyCE, GenericReadRequest *genericRead);
#endif //(defined(ENABLE_VENDOR_UNIQUE_QUERIES) && ENABLE_VENDOR_UNIQUE_QUERIES)
BOOL32 h2fmi_reset_and_read_chipids(h2fmi_t* fmi, h2fmi_chipid_t* ids, UInt8 addr);
BOOL32 h2fmi_nand_read_id_all(h2fmi_t* fmi, h2fmi_chipid_t* ids, UInt8 addr);
BOOL32 h2fmi_nand_reset_all(h2fmi_t* fmi);
BOOL32 h2fmi_write_multi(h2fmi_t* fmi, UInt32 page_count, h2fmi_ce_t* chip_enable_array, UInt32* page_number_array, struct dma_segment* data_segment_array, struct dma_segment* meta_segment_array, BOOL32* status_failed, UInt32 wVendorType);
void h2fmi_nand_read_chipid(h2fmi_t* fmi, h2fmi_ce_t ce, h2fmi_chipid_t* id);
void h2fmi_build_ce_bitmask(h2fmi_t* fmi, h2fmi_chipid_t* ids, h2fmi_chipid_t* id_filter, UInt8 addr);
void h2fmi_set_bootpage_data_format(h2fmi_t* fmi);
void h2fmi_set_raw_write_data_format(h2fmi_t* fmi, UInt32 spare_per_sector);
void h2fmi_set_page_format(h2fmi_t* fmi);
void h2fmi_config_page_addr(h2fmi_t* fmi, UInt32 page);
UInt32 h2fmi_calculate_ecc_bits(h2fmi_t* fmi);
UInt32 h2fmi_calculate_ecc_output_bytes(h2fmi_t* fmi);
BOOL32 h2fmi_read_raw_page(h2fmi_t* fmi, UInt32 ce, UInt32 page, UInt8* data_buf, UInt8* spare_buf);
UInt32 h2fmi_read_bootpage(h2fmi_t* fmi, UInt32 ce, UInt32 page, UInt8* data_buf, UInt8* max_corrected);
UInt32 h2fmi_read_bootpage_pio(h2fmi_t* fmi, UInt32 ce, UInt32 page, UInt8* data_buf, UInt8* max_corrected);
void h2fmi_prepare_wait_status(h2fmi_t* fmi, UInt8 io_mask, UInt8 io_cond);
BOOL32 h2fmi_wait_status(h2fmi_t* fmi, UInt8 io_mask, UInt8 io_cond, UInt8* status);
h2fmi_t *h2fmiTranslateVirtualCEToBus(UInt32 virtualCE);
h2fmi_ce_t h2fmiTranslateVirtualCEToCe(UInt32 virutalCE);
void h2fmi_set_if_ctrl(h2fmi_t* fmi, UInt32 if_ctrl);
void restoreTimingRegs(h2fmi_t* fmi);
// =============================================================================
// implementation function declarations
// =============================================================================
BOOL32 h2fmi_init(h2fmi_t* fmi, UInt32 interface, h2fmi_chipid_t* ids);
Int32 h2fmiInitVirtToPhysMap(UInt16 busCount, UInt16 bankCount);
void h2fmiMapBankToBusAndEnable(UInt32 bank, UInt32 bus, h2fmi_ce_t enable);
h2fmi_t* h2fmiTranslateBankToBus(UInt32 bank);
h2fmi_ce_t h2fmiTranslateBankToCe(UInt32 bank);
void h2fmi_fmc_enable_ce(h2fmi_t* fmi, h2fmi_ce_t ce);
void h2fmi_fmc_disable_ce(h2fmi_t* fmi, h2fmi_ce_t ce);
void h2fmi_fmc_disable_all_ces(h2fmi_t* fmi);
void h2fmi_aes_iv(void* arg, UInt32 chunk_index, void* iv_buffer);
void h2fmi_whitening_iv(void* arg, UInt32 chunk_index, void* iv_buffer);
// =============================================================================
// implementation function declarations used only for debug during development
//
// note that these are designed so that the calls will disappear when
// not compiling for debug
// =============================================================================
#if (H2FMI_DEBUG)
BOOL32 h2fmi_test_hook(h2fmi_t* fmi);
void h2fmi_dump_config(h2fmi_t* fmi);
void h2fmi_dump_status_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_dump_fmi_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_dump_fmc_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_dump_ecc_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_dump_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_dump_buffer(UInt8* buf, UInt32 size);
void h2fmi_spew_regs(h2fmi_t* fmi, const char* prefix);
#else // H2FMI_DEBUG
#define h2fmi_test_hook(fmi_ignored) (TRUE32)
#define h2fmi_dump_config(fmi_ignored)
#define h2fmi_dump_status_regs(fmi_ignored, prefix_ignored)
#define h2fmi_dump_fmi_regs(fmi_ignored, prefix_ignored)
#define h2fmi_dump_fmc_regs(fmi_ignored, prefix_ignored)
#define h2fmi_dump_ecc_regs(fmi_ignored, prefix_ignored)
#define h2fmi_dump_regs(fmi_ignored, prefix_ignored)
#define h2fmi_dump_buffer(buf_ignored, size_ignored)
#endif // H2FMI_DEBUG
#if SUPPORT_TOGGLE_NAND
#define turn_on_fmc(fmi) (h2fmi_wr((fmi), FMC_ON, FMC_ON__ENABLE | (((fmi)->is_toggle) ? (FMC_ON__DDR_NAND_TYPE_TOGGLE | FMC_ON__DDR_ENABLE) : 0)))
#else
#define turn_on_fmc(fmi) (h2fmi_wr((fmi), FMC_ON, FMC_ON__ENABLE))
#endif
void h2fmi_handle_write_ISR_state_machine( h2fmi_t* fmi );
void h2fmi_handle_read_ISR_state_machine( h2fmi_t* fmi );
typedef enum
{
CE_TIMEOUT,
CE_BUSY,
CE_IDLE
} CE_STATE;
CE_STATE h2fmi_get_current_CE_state( h2fmi_t* fmi );
BOOL32 h2fmi_tick_delta_timeout(UInt64 wStartTick, UInt64 wMaxDeltaTick);
void h2fmi_clear_interrupts_and_reset_masks(h2fmi_t* fmi);
void h2fmi_prepare_for_ready_busy_interrupt(h2fmi_t* fmi);
void h2fmi_set_page_format_and_ECC_level(h2fmi_t* fmi, UInt32 wErrorAlertLevel);
BOOL32 h2fmi_common_idle_handler( h2fmi_t* fmi );
BOOL32 h2fmi_start_dma( h2fmi_t* fmi );
#if ( H2FMI_INSTRUMENT_BUS_1 )
extern void h2fmi_instrument_bit_set(int iBit);
extern void h2fmi_instrument_bit_clear(int iBit);
#endif
UInt32 h2fmi_calculate_fmi_config(h2fmi_t* fmi);
UInt32 h2fmi_calculate_fmi_data_size(h2fmi_t* fmi);
void h2fmi_restoreFmiRegs(h2fmi_t *fmi);
void fmiss_init_sequences(h2fmi_t *fmi);
UInt32 h2fmi_rx_check_page_ecc(h2fmi_t* fmi, UInt32 ecc_pnd, UInt8* max_corrected, UInt8* sector_stats, UInt32 sectors_per_page);
#if FMISS_ENABLED
void fmiss_raw_init_sequences(h2fmi_t *fmi);
#endif // FMISS_ENABLED
#if SUPPORT_TOGGLE_NAND && !APPLICATION_EMBEDDEDIOP
void transitionWorldFromDDR(UInt32 powerstate_to);
void transitionWorldToDDR(UInt32 powerstate_from);
#endif
#if !APPLICATION_EMBEDDEDIOP
void h2fmi_ppn_all_channel_power_state_transition(UInt32 ps_tran);
#endif // !APPLICATION_EMBEDDEDIOP
#if SUPPORT_NAND_DLL
BOOL32 h2fmiTrainDLL(UInt32 *lock);
#endif
#endif // _H2FMI_PRIVATE_H_
// ********************************** EOF **************************************
File diff suppressed because it is too large. Load diff
+490
View File
@@ -0,0 +1,490 @@
// *****************************************************************************
//
// File: H2fmi_test.c
//
// *****************************************************************************
//
// Notes:
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#include "H2fmi_private.h"
#if (H2FMI_TEST_HOOK)
#include "H2fmi.h"
#include <debug.h>
#include <platform/memmap.h>
#include <stdlib.h>
// =============================================================================
// preprocessor compilation control
// =============================================================================
#define TEST_WRITE_WITH_CORRUPTED_BITS true
#define TEST_WRITE_WITH_CORRUPT_META true
#define TEST_WRITE_WITH_CORRUPT_MAIN true
#define TESTING_BASIC_OPS true
#define DUMP_BUFS false
#define DUMP_ERASE_BUFS true
#define DUMP_WRITE_BUFS true
#define DUMP_CORRUPTED_BUFS true
#define ERASE_DIRTY_THRESHOLD 10
// TODO: fix this some other way
#define FIL_SUCCESS ((int32_t)0)
#define FIL_SUCCESS_CLEAN ((int32_t)1)
// =============================================================================
// external function declarations
// =============================================================================
extern int nand_read_bootblock(u_int8_t interface, uint8_t cs, void* address, size_t* size);
// =============================================================================
// private implementation function declarations
// =============================================================================
static bool h2fmi_test_erase(h2fmi_t* fmi, uint32_t ce, uint32_t block, uint32_t page);
static bool h2fmi_test_write(h2fmi_t* fmi, uint32_t ce, uint32_t page);
static bool h2fmi_test_read_bootblock(void);
// =============================================================================
// externally visible test function definitions
// =============================================================================
bool h2fmi_test_hook(h2fmi_t* fmi)
{
bool result = false;
dprintf(DEBUG_CRITICAL, "running test hook\n");
h2fmi_spew_config(fmi);
if (TESTING_BASIC_OPS)
{
const uint32_t ce = 0;
const uint32_t block = 517;
const uint32_t page = (block * fmi->pages_per_block);
result = h2fmi_test_erase(fmi, ce, block, page);
result = h2fmi_test_write(fmi, ce, page);
}
else
{
result = h2fmi_test_read_bootblock();
}
return result;
}
// =============================================================================
// static test function definitions
// =============================================================================
static bool h2fmi_test_read_bootblock(void)
{
const uint32_t bootpage_size = 3 * 512;
const uint32_t bootblock_max_size = 128 * bootpage_size;
uint8_t* boot_buf = (uint8_t*)malloc(bootblock_max_size);
bool result = false;
uint32_t interface;
uint32_t ce;
for (interface = 0; interface < 2; interface++)
{
for (ce = 0; ce < 8; ce++)
{
size_t bootblock_size = bootblock_max_size;
dprintf(DEBUG_INFO,
"attempting boot from NAND %d CS %d\n",
interface, ce);
// clean read buffer
memset(boot_buf, 0x00, bootblock_max_size);
// attempt to read bootblock
if (nand_read_bootblock(interface, ce, boot_buf, &bootblock_size) == 0)
{
// TODO: do minimal verification of bootblock by checking
// for known pattern
if ((boot_buf[0] == '3') &&
(boot_buf[1] == 'g') &&
(boot_buf[2] == 'm') &&
(boot_buf[3] == 'I'))
{
dprintf(DEBUG_INFO, "loaded boot image\n");
result = true;
}
}
else
{
dprintf(DEBUG_SPEW, "load failed\n");
}
if (DUMP_BUFS)
{
dprintf(DEBUG_SPEW, "boot_buf\n");
h2fmi_spew_buffer(boot_buf, bootpage_size);
}
}
}
// TODO: free allocated buffers
if (!result)
{
dprintf(DEBUG_CRITICAL, "ERROR: failed to load any boot images!\n");
}
return result;
}
static bool h2fmi_test_erase(h2fmi_t* fmi,
uint32_t ce,
uint32_t block,
uint32_t page)
{
bool result = true;
const uint32_t bytes_per_page = fmi->bytes_per_page;
const uint32_t bytes_per_spare = fmi->bytes_per_spare;
const uint32_t bytes_per_meta = fmi->bytes_per_meta;
uint8_t* data_buf_0 = (uint8_t*)malloc(bytes_per_page);
uint8_t* spare_buf_0 = (uint8_t*)malloc(bytes_per_spare);
uint8_t* data_buf_1 = (uint8_t*)malloc(bytes_per_page);
uint8_t* meta_buf_1 = (uint8_t*)malloc(bytes_per_meta);
dprintf(DEBUG_INFO, "h2fmi_test_erase()...\n");
uint32_t byte_idx;
uint32_t dirty_count = 0;
uint8_t bCorrectedBits = 0;
// clean read buffers
memset(data_buf_0, 0x00, bytes_per_page);
memset(spare_buf_0, 0x00, bytes_per_spare);
memset(data_buf_1, 0x00, bytes_per_page);
memset(meta_buf_1, 0x00, bytes_per_meta);
if (FIL_SUCCESS != h2fmiEraseSingleBlock(ce, block))
{
dprintf(DEBUG_CRITICAL, "ERROR: failed erase\n");
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_SPEW, "h2fmiEraseSingleBlock succeeded\n");
}
// read back with ECC, verifying that page is reported as "clean"
if (FIL_SUCCESS_CLEAN != h2fmiReadSinglePage(ce, page,
data_buf_1,
meta_buf_1,
&bCorrectedBits,
NULL))
{
dprintf(DEBUG_CRITICAL, "ERROR: failed read single of erased page without detecting clean\n");
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_SPEW, "h2fmiReadSinglePage correctly reported FIL_SUCCESS_CLEAN\n");
}
// read back raw contents of page (i.e. with no ECC)
if (FIL_SUCCESS != h2fmiReadNoECC(ce, page,
data_buf_0,
spare_buf_0))
{
dprintf(DEBUG_CRITICAL, "ERROR: failed raw readback from erased page\n");
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_SPEW, "h2fmiReadNoECC succeeded\n");
}
// verify that raw readback buffer is mostly all 0xFF
for (byte_idx = 0; byte_idx < bytes_per_page; byte_idx++)
{
if (0xFF != data_buf_0[byte_idx])
{
dirty_count++;
}
}
for (byte_idx = 0; byte_idx < bytes_per_spare; byte_idx++)
{
if (0xFF != spare_buf_0[byte_idx])
{
dirty_count++;
}
}
if (dirty_count > ERASE_DIRTY_THRESHOLD)
{
dprintf(DEBUG_CRITICAL,
"ERROR: %d bytes reported not 0xFF by ReadNoECC after Erase\n",
dirty_count);
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_INFO, "%d bytes reported dirty\n", dirty_count);
}
if (!result && DUMP_ERASE_BUFS)
{
dprintf(DEBUG_INFO, "data_buf_0\n");
h2fmi_spew_buffer(data_buf_0, bytes_per_page);
dprintf(DEBUG_INFO, "spare_buf_0\n");
h2fmi_spew_buffer(spare_buf_0, bytes_per_spare);
dprintf(DEBUG_INFO, "data_buf_1\n");
h2fmi_spew_buffer(data_buf_1, bytes_per_page);
dprintf(DEBUG_INFO, "meta_buf_1\n");
h2fmi_spew_buffer(meta_buf_1, bytes_per_meta);
}
// using free causes panic with error...
//free(data_buf_0);
//free(spare_buf_0);
//free(data_buf_1);
//free(meta_buf_1);
dprintf(DEBUG_INFO, "...%s\n", result ? "succeeded" : "failed");
return result;
}
static bool h2fmi_test_write(h2fmi_t* fmi, uint32_t ce, uint32_t page)
{
bool result = true;
const uint32_t bytes_per_page = fmi->bytes_per_page;
const uint32_t bytes_per_meta = fmi->bytes_per_meta;
uint8_t* data_buf_2 = (uint8_t*)malloc(bytes_per_page);
uint8_t* meta_buf_2 = (uint8_t*)malloc(bytes_per_meta);
uint8_t* data_buf_3 = (uint8_t*)malloc(bytes_per_page);
uint8_t* meta_buf_3 = (uint8_t*)malloc(bytes_per_meta);
uint8_t* data_buf_4 = (uint8_t*)malloc(bytes_per_page);
uint8_t* meta_buf_4 = (uint8_t*)malloc(bytes_per_meta);
uint8_t* data_buf_5 = (uint8_t*)malloc(bytes_per_page);
uint8_t* meta_buf_5 = (uint8_t*)malloc(bytes_per_meta);
dprintf(DEBUG_INFO, "h2fmi_test_write()...\n");
const uint32_t row_addr = (page << 16);
uint32_t word_idx;
uint32_t byte_idx;
uint8_t max_corrected = 0;
// clean read buffers
memset(data_buf_4, 0xA5, bytes_per_page);
memset(meta_buf_4, 0x81, bytes_per_meta);
memset(data_buf_5, 0x5A, bytes_per_page);
memset(meta_buf_5, 0x18, bytes_per_meta);
// watermark metadata buffers
for (byte_idx = 0; (int32_t)byte_idx < bytes_per_meta; byte_idx++)
{
uint8_t marker = (uint8_t)(0xC0 | byte_idx);
meta_buf_2[byte_idx] = marker;
#if (TEST_WRITE_WITH_CORRUPT_META)
meta_buf_3[byte_idx] = ~marker;
#else
meta_buf_3[byte_idx] = marker;
#endif
}
// watermark both data buffers identically
for (word_idx = 0; word_idx < (bytes_per_page >> 2); word_idx++)
{
const uint32_t col_addr = (word_idx << 2);
const uint32_t marker = (row_addr | col_addr) + 1;
uint32_t* page_words_2 = (uint32_t*)data_buf_2;
uint32_t* page_words_3 = (uint32_t*)data_buf_3;
page_words_2[word_idx] = marker;
page_words_3[word_idx] = marker;
}
#if (TEST_WRITE_WITH_CORRUPT_MAIN)
// corrupt second data buffer
for (word_idx = 0; word_idx < 24; word_idx++)
{
uint32_t* page_words_3 = (uint32_t*)data_buf_3;
page_words_3[word_idx] ^= 0xFFFFFFFF;
}
#endif
// write to erased page
if (FIL_SUCCESS != h2fmiWriteSinglePage(ce,
page,
data_buf_2,
meta_buf_2))
{
dprintf(DEBUG_CRITICAL, "ERROR: failed write of page\n");
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_SPEW, "h2fmiWriteSinglePage succeeded\n");
}
// read back page, expecting it to not have uncorrectable ECC errors
if (FIL_SUCCESS != h2fmiReadSinglePage(ce,
page,
data_buf_4,
meta_buf_4,
&max_corrected,
NULL))
{
dprintf(DEBUG_CRITICAL, "ERROR: failed read of written page\n");
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_SPEW, "h2fmiReadSinglePage succeeded\n");
}
#if (TEST_WRITE_WITH_CORRUPTED_BITS)
// write again to same page, with significant bit toggles in main data (and possibly meta data)
if (FIL_SUCCESS != h2fmiWriteSinglePage(ce,
page,
data_buf_3,
meta_buf_3))
{
dprintf(DEBUG_CRITICAL, "ERROR: failed second (corrupting) write\n");
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_SPEW, "h2fmiWriteSinglePage (corrupting) succeeded\n");
}
// read back page, expecting it to fail due to uncorrectable ECC errors
if (FIL_SUCCESS == h2fmiReadSinglePage(ce,
page,
data_buf_5,
meta_buf_5,
&max_corrected,
NULL))
{
// yell if we did NOT get an error
dprintf(DEBUG_CRITICAL, "ERROR: succeeded read of corrupted page\n");
h2fmi_fail(result);
}
else
{
dprintf(DEBUG_SPEW, "h2fmiReadSinglePage (corrupting) failed as expected\n");
}
#endif // TEST_WRITE_WITH_CORRUPTED_BITS
// TODO: check fail with blank check as well
// verify clean readback buffer
//
// TODO: add quick memcmp for initial failure detection and
// then scan byte by byte only if failed
for (byte_idx = 0; byte_idx < bytes_per_page; byte_idx++)
{
const uint8_t wrote = data_buf_2[byte_idx];
const uint8_t read = data_buf_4[byte_idx];
if (wrote != read)
{
dprintf(DEBUG_CRITICAL,
"ERROR: failed main data verify at byte %d, 0x%02X != 0x%02X\n",
byte_idx, wrote, read);
h2fmi_fail(result);
}
}
for (byte_idx = 0; (int32_t)byte_idx < fmi->bytes_per_meta; byte_idx++)
{
const uint8_t wrote = meta_buf_2[byte_idx];
const uint8_t read = meta_buf_4[byte_idx];
if (wrote != read)
{
dprintf(DEBUG_CRITICAL,
"ERROR: failed meta data verify at byte %d, 0x%02X != 0x%02X\n",
byte_idx, wrote, read);
h2fmi_fail(result);
}
}
// TODO: verify corrupted readback buffer (using raw read)
if (!result && DUMP_WRITE_BUFS)
{
dprintf(DEBUG_INFO, "data_buf_2\n");
h2fmi_spew_buffer(data_buf_2, bytes_per_page);
dprintf(DEBUG_INFO, "meta_buf_2\n");
h2fmi_spew_buffer(meta_buf_2, bytes_per_meta);
dprintf(DEBUG_INFO, "data_buf_4\n");
h2fmi_spew_buffer(data_buf_4, bytes_per_page);
dprintf(DEBUG_INFO, "meta_buf_4\n");
h2fmi_spew_buffer(meta_buf_4, bytes_per_meta);
}
if (!result && DUMP_CORRUPTED_BUFS)
{
dprintf(DEBUG_INFO, "data_buf_3\n");
h2fmi_spew_buffer(data_buf_3, bytes_per_page);
dprintf(DEBUG_INFO, "meta_buf_3\n");
h2fmi_spew_buffer(meta_buf_3, bytes_per_meta);
dprintf(DEBUG_INFO, "data_buf_5\n");
h2fmi_spew_buffer(data_buf_5, bytes_per_page);
dprintf(DEBUG_INFO, "meta_buf_5\n");
h2fmi_spew_buffer(meta_buf_5, bytes_per_meta);
}
// using free causes panic with error...
//free(data_buf_2);
//free(meta_buf_2);
//free(data_buf_3);
//free(meta_buf_3);
//free(data_buf_4);
//free(meta_buf_4);
//free(data_buf_5);
//free(meta_buf_5);
dprintf(DEBUG_INFO, "...%s\n", result ? "succeeded" : "failed");
return result;
}
#endif // H2FMI_TEST_HOOK
// ********************************** EOF **************************************
+288
View File
@@ -0,0 +1,288 @@
// Copyright (C) 2010 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.
//
//
// Note: This file is intended to compile for an iBoot and x86 host target
#include "H2fmi_timing.h"
#include "WMROAM.h" // WMR_MAX, ROUNDUPTO,
#if 0
#define DUMP_VAR(variable) WMR_PRINT(ALWAYS, "%s:%d %s : %u\n", \
__FUNCTION__, __LINE__, #variable, (UInt32)(variable))
#else
#define DUMP_VAR(variable)
#endif
// timings required by PPN 1.5 spec
#define FPGA_TIMINGS (0)
#if FPGA_TIMINGS // Based on SAMSUNG PPN 1.5 FPGA (will be removed once we get PPN 1.5 Si)
#define WH_MIN_NS (35)
#define WP_MIN_NS (65)
#define WC_MIN_NS (100)
#define RPRE_MIN_NS (116)
#define WPRE_MIN_NS (76)
#define WPST_MIN_PS (1888000)
#define DQSRE_MAX_PS (50 * 1000)
#define CS_MIN_NS (383)
#define CH_MIN_NS (5)
#define ADL_MIN_NS (300)
#define WHR_MIN_NS (120)
#else // these are timings specified by PPN 1.5 spec
#define RPRE_MIN_NS (35)
#define WPRE_MIN_NS (15)
#define WPST_MIN_PS (6500)
#define DQSRE_MAX_PS (25 * 1000)
#define CS_MIN_NS (20)
#define CH_MIN_NS (5)
#define ADL_MIN_NS (300)
#define WHR_MIN_NS (120)
#define RPSTH_MIN_NS (15)
#endif
#if FMI_VERSION >= 5
#define RPST_MAX_CYCLES (5)
#endif // FMI_VERSION >= 5
Int32 HertzToPicoseconds
(UInt64 hertz)
{
const UInt32 KHz = hertz / 1000;
const UInt32 ps = ((UInt32)1000000000) / KHz;
return ps;
}
UInt32
NandRequirementToIFCTRL (
const NandRequiredTimings *required,
NandFmcSettings *actual)
{
DUMP_VAR(required->clock_hz);
DUMP_VAR(required->tRC_ns);
DUMP_VAR(required->tRP_ns);
DUMP_VAR(required->tREH_ns);
DUMP_VAR(required->tREA_ns);
DUMP_VAR(required->tRHOH_ns);
DUMP_VAR(required->tRLOH_ns);
DUMP_VAR(required->tWC_ns);
DUMP_VAR(required->tWP_ns);
DUMP_VAR(required->tWH_ns);
// avoid using
const Int32 ps_per_clock = HertzToPicoseconds(required->clock_hz);
// Minimum time from SoC falling edge until first possible data sample
const Int32 data_sample_time = ROUNDUPTO((required->tREA_ns + required->soc_tx_prop_ns + required->soc_rx_prop_ns) * PS_PER_NS, ps_per_clock);
const Int32 data_sample_clocks = data_sample_time / ps_per_clock;
DUMP_VAR(data_sample_clocks);
const Int32 reb_setup_time = ROUNDUPTO(WMR_MAX((required->tRP_ns * PS_PER_NS), (data_sample_time - (required->tRHOH_ns * PS_PER_NS))), ps_per_clock);
Int32 reb_setup_clocks = reb_setup_time / ps_per_clock;
DUMP_VAR(reb_setup_clocks);
Int32 reb_high_estimate_clocks = 0;
// Minimum cycle time as determined by actual setup plus required hold vs. tRC
const Int32 reb_adjusted_cycle_time = ROUNDUPTO(WMR_MAX((required->tREH_ns * PS_PER_NS) + reb_setup_time, (required->tRC_ns * PS_PER_NS)), ps_per_clock);
DUMP_VAR(reb_adjusted_cycle_time);
const Int32 tRLOH_clocks = ROUNDUPTO(required->tRLOH_ns * PS_PER_NS, ps_per_clock) / ps_per_clock;
// Check for EDO mode (data ready time > actual cycle + tRLOH)
if (data_sample_time > (reb_adjusted_cycle_time + ROUNDUPTO(required->tRLOH_ns * PS_PER_NS, ps_per_clock)))
{
WMR_ASSERT(data_sample_clocks > (tRLOH_clocks + reb_setup_clocks));
reb_high_estimate_clocks = data_sample_clocks - tRLOH_clocks - reb_setup_clocks;
}
else
{
reb_high_estimate_clocks = ROUNDUPTO(WMR_MAX((required->tREH_ns * PS_PER_NS), ((required->tRC_ns * PS_PER_NS) - reb_setup_time)), ps_per_clock) / ps_per_clock;
}
DUMP_VAR(reb_high_estimate_clocks);
Int32 reb_high_revised_clocks = 0;
// data sampling is done with a delay relative to the risine edge of REB
// thus, the sampling cannot occur past the rising edge of the subsequent cycle
if (((data_sample_clocks - reb_setup_clocks) <= (reb_setup_clocks + reb_high_estimate_clocks - 1)))
{
reb_high_revised_clocks = reb_high_estimate_clocks;
}
else
{
reb_setup_clocks = data_sample_clocks;
}
DUMP_VAR(reb_high_revised_clocks);
Int32 reb_setup_final_clocks = reb_setup_clocks;
Int32 reb_high_final_clocks = reb_high_revised_clocks;
// Shift extra cycles to setup phase if possible
if ((reb_high_revised_clocks > 1) && (((reb_high_revised_clocks - 1) * ps_per_clock) > (required->tREH_ns * PS_PER_NS)))
{
reb_high_final_clocks -= 1;
reb_setup_final_clocks += 1;
}
actual->read_setup_clocks = reb_setup_final_clocks > 0 ? reb_setup_final_clocks - 1 : 0;
actual->read_hold_clocks = reb_high_final_clocks > 0 ? reb_high_final_clocks - 1 : 0;
actual->read_dccycle_clocks = data_sample_clocks > reb_setup_final_clocks ? data_sample_clocks - reb_setup_final_clocks : 0;
// Some chips cannot sample after the next byte's /RE - rdar://7063954
if (required->edo_limit &&
((actual->read_setup_clocks + actual->read_hold_clocks + 1) < actual->read_dccycle_clocks))
{
return FALSE32;
}
const Int32 write_hold_time = ROUNDUPTO(required->tWH_ns * PS_PER_NS, ps_per_clock);
const Int32 write_setup_time = ROUNDUPTO(WMR_MAX(((required->tWC_ns * PS_PER_NS) - write_hold_time), (required->tWP_ns * PS_PER_NS)), ps_per_clock);
Int32 write_hold_revised_time = write_hold_time;
Int32 write_setup_revised_time = write_setup_time;
// Balance write setup and hold if balance_write_cycle is set
if (required->balance_write_cycle &&
((write_setup_time - ps_per_clock) > (required->tWP_ns * PS_PER_NS)))
{
write_hold_revised_time += ps_per_clock;
write_setup_revised_time -= ps_per_clock;
}
actual->write_setup_clocks = (write_setup_revised_time / ps_per_clock) - 1;
actual->write_hold_clocks = (write_hold_revised_time / ps_per_clock) - 1;
return TRUE32;
}
static UInt32
h2fmi_nanos_to_clocks(UInt8 nsPerClock,
UInt8 nsPerOperation)
{
UInt8 rawValue = (nsPerOperation / nsPerClock) + ((nsPerOperation % nsPerClock) ? 1 : 0);
UInt8 registerValue = (rawValue ? rawValue - 1 : 0);
return registerValue;
}
BOOL32
Legacy_NandRequirementToIFCTRL (
const NandRequiredTimings *required,
NandFmcSettings *actual)
{
#define timing_nanos(cycles, hz) ((((UInt64)1000000000) * cycles) / hz)
#define SUB_MIN_ZERO(minuend, subtrahend) (((minuend) > (subtrahend)) ? ((minuend) - (subtrahend)) : 0)
UInt32 nsAdjustedWriteSetup;
UInt32 nsAdjustedWriteHold;
UInt32 nsWriteCycleRemainder;
UInt32 nsAdjustedReadSetup;
UInt32 nsAdjustedReadHold;
UInt32 nsActualReadSetup;
UInt32 nsAdjustedReadCycle;
UInt32 nsReadCycleRemainder;
UInt32 nsAdjustedReadSample;
UInt32 write_setup_clocks;
UInt32 write_hold_clocks;
UInt32 read_setup_clocks;
UInt32 read_hold_clocks;
UInt32 edo_delay;
const UInt32 nsNandRiseTime = required->nand_to_soc_rise_ns;
const UInt32 nsSocRiseTime = required->soc_to_nand_rise_ns;
const UInt32 nsSocFallTime = required->soc_to_nand_fall_ns;
Int32 nsPerClock;
nsPerClock = HertzToPicoseconds(required->clock_hz) / 1000;
nsAdjustedWriteSetup = required->tWP_ns + nsSocFallTime;
write_setup_clocks = h2fmi_nanos_to_clocks(nsPerClock, nsAdjustedWriteSetup);
// Check if cycle time remaining or write hold requirement is greater
nsWriteCycleRemainder = SUB_MIN_ZERO((UInt32)required->tWC_ns,(write_setup_clocks * nsPerClock));
nsAdjustedWriteHold = WMR_MAX(nsWriteCycleRemainder, required->tWH_ns + nsSocRiseTime);
write_hold_clocks = h2fmi_nanos_to_clocks(nsPerClock, nsAdjustedWriteHold);
nsAdjustedReadSetup = required->tRP_ns + nsSocFallTime;
read_setup_clocks = h2fmi_nanos_to_clocks(nsPerClock, nsAdjustedReadSetup);
nsActualReadSetup = (read_setup_clocks + 1) * nsPerClock;
// Since read has round-trip rise/fall delays, account for both
nsAdjustedReadCycle = WMR_MAX((UInt32)required->tRC_ns,
nsSocFallTime + required->tREA_ns + nsNandRiseTime);
nsReadCycleRemainder = SUB_MIN_ZERO((UInt32)nsAdjustedReadCycle, nsActualReadSetup);
nsAdjustedReadHold = WMR_MAX(nsReadCycleRemainder, required->tREH_ns + nsSocRiseTime);
read_hold_clocks = h2fmi_nanos_to_clocks(nsPerClock, nsAdjustedReadHold);
// Make sure we sample tREA from fall, but before tRHOH from rise
nsAdjustedReadSample = SUB_MIN_ZERO(nsSocFallTime + required->tREA_ns+ nsNandRiseTime,
nsActualReadSetup);
edo_delay = ROUNDUPTO(nsAdjustedReadSample, nsPerClock) / nsPerClock; // how many cycles after the falling edge to sample
actual->read_setup_clocks = read_setup_clocks;
actual->read_hold_clocks = read_hold_clocks;
actual->read_dccycle_clocks = edo_delay;
actual->write_setup_clocks = write_setup_clocks;
actual->write_hold_clocks = write_hold_clocks;
return TRUE32;
}
#if SUPPORT_TOGGLE_NAND
BOOL32 Toggle_NandRequirementToIFCTRL (
const NandRequiredTimings *required,
NandFmcSettings *actual
)
{
UInt64 clk_Hz = required->clock_hz;
UInt32 toggleCycleTimePS = WMR_MAX(WMR_MAX(WMR_MAX(required->ddr_tREH_ps * 2, required->ddr_tRP_ps * 2),
WMR_MAX(required->tDQSH_ps * 2, required->tDQSL_ps * 2)),
WMR_MAX(required->tDSC_ps, required->ddr_tRC_ps));
actual->ddr_half_cycle_clocks = CEIL_DIV(toggleCycleTimePS * clk_Hz, 2 * PS_PER_S) - 1;
actual->read_pre_clocks = CEIL_DIV(RPRE_MIN_NS * clk_Hz, NS_PER_S) - 1;
#if FMI_VERSION < 5
actual->read_post_clocks = CEIL_DIV((DQSRE_MAX_PS + toggleCycleTimePS / 2) * clk_Hz, PS_PER_S) - 1;
#else // FMI_VERSION >= 5
// <rdar://problem/11024771> Change the read post amble delay to workaround Read dma timeout with DQS_TIMING_CTRL::DELTAV_SUSPENDS_READS
actual->read_post_clocks = RPST_MAX_CYCLES;
#endif // FMI_VERSION >= 5
actual->write_pre_clocks = CEIL_DIV(WPRE_MIN_NS * clk_Hz, NS_PER_S) - 1;
actual->write_post_clocks = CEIL_DIV(WPST_MIN_PS * clk_Hz, PS_PER_S) - 1;
actual->ce_setup_clocks = CEIL_DIV(CS_MIN_NS * clk_Hz, NS_PER_S) - 1;
//H5P violates tRPSTH. SoC team recommends increasing CE Hold Time as a workaround
//to increase tRPSTH: <rdar://problem/9894530> PPN1.5: tRPSTH is being violated
actual->ce_hold_clocks = CEIL_DIV(WMR_MAX(CH_MIN_NS, RPSTH_MIN_NS) * clk_Hz, NS_PER_S) - 1;
actual->adl_clocks = CEIL_DIV(ADL_MIN_NS * clk_Hz, NS_PER_S) - 1;
actual->whr_clocks = CEIL_DIV(WHR_MIN_NS * clk_Hz, NS_PER_S) - 1;
return TRUE32;
}
#endif
+110
View File
@@ -0,0 +1,110 @@
// Copyright (C) 2010 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.
//
//
// Note: This file is intended to compile for an iBoot and x86 host target
#ifndef _H2FMI_TIMING_H_
#define _H2FMI_TIMING_H_
#include "WMRTypes.h"
#include "H2fmi_private.h"
#define CEIL_DIV(a,b) (((a)/(b)) + (((a) % (b)) ? 1 : 0))
#define PS_PER_NS (1000)
#define NS_PER_S ((UInt64)1000000000)
#define PS_PER_S ((UInt64)1000000000000)
typedef struct _NandRequiredTimings
{
UInt64 clock_hz;
Int32 soc_tx_prop_ns;
Int32 soc_rx_prop_ns;
BOOL32 edo_limit; // TRUE32 if using H2P/H2A/H3P for rdar://7063954
BOOL32 balance_write_cycle;
// -- Legacy only
Int32 soc_to_nand_rise_ns;
Int32 soc_to_nand_fall_ns;
Int32 nand_to_soc_rise_ns;
Int32 nand_to_soc_fall_ns;
// -- End Legacy only
Int32 tRC_ns;
Int32 tRP_ns;
Int32 tREH_ns;
Int32 tREA_ns;
Int32 tRHOH_ns;
Int32 tRLOH_ns;
Int32 tWC_ns;
Int32 tWP_ns;
Int32 tWH_ns;
#if SUPPORT_TOGGLE_NAND
UInt32 ddr_tRC_ps;
UInt32 ddr_tREH_ps;
UInt32 ddr_tRP_ps;
UInt32 tDSC_ps;
UInt32 tDQSH_ps;
UInt32 tDQSL_ps;
#endif
} NandRequiredTimings;
typedef struct _NandFmcSettings
{
UInt8 read_setup_clocks; // 0 is one cycle
UInt8 read_hold_clocks; // 0 is one cycle
UInt8 read_dccycle_clocks; // 0 means rising edge of /RE
UInt8 write_setup_clocks; // 0 is one cycle
UInt8 write_hold_clocks; // 0 is one cycle
#if SUPPORT_TOGGLE_NAND
UInt8 ddr_half_cycle_clocks;
UInt8 read_pre_clocks;
UInt8 read_post_clocks;
UInt8 write_pre_clocks;
UInt8 write_post_clocks;
UInt8 ce_setup_clocks;
UInt8 ce_hold_clocks;
UInt8 adl_clocks;
UInt8 whr_clocks;
#endif
} NandFmcSettings;
BOOL32
NandRequirementToIFCTRL (
const NandRequiredTimings *required,
NandFmcSettings *actual
);
BOOL32
Legacy_NandRequirementToIFCTRL (
const NandRequiredTimings *required,
NandFmcSettings *actual
);
#if SUPPORT_TOGGLE_NAND
BOOL32
Toggle_NandRequirementToIFCTRL (
const NandRequiredTimings *required,
NandFmcSettings *actual
);
#endif
#endif // _H2FMI_TIMING_H_
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+387
View File
@@ -0,0 +1,387 @@
// *****************************************************************************
//
// File: H2fmi_private.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position; add definitions for extracting value from register
// position
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#ifndef _H2FMI_PRIVATE_H_
#define _H2FMI_PRIVATE_H_
#include <sys/task.h>
#include "H2fmi_regs.h"
// =============================================================================
// preprocessor platform identification
// =============================================================================
#if (defined(APPLICATION_SECUREROM) && APPLICATION_SECUREROM)
#define H2FMI_BOOTROM true
#else
#define H2FMI_BOOTROM false
#endif
#if (defined(APPLICATION_EMBEDDEDIOP) && APPLICATION_EMBEDDEDIOP)
#define H2FMI_IOP true
#else
#define H2FMI_IOP false
#endif
#if (defined(APPLICATION_IBOOT) && APPLICATION_IBOOT)
#define H2FMI_IBOOT true
#else
#define H2FMI_IBOOT false
#endif
// TODO: add EFI platform identification
// =============================================================================
// configurable preprocessor compilation control
// =============================================================================
// Set H2FMI_DEBUG below to true if you want to build with extra
// debugging features (default to false).
#define H2FMI_DEBUG false
// Set H2FMI_TEST_HOOK below to true if you want to insert tests at the end
// of FIL_Init in iBoot (default to false).
#define H2FMI_TEST_HOOK false
// Set H2FMI_DMA_SYNC_READ and/or H2FMI_DMA_SYNC_WRITE to true in order to
// force read and/or write operations to only use the synchronous interface
// to the CDMA. This is a workaround for a problem with async dma that is
// currently under investigation.
#define H2FMI_DMA_SYNC_READ false
#define H2FMI_DMA_SYNC_WRITE false
// Set H2FMI_WAIT_USING_ISR to true if you want operations to wait for
// dma and bus events by hooking an interrupt service routine to the
// FMI interrupt vector; set to false for waiting using register
// polling with yield (default to true).
#define H2FMI_WAIT_USING_ISR true
// =============================================================================
// fixed preprocessor compilation control
// =============================================================================
// Always build SecureROM read-only.
#if (H2FMI_BOOTROM)
#define H2FMI_READONLY true
// Also, EmbeddedIOP builds should always be read/write.
#elif (H2FMI_IOP)
#define H2FMI_READONLY false
// Otherwise, ignore nand driver read-only configuration in iBoot
// debug builds so that erase/write are available for use in testing
// read operations.
#elif (H2FMI_IBOOT && defined(AND_READONLY) && H2FMI_DEBUG)
#define H2FMI_READONLY false
// Otherwise, mirror nand driver configuration in iBoot.
#elif (defined(AND_READONLY))
#define H2FMI_READONLY true
#else
#define H2FMI_READONLY false
#endif
// =============================================================================
// preprocessor constant definitions
// =============================================================================
#define H2FMI_META_PER_ENVELOPE 10
#define H2FMI_BYTES_PER_META 10
#define H2FMI_MAX_DEVICE 8UL
#define H2FMI_BYTES_PER_SECTOR 512UL
#define H2FMI_WORDS_PER_SECTOR (H2FMI_BYTES_PER_SECTOR / sizeof(uint32_t))
#define H2FMI_BOOT_SECTORS_PER_PAGE 3UL
#define H2FMI_BOOT_BYTES_PER_PAGE (H2FMI_BYTES_PER_SECTOR * H2FMI_BOOT_SECTORS_PER_PAGE)
#define H2FMI_DEFAULT_TIMEOUT_MICROS ((utime_t)(2 * 1000 * 1000))
#define H2FMI_PAGE_TIMEOUT_MICROS ((utime_t)(2 * 1000 * 1000))
#define H2FMI_NAND_ID_SIZE 5
// conservative bus timings used for boot and Read Id during init
#define H2FMI_INIT_READ_CYCLE_NANOS 200
#define H2FMI_INIT_READ_SETUP_NANOS 100
#define H2FMI_INIT_READ_HOLD_NANOS 100
#define H2FMI_INIT_WRITE_CYCLE_NANOS 200
#define H2FMI_INIT_WRITE_SETUP_NANOS 100
#define H2FMI_INIT_WRITE_HOLD_NANOS 100
// =============================================================================
// type declarations
// =============================================================================
typedef uint32_t h2fmi_ce_t;
typedef uint32_t h2fmi_chipid_t;
struct _h2fmi_t
{
volatile uint32_t* regs;
uint32_t num_of_ce;
uint32_t pages_per_block;
uint32_t sectors_per_page;
uint32_t bytes_per_spare;
uint32_t blocks_per_ce;
uint32_t banks_per_ce;
uint32_t bytes_per_meta;
uint32_t if_ctrl;
uint32_t isr_condition;
struct task_event dma_data_done_event;
struct task_event dma_meta_done_event;
struct task_event isr_event;
bool initialized;
};
typedef struct _h2fmi_t h2fmi_t;
struct _h2fmi_virt_to_phys_map_t
{
uint32_t bus;
h2fmi_ce_t ce;
};
typedef struct _h2fmi_virt_to_phys_map_t h2fmi_virt_to_phys_map_t;
// =============================================================================
// general fail macro
// =============================================================================
#define h2fmi_fail(b) \
do { \
dprintf(DEBUG_CRITICAL, \
"[FIL:ERR] FAIL -> %s@%d\n", \
__FILE__, __LINE__); \
b = false; \
} while (0)
// =============================================================================
// fmi bus selection macros
//
// Note: this doesn't scale nicely past two buses
// =============================================================================
#define h2fmi_select_by_bus(fmi, sel0, sel1) ((fmi->regs == FMI0) ? sel0 : sel1)
#define h2fmi_bus_index(fmi) h2fmi_select_by_bus(fmi, 0, 1)
// =============================================================================
// dma-related macros
// =============================================================================
#define h2fmi_dma_data_chan(fmi) h2fmi_select_by_bus(fmi, DMA_FMI0DATA, DMA_FMI1DATA)
#define h2fmi_dma_meta_chan(fmi) h2fmi_select_by_bus(fmi, DMA_FMI0CHECK, DMA_FMI1CHECK)
#define h2fmi_dma_meta_fifo(fmi) ((void*)(((uint32_t)fmi->regs) + FMI_META_FIFO))
#define h2fmi_dma_data_fifo(fmi) ((void*)(((uint32_t)fmi->regs) + FMI_DATA_BUF))
// =============================================================================
// busy wait macro
//
// this should only be used for very short waits that should never halt
// during code sequences where performance matters
// =============================================================================
#define h2fmi_busy_wait(fmi, reg, mask, cond) \
do { \
uint32_t val; \
do { \
val = h2fmi_rd(fmi, reg); \
} while ((val & (mask)) != (cond)); \
h2fmi_wr(fmi, reg, (val & ~(mask)) | (~(cond) & (mask))); \
} while (0)
// =============================================================================
// cache operation size macro
// =============================================================================
// TODO: refactor this cache line rounding functionality
#if (H2FMI_IOP)
#define cache_op_size(buf_size) (((buf_size) + (CPU_CACHELINE_SIZE-1)) & ~(CPU_CACHELINE_SIZE-1))
#else
#define cache_op_size(buf_size) buf_size
#endif
// =============================================================================
// nand device command bytes
// =============================================================================
#define NAND_CMD__RESET ((uint8_t)0xFF)
#define NAND_CMD__READ_ID ((uint8_t)0x90)
#define NAND_CMD__READ_STATUS ((uint8_t)0x70)
#define NAND_CMD__READ ((uint8_t)0x00)
#define NAND_CMD__READ_CONFIRM ((uint8_t)0x30)
#define NAND_CMD__ERASE ((uint8_t)0x60)
#define NAND_CMD__ERASE_CONFIRM ((uint8_t)0xD0)
#define NAND_CMD__WRITE ((uint8_t)0x80)
#define NAND_CMD__WRITE_CONFIRM ((uint8_t)0x10)
// =============================================================================
// nand operations timeout specifications
// =============================================================================
#define TIMEOUT_MICROSEC_READ ((uint32_t)1000)
#define TIMEOUT_MICROSEC_WRITE ((uint32_t)5000)
#define TIMEOUT_MICROSEC_ERASE ((uint32_t)15000)
// =============================================================================
// nand operations status specifications
// =============================================================================
#define NAND_STATUS__CHIP_STATUS1 ((uint8_t)1 << 0)
#define NAND_STATUS__CHIP_STATUS1_FAIL ((uint8_t)1 << 0)
#define NAND_STATUS__CHIP_STATUS1_PASS ((uint8_t)0 << 0)
#define NAND_STATUS__CHIP_STATUS2 ((uint8_t)1 << 1)
#define NAND_STATUS__CHIP_STATUS2_FAIL ((uint8_t)1 << 1)
#define NAND_STATUS__CHIP_STATUS2_PASS ((uint8_t)0 << 1)
// bits 2-4 are not used
#define NAND_STATUS__PAGE_BUFFER_RB ((uint8_t)1 << 5)
#define NAND_STATUS__PAGE_BUFFER_RB_READY ((uint8_t)1 << 5)
#define NAND_STATUS__PAGE_BUFFER_RB_BUSY ((uint8_t)0 << 5)
#define NAND_STATUS__DATA_CACHE_RB ((uint8_t)1 << 6)
#define NAND_STATUS__DATA_CACHE_RB_READY ((uint8_t)1 << 6)
#define NAND_STATUS__DATA_CACHE_RB_BUSY ((uint8_t)0 << 6)
#define NAND_STATUS__WRITE_PROTECT ((uint8_t)1 << 7)
#define NAND_STATUS__WRITE_PROTECT_NOT_PROTECTED ((uint8_t)1 << 7)
#define NAND_STATUS__WRITE_PROTECT_PROTECTED ((uint8_t)0 << 7)
// =============================================================================
// implementation function declarations shared between SecureROM and iBoot
// =============================================================================
bool h2fmi_init_minimal(h2fmi_t* fmi, uint32_t interface);
void h2fmi_ungate(h2fmi_t* fmi);
void h2fmi_gate(h2fmi_t* fmi);
void h2fmi_reset(h2fmi_t* fmi);
void h2fmi_calc_bus_timings(h2fmi_t* fmi, uint32_t min_read_cycle_nanos, uint32_t min_read_setup_nanos, uint32_t min_read_hold_nanos, uint32_t min_write_cycle_nanos, uint32_t min_write_setup_nanos, uint32_t min_write_hold_nanos);
bool h2fmi_is_chipid_invalid(uint32_t id);
bool h2fmi_wait_done(h2fmi_t* fmi, uint32_t reg, uint32_t mask, uint32_t bits);
bool h2fmi_wait_dma_task_pending(h2fmi_t* fmi);
void h2fmi_clean_ecc(h2fmi_t* fmi);
void h2fmi_fmc_read_data(h2fmi_t* fmi, uint32_t size, uint8_t* data);
bool h2fmi_nand_reset(h2fmi_t* fmi, h2fmi_ce_t ce);
bool h2fmi_nand_read_id(h2fmi_t* fmi, h2fmi_ce_t ce, uint32_t* id);
bool h2fmi_pio_read_sector(h2fmi_t* fmi, void* buf);
// =============================================================================
// implementation function declarations not used by SecureROM
// =============================================================================
#if (!H2FMI_BOOTROM)
bool h2fmi_init_fil(h2fmi_t* fmi, uint32_t interface, void* scratch_buf);
void h2fmi_init_sys(h2fmi_t* fmi);
bool h2fmi_erase_blocks(h2fmi_t* fmi, uint32_t ce, uint32_t block, bool* status_failed);
bool h2fmi_write_page(h2fmi_t* fmi, uint32_t ce, uint32_t page, uint8_t* data_buf, uint8_t* meta_buf, bool* status_failed);
bool h2fmi_read_page(h2fmi_t* fmi, uint32_t ce, uint32_t page, uint8_t* data_buf, uint8_t* meta_buf, uint8_t* max_corrected, bool* is_clean);
bool h2fmi_write_multi(h2fmi_t* fmi, uint32_t page_count, uint32_t* chip_enable_array, uint32_t* page_number_array, uint8_t** data_buf_array, uint8_t** meta_buf_array, bool* status_failed);
bool h2fmi_reset_and_read_chipids(h2fmi_t* fmi, h2fmi_chipid_t* ids);
bool h2fmi_nand_reset_all(h2fmi_t* fmi);
void h2fmi_nand_read_chipid(h2fmi_t* fmi, h2fmi_ce_t ce, h2fmi_chipid_t* id);
uint32_t h2fmi_config_raw_data_format(h2fmi_t* fmi);
uint32_t h2fmi_config_raw_spare_format(void);
uint32_t h2fmi_config_page_format(h2fmi_t* fmi);
void h2fmi_config_page_addr(h2fmi_t* fmi, uint32_t page);
bool h2fmi_using_16bit_ecc(h2fmi_t* fmi);
bool h2fmi_read_raw_page(h2fmi_t* fmi, uint32_t ce, uint32_t page, uint8_t* data_buf, uint8_t* spare_buf);
bool h2fmi_wait_status(h2fmi_t* fmi, uint8_t io_mask, uint8_t io_cond, uint8_t* status);
void h2fmi_dma_data_done_handler(void* arg);
void h2fmi_dma_meta_done_handler(void* arg);
void h2fmiInitVirtToPhysMap(void);
void h2fmiMapBankToBusAndEnable(uint32_t bank, uint32_t bus, h2fmi_ce_t enable);
h2fmi_t* h2fmiTranslateBankToBus(uint32_t bank);
h2fmi_ce_t h2fmiTranslateBankToCe(uint32_t bank);
#endif // !H2FMI_BOOTROM
// =============================================================================
// implementation function declarations used only for debug during development
//
// note that these are designed so that the calls will disappear when
// not compiling for debug
// =============================================================================
#if (H2FMI_DEBUG)
bool h2fmi_test_hook(h2fmi_t* fmi);
void h2fmi_spew_config(h2fmi_t* fmi);
void h2fmi_spew_status_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_spew_fmi_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_spew_fmc_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_spew_ecc_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_spew_regs(h2fmi_t* fmi, const char* prefix);
void h2fmi_spew_buffer(uint8_t* buf, size_t size);
#else
#define h2fmi_test_hook(fmi_ignored) true
#define h2fmi_spew_config(fmi_ignored)
#define h2fmi_spew_status_regs(fmi_ignored, prefix_ignored)
#define h2fmi_spew_fmi_regs(fmi_ignored, prefix_ignored)
#define h2fmi_spew_fmc_regs(fmi_ignored, prefix_ignored)
#define h2fmi_spew_ecc_regs(fmi_ignored, prefix_ignored)
#define h2fmi_spew_regs(fmi_ignored, prefix_ignored)
#define h2fmi_spew_buffer(buf_ignored, size_ignored)
#endif
#endif // _H2FMI_PRIVATE_H_
// ********************************** EOF **************************************
+761
View File
@@ -0,0 +1,761 @@
// *****************************************************************************
//
// File: H2fmi_regs.h
//
// *****************************************************************************
//
// Notes:
//
// - register bitfield definitions are only good for creating bitfield in
// register position
//
// - consider adding definitions for extracting value from register position
//
// *****************************************************************************
//
// Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 Computer, Inc.
//
// *****************************************************************************
#ifndef _H2FMI_REGS_H_
#define _H2FMI_REGS_H_
#include <sys/types.h>
#include <platform/soc/hwregbase.h>
// =============================================================================
// preprocessor compilation control
// =============================================================================
// Change the constant below to true if you want to see all FMI
// subsystem register writes; note that doing so is likely to change
// timing and therefore behavior, so it should be a rare case that you
// would ever want to do this.
#define H2FMI_TRACE_REG_WRITES false
// =============================================================================
// register access macros
// =============================================================================
#define h2fmi_wr(fmi, reg, val) ((fmi)->regs[(reg) >> 2] = (val))
#define h2fmi_rd(fmi, reg) ((fmi)->regs[(reg) >> 2])
#define h2fmi_rd8(fmi, reg) (((volatile uint8_t*)((fmi)->regs))[reg])
// =============================================================================
// register bases and offsets
// =============================================================================
#define FMI0 ((volatile uint32_t*)FMI0_BASE_ADDR)
#define FMI1 ((volatile uint32_t*)FMI1_BASE_ADDR)
#if FMI_VERSION == 0
#define FMI_BA(offset) ((uint32_t)(0x000 + offset))
#define FMC_BA(offset) ((uint32_t)(0x400 + offset))
#define ECC_BA(offset) ((uint32_t)(0x800 + offset))
#else
#define FMI_BA(offset) ((uint32_t)(0x00000 + offset))
#define FMC_BA(offset) ((uint32_t)(0x40000 + offset))
#define ECC_BA(offset) ((uint32_t)(0x80000 + offset))
#endif
#define FMI_CONFIG FMI_BA(0x00)
#define FMI_CONTROL FMI_BA(0x04)
#define FMI_STATUS FMI_BA(0x08)
#define FMI_INT_PEND FMI_BA(0x0C)
#define FMI_INT_EN FMI_BA(0x10)
#define FMI_DATA_BUF FMI_BA(0x14)
#define FMI_META_FIFO FMI_BA(0x18)
#define FMI_DEBUG0 FMI_BA(0x1C)
#define FMI_DEBUG1 FMI_BA(0x20)
#define FMI_DEBUG2 FMI_BA(0x24)
#if FMI_VERSION > 2
#define FMI_SCRAMBLER_SEED_FIFO FMI_BA(0x3C)
#endif
#if FMI_VERSION > 0
#define FMI_DEBUG3 FMI_BA(0x28)
#define FMI_HW_VERSION FMI_BA(0x30)
#define FMI_DATA_SIZE FMI_BA(0x34)
#endif
#define FMC_ON FMC_BA(0x00)
#define FMC_VER FMC_BA(0x04)
#define FMC_IF_CTRL FMC_BA(0x08)
#define FMC_CE_CTRL FMC_BA(0x0C)
#define FMC_RW_CTRL FMC_BA(0x10)
#define FMC_CMD FMC_BA(0x14)
#define FMC_ADDR0 FMC_BA(0x18)
#define FMC_ADDR1 FMC_BA(0x1C)
#define FMC_ADDRNUM FMC_BA(0x20)
#define FMC_DATANUM FMC_BA(0x24)
#define FMC_UNDEF0 FMC_BA(0x28)
#define FMC_UNDEF1 FMC_BA(0x2C)
#define FMC_TO_CTRL FMC_BA(0x30)
#define FMC_TO_CNT FMC_BA(0x34)
#define FMC_UNDEF2 FMC_BA(0x38)
#define FMC_UNDEF3 FMC_BA(0x3C)
#define FMC_INTMASK FMC_BA(0x40)
#define FMC_STATUS FMC_BA(0x44)
#define FMC_NAND_STATUS FMC_BA(0x48)
#define FMC_RBB_CONFIG FMC_BA(0x4C)
#define FMC_LOCK0_L FMC_BA(0x50)
#define FMC_LOCK0_H FMC_BA(0x54)
#define FMC_LOCK1_L FMC_BA(0x58)
#define FMC_LOCK1_H FMC_BA(0x5C)
#define FMC_LOCK2_L FMC_BA(0x60)
#define FMC_LOCK2_H FMC_BA(0x64)
#define FMC_ALARMCMD FMC_BA(0x68)
#define FMC_REJECTCMD FMC_BA(0x6C)
#define ECC_VERSION ECC_BA(0x00)
#define ECC_CON0 ECC_BA(0x04)
#define ECC_CON1 ECC_BA(0x08)
#define ECC_RESULT ECC_BA(0x0C)
#define ECC_PND ECC_BA(0x10)
#define ECC_MASK ECC_BA(0x14)
#define ECC_HISTORY ECC_BA(0x18)
#define ECC_CORE_SW_RESET ECC_BA(0x1C)
#define ECC_LOC0 ECC_BA(0x20)
#define ECC_LOC1 ECC_BA(0x24)
#define ECC_LOC2 ECC_BA(0x28)
#define ECC_LOC3 ECC_BA(0x2C)
#define ECC_LOC4 ECC_BA(0x30)
#define ECC_LOC5 ECC_BA(0x34)
#define ECC_LOC6 ECC_BA(0x38)
#define ECC_UNDEF0 ECC_BA(0x3C)
#define ECC_PARITY0 ECC_BA(0x40)
#define ECC_PARITY1 ECC_BA(0x44)
#define ECC_PARITY2 ECC_BA(0x48)
#define ECC_PARITY3 ECC_BA(0x4C)
#define ECC_PARITY4 ECC_BA(0x50)
#define ECC_PARITY5 ECC_BA(0x54)
#define ECC_PARITY6 ECC_BA(0x58)
// =============================================================================
// FMI_CONFIG bitfields
// =============================================================================
#if FMI_VERSION == 0
#define FMI_CONFIG__DMA_BURST(n) (((n) & 0x7) << 17)
#define FMI_CONFIG__LBA_MODE(v) (((v) & 0x3) << 15)
#define FMI_CONFIG__ECC_MODE(m) (((m) & 0x1) << 14)
#define FMI_CONFIG__META_PER_ENVELOPE(n) (((n) & 0x3F) << 8)
#define FMI_CONFIG__META_PER_PAGE(n) (((n) & 0x3F) << 2)
#define FMI_CONFIG__PAGE_SIZE(n) (((n) & 0x03) << 0)
#else
#define FMI_CONFIG__ECC_CORRECTABLE_BITS(m) (((m) & 0x1F) << 3)
#define FMI_CONFIG__DMA_BURST(n) (((n) & 0x7) << 0)
#endif
#define FMI_CONFIG__DMA_BURST__32_CYCLES FMI_CONFIG__DMA_BURST(5)
#define FMI_CONFIG__DMA_BURST__16_CYCLES FMI_CONFIG__DMA_BURST(4)
#define FMI_CONFIG__DMA_BURST__8_CYCLES FMI_CONFIG__DMA_BURST(3)
#define FMI_CONFIG__DMA_BURST__4_CYCLES FMI_CONFIG__DMA_BURST(2)
#define FMI_CONFIG__DMA_BURST__2_CYCLES FMI_CONFIG__DMA_BURST(1)
#define FMI_CONFIG__DMA_BURST__1_CYCLES FMI_CONFIG__DMA_BURST(0)
#if FMI_VERSION == 0
#define FMI_CONFIG__LBA_MODE__NORMAL FMI_CONFIG__LBA_MODE(0)
#define FMI_CONFIG__LBA_MODE__BYPASS_ECC FMI_CONFIG__LBA_MODE(1)
#define FMI_CONFIG__LBA_MODE__LBA_TYPE_AB FMI_CONFIG__LBA_MODE(2)
#define FMI_CONFIG__LBA_MODE__LBA_TYPE_C FMI_CONFIG__LBA_MODE(3)
#define FMI_CONFIG__ECC_MODE__16BIT FMI_CONFIG__ECC_MODE(1)
#define FMI_CONFIG__ECC_MODE__8BIT FMI_CONFIG__ECC_MODE(0)
#define FMI_CONFIG__PAGE_SIZE__2K FMI_CONFIG__PAGE_SIZE(0)
#define FMI_CONFIG__PAGE_SIZE__4K FMI_CONFIG__PAGE_SIZE(1)
#define FMI_CONFIG__PAGE_SIZE__8K FMI_CONFIG__PAGE_SIZE(2)
#define FMI_CONFIG__PAGE_SIZE__512 FMI_CONFIG__PAGE_SIZE(3)
#else
#define FMI_CONFIG__ECC_MAX_CORRECTION FMI_CONFIG__ECC_CORRECTABLE_BITS(30)
#endif
#if FMI_VERSION > 2
#define FMI_CONFIG__ENABLE_WHITENING (0x1UL << 8)
#endif
#if FMI_VERSION > 3
#define FMI_CONFIG__SCRAMBLE_SEED (0x1UL << 14)
#endif
// =============================================================================
// FMI_CONTROL bitfields
// =============================================================================
#if FMI_VERSION == 0
#define FMI_CONTROL__MODE(m) (((m) & 0x3) << 1)
#define FMI_CONTROL__START_BIT (0x1UL << 0)
#define FMI_CONTROL__MODE__IDLE FMI_CONTROL__MODE(0)
#define FMI_CONTROL__MODE__READ FMI_CONTROL__MODE(1)
#define FMI_CONTROL__MODE__WRITE FMI_CONTROL__MODE(2)
#define FMI_CONTROL__MODE__UNDEF FMI_CONTROL__MODE(3)
#else
#if FMI_VERSION > 3
#define FMI_CONTROL__RESET_SEED (0x1UL << 11)
#endif
#define FMI_CONTROL__BUFFER_1_LOCK(m) (((m) & 0x3) << 5)
#define FMI_CONTROL__BUFFER_0_LOCK(m) (((m) & 0x3) << 3)
#define FMI_CONTROL__MODE(m) (((m) & 0x3) << 1)
#define FMI_CONTROL__START_BIT (0x1UL << 0)
#define FMI_CONTROL__MODE__IDLE FMI_CONTROL__MODE(0)
#define FMI_CONTROL__MODE__READ FMI_CONTROL__MODE(1)
#define FMI_CONTROL__MODE__WRITE FMI_CONTROL__MODE(2)
#define FMI_CONTROL__MODE__SOFTWARE_RESET FMI_CONTROL__MODE(3)
#define FMI_CONTROL__BUFFER_0_LOCK_FREE FMI_CONTROL__BUFFER_0_LOCK(0)
#define FMI_CONTROL__BUFFER_0_LOCK_DMA FMI_CONTROL__BUFFER_0_LOCK(1)
#define FMI_CONTROL__BUFFER_0_LOCK_ECC FMI_CONTROL__BUFFER_0_LOCK(2)
#define FMI_CONTROL__BUFFER_0_LOCK_FMC FMI_CONTROL__BUFFER_0_LOCK(3)
#define FMI_CONTROL_BUFFER_1_LOCK_FREE FMI_CONTROL__BUFFER_1_LOCK(0)
#define FMI_CONTROL_BUFFER_1_LOCK_DMA FMI_CONTROL__BUFFER_1_LOCK(1)
#define FMI_CONTROL_BUFFER_1_LOCK_ECC FMI_CONTROL__BUFFER_1_LOCK(2)
#define FMI_CONTROL_BUFFER_1_LOCK_FMC FMI_CONTROL__BUFFER_1_LOCK(3)
#endif
// =============================================================================
// FMI_STATUS bitfields
// =============================================================================
#define FMI_STATUS__FMC_ACTIVE (0x1UL << 3)
#define FMI_STATUS__ECC_ACTIVE (0x1UL << 2)
#define FMI_STATUS__DMA_ACTIVE (0x1UL << 1)
#define FMI_STATUS__BUS_ACTIVE (0x1UL << 0)
// =============================================================================
// FMI_INT_PEND bitfields
// =============================================================================
#if FMI_VERSION == 0
#define FMI_INT_PEND__ECC_INTERRUPT (0x1UL << 14)
#define FMI_INT_PEND__ECC_READY_BUSY (0x1UL << 13)
#define FMI_INT_PEND__ECC_DONE (0x1UL << 12)
#define FMI_INT_PEND__FMC_INTERRUPT (0x1UL << 11)
#define FMI_INT_PEND__FMC_READY_BUSY (0x1UL << 10)
#else
#define FMI_INT_PEND__ECC_INTERRUPT (0x1UL << 21)
#define FMI_INT_PEND__ECC_READY_BUSY (0x1UL << 20)
#define FMI_INT_PEND__ECC_DONE (0x1UL << 19)
#define FMI_INT_PEND__FMC_INTERRUPT (0x1UL << 18)
#define FMI_INT_PEND__FMC_READY_BUSY(n) (((n) & 0xFF << 10)
#endif
#define FMI_INT_PEND__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_PEND__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_PEND__FMC_NSERR (0x1UL << 7)
#define FMI_INT_PEND__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_PEND__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_PEND__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_PEND__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_PEND__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_PEND__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_PEND__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_INT_EN bitfields
// =============================================================================
#define FMI_INT_EN__ECC_INTERRUPT (0x1UL << 14)
#define FMI_INT_EN__ECC_READY_BUSY (0x1UL << 13)
#define FMI_INT_EN__ECC_DONE (0x1UL << 12)
#define FMI_INT_EN__FMC_INTERRUPT (0x1UL << 11)
#define FMI_INT_EN__FMC_READY_BUSY (0x1UL << 10)
#define FMI_INT_EN__FMC_TIMEOUT (0x1UL << 9)
#define FMI_INT_EN__FMC_NSRBBDONE (0x1UL << 8)
#define FMI_INT_EN__FMC_NSERR (0x1UL << 7)
#define FMI_INT_EN__FMC_TRANSDONE (0x1UL << 6)
#define FMI_INT_EN__FMC_ADDRESSDONE (0x1UL << 5)
#define FMI_INT_EN__FMC_CMDDONE (0x1UL << 4)
#define FMI_INT_EN__META_FIFO_OVERFLOW (0x1UL << 3)
#define FMI_INT_EN__META_FIFO_UNDERFLOW (0x1UL << 2)
#define FMI_INT_EN__LAST_FMC_DONE (0x1UL << 1)
#define FMI_INT_EN__TRANSACTION_COMPLETE (0x1UL << 0)
// =============================================================================
// FMI_DEBUG0 bitfields
// =============================================================================
#if FMI_VERSION == 0
#define FMI_DEBUG0__DMA_BLOCK_COUNT(n) (((n) & 0x1F) << 24)
#define FMI_DEBUG0__DATA_TC_RECEIVED (0x1UL << 23)
#define FMI_DEBUG0__DATA_DMA_DONE (0x1UL << 22)
#define FMI_DEBUG0__DMA_DATA_RW_PTR(n) (((n) & 0x7F) << 15)
#else
#define FMI_DEBUG0__DMA_SECTOR_COUNT(n) (((n) & 0x7F) << 25)
#define FMI_DEBUG0__DATA_TC_RECEIVED (0x1UL << 24)
#define FMI_DEBUG0__DMA_WORD_COUNT(n) (((n) & 0x1FF << 15)
#endif
#define FMI_DEBUG0__META_BYTE_COUNT(n) (((n) & 0x3F) << 9)
#define FMI_DEBUG0__FMC_TASKS_PENDING(n) (((n) & 0x3) << 7)
#define FMI_DEBUG0__ECC_TASKS_PENDING(n) (((n) & 0x3) << 5)
#define FMI_DEBUG0__DMA_TASKS_PENDING(n) (((n) & 0x3) << 3)
#define FMI_DEBUG0__FMC_TARGET_BUFFER(b) (((b) & 0x1) << 2)
#define FMI_DEBUG0__ECC_TARGET_BUFFER(b) (((b) & 0x1) << 1)
#define FMI_DEBUG0__DMA_TARGET_BUFFER(b) (((b) & 0x1) << 0)
// =============================================================================
// FMI_DEBUG1 bitfields
// =============================================================================
#if FMI_VERSION == 0
#define FMI_DEBUG1__META_TC_RECEIVED (0x1UL << 28)
#define FMI_DEBUG1__NEXT_META_LOCATION(n) (((n) & 0x3F) << 22)
#define FMI_DEBUG1__FMC_PAGE_DONE (0x1UL << 21)
#define FMI_DEBUG1__FMC_BLOCK_COUNT(n) (((n) & 0x1F) << 16)
#else
#define FMI_DEBUG1__METADATA_TC_RECEIVED (0x1UL << 27)
#define FMI_DEBUG1__METADATA_ADDRESS(n) (((n) & 0x7FF) << 16)
#endif
#define FMI_DEBUG1__META_FIFO_LEVEL(n) (((n) & 0x3F) << 10)
#define FMI_DEBUG1__META_FIFO_WRITE_PTR(n) (((n) & 0x1F) << 5)
#define FMI_DEBUG1__META_FIFO_READ_PTR(n) (((n) & 0x1F) << 0)
// =============================================================================
// FMI_DEBUG2 bitfields
// =============================================================================
#if FMI_VERSION == 0
#define FMI_DEBUG2__BUFFER_1_META_BYTES(n) (((n) & 0x3F) << 24)
#define FMI_DEBUG2__BUFFER_0_META_BYTES(n) (((n) & 0x3F) << 18)
#define FMI_DEBUG2__META_BYTES_REMAINING(n) (((n) & 0x3F) << 12)
#define FMI_DEBUG2__PAUSED_AHB_ADDRESS(n) (((n) & 0xFF) << 4)
#define FMI_DEBUG2__AHB_STATE(n) (((n) & 0x3) << 1)
#define FMI_DEBUG2__PAUSED_AHB_BUS (0x1UL << 0)
#else
#define FMI_DEBUG2__BUFFER_1_META_BYTES(n) (((n) & 0x3F) << 19)
#define FMI_DEBUG2__BUFFER_0_META_BYTES(n) (((n) & 0x3F) << 13)
#define FMI_DEBUG2__META_BYTES_REMAINING(n) (((n) & 0x3F) << 7)
#define FMI_DEBUG2__DATA_STATE(n) (((n) & 0xF) << 3)
#define FMI_DEBUG2__AHB_STATE(n) (((n) & 0x7) << 0)
#endif
// =============================================================================
// FMI_DEBUG3 bitfields
// =============================================================================
#if FMI_VERSION > 0
#define FMI_DEBUG3__PAUSED_AHB_ADDRESS(n) (((n) & 0xFF) << 9)
#define FMI_DEBUG3__PAUSE_AHB_BUS (0x1UL << 8)
#define FMI_DEBUG3__FMC_PAGE_DONE (0x1UL << 7)
#define FMI_DEBUG3__FMC_BLOCK_COUNT(n) (((n) & 0x7F) << 0)
#endif
// =============================================================================
// FMI_DATA_SIZE bitfields
// =============================================================================
#if FMI_VERSION > 0
#define FMI_DATA_SIZE__META_BYTES_PER_ENVELOPE(n) (((n) & 0x3F) << 25)
#define FMI_DATA_SIZE__META_BYTES_PER_PAGE(n) (((n) & 0x3F) << 19)
#define FMI_DATA_SIZE__BYTES_PER_SECTOR(n) (((n) & 0x7FF) << 8)
#define FMI_DATA_SIZE__SECTORS_PER_PAGE(n) (((n) & 0xFF) << 0)
#endif
// =============================================================================
// FMC_ON bitfields
// =============================================================================
#define FMC_ON__SWRST (0x1UL << 8)
#define FMC_ON__LOCK_ON (0x1UL << 4)
#define FMC_ON__CLKGATING_RDY (0x1UL << 1)
#define FMC_ON__ENABLE (0x1UL << 0)
#define FMC_ON__DISABLE (!FMC_ON__ENABLE)
// =============================================================================
// FMC_IF_CTRL bitfields
// =============================================================================
#define FMC_IF_CTRL__WPB (0x1UL << 21)
#define FMC_IF_CTRL__RBBEN (0x1UL << 20)
#define FMC_IF_CTRL__DCCYCLE(v) (((v) & 0xF) << 16)
#define FMC_IF_CTRL__REB_SETUP(v) (((v) & 0xF) << 12)
#define FMC_IF_CTRL__REB_HOLD(v) (((v) & 0xF) << 8)
#define FMC_IF_CTRL__WEB_SETUP(v) (((v) & 0xF) << 4)
#define FMC_IF_CTRL__WEB_HOLD(v) (((v) & 0xF) << 0)
#define FMC_IF_CTRL__TIMING_MAX_CLOCKS (0xFUL)
// =============================================================================
// FMC_CE_CTRL bitfields
// =============================================================================
#define FMC_CE_CTRL__CE_COUNT (8)
#define FMC_CE_CTRL__CEB(n) (0x1UL << ((n) & 0x7))
#define FMC_CE_CTRL__CEB7 FMC_CE_CTRL__CEB(7)
#define FMC_CE_CTRL__CEB6 FMC_CE_CTRL__CEB(6)
#define FMC_CE_CTRL__CEB5 FMC_CE_CTRL__CEB(5)
#define FMC_CE_CTRL__CEB4 FMC_CE_CTRL__CEB(4)
#define FMC_CE_CTRL__CEB3 FMC_CE_CTRL__CEB(3)
#define FMC_CE_CTRL__CEB2 FMC_CE_CTRL__CEB(2)
#define FMC_CE_CTRL__CEB1 FMC_CE_CTRL__CEB(1)
#define FMC_CE_CTRL__CEB0 FMC_CE_CTRL__CEB(0)
// =============================================================================
// FMC_RW_CTRL bitfields
// =============================================================================
#define FMC_RW_CTRL__REBHOLD (0x1UL << 6)
#define FMC_RW_CTRL__WR_MODE (0x1UL << 5)
#define FMC_RW_CTRL__RD_MODE (0x1UL << 4)
#define FMC_RW_CTRL__ADDR_MODE (0x1UL << 3)
#define FMC_RW_CTRL__CMD3_MODE (0x1UL << 2)
#define FMC_RW_CTRL__CMD2_MODE (0x1UL << 1)
#define FMC_RW_CTRL__CMD1_MODE (0x1UL << 0)
// =============================================================================
// FMC_CMD bitfields
// =============================================================================
#define FMC_CMD__CMD3(c) (((c) & 0xFF) << 16)
#define FMC_CMD__CMD2(c) (((c) & 0xFF) << 8)
#define FMC_CMD__CMD1(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR0 bitfields
// =============================================================================
#define FMC_ADDR0__SEQ3(a) (((a) & 0xFF) << 24)
#define FMC_ADDR0__SEQ2(a) (((a) & 0xFF) << 16)
#define FMC_ADDR0__SEQ1(a) (((a) & 0xFF) << 8)
#define FMC_ADDR0__SEQ0(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDR1 bitfields
// =============================================================================
#define FMC_ADDR1__SEQ7(a) (((a) & 0xFF) << 24)
#define FMC_ADDR1__SEQ6(a) (((a) & 0xFF) << 16)
#define FMC_ADDR1__SEQ5(a) (((a) & 0xFF) << 8)
#define FMC_ADDR1__SEQ4(a) (((a) & 0xFF) << 0)
// =============================================================================
// FMC_ADDRNUM bitfields
// =============================================================================
#define FMC_ADDRNUM__NUM(n) (((n) & 0x7) << 0)
// =============================================================================
// FMC_DATANUM bitfields
// =============================================================================
#if FMI_VERSION == 0
#define FMC_DATANUM__NUM(n) (((n) & 0x3F) << 0)
#else
#define FMC_DATANUM__NUM(n) (((n) & 0x3FF) << 0)
#endif
// =============================================================================
// FMC_TO_CTRL bitfields
// =============================================================================
#define FMC_TO_CTRL__EN (0x1UL << 12)
#define FMC_TO_CTRL__DIV(d) (((d) & 0xF) << 8)
#define FMC_TO_CTRL__VAL(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_TO_CNT bitfields
// =============================================================================
#define FMC_TO_CNT__CNT(c) (((c) & 0xFF) << 0)
// =============================================================================
// FMC_INTMASK bitfields
// =============================================================================
#define FMC_INTMASK__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_INTMASK__RBBDONE7 FMC_INTMASK__RBBDONE(7)
#define FMC_INTMASK__RBBDONE6 FMC_INTMASK__RBBDONE(6)
#define FMC_INTMASK__RBBDONE5 FMC_INTMASK__RBBDONE(5)
#define FMC_INTMASK__RBBDONE4 FMC_INTMASK__RBBDONE(4)
#define FMC_INTMASK__RBBDONE3 FMC_INTMASK__RBBDONE(3)
#define FMC_INTMASK__RBBDONE2 FMC_INTMASK__RBBDONE(2)
#define FMC_INTMASK__RBBDONE1 FMC_INTMASK__RBBDONE(1)
#define FMC_INTMASK__RBBDONE0 FMC_INTMASK__RBBDONE(0)
#define FMC_INTMASK__TIMEOUT (0x1UL << 7)
#define FMC_INTMASK__NSERR (0x1UL << 6)
#define FMC_INTMASK__NSRBBDONE (0x1UL << 5)
#define FMC_INTMASK__TRANSDONE (0x1UL << 4)
#define FMC_INTMASK__ADDRESSDONE (0x1UL << 3)
#define FMC_INTMASK__CMD3DONE (0x1UL << 2)
#define FMC_INTMASK__CMD2DONE (0x1UL << 1)
#define FMC_INTMASK__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_STATUS bitfields
// =============================================================================
#define FMC_STATUS__RBBDONE(n) (0x1UL << (((n) & 0x7) + 8))
#define FMC_STATUS__EMERGENCY2 (0x1UL << 21)
#define FMC_STATUS__EMERGENCY01 (0x1UL << 20)
#define FMC_STATUS__RDATADIRTY (0x1UL << 16)
#define FMC_STATUS__RBBDONE7 FMC_STATUS__RBBDONE(7)
#define FMC_STATUS__RBBDONE6 FMC_STATUS__RBBDONE(6)
#define FMC_STATUS__RBBDONE5 FMC_STATUS__RBBDONE(5)
#define FMC_STATUS__RBBDONE4 FMC_STATUS__RBBDONE(4)
#define FMC_STATUS__RBBDONE3 FMC_STATUS__RBBDONE(3)
#define FMC_STATUS__RBBDONE2 FMC_STATUS__RBBDONE(2)
#define FMC_STATUS__RBBDONE1 FMC_STATUS__RBBDONE(1)
#define FMC_STATUS__RBBDONE0 FMC_STATUS__RBBDONE(0)
#define FMC_STATUS__TIMEOUT (0x1UL << 7)
#define FMC_STATUS__NSERR (0x1UL << 6)
#define FMC_STATUS__NSRBBDONE (0x1UL << 5)
#define FMC_STATUS__TRANSDONE (0x1UL << 4)
#define FMC_STATUS__ADDRESSDONE (0x1UL << 3)
#define FMC_STATUS__CMD3DONE (0x1UL << 2)
#define FMC_STATUS__CMD2DONE (0x1UL << 1)
#define FMC_STATUS__CMD1DONE (0x1UL << 0)
// =============================================================================
// FMC_RBB_CONFIG bitfields
// =============================================================================
#define FMC_RBB_CONFIG__POL(v) (((v) & 0xFF) << 8)
#define FMC_RBB_CONFIG__POS(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_ALARMCMD bitfields
// =============================================================================
#define FMC_ALARMCMD__READ1(v) (((v) & 0xFF) << 16)
#define FMC_ALARMCMD__PROG1(v) (((v) & 0xFF) << 8)
#define FMC_ALARMCMD__ERASE1(v) (((v) & 0xFF) << 0)
// =============================================================================
// FMC_REJECTCMD bitfields
// =============================================================================
#define FMC_REJECTCMD__READ2(v) (((v) & 0xFF) << 16)
#define FMC_REJECTCMD__PROG2(v) (((v) & 0xFF) << 8)
#define FMC_REJECTCMD__ERASE2(v) (((v) & 0xFF) << 0)
// =============================================================================
// ECC_CON0 bitfields
// =============================================================================
#define ECC_CON0__START_ENC (0x1UL << 1)
#define ECC_CON0__START_DEC (0x1UL << 0)
#if FMI_VERSION == 0
#define ECC_CON0__META_LENGTH(n) (((n) & 0x1F) << 8)
#define ECC_CON0__MODE_SEL(m) (((m) & 0x1) << 2)
#define ECC_CON0__MODE_SEL__16BIT ECC_CON0__MODE_SEL(1)
#define ECC_CON0__MODE_SEL__8BIT ECC_CON0__MODE_SEL(0)
#else
#define ECC_CON0__INFORMATION_LENGTH(n) (((n) & 0x7FF) << 16)
#define ECC_CON0__MODE_SEL(m) (((m) & 0x1F) << 4)
#define ECC_CON0__MAX_CORRECTION ECC_CON0__MODE_SEL(30)
#endif
// =============================================================================
// ECC_CON1 bitfields
// =============================================================================
#if FMI_VERSION > 0
#define ECC_CON1__ALLOWED_STUCK_BIT_IN_FP(n) (((n) & 0x1F) << 16)
#endif
#if FMI_VERSION > 2
#define ECC_CON1__IMPLICIT_WRITE_MARK (1UL << 31)
#endif
#define ECC_CON1__ERROR_ALERT_LEVEL(n) (((n) & 0x1F) << 8)
#define ECC_CON1__INT_ENABLE(b) (((b) & 0x1) << 7)
#define ECC_CON1__INT_ENABLE__ENABLE ECC_CON1__INT_ENABLE(1)
#define ECC_CON1__INT_ENABLE__DISABLE ECC_CON1__INT_ENABLE(0)
// =============================================================================
// ECC_RESULT bitfields
// =============================================================================
#if FMI_VERSION == 0
#define ECC_RESULT__ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_RESULT__ERROR_FLAG (0x1UL << 0)
#else
#define ECC_RESULT_FIFO__ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_RESULT_FIFO__STUCK_BIT_EXCEEDED (0x1UL << 14)
#define ECC_RESULT_FIFO__STUCK_BIT_CNT(n) (((n) & 0x3F) << 8)
#define ECC_RESULT_FIFO__ALL_FF (0x1UL << 3)
#define ECC_RESULT_FIFO__ALL_ZERO (0x1UL << 2)
#define ECC_RESULT_FIFO__FREE_PAGE (0x1UL << 1)
#define ECC_RESULT_FIFO__UNCORRECTABLE (0x1UL << 0)
#define ECC_RESULT_FIFO__RESET_FIFO (0x1UL << 0)
#endif
// =============================================================================
// ECC_PND bitfields
// =============================================================================
#if FMI_VERSION == 0
#define ECC_PND__BCH_ALL_FF (0x1UL << 6)
#define ECC_PND__SECTOR_ERROR_ALERT (0x1UL << 5)
#define ECC_PND__READY_BUSY (0x1UL << 4)
#define ECC_PND__UNCORRECTABLE (0x1UL << 3)
#define ECC_PND__DEC_DONE (0x1UL << 2)
#define ECC_PND__ENC_DONE (0x1UL << 1)
#define ECC_PND__ENC_DEC_DONE (0x1UL << 0)
#else
#define ECC_PND__MAX_STUCK_BIT_CNT(n) (((n) & 0x3F) << 24)
#define ECC_PND__MAX_ERROR_CNT(n) (((n) & 0x1F) << 16)
#define ECC_PND__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_PND__SOME_ALL_FF (0x1UL << 8)
#define ECC_PND__SOME_ALL_ZERO (0x1UL << 7)
#define ECC_PND__ALL_FREE_PAGE (0x1UL << 6)
#define ECC_PND__SOME_ERROR_ALERT (0x1UL << 5)
#define ECC_PND__READY_BUSY (0x1UL << 4)
#define ECC_PND__UNCORRECTABLE (0x1UL << 3)
#define ECC_PND__ENC_DONE (0x1UL << 2) // note swap from 8920
#define ECC_PND__DEC_DONE (0x1UL << 1) // note swap from 8920
#define ECC_PND__ENC_DEC_DONE (0x1UL << 0)
#endif
// =============================================================================
// ECC_MASK bitfields
// =============================================================================
#if FMI_VERSION == 0
#define ECC_MASK__SECTOR_ERR_ALERT_MASK (0x1UL << 5)
#define ECC_MASK__UNCORRECTABLE_MASK (0x1UL << 3)
#define ECC_MASK__DEC_DONE_MASK (0x1UL << 2)
#define ECC_MASK__ENC_DONE_MASK (0x1UL << 1)
#define ECC_MASK__ENC_DEC_DONE_MASK (0x1UL << 0)
#else
#define ECC_MASK__SOME_STUCK_BIT_EXCEEDED (0x1UL << 9)
#define ECC_MASK__SOME_ALL_FF_MASK (0x1UL << 8)
#define ECC_MASK__SOME_ALL_ZERO_MASK (0x1UL << 7)
#define ECC_MASK__SOME_ERROR_ALERT_MASK (0x1UL << 5)
#define ECC_MASK__ANY_UNCORRECTABLE_MASK (0x1UL << 3)
#define ECC_MASK__ENC_DONE_MASK (0x1UL << 2) // note swap from 8920
#define ECC_MASK__DEC_DONE_MASK (0x1UL << 1) // note swap from 8920
#define ECC_MASK__ENC_DEC_DONE_MASK (0x1UL << 0)
#endif
// =============================================================================
// ECC_HISTORY bitfields
// =============================================================================
#if FMI_VERSION == 0
#define ECC_HISTORY__ERROR_COUNT_CLEAR (0x1UL << 24)
#define ECC_HISTORY__ERROR_COUNT(n) (((n) & 0x1FFF) << 11)
#define ECC_HISTORY__DECODING_NUMBER_CLEAR (0x1UL << 10)
#define ECC_HISTORY__DECODING_NUMBER(n) (((n) & 0x3FF) << 0)
#else
#define ECC_HISTORY__ERROR_COUNT_CLEAR (0x1UL << 26)
#define ECC_HISTORY__ERROR_COUNT(n) (((n) & 0x7FFF) << 11)
#define ECC_HISTORY__DECODING_NUMBER_CLEAR (0x1UL << 10)
#define ECC_HISTORY__DECODING_NUMBER(n) (((n) & 0x3FF) << 0)
#endif
#endif // _H2FMI_REGS_H_
// ********************************** EOF **************************************
+15
View File
@@ -0,0 +1,15 @@
# Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
#
# This document is the property of Apple Computer, 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 Computer, Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
OPTIONS += WITH_HW_BOOTROM_NAND=1
ALL_OBJS += \
$(LOCAL_DIR)/H2fmi_bootrom.o
+865
View File
@@ -0,0 +1,865 @@
// *****************************************************************************
//
// File: debug.c
//
// Copyright (C) 2010-2012, 2014 Apple Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 <libDER/DER_Keys.h>
#include <libDER/DER_Decode.h>
#include <libDER/asn1Types.h>
#include "WMROAM.h"
#include <FIL.h>
#include <FILTypes.h>
#include "H2fmi_private.h"
#include "H2fmi.h"
#include "H2fmi_ppn.h"
#include <platform/memmap.h>
#include <sys/menu.h>
#include <lib/env.h>
#include <platform/clocks.h>
#include <platform/soc/chipid.h>
#include <platform/soc/hwclocks.h>
#include <lib/random.h>
#include <drivers/power.h>
#include <drivers/usb/usb_debug.h>
#if SUPPORT_PPN
extern UInt32 *g_pScratchBuf;
extern h2fmi_t g_fmi0;
extern h2fmi_t g_fmi1;
static int do_vthsweep(int argc, struct cmd_arg *argv);
static int do_ppnfw(int argc, struct cmd_arg *argv);
static int do_ppnver(int argc, struct cmd_arg *argv);
static int do_ppnrma(int argc, struct cmd_arg *args);
static int do_ppnscratchpad(int argc, struct cmd_arg *argv);
#if SUPPORT_TOGGLE_NAND
static int do_nand_dqs_delay(int argc, struct cmd_arg *args);
#endif // SUPPORT_TOGGLE_NAND
MENU_COMMAND_DEVELOPMENT(ppnfw, do_ppnfw, "Update PPN controller firmware", NULL);
MENU_COMMAND_DEVELOPMENT(ppnver, do_ppnver, "Get PPN controller firmware version", NULL);
MENU_COMMAND_DEVELOPMENT(ppnrma, do_ppnrma, "Get PPN RMA data for a particular page", NULL);
MENU_COMMAND_DEVELOPMENT(ppnscratchpad, do_ppnscratchpad, "Perform a PPN Scratch Pad test", NULL);
MENU_COMMAND_DEVELOPMENT(vthsweep, do_vthsweep, "Performs Vth sweep on a block of a given CE and dumps the data to a file", NULL);
#define VTHSWEEP_ARGC (4)
#define VENDOR_CODE__MICRON (0x2C)
#define VENDOR_CODE__HYNIX (0xAD)
#define VENDOR_CODE__SANDISK (0x45)
#define DMA_TRANSFER_LIMIT (16 * 1024 * 1024)
#define SCRATCHPAD_LEN (2 << 10) // there is currently a 2KB limit with Toshiba: rdar://problem/10134035
#define DUMPLEN (8)
#define PREFILL (0xa5)
static UInt8 scratchpad_buf_get[SCRATCHPAD_LEN];
static UInt8 scratchpad_buf_set[SCRATCHPAD_LEN];
#if SUPPORT_TOGGLE_NAND
MENU_COMMAND_DEVELOPMENT(nand_dqs_delay, do_nand_dqs_delay, "NAND DQS read delay test (see \"nand_dqs_delay help\")", NULL);
#if SUPPORT_NAND_DLL
static void dll_lock_sweep(UInt32 vdd_min, UInt32 vdd_max, UInt32 vdd_step){
UInt32 vdd;
UInt32 lock;
char pbuf[16];
printf("DLL lock sweep:\n");
printf("SOC voltage: ");
for (vdd = vdd_min; vdd <= vdd_max; vdd += vdd_step)
{
snprintf(pbuf, sizeof(pbuf), "%u mV", vdd);
printf("%-7s ", pbuf);
}
printf("\nDLL lock: ");
for (vdd = vdd_min; vdd <= vdd_max; vdd += vdd_step)
{
power_set_soc_voltage(vdd, true);
WMR_DLL_CLOCK_GATE(TRUE32);
h2fmi_dll_wr(NAND_DLL_CONTROL, NAND_DLL_CONTROL__REFERENCE(0));
WMR_DLL_CLOCK_GATE(FALSE32);
h2fmiTrainDLL(&lock);
printf("%-7u ", lock);
}
printf("\n");
power_set_soc_voltage(platform_get_base_soc_voltage(), true);
}
#endif // SUPPORT_NAND_DLL
static int do_nand_dqs_delay(int argc, struct cmd_arg *args)
{
h2fmi_ce_t ce;
UInt8 status;
UInt32 *errors;
Int32 e_min;
Int32 e_max;
Int32 e0_min;
Int32 e0_max;
Int32 i;
UInt32 ei = 0;
UInt32 di;
UInt32 iter;
UInt32 dqsd;
UInt32 vdd;
UInt32 fq ;
UInt32 fmi_mask = 3;
UInt32 freq_mask;
UInt32 vdd_min;
UInt32 vdd_max;
UInt32 vdd_step = 50;
UInt32 dqsd_min = 8;
UInt32 dqsd_max = 511;
UInt32 fmi_freq;
UInt32 rd_freq;
UInt32 tHALF_CYCLE_ori;
UInt32 def_dqsd;
UInt32 timing_size;
UInt32 errors_size;
UInt32 num_freq = 0;
UInt32 num_ce = 0;
UInt32 num_iter = 5;
UInt32 num_vdd;
UInt32 num_dqsd;
Int32 num_arg;
BOOL32 vdd_ok;
NandTimingParams timing;
if (!g_fmi0.is_toggle || !g_fmi1.is_toggle)
{
printf("Not in toggle mode.\n");
return -1;
}
memset(&timing, 0xFF, sizeof(timing));
timing_size = sizeof(timing);
FIL_GetStruct(AND_STRUCT_FIL_GET_TIMINGS, &timing, &timing_size);
freq_mask = (1 << timing.ddr_tHALFCYCLE);
vdd_min = chipid_get_soc_voltage(CHIPID_SOC_VOLTAGE_LOW);
vdd_max = chipid_get_soc_voltage(CHIPID_SOC_VOLTAGE_HIGH);
for (i = 1; i < argc; i += num_arg + 1){
if (!strcmp(args[i].str, "iter") && (argc-i > (num_arg = 1)))
{
if (args[i+1].u == 0)
{
printf("Invalid number of iterations.\n");
return -1;
}
num_iter = args[i+1].u;
}
else if (!strcmp(args[i].str, "vdd") && (argc-i > (num_arg = 3)))
{
vdd_ok = ((power_set_soc_voltage(args[i+1].u, true) == 0) && (power_set_soc_voltage(args[i+2].u, true) == 0));
power_set_soc_voltage(platform_get_base_soc_voltage(), true);
if (!vdd_ok || (args[i+1].u > args[i+2].u))
{
printf("Invalid vdd range.\n");
return -1;
}
vdd_min = args[i+1].u;
vdd_max = args[i+2].u;
vdd_step = (args[i+3].u == 0) ? 1 : args[i+3].u;
}
else if (!strcmp(args[i].str, "freq") && (argc-i > (num_arg = 1)))
{
if ((args[i+1].u < 1) || (args[i+1].u > 0xFFFF))
{
printf("Invalid 16-bit bitmask of read frequencies to test.\n");
return -1;
}
freq_mask = args[i+1].u;
}
else if (!strcmp(args[i].str, "fmi") && (argc-i > (num_arg = 1)))
{
if ((args[i+1].u < 1) || (args[i+1].u > 3))
{
printf("Invalid 2-bit bitmask of FMI channels to use.\n");
return -1;
}
fmi_mask = args[i+1].u;
}
else if (!strcmp(args[i].str, "dqsdel") && (argc-i > (num_arg = 2)))
{
if ((args[i+1].u < dqsd_min) || (args[i+2].u > dqsd_max) || (args[i+1].u > args[i+2].u))
{
printf("Invalid DQS delay range (must be between %u and %u).\n", dqsd_min, dqsd_max);
return -1;
}
dqsd_min = args[i+1].u;
dqsd_max = args[i+2].u;
}
else
{
printf("Usage: nand_dqs_delay [iter <num_iter>] [vdd <vdd_min_mv> <vdd_max_mv> <vdd_step_mv>] ");
printf("[freq <read_freq_mask>] [fmi <fmi_mask>] [dqsdel <dqs_delay_min> <dqs_delay_max>]\n");
return -1;
}
}
for(ce = 0; ce < H2FMI_MAX_CE_TOTAL; ce++)
{
if (g_fmi0.valid_ces & (1 << ce))
{
if(FIL_SUCCESS != h2fmi_ppn_set_features(&g_fmi0, ce, PPN_FEATURE__SCRATCH_PAD, (UInt8 *) scratchpad_buf_set, SCRATCHPAD_LEN, FALSE32, NULL))
{
printf("Unable to access scratch pad.\n");
return -1;
}
}
}
num_vdd = (vdd_max - vdd_min) / vdd_step + 1;
num_dqsd = dqsd_max - dqsd_min + 1;
for(fq = 0; fq < 16; fq++)
{
if (freq_mask & (1 << fq))
{
num_freq++;
}
}
for(ce = 0; ce < H2FMI_MAX_CE_TOTAL; ce++)
{
if (((fmi_mask & 1) && (g_fmi0.valid_ces & (1 << ce))) ||
((fmi_mask & 2) && (g_fmi1.valid_ces & (1 << ce))))
{
num_ce++;
}
}
errors_size = num_ce * num_freq * num_vdd * num_dqsd;
errors = calloc(errors_size, sizeof(errors[0]));
fmi_freq = clock_get_frequency(CLK_FMI);
def_dqsd = FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL_GET(g_fmi0.dqs_ctrl);
printf("NAND DQS read delay test\n");
printf("Data per iteration: %u bytes\n", SCRATCHPAD_LEN);
printf("DQS delay test range: %u - %u\n", dqsd_min, dqsd_max);
printf("FMI clock frequency: %u.%06u MHz\n", fmi_freq / 1000000, fmi_freq % 1000000);
printf("Current (default) SOC voltage: %u mV\n", platform_get_base_soc_voltage());
#if SUPPORT_NAND_DLL
dll_lock_sweep(vdd_min, vdd_max, vdd_step);
#else
printf("Current (default) DQS read delay value: %u\n", def_dqsd);
printf("Using DLL: no\n");
#endif // SUPPORT_NAND_DLL
printf("Generating random data ");
for (i = 0; i < SCRATCHPAD_LEN; i += 1000){
random_get_bytes(&scratchpad_buf_set[i], WMR_MIN(1000, SCRATCHPAD_LEN - i));
printf(".");
}
printf("\nInterface Freq [Mhz] Vdd [mV] Iter Zero error range\n");
printf("Bytes per test setting,%u\n\n", num_iter * SCRATCHPAD_LEN);
printf(",Byte errors\nDQS Delay");
tHALF_CYCLE_ori = timing.ddr_tHALFCYCLE;
for(ce = 0; ce < H2FMI_MAX_CE_TOTAL; ce++)
{
h2fmi_t* fmi;
UInt32 dqs_ctrl_ori;
if ((fmi_mask & 1) && (g_fmi0.valid_ces & (1 << ce)))
{
fmi = &g_fmi0;
}
else if ((fmi_mask & 2) && (g_fmi1.valid_ces & (1 << ce)))
{
fmi = &g_fmi1;
}
else
{
continue;
}
h2fmi_ppn_set_features(fmi, ce, PPN_FEATURE__SCRATCH_PAD, (UInt8 *) scratchpad_buf_set, SCRATCHPAD_LEN, FALSE32, NULL);
dqs_ctrl_ori = fmi->dqs_ctrl;
for(fq = 0; fq < 16; fq++)
{
if (!(freq_mask & (1 << fq))) continue;
timing.ddr_tHALFCYCLE = fq;
FIL_SetStruct(AND_STRUCT_FIL_SET_TIMINGS, &timing, timing_size);
rd_freq = fmi_freq / (timing.ddr_tHALFCYCLE + 1) / 2;
for (vdd = vdd_min; vdd <= vdd_max; vdd += vdd_step)
{
printf(",\"FMI%d:CE%d, %u.%06uMhz, %umV\"", fmi->bus_id, ce, rd_freq / 1000000, rd_freq % 1000000, vdd);
power_set_soc_voltage(vdd, true);
for (iter = 0; iter < num_iter; iter++)
{
e_min = 0;
e_max = -1;
e0_min = 0;
e0_max = -1;
for (di = 0; di < num_dqsd; di++)
{
dqsd = dqsd_min + di;
fmi->dqs_ctrl = FMC_DQS_TIMING_CTRL__DQS_READ_DELAY_CTRL(dqsd);
h2fmi_wr(fmi, FMC_DQS_TIMING_CTRL, fmi->dqs_ctrl);
h2fmi_ppn_get_feature(fmi, ce, PPN_FEATURE__SCRATCH_PAD, (UInt8 *) scratchpad_buf_get, SCRATCHPAD_LEN, &status);
WMR_ASSERT((ei+di) < errors_size);
for (i = 0; i < SCRATCHPAD_LEN; i++)
{
if (scratchpad_buf_set[i] != scratchpad_buf_get[i])
{
errors[ei+di]++;
}
}
if (!errors[ei+di])
{
e0_max = dqsd;
}
if (!errors[ei+di] && (di == 0 || errors[ei+di-1]))
{
e0_min = dqsd;
}
if ((e0_max-e0_min) > (e_max-e_min))
{
e_max = e0_max;
e_min = e0_min;
}
}
}
printf("\n");
ei += num_dqsd;
}
}
fmi->dqs_ctrl = dqs_ctrl_ori;
h2fmi_wr(fmi, FMC_DQS_TIMING_CTRL, fmi->dqs_ctrl);
}
printf("\n");
for (di = 0; di < num_dqsd; di++)
{
printf("%u", di + dqsd_min);
for (ei = 0; ei < errors_size; ei += num_dqsd)
{
printf(",%u", errors[ei+di]);
}
printf("\n");
}
power_set_soc_voltage(platform_get_base_soc_voltage(), true);
timing.ddr_tHALFCYCLE = tHALF_CYCLE_ori;
FIL_SetStruct(AND_STRUCT_FIL_SET_TIMINGS, &timing, timing_size);
free(errors);
return 0;
}
#endif // SUPPORT_TOGGLE_NAND
static bool find_blobs(void *src_buffer, UInt32 src_length, void **fw, UInt32 *fw_len, void **fwa, UInt32 *fwa_len)
{
DERReturn drtn;
DERSequence rdn;
DERItem seq, top = { src_buffer, src_length };
DERDecodedInfo topDecode, keyC, valC;
if (DR_Success != DERDecodeItem(&top, &topDecode)) {
printf("couldn't crack top level\n");
return false;
}
if ((ASN1_CONSTRUCTED|ASN1_APPLICATION) != ((ASN1_CONSTRUCTED|ASN1_APPLICATION) & topDecode.tag)) {
printf("top should be cons app\n");
return false;
}
seq.length = topDecode.content.length;
seq.data = topDecode.content.data;
if (DR_Success != DERDecodeSeqContentInit(&seq, &rdn)) {
printf("could not initialize DER decode\n");
return false;
}
while ((drtn = DERDecodeSeqNext(&rdn, &keyC)) == DR_Success) {
// Got key UTF8-str, check
if (ASN1_UTF8_STRING != keyC.tag) {
printf("key invalid: %lld\n", keyC.tag);
return false;
}
// Get value Octet-str
if (DR_Success != ((drtn = DERDecodeSeqNext(&rdn, &valC)))) {
printf("no value found for key %lld\n", keyC.tag);
return false;
}
// Check value tag
if (ASN1_OCTET_STRING != valC.tag) {
printf("value invalid: %lld\n", valC.tag);
return false;
}
// Decode
if ((11 == keyC.content.length) && (0 == strncmp((char*)keyC.content.data, "ppn-fw-args", 11))) {
*fwa = valC.content.data;
*fwa_len = valC.content.length;
} else if ((6 == keyC.content.length) && (0 == strncmp((char*)keyC.content.data, "ppn-fw", 6))) {
*fw = valC.content.data;
*fw_len = valC.content.length;
} else {
printf("unknown key\n");
return false;
}
}
return true;
}
static int do_vthsweep(int argc, struct cmd_arg *args)
{
// investigate if there's an easy way to limit which ppn fw can run this cmd
// <rdar://problem/11853291> Limit Vth sweep cmd to firmware that support it
UInt8 virtual_ce;
UInt32 blk;
UInt32 numPerfPagesThatFit = DEFAULT_RAMDISK_SIZE / PPN_PERFECT_PAGE_SIZE;
struct dma_segment sgl;
h2fmi_ppn_failure_info_t failInfo;
UInt32 pagesRead = 0;
UInt32 totalPagesToRead;
UInt32 startPage;
UInt32 bytesToRead;
UInt16 gebType;
Int32 ret;
UInt8 mfgID[H2FMI_NAND_ID_SIZE];
int thisFuncRet = -1;
LowFuncTbl *fil = FIL_GetFuncTbl();
const UInt32 blocks_per_cau = fil->GetDeviceInfo(AND_DEVINFO_BLOCKS_PER_CAU);
const UInt32 block_bits = fil->GetDeviceInfo(AND_DEVINFO_BITS_PER_BLOCK_ADDRESS);
const UInt32 block_shift = 0;
const UInt32 block_mask = (1UL << block_bits) - 1;
const UInt32 caus_per_ce = fil->GetDeviceInfo(AND_DEVINFO_CAUS_PER_CE);
const UInt32 cau_bits = fil->GetDeviceInfo(AND_DEVINFO_BITS_PER_CAU_ADDRESS);
const UInt32 cau_shift = block_bits + block_shift;
const UInt32 cau_mask = (1UL << cau_bits) - 1;
const UInt32 slc_bits = 1;
const UInt32 slc_shift = cau_bits + cau_shift;
const UInt32 slc_mask = (1UL << slc_bits) - 1;
const UInt32 invalid_shift = slc_bits + slc_shift;
if (argc != VTHSWEEP_ARGC)
{
printf("Usage: vthsweep <virtual_ce> <blk> <file_path>\n");
return -1;
}
if ((virtual_ce = args[1].u) >= g_fmi0.num_of_ce + g_fmi1.num_of_ce)
{
printf("Invalid ce = %d. ce < %d\n", virtual_ce, g_fmi0.num_of_ce + g_fmi1.num_of_ce);
return -1;
}
blk = args[2].u;
if ((0 != (blk >> invalid_shift)) ||
(blocks_per_cau <= ((blk >> block_shift) & block_mask)) ||
(caus_per_ce <= ((blk >> cau_shift) & cau_mask)))
{
printf("Invalid address: block %u (max %u). cau %u (max %u), slc %u, reserved %u\n",
((blk >> block_shift) & block_mask), blocks_per_cau - 1,
((blk >> cau_shift) & cau_mask), caus_per_ce - 1,
((blk >> slc_shift) & slc_mask),
blk >> invalid_shift);
return -1;
}
#if SUPPORT_TOGGLE_NAND
if (g_fmi0.is_toggle_system)
{
transitionWorldFromDDR(PPN_PS_TRANS_DDR_TO_LOW_POWER);
}
else
{
#endif
h2fmi_ppn_all_channel_power_state_transition(PPN_PS_TRANS_ASYNC_TO_LOW_POWER);
#if SUPPORT_TOGGLE_NAND
}
#endif
ret = h2fmiPpnGetManufacturerId(virtual_ce, mfgID);
if (ret != FIL_SUCCESS)
{
printf("Failed to read Mfg ID! ret = 0x%x\n", ret);
goto finish;
}
if ((mfgID[0] != VENDOR_CODE__HYNIX) && (mfgID[0] != VENDOR_CODE__SANDISK) && (mfgID[0] != VENDOR_CODE__MICRON))
{
printf("Vendor 0x%x not supported!\n", mfgID[0]);
goto finish;
}
if ((ret = h2fmiVthSweepSetup(virtual_ce, blk, &failInfo, &bytesToRead)) != FIL_SUCCESS)
{
printf("h2fmiVthSweepSetup failed! ret = 0x%x, bytesToRead = 0x%x\n", ret, bytesToRead);
goto finish;
}
totalPagesToRead = FAIL_INFO_GET_PAGE_COUNT(g_fmi0.ppn->bytes_per_row_address, failInfo);
startPage = FAIL_INFO_GET_START_PAGE(g_fmi0.ppn->bytes_per_row_address, failInfo);
gebType = FAIL_INFO_GET_TYPE(g_fmi0.ppn->bytes_per_row_address, failInfo);
WMR_ASSERT(gebType == PPN_GEB_TYPE__EMB_SWEEP_GEB_TYPE);
WMR_ASSERT(bytesToRead == totalPagesToRead * PPN_PERFECT_PAGE_SIZE);
sgl.paddr = (UInt32)env_get_uint("loadaddr", DEFAULT_LOAD_ADDRESS);
printf("\033[1;31m"); // change font color to red & bold
while (pagesRead < totalPagesToRead)
{
UInt32 currentPagesToRead = WMR_MIN(WMR_MIN(numPerfPagesThatFit, totalPagesToRead - pagesRead), DMA_TRANSFER_LIMIT / PPN_PERFECT_PAGE_SIZE);
sgl.length = currentPagesToRead * PPN_PERFECT_PAGE_SIZE;
printf("Status: %d%%, Pages: %d/%d", pagesRead * 100 / totalPagesToRead, pagesRead, totalPagesToRead);
if ((ret = h2fmiDmaDebugData(virtual_ce, startPage + pagesRead, currentPagesToRead, &sgl, FALSE32)) != FIL_SUCCESS)
{
printf("h2fmiDmaDebugData failed ret = 0x%x\n", ret);
goto finish;
}
pagesRead += currentPagesToRead;
if ((ret = usb_send_data_to_file(args[3].str, sgl.length, sgl.paddr, 0)))
{
printf("usb_cmd_put failed ret = 0x%x\n", ret);
goto finish;
}
printf("\033[0E\033[2K"); // go to start of line and erase the line respectively
}
printf("Status: %d%%, Pages: %d/%d\n", pagesRead * 100 / totalPagesToRead, pagesRead, totalPagesToRead);
printf("\033[0m"); // change font color back to default
thisFuncRet = 0;
finish:
// not going back to normal/DDR mode because the nand needs to be reset
h2fmi_ppn_recover_nand();
return thisFuncRet;
}
static int do_ppnfw(int argc, struct cmd_arg *args)
{
addr_t buf_ptr;
size_t buf_len;
UInt32 virtualCe;
Int32 status;
void *fw_buffer = NULL;
UInt32 fw_length;
void *fwa_buffer = NULL;
UInt32 fwa_length;
int ret = 0;
if (argc > 3)
{
return -1;
}
buf_ptr = (argc > 1) ? args[1].u : env_get_uint("loadaddr", DEFAULT_LOAD_ADDRESS);
buf_len = (argc > 2) ? args[2].u : env_get_uint("filesize", 0);
if (!security_allow_memory((void*)buf_ptr, buf_len))
{
return -2;
}
fw_buffer = NULL;
fw_length = 0;
fwa_buffer = NULL;
fwa_length = 0;
find_blobs((void*)buf_ptr, buf_len, &fw_buffer, &fw_length, &fwa_buffer, &fwa_length);
if ((NULL == fw_buffer) && (NULL == fwa_buffer))
{
printf("couldn't find both fw and fwa payloads\n");
return -3;
}
#if SUPPORT_TOGGLE_NAND
if (g_fmi0.is_toggle_system)
{
transitionWorldFromDDR(PPN_FEATURE__POWER_STATE__LOW_POWER);
}
#endif
// reset device to ensure clean initial state (and ensure PPN 1.0 device is in LP mode)
h2fmi_nand_reset_all(&g_fmi0);
h2fmi_nand_reset_all(&g_fmi1);
h2fmi_ppn_post_rst_pre_pwrstate_operations(&g_fmi0);
h2fmi_ppn_post_rst_pre_pwrstate_operations(&g_fmi1);
for (virtualCe = 0; virtualCe < H2FMI_MAX_CE_TOTAL; virtualCe++)
{
printf("Updating virtual CE %d\n", virtualCe);
status = h2fmiPpnUpdateFw(virtualCe, fw_buffer, fw_length, fwa_buffer, fwa_length);
if (status == FIL_SUCCESS)
{
printf("Firmware successfully updated on virtual CE %d\n",
virtualCe);
}
else if (status == FIL_UNSUPPORTED_ERROR)
{
printf("Virtual CE %d doesn't support firmware updates; skipping\n",
virtualCe);
}
else
{
printf("PPN Firmware Update failed\n");
ret = -10;
goto done;
}
}
done:
// issue FF reset after the firmware update to allow the device to transition to the new firmware
// on monodie parts running invalid fw, fmi1 may not be valid <rdar://problem/11286520>
// a reboot is required to sync up the system with the new firmware
printf("System running in low power mode, reboot required after firmware update\n");
h2fmi_nand_reset_all(&g_fmi0);
h2fmi_nand_reset_all(&g_fmi1);
return ret;
}
static int do_ppnver(int argc, struct cmd_arg *argv)
{
UInt32 virtualCe;
UInt8 buffer[NAND_DEV_PARAM_LEN_PPN];
if (!g_fmi0.is_ppn)
{
WMR_PRINT(ERROR, "Target is not a PPN device\n");
return -1;
}
for (virtualCe = 0; virtualCe < H2FMI_MAX_CE_TOTAL; virtualCe++)
{
if (FIL_SUCCESS == h2fmiPpnGetFirmwareVersion(virtualCe, buffer))
{
printf("PPN Version for virtual CE %d: %16.16s\n", virtualCe, buffer);
}
}
return 0;
}
static void rma_usage(void)
{
printf("Usage: \n");
printf(" ppnrma get <virtual ce> [<page>]\n");
printf(" ppnrma delete <virtual ce>\n");
printf(" ppnrma configure <virtual ce> <flags>\n");
printf(" ppnrma recover\n");
}
static int do_ppnrma(int argc, struct cmd_arg *args)
{
h2fmi_t *fmi;
UInt32 virtualCe;
UInt32 ce;
UInt32 page;
h2fmi_ppn_failure_info_t failureInfo;
UInt32 failureLength;
void *buffer;
struct dma_segment sgl;
if ((argc != 2) && (argc != 3) && (argc != 4))
{
rma_usage();
return -1;
}
virtualCe = args[2].u;
page = argc > 3 ? args[3].u : 0;
fmi = h2fmiTranslateVirtualCEToBus(virtualCe);
ce = h2fmiTranslateVirtualCEToCe(virtualCe);
if (!strcmp(args[1].str, "get"))
{
buffer = (void *)env_get_uint("loadaddr", DEFAULT_LOAD_ADDRESS);
if (argc == 4)
{
// Force Debug Data for a particular page
h2fmi_ppn_force_geb_address(fmi, ce, (PageAddressType)page);
}
// Get general error info and additional data length
if ( h2fmi_ppn_get_general_error_info(fmi, ce, &failureInfo, &failureLength, NULL) &&
(failureLength > 0))
{
printf("Reading %d bytes of Debug Data to %p\n", failureLength, buffer);
sgl.paddr = (UInt32)buffer;
sgl.length = failureLength;
WMR_PREPARE_READ_BUFFER(buffer, failureLength);
// Get full buffer
h2fmi_ppn_get_general_error_info(fmi, ce, &failureInfo, &failureLength, &sgl);
WMR_COMPLETE_READ_BUFFER(buffer, failureLength);
printf("Debug Data buffer extracted. Save to host by running 'usb put <filename> %d'\n", failureLength);
}
}
else if (!strcmp(args[1].str, "delete"))
{
UInt32 feature_data = PPN_DELETE_DEBUG_DATA__ENABLE;
if (FIL_SUCCESS != h2fmi_ppn_set_features(fmi,
ce,
PPN_FEATURE__DELETE_DEBUG_DATA,
(UInt8*) &feature_data,
PPN_FEATURE_LENGTH_DEFAULT,
FALSE32,
NULL))
{
printf("delete debug data failed\n");
return -1;
}
else
{
printf("Debug data deleted\n");
}
}
else if (!strcmp(args[1].str, "configure"))
{
if (argc < 4)
{
rma_usage();
return -1;
}
fmi->ppn->allow_saving_debug_data = TRUE32;
fmi->ppn->debug_flags_valid = TRUE32;
fmi->ppn->debug_flags = args[3].u;
fmi->ppn->vs_debug_flags_valid = FALSE32;
if (FIL_SUCCESS != h2fmi_ppn_configure_debug_data(fmi, ce))
{
printf("configuration failed\n");
return -1;
}
}
else if (!strcmp(args[1].str, "recover"))
{
h2fmi_ppn_recover_nand();
}
else
{
rma_usage();
return -1;
}
return 0;
}
static int do_ppnscratchpad(int argc, struct cmd_arg *argv)
{
int ret = 0;
int argi = 1;
uint32_t len = (argi < argc ? argv[argi++].u : SCRATCHPAD_LEN);
void *src = (argi < argc ? (void *)argv[argi++].u : NULL);
uint32_t ce;
if (SCRATCHPAD_LEN < len)
{
printf("truncating length (%u) to maximum (%u)\n", len, SCRATCHPAD_LEN);
len = SCRATCHPAD_LEN;
}
if (NULL != src)
{
memcpy(scratchpad_buf_set, src, len);
}
else
{
random_get_bytes(scratchpad_buf_set, len);
}
for(ce = 0; ce < H2FMI_MAX_CE_TOTAL; ce++)
{
h2fmi_t* fmi;
Int32 status;
UInt32 i;
if (0 != (g_fmi0.valid_ces & (1 << ce)))
{
fmi = &g_fmi0;
}
else if (0 != (g_fmi1.valid_ces & (1 << ce)))
{
fmi = &g_fmi1;
}
else
{
continue;
}
status = h2fmi_ppn_set_features(fmi, ce, PPN_FEATURE__SCRATCH_PAD, scratchpad_buf_set, len, FALSE32, NULL);
if (FIL_SUCCESS != status)
{
printf("scratch pad write returned %i on bus %u, ce %u\n", status, fmi->bus_id, ce);
ret = -1;
continue;
}
memset(scratchpad_buf_get, PREFILL, len);
if (!h2fmi_ppn_get_feature(fmi, ce, PPN_FEATURE__SCRATCH_PAD, scratchpad_buf_get, len, NULL))
{
printf("scratch pad read returned %i on bus %u, ce %u\n", status, fmi->bus_id, ce);
ret = -1;
continue;
}
for (i = 0; i < len; i++)
{
if (scratchpad_buf_set[i] != scratchpad_buf_get[i])
{
UInt32 j, k;
j = ROUNDDOWNTO(i, DUMPLEN);
printf("Expected @ 0x%08x:", j);
for (k = 0 ; DUMPLEN > k ; k++)
{
printf(" %02x", scratchpad_buf_set[j++]);
}
printf("\n");
j = ROUNDDOWNTO(i, DUMPLEN);
printf("Actual @ 0x%08x:", j);
for (k = 0 ; DUMPLEN > k ; k++)
{
printf(" %02x", scratchpad_buf_get[j++]);
}
printf("\n");
i = ROUNDUPTO(i, DUMPLEN);
ret = -1;
}
}
}
return ret;
}
#endif //SUPPORT_PPN
+131
View File
@@ -0,0 +1,131 @@
// *****************************************************************************
//
// File: fmiss.c
//
// Copyright (C) 2010 Apple Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 "fmiss.h"
#if FMISS_ENABLED
#if FMISS_DUMP_ENABLED
static void fmiss_fifo_print(UInt32 val, UInt32 cur, UInt32 ptr, UInt32 lev, UInt32 len, BOOL32 err)
{
BOOL32 is_head = FALSE32;
BOOL32 is_edge = FALSE32;
BOOL32 is_queued = FALSE32;
if (ptr > cur)
{
cur += len;
}
if (ptr + lev == cur)
{
is_edge = TRUE32;
}
else if (ptr == cur)
{
is_head = TRUE32;
is_edge = TRUE32;
}
else if (ptr + lev > cur)
{
is_queued = TRUE32;
}
printf("0x%08x %c %c%c ", val,
(err ? '!' : ' '),
(is_head ? '<' : ' '),
(is_edge ? '-' : (is_queued ? '|' : ' ')));
}
void fmiss_dump(h2fmi_t *fmi)
{
const UInt32 mLength = SEQUENCER_MACROS(~0) - SEQUENCER_MACROS(0) + 1;
const UInt32 mControl = h2fmi_rd(fmi, SEQ_MACRO_CONTROL);
const UInt32 mHead = SEQ_MACRO_CONTROL__GET_MACRO_ADDRESS(mControl);
const UInt32 mLevel = SEQ_MACRO_CONTROL__GET_WORD_COUNT(mControl);
const UInt32 cLength = SEQUENCER_COMMANDS(~0) - SEQUENCER_COMMANDS(0) + 1;
const UInt32 cPointer = h2fmi_rd(fmi, COMMAND_FIFO_PTR);
const UInt32 cHead = COMMAND_FIFO_PTR__READ(cPointer);
const UInt32 cLevel = COMMAND_FIFO_PTR__LEVEL(cPointer);
const UInt32 oLength = SEQUENCER_OPERANDS(~0) - SEQUENCER_OPERANDS(0) + 1;
const UInt32 oPointer = h2fmi_rd(fmi, OPERAND_FIFO_PTR);
const UInt32 oHead = OPERAND_FIFO_PTR__READ(oPointer);
const UInt32 oLevel = OPERAND_FIFO_PTR__LEVEL(oPointer);
#if FMI_VERSION >= 4
const UInt32 sLength = SEQUENCER_STORES(~0) - SEQUENCER_STORES(0) + 1;
const UInt32 sPointer = h2fmi_rd(fmi, STORE_FIFO_PTR);
const UInt32 sHead = STORE_FIFO_PTR__READ(sPointer);
const UInt32 sLevel = STORE_FIFO_PTR__LEVEL(sPointer);
#else // FMI_VERSION < 4
const UInt32 sLength = 0;
const UInt32 sPointer = 0;
#endif // FMI_VERSION < 4
const UInt32 maxLength = WMR_MAX(WMR_MAX(mLength, cLength), WMR_MAX(oLength, sLength));
UInt32 *macros;
UInt32 macro_count = 0;
UInt32 reg, i, j;
printf("SEQ_MACRO_CONTROL: 0x%08x, COMMAND_FIFO_PTR: 0x%08x, OPERAND_FIFO_PTR: 0x%08x, STORE_FIFO_PTR: 0x%08x\n",
mControl, cPointer, oPointer, sPointer);
printf("SEQ_INT_PND: 0x%08x, TIMEOUT_VALUE: 0x%08x, COMMAND_INT_CODE: 0x%08x\n",
h2fmi_rd(fmi, SEQ_INT_PEND),
h2fmi_rd(fmi, TIMEOUT_VALUE),
h2fmi_rd(fmi, COMMAND_INT_CODE));
macros = (fmi->is_ppn ? fmiss_ppn_macros(&macro_count) : fmiss_raw_macros(&macro_count));
printf(" %-18s%-18s%-18s%-18s", "Seq Macros:", "Seq Commands:", "Seq Operands:", "Seq Stores:");
for (i = 0, j = 0 ; i < maxLength; i += sizeof(UInt32), j++)
{
printf("\n%-3d: ", j);
if (i < mLength)
{
reg = h2fmi_rd(fmi, SEQUENCER_MACROS(i));
fmiss_fifo_print(reg, j, mHead, mLevel, mLength / sizeof(UInt32),
(j < macro_count ? reg != macros[j] : FALSE32));
}
if (i < cLength)
{
reg = h2fmi_rd(fmi, SEQUENCER_COMMANDS(i));
fmiss_fifo_print(reg, j, cHead, cLevel, cLength / sizeof(UInt32), FALSE32);
}
if (i < oLength)
{
reg = h2fmi_rd(fmi, SEQUENCER_OPERANDS(i));
fmiss_fifo_print(reg, j, oHead, oLevel, oLength / sizeof(UInt32), FALSE32);
}
#if FMI_VERSION >= 4
if (i < sLength)
{
reg = h2fmi_rd(fmi, SEQUENCER_STORES(i));
fmiss_fifo_print(reg, j, sHead, sLevel, sLength / sizeof(UInt32), FALSE32);
}
#endif // FMI_VERSION >= 4
}
printf("\n");
}
#endif // FMISS_DUMP_ENABLED
#endif // FMISS_ENABLED
+42
View File
@@ -0,0 +1,42 @@
// *****************************************************************************
//
// File: fmiss.h
//
// Copyright (C) 2010 Apple Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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.
//
// *****************************************************************************
#ifndef _FMISS_H_
#define _FMISS_H_
#include "H2fmi_private.h"
#if FMISS_ENABLED
#if H2FMI_IOP
#define FMISS_DUMP_ENABLED (1)
#endif // H2FMI_IOP
// Common
#if FMISS_DUMP_ENABLED
void fmiss_dump(h2fmi_t *fmi);
#endif // FMISS_DUMP_ENABLED
// Raw
UInt32 *fmiss_raw_macros(UInt32 *count);
// PPN
//
UInt32 *fmiss_ppn_macros(UInt32 *count);
#endif // FMISS_ENABLED
#endif // _FMISS_H_
File diff suppressed because it is too large. Load diff
+553
View File
@@ -0,0 +1,553 @@
// *****************************************************************************
//
// File: fmiss_raw.c
//
// Copyright (C) 2010 Apple Inc. All rights reserved.
//
// This document is the property of Apple Computer, 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 "H2fmi_private.h"
#include "H2fmi_dma.h"
#include <FIL.h>
#include <FILTypes.h>
#if FMISS_ENABLED
#define FMISS_TIMEOUT_VALUE(f) (1 * 1000 * f->clock_speed_khz)
#define FMISS_NS_TO_CLKS(f, t) (t * f->clock_speed_khz / (1000 * 1000))
#define FMI_INT_ENABLE \
(FMI_INT_EN__LAST_ECC_DONE | \
FMI_INT_EN__SEQUENCER_INTERRUPT | \
FMI_INT_EN__ECC_RESULTS_FIFO_OVERFLOW | \
FMI_INT_EN__ECC_RESULTS_FIFO_UNDERFLOW)
#define FMI_INT_EXPECTED \
(FMI_INT_PEND__LAST_ECC_DONE | \
FMI_INT_PEND__SEQUENCER_INTERRUPT)
#define FMI_INT_ERRORS \
(FMI_INT_PEND__ECC_RESULTS_FIFO_OVERFLOW | \
FMI_INT_PEND__ECC_RESULTS_FIFO_UNDERFLOW)
#define SEQ_INT_ENABLE \
(SEQ_INT_EN__TIMEOUT | \
SEQ_INT_EN__COMMAND_FIFO_OVERFLOW | \
SEQ_INT_EN__OPERAND_FIFO_OVERFLOW)
#define SEQ_INT_ERRORS \
(SEQ_INT_PEND__TIMEOUT | \
SEQ_INT_PEND__COMMAND_FIFO_OVERFLOW | \
SEQ_INT_PEND__OPERAND_FIFO_OVERFLOW)
#define MACRO_LENGTH(s) \
(sizeof((UInt32[]){s})/sizeof(UInt32))
#define PREP_PAGE_SEQ \
CMD_LOAD_FROM_FIFO(FMC_ADDR1), \
CMD_LOAD_FROM_FIFO(FMC_ADDR0), \
CMD_LOAD_NEXT_WORD(FMC_CMD), \
FMC_CMD__CMD1(NAND_CMD__READ) | FMC_CMD__CMD2(NAND_CMD__READ_CONFIRM), \
CMD_LOAD_NEXT_WORD(FMC_RW_CTRL), \
FMC_RW_CTRL__ADDR_MODE | FMC_RW_CTRL__CMD1_MODE | FMC_RW_CTRL__CMD2_MODE, \
CMD_POLL(FMC_STATUS), \
FMC_STATUS__ADDRESSDONE | FMC_STATUS__CMD1DONE | FMC_STATUS__CMD2DONE, \
FMC_STATUS__ADDRESSDONE | FMC_STATUS__CMD1DONE | FMC_STATUS__CMD2DONE, \
CMD_LOAD_NEXT_WORD(FMC_STATUS), \
FMC_STATUS__ADDRESSDONE | FMC_STATUS__CMD1DONE | FMC_STATUS__CMD2DONE
// CMD_TIMED_WAIT() takes an index into timed_wait_ns[]
#define READ_PAGE_SEQ \
CMD_COMMAND(NAND_CMD__READ_STATUS), \
CMD_WAIT_FOR_READY(0x01, 0x40, 0x40), \
CMD_TIMED_WAIT(0), \
CMD_COMMAND(NAND_CMD__READ), \
CMD_TIMED_WAIT(1), \
CMD_TX_PAGE
typedef struct
{
h2fmi_ce_t *chip_enable_array;
UInt8 *max_corrected_array;
UInt8 *sector_stats;
UInt32 clean_pages;
UInt32 fused_pages;
UInt32 uecc_pages;
UInt32 ecc_idx;
BOOL32 timeout;
} fmiss_cxt_t;
static UInt32 sequencer_macros[] =
{
PREP_PAGE_SEQ,
READ_PAGE_SEQ,
};
static const UInt32 sequencer_macro_count = sizeof(sequencer_macros)/sizeof(sequencer_macros[0]);
static const UInt32 timed_wait_ns[] =
{
100, // tRHW
60, // tWHR
};
static const UInt32 timed_wait_count = sizeof(timed_wait_ns)/sizeof(timed_wait_ns[0]);
typedef enum
{
kPrepPageHead,
kPrepPageLength = MACRO_LENGTH(PREP_PAGE_SEQ),
kPrepPageTail = kPrepPageHead + kPrepPageLength - 1,
kReadPageHead,
kReadPageLength = MACRO_LENGTH(READ_PAGE_SEQ),
kReadPageTail = kReadPageHead + kReadPageLength - 1,
} sequence_entry_t;
static void fmiss_raw_init(h2fmi_t *fmi)
{
BOOL32 initialized = FALSE32;
if (!initialized)
{
UInt32 i, j;
for (i = 0 ; i < sequencer_macro_count ; i++)
{
if (CMD_TIMED_WAIT(0) != (COMMAND_FIFO__COMMAND(~0UL) & sequencer_macros[i]))
{
continue;
}
for (j = 0 ; j < timed_wait_count ; j++)
{
if (CMD_TIMED_WAIT(j) == sequencer_macros[i])
{
const UInt32 clks = FMISS_NS_TO_CLKS(fmi, timed_wait_ns[j]);
sequencer_macros[i] = CMD_TIMED_WAIT(clks);
break;
}
}
}
initialized = TRUE32;
}
}
void fmiss_raw_init_sequences(h2fmi_t *fmi)
{
UInt32 i, j;
fmiss_raw_init(fmi);
for (i = 0, j = 0 ; i < sequencer_macro_count ; i++, j += sizeof(*sequencer_macros))
{
h2fmi_wr(fmi, SEQUENCER_MACROS(j), sequencer_macros[i]);
}
}
static UInt8 fmiss_ce_to_mask(h2fmi_ce_t ce)
{
return FMC_CE_CTRL__CEB(ce & (H2FMI_MAX_CE_PER_BUS - 1));
}
static BOOL32 fmiss_process_ecc(h2fmi_t *fmi)
{
BOOL32 ret = FALSE32;
fmiss_cxt_t *cxt = fmi->fmiss_cxt;
UInt32 sector_idx = 0;
BOOL32 clean = TRUE32;
BOOL32 fused = TRUE32;
BOOL32 uecc = FALSE32;
if (cxt->max_corrected_array)
{
*cxt->max_corrected_array = 0;
}
for (sector_idx = 0; sector_idx < fmi->sectors_per_page; sector_idx++)
{
const UInt32 ecc_result = h2fmi_rd(fmi, ECC_RESULT);
const BOOL32 free_page = (ecc_result & ECC_RESULT__FREE_PAGE) ? TRUE32 : FALSE32;
const BOOL32 all_zero = (ecc_result & ECC_RESULT__ALL_ZERO) ? TRUE32 : FALSE32;
const BOOL32 uncorrectable = (ecc_result & ECC_RESULT__UNCORRECTABLE) ? TRUE32 : FALSE32;
const BOOL32 stuck_bit_err = ((ecc_result & ECC_RESULT__STUCK_BIT_CNT(~0)) >
ECC_RESULT__STUCK_BIT_CNT(H2FMI_ALLOWED_STUCK_BITS_IN_FP)) ?
TRUE32 : FALSE32;
UInt32 err_cnt = (ecc_result & ECC_RESULT__ERROR_CNT_MASK) >> ECC_RESULT__ERROR_CNT_SHIFT;
if (free_page)
{
if (stuck_bit_err)
{
clean = FALSE32;
fused = FALSE32;
uecc = TRUE32;
err_cnt = 0xFF;
}
else
{
fused = FALSE32;
err_cnt = 0xFE;
}
}
else if (all_zero)
{
clean = FALSE32;
err_cnt = 0xFF;
}
else if (uncorrectable)
{
clean = FALSE32;
fused = FALSE32;
uecc = TRUE32;
err_cnt = 0xFF;
}
else
{
clean = FALSE32;
fused = FALSE32;
}
if (cxt->sector_stats)
{
*cxt->sector_stats = err_cnt;
cxt->sector_stats++;
}
if (cxt->max_corrected_array && (err_cnt > *cxt->max_corrected_array))
{
*cxt->max_corrected_array = err_cnt;
}
}
cxt->max_corrected_array++;
if (clean)
{
cxt->clean_pages++;
}
else if (fused)
{
cxt->fused_pages++;
}
else if (uecc)
{
cxt->uecc_pages++;
}
else
{
ret = TRUE32;
}
if (!ret && (((UInt32) ~0) == fmi->failureDetails.wFirstFailingCE))
{
fmi->failureDetails.wFirstFailingCE = *cxt->chip_enable_array;
}
cxt->chip_enable_array++;
cxt->ecc_idx++;
return ret;
}
static void fmiss_interrupt_handler(void *arg)
{
h2fmi_t* fmi = (h2fmi_t*)arg;
const UInt32 fmi_int_pend = h2fmi_rd(fmi, FMI_INT_PEND);
h2fmi_wr(fmi, FMI_INT_PEND, fmi_int_pend & (FMI_INT_EXPECTED | FMI_INT_ERRORS));
if (0 != (FMI_INT_ERRORS & fmi_int_pend))
{
WMR_PANIC("Unexpected FMI interrupt: 0x%08x", (uint32_t)(FMI_INT_ERRORS & fmi_int_pend));
}
if (0 != (FMI_INT_PEND__SEQUENCER_INTERRUPT & fmi_int_pend))
{
const UInt32 seq_int_pend = h2fmi_rd(fmi, SEQ_INT_PEND);
h2fmi_wr(fmi, SEQ_INT_PEND, seq_int_pend & SEQ_INT_ERRORS);
if (0 != (SEQ_INT_ERRORS & seq_int_pend))
{
#if H2FMI_IOP
if (0 != (SEQ_INT_PEND__TIMEOUT & seq_int_pend))
{
fmiss_cxt_t *cxt = fmi->fmiss_cxt;
cxt->timeout = TRUE32;
}
else
#endif // H2FMI_IOP
{
WMR_PANIC("Unexpected SEQ interrupt: 0x%08x", (uint32_t)(SEQ_INT_ERRORS & seq_int_pend));
}
}
}
if (0 != (FMI_INT_PEND__LAST_ECC_DONE & fmi_int_pend))
{
while (fmi->sectors_per_page <= ECC_RESULTS_FIFO_PTR__LEVEL(h2fmi_rd(fmi, ECC_RESULTS_FIFO_PTR)))
{
fmiss_process_ecc(fmi);
}
}
}
static void fmiss_yield(h2fmi_t* fmi)
{
WMR_YIELD();
#if !(H2FMI_WAIT_USING_ISR)
fmiss_interrupt_handler(fmi);
#endif // !H2FMI_WAIT_USING_ISR
}
static void fmiss_put_command(h2fmi_t *fmi, UInt32 value, UInt8 *level)
{
const fmiss_cxt_t *cxt = fmi->fmiss_cxt;
BOOL32 first = TRUE32;
while ((COMMAND_FIFO_SIZE <= *level) && !cxt->timeout)
{
if (!first)
{
fmiss_yield(fmi);
}
else
{
first = FALSE32;
}
*level = COMMAND_FIFO_PTR__LEVEL(h2fmi_rd(fmi, COMMAND_FIFO_PTR));
}
if (!cxt->timeout)
{
h2fmi_wr(fmi, COMMAND_FIFO, value);
(*level)++;
}
}
static void fmiss_put_operand(h2fmi_t *fmi, UInt32 value, UInt8 *level)
{
const fmiss_cxt_t *cxt = fmi->fmiss_cxt;
BOOL32 first = TRUE32;
while ((OPERAND_FIFO_SIZE <= *level) && !cxt->timeout)
{
if (!first)
{
fmiss_yield(fmi);
}
else
{
first = FALSE32;
}
*level = OPERAND_FIFO_PTR__LEVEL(h2fmi_rd(fmi, OPERAND_FIFO_PTR));
}
if (!cxt->timeout)
{
h2fmi_wr(fmi, OPERAND_FIFO, value);
(*level)++;
}
}
UInt32 h2fmi_read_multi(h2fmi_t* fmi,
UInt32 page_count,
h2fmi_ce_t* chip_enable_array,
UInt32* page_number_array,
struct dma_segment* data_segment_array,
struct dma_segment* meta_segment_array,
UInt8* max_corrected_array,
UInt8* sector_stats)
{
UInt32 ret = _kIOPFMI_STATUS_SUCCESS;
UInt32 prep_idx = 0;
UInt32 read_idx = 0;
UInt32 prep_ce_mask = 0;
UInt32 last_ce = 0;
UInt8 command_level = 0;
UInt8 operand_level = 0;
UInt32 fmi_control = (FMI_CONTROL__RESET_SEQUENCER |
FMI_CONTROL__ENABLE_SEQUENCER |
FMI_CONTROL__SEQUENCER_TIMEOUT_ENABLE |
FMI_CONTROL__MODE__READ);
fmiss_cxt_t cxt;
#if FMI_VERSION == 4
if (fmi->read_stream_disable)
{
fmi_control |= FMI_CONTROL__DISABLE_STREAMING;
}
#endif // FMI_VERSION == 4
// Updated by the ECC interrupt handler
cxt.chip_enable_array = chip_enable_array;
cxt.max_corrected_array = max_corrected_array;
cxt.sector_stats = sector_stats;
cxt.clean_pages = 0;
cxt.fused_pages = 0;
cxt.uecc_pages = 0;
cxt.ecc_idx = 0;
cxt.timeout = FALSE32;
fmi->fmiss_cxt = &cxt;
// Used by IOP layer
fmi->failureDetails.wNumCE_Executed = 0;
fmi->failureDetails.wOverallOperationFailure = 0;
fmi->failureDetails.wFirstFailingCE = ~0;
fmi->isr_handler = fmiss_interrupt_handler;
h2fmi_reset(fmi);
h2fmi_set_page_format_and_ECC_level(fmi, fmi->correctable_bits + 1);
h2fmi_wr(fmi, TIMEOUT_VALUE, FMISS_TIMEOUT_VALUE(fmi));
h2fmi_wr(fmi, FMI_CONTROL, fmi_control);
h2fmi_wr(fmi, SEQ_INT_EN, SEQ_INT_ENABLE);
h2fmi_wr(fmi, FMI_INT_EN, FMI_INT_ENABLE);
h2fmi_wr(fmi, SEQ_INT_PEND, 0xFFFFFFFF);
h2fmi_wr(fmi, FMI_INT_PEND, 0xFFFFFFFF);
h2fmi_wr(fmi, FMC_RW_CTRL, 0);
h2fmi_wr(fmi, ECC_RESULT, ECC_RESULT__FIFO_RESET);
h2fmi_wr(fmi, FMC_ADDRNUM, FMC_ADDRNUM__NUM(4));
for (read_idx = 0 ; page_count > read_idx ; read_idx++)
{
const UInt8 read_ce = fmiss_ce_to_mask(chip_enable_array[read_idx]);
while (page_count > prep_idx)
{
const UInt8 prep_ce = fmiss_ce_to_mask(chip_enable_array[prep_idx]);
const UInt32 prep_page = page_number_array[prep_idx];
if (0 != (prep_ce_mask & prep_ce))
{
break;
}
if (last_ce != prep_ce)
{
fmiss_put_command(fmi, CMD_ENABLE_CHIP(prep_ce), &command_level);
last_ce = prep_ce;
}
fmiss_put_operand(fmi, FMC_ADDR1__SEQ4((prep_page >> 16) & 0xFF), &operand_level);
fmiss_put_operand(fmi, FMC_ADDR0__SEQ3((prep_page >> 8) & 0xFF) |
FMC_ADDR0__SEQ2((prep_page >> 0) & 0xFF), &operand_level);
fmiss_put_command(fmi, CMD_MACRO(kPrepPageHead, kPrepPageLength), &command_level);
if (cxt.timeout)
{
break;
}
prep_ce_mask |= prep_ce;
prep_idx++;
fmi->failureDetails.wNumCE_Executed++;
}
if (last_ce != read_ce)
{
fmiss_put_command(fmi, CMD_ENABLE_CHIP(read_ce), &command_level);
last_ce = read_ce;
}
fmiss_put_command(fmi, CMD_MACRO(kReadPageHead, kReadPageLength), &command_level);
if (cxt.timeout)
{
break;
}
if (0 == read_idx)
{
h2fmi_dma_execute_async(DMA_CMD_DIR_RX,
h2fmi_dma_data_chan(fmi),
data_segment_array,
h2fmi_dma_data_fifo(fmi),
page_count * fmi->bytes_per_page,
sizeof(UInt32),
8,
fmi->current_aes_cxt);
h2fmi_dma_execute_async(DMA_CMD_DIR_RX,
h2fmi_dma_meta_chan(fmi),
meta_segment_array,
h2fmi_dma_meta_fifo(fmi),
page_count * fmi->valid_bytes_per_meta,
sizeof(UInt8),
1,
NULL);
}
prep_ce_mask &= ~read_ce;
}
fmiss_put_command(fmi, CMD_ENABLE_CHIP(0), &command_level);
while (page_count > cxt.ecc_idx)
{
fmiss_yield(fmi);
if (cxt.timeout)
{
break;
}
}
if (cxt.timeout ||
!h2fmi_dma_wait(h2fmi_dma_data_chan(fmi), H2FMI_PAGE_TIMEOUT_MICROS) ||
!h2fmi_dma_wait(h2fmi_dma_meta_chan(fmi), H2FMI_PAGE_TIMEOUT_MICROS))
{
h2fmi_dma_cancel(h2fmi_dma_meta_chan(fmi));
h2fmi_dma_cancel(h2fmi_dma_data_chan(fmi));
ret = _kIOPFMI_STATUS_DMA_DONE_TIMEOUT;
}
if (_kIOPFMI_STATUS_SUCCESS == ret)
{
if(0 < cxt.clean_pages)
{
ret = (page_count > cxt.clean_pages ) ? _kIOPFMI_STATUS_NOT_ALL_CLEAN : _kIOPFMI_STATUS_BLANK;
}
else if (0 < cxt.fused_pages)
{
ret = (page_count > cxt.fused_pages ) ? _kIOPFMI_STATUS_AT_LEAST_ONE_UECC : _kIOPFMI_STATUS_FUSED;
}
else if (0 < cxt.uecc_pages)
{
ret = _kIOPFMI_STATUS_AT_LEAST_ONE_UECC;
}
}
h2fmi_wr(fmi, SEQ_INT_EN, 0);
h2fmi_wr(fmi, FMI_INT_EN, 0);
fmi->isr_handler = NULL;
fmi->fmiss_cxt = NULL;
fmi->failureDetails.wOverallOperationFailure = ret;
return ret;
}
UInt32 *fmiss_raw_macros(UInt32 *count)
{
if (NULL != count)
{
*count = sequencer_macro_count;
}
return sequencer_macros;
}
#endif /* FMISS_ENABLED */
+78
View File
@@ -0,0 +1,78 @@
# Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
#
# This document is the property of Apple Computer, 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 Computer, Inc.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
GLOBAL_INCLUDES += \
drivers/flash_nand/raw/Whimory/Inc \
lib \
$(LOCAL_DIR)
MODULES += \
drivers/flash_nand/OAM
ifeq ($(APPLICATION),EmbeddedIOP)
# we need the CDMA
MODULES += \
drivers/apple/cdma
ALL_OBJS += \
$(LOCAL_DIR)/H2fmi_iop.o \
$(LOCAL_DIR)/H2fmi_boot.o \
$(LOCAL_DIR)/H2fmi_debug.o \
$(LOCAL_DIR)/H2fmi_erase.o \
$(LOCAL_DIR)/H2fmi_misc.o \
$(LOCAL_DIR)/H2fmi_read.o \
$(LOCAL_DIR)/H2fmi_write.o \
$(LOCAL_DIR)/H2fmi_dma_iboot.o \
$(LOCAL_DIR)/fmiss.o \
$(LOCAL_DIR)/fmiss_raw.o
#ppn modules
ALL_OBJS += \
$(LOCAL_DIR)/H2fmi_ppn.o \
$(LOCAL_DIR)/H2fmi_ppn_iop.o \
$(LOCAL_DIR)/fmiss_ppn.o
# Regular support for the FMI
else
MODULES += \
drivers/flash_nand/id
OPTIONS += \
WITH_HW_FLASH_NAND=1 \
WITH_FMI=1
ALL_OBJS += \
$(LOCAL_DIR)/H2FIL.o \
$(LOCAL_DIR)/H2fmi.o \
$(LOCAL_DIR)/H2fmi_boot.o \
$(LOCAL_DIR)/H2fmi_debug.o \
$(LOCAL_DIR)/H2fmi_erase.o \
$(LOCAL_DIR)/H2fmi_misc.o \
$(LOCAL_DIR)/H2fmi_read.o \
$(LOCAL_DIR)/H2fmi_write.o \
$(LOCAL_DIR)/H2fmi_dma_iboot.o \
$(LOCAL_DIR)/H2fmi_test.o \
$(LOCAL_DIR)/H2fmi_timing.o \
$(LOCAL_DIR)/fmiss.o \
$(LOCAL_DIR)/fmiss_raw.o
#ppn modules
ALL_OBJS += \
$(LOCAL_DIR)/H2fmi_ppn.o \
$(LOCAL_DIR)/H2fmi_ppn_fil.o \
$(LOCAL_DIR)/fmiss_ppn.o
ALL_OBJS += \
$(LOCAL_DIR)/debug.o
endif
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* This document is the property of Apple Computer, 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 Computer, Inc.
*/
#ifndef _H_SOC_
#define _H_SOC_ 1
#define SAMSUNG 0
#define PROC_REG_UCHAR_RW(a) ((volatile unsigned char *) (a))
#define PROC_REG_UCHAR_RO(a) ((volatile const unsigned char *) (a))
#define PROC_REG_USHORT_RW(a) ((volatile unsigned short *) (a))
#define PROC_REG_USHORT_RO(a) ((volatile const unsigned short *) (a))
#define PROC_REG_ULONG_RW(a) ((volatile unsigned long *) (a))
#define PROC_REG_ULONG_RO(a) ((volatile const unsigned long *) (a))
#define FLD_SHIFT(abc, ab) (abc << (0? ab))
// This returns a mask for m:n where only bits m to n are set
// Yes, this could be expressed perhaps with fewer characters, but this version is very readable
// and it is evaluated at compile time anyway... Are you sure you want to optimize it? 02/10/2006 sjb
#define NET_MASK(a) (0xffffffffUL >> (0?a) << (0?a) << (31-(1?a)) >> (31-(1?a)))
#define NET_SHIFT(a) ((0?a) % 32)
// Macros for regular registers
// Read or write entire register
#define mmioReg_Val(a) (mmioReg(a))
/// Read or write a particular field
#define mmioReg_ReadFld(a, b) ((mmioReg(a) & NET_MASK(a ## b)) >> NET_SHIFT(a ## b))
#define mmioReg_WriteFld(a, b, c) ((mmioReg(a) = ((mmioReg(a) & ~NET_MASK(a ## b))) | FLD_SHIFT(a ## b ## c, a ## b)))
// Write a value to a particular field
#define mmioReg_WriteFldVal(a, b, c) ((mmioReg(a) = ((mmioReg(a) & ~NET_MASK(a ## b))) | c))
// I turned these off because they are not used yet, and because I'm not sure they're correct.
// Feel free to turn them on when you're ready to test them too... 02/10/2006 sjb
#if 1
// Macros for registers with base offsets
// Read or write entire register
#define mmioReg_Val_Base(a, d) (mmioReg(a(d)))
/// Read or write a particular field
#define mmioReg_ReadFld_Base(a, b, d) ((mmioReg(a(d)) & NET_MASK(a ## b)) >> NET_SHIFT(a ## b))
#define mmioReg_WriteFld_Base(a, b, c, d) ((mmioReg(a(d)) = ((mmioReg(a(d)) & ~NET_MASK(a ## b))) | FLD_SHIFT(a ## b ## c, a ## b)))
// Write a value to a particular field
#define mmioReg_WriteFldVal_Base(a, b, c, d) ((mmioReg(a(d)) = ((mmioReg(a(d)) & ~NET_MASK(a ## b))) | c))
#endif
// Macros for setting fields
#define SetFld(a, b, c) (NET_MASK(a ## b) & FLD_SHIFT(a ## b ## c, a ## b))
#define SetFldVal(a, b, c) (NET_MASK(a ## b) & FLD_SHIFT(c, a ## b))
#if 0
#ifdef SAMSUNG
#include "samsung/soc8900.h"
#else
// Include soc files for other platforms
#endif
#endif
#endif // _H_SOC_