📄 tmbtnanddrv.c
字号:
+++ Additional Notes
After this call the following global variables are valid:
gtmbtNandDrvNumOfBlocks
gtmbtNandDrvNumOfPages
gtmbtNandDrvNumOfBytesMain
gtmbtNandDrvNumOfBytesSpare
gtmbtNandDrvNumOfBytesBlock
gtmbtNandDrvNumOfBytesDevice
gtmbtNandDrv16bit
*/
/******************************************************************************/
tmErrorCode_t tmbtNandDrvInit(UInt32 *pMmioBasePhys)
{
register tmErrorCode_t err = TM_OK;
register UInt32 devMfrMask;
register UInt32 i;
/*Setup Selection Profile specified by selprofile*/
gptmbtNandDrvXioBase = (UInt32*)(((UInt32)pMmioBasePhys + MMIO_PCI_XIO_REGS_OFFSET) | K1BASE);
i = XIO_REG(MMIO_XIO_SEL0_PROF);
if ((i & EN_SELX_M) == 0)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_XIO_PROFILE;
goto functionreturn;
}
if ((i & SELX_TYPE_M) != SELX_TYPE_NAND)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_XIO_PROFILE;
goto functionreturn;
}
gptmbtNandDrvNandBase = (UInt32*)PHYS_TO_UNCACHED(XIO_REG(MMIO_BASE18) + (((i & SELX_OFFSET_M) >> SELX_OFFSET) * 8 * MBYTE));
/*Read Manufacturer ID and Device ID*/
NAND_CMD_WITH_DATA(1, 1, gtmbtNandDrv64MegDevice, NAND_CMD_READ_ID, 0);
#ifdef NAND16BIT
i = *gptmbtNandDrvNandBase;
devMfrMask = ((i >> 8) &0xFF00) | (i & 0xff);
#else
devMfrMask = (UInt32) *((UInt16*)gptmbtNandDrvNandBase);
#endif
for (i = 0; gDeviceList[i] != 0; i ++ )
{
if ((gDeviceList[i] & (NAND_MFR_ID_M | NAND_DEV_ID_M)) == devMfrMask)
{
gtmbtNandDrvCapabilities = gDeviceList[i];
gtmbtNandDrvNumOfBlocks = 1 << NAND_NROF_BLOCKS_GET(gtmbtNandDrvCapabilities);
gtmbtNandDrvNumOfPages = 1 << NAND_NROF_PAGES_GET(gtmbtNandDrvCapabilities);
gtmbtNandDrvNumOfBytesMain = 1 << NAND_NROF_BYTES_MAIN_GET(gtmbtNandDrvCapabilities);
gtmbtNandDrvNumOfBytesSpare = 1 << NAND_NROF_BYTES_SPARE_GET(gtmbtNandDrvCapabilities);
gtmbtNandDrvNumOfBytesBlock = gtmbtNandDrvNumOfPages * gtmbtNandDrvNumOfBytesMain;
gtmbtNandDrvNumOfBytesDevice= gtmbtNandDrvNumOfBytesBlock * gtmbtNandDrvNumOfBlocks;
gtmbtNandDrv16bit = NAND_16BIT_GET(gtmbtNandDrvCapabilities);
if (gtmbtNandDrvNumOfBytesDevice > NAND_SIZE_256_MBIT)
{
/* Special handling required for devices > 32 megs */
/* See Viper 2 UM 13-34 */
gtmbtNandDrvAddressCyclesRW = 3; /* NB. This actually means 4 cycles. */
gtmbtNandDrvAddressCyclesBE = 2; /* NB. This actually means 3 cycles. */
gtmbtNandDrv64MegDevice = 1;
}
else
{
gtmbtNandDrvAddressCyclesRW = 3;
gtmbtNandDrvAddressCyclesBE = 2;
gtmbtNandDrv64MegDevice = 0;
}
err = TM_OK;
goto functionreturn;
}
}
err = TM_BT_ERR_NAND_DRV_DETECTED_DEVICE_NOT_SUPPORTED;
functionreturn:
return err;
}
/******************************************************************************/
/** +++ tmbtNandDrvReadMainArea
Read the main page area of flash at the specified flash address into memory
+++ Parameter Flow Description
nandaddr IN Address in flash to read.
dramaddr IN/OUT Address to read flash data into.
MUST be 32bit aligned.
length IN Amount of page to read in.
+++ Return value
+++ Additional Notes
*/
/******************************************************************************/
tmErrorCode_t tmbtNandDrvReadMainArea(UInt32 nandaddr, void * dramaddr, UInt32 length)
{
register tmErrorCode_t err = TM_OK;
register UInt32 nandPhys;
register UInt32 dramPhys;
if (length == 0)
{
goto functionreturn;
}
if ((nandaddr & 3) != 0)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_UNALIGNED_NAND_ADDRESS;
goto functionreturn;
}
if (((UInt32)dramaddr & 3) != 0)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_UNALIGNED_RAM_ADDRESS;
goto functionreturn;
}
if (nandaddr >= gtmbtNandDrvNumOfBytesDevice)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_NAND_ADDRESS_TOO_HIGH;
goto functionreturn;
}
length = (length + 3) & 0xFFFFFFFC; /* Round Up Length */
if ((nandaddr + length) > gtmbtNandDrvNumOfBytesDevice)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_LENGTH_TO_BIG;
goto functionreturn;
}
nandPhys = VIRT_TO_PHYS(gptmbtNandDrvNandBase) + nandaddr;
dramPhys = VIRT_TO_PHYS(dramaddr);
NAND_CMD_WITH_DATA(1, gtmbtNandDrvAddressCyclesRW, gtmbtNandDrv64MegDevice, NAND_CMD_READ_MAIN, 0);
err = tmbtNandDrvDMA(dramPhys, nandPhys, length, 6);
/* Invalidate Data cache */
cachePr4450DCInvalidate(dramaddr, length);
functionreturn:
return err;
}
/******************************************************************************/
/** +++ tmbtNandDrvReadSpareArea
Read the spare/OOB page area of flash at the specified flash address into memory
+++ Parameter Flow Description
nandaddr IN Address in flash to read.
dramaddr IN/OUT Address to read flash data into.
MUST be 32bit aligned.
+++ Return value
+++ Additional Notes
*/
/******************************************************************************/
tmErrorCode_t tmbtNandDrvReadSpareArea(unsigned long nandaddr, void * dramaddr)
{
register tmErrorCode_t err = TM_OK;
register UInt32 nandPhys;
register UInt32 dramPhys;
if (((UInt32)dramaddr & 3) != 0)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_UNALIGNED_RAM_ADDRESS;
goto functionreturn;
}
if (nandaddr >= gtmbtNandDrvNumOfBytesDevice)
{
err = TM_BT_ERR_NAND_DRV_INVALID_PARAMETER_NAND_ADDRESS_TOO_HIGH;
goto functionreturn;
}
nandaddr = nandaddr & (~(gtmbtNandDrvNumOfBytesMain - 1)); /* align NAND offset to page start*/
nandPhys = VIRT_TO_PHYS(gptmbtNandDrvNandBase) + nandaddr;
dramPhys = VIRT_TO_PHYS(dramaddr);
NAND_CMD_WITH_DATA(1, gtmbtNandDrvAddressCyclesRW, gtmbtNandDrv64MegDevice, NAND_CMD_READ_SPARE, 0);
err = tmbtNandDrvDMA(dramPhys, nandPhys, gtmbtNandDrvNumOfBytesSpare, 6);
/* Invalidate Data cache */
cachePr4450DCInvalidate(dramaddr, gtmbtNandDrvNumOfBytesSpare);
functionreturn:
return err;
}
/******************************************************************************/
/** +++ tmbtNandDrvDMA
Function to transfer data to/from NAND Flash using the DMA engine.
+++ Parameter Flow Description
internal IN Internal Memory Address (RAM)
external IN External Memory Address (Flash)
length IN Length of data to transfer
cmd IN DMA engine command, (read/write)
+++ Return value
TM_OK on success
OR
TM_BT_ERR_NAND_DRV_DMA_TIMEOUT if the DMA took too long
+++ Additional Notes
*/
/******************************************************************************/
tmErrorCode_t tmbtNandDrvDMA(UInt32 internal, UInt32 external, UInt32 length, UInt cmd)
{
register UInt32 i;
XIO_REG(MMIO_DMA_LENGTH) = length >> 2; /* Length in words */
XIO_REG(MMIO_DMA_EADDR) = external;
XIO_REG(MMIO_DMA_IADDR) = internal;
XIO_REG(MMIO_DMA_INT_CLR)= DMA_DONE_M;
XIO_REG(MMIO_DMA_CTRL) = SND2XIO_M | (MAX_BURST_SIZE_128 << MAX_BURST_SIZE) | INIT_DMA_M | (cmd << CMD_TYPE);
for (i = 0; i < DMA_TIMEOUT; i ++)
{
register UInt32 status;
status =XIO_REG(MMIO_DMA_INT_STATUS);
if (status & DMA_DONE_M)
{
return TM_OK;
}
}
return TM_BT_ERR_NAND_DRV_DMA_TIMEOUT;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -