ocld.cpp

来自「SAMSUNG S3C6410 CPU BSP for winmobile6」· C++ 代码 · 共 1,751 行 · 第 1/5 页

CPP
1,751
字号
					astONLDMemAddr[nDev].nDFSDBSMask = 1;
				}
				else
				{
					OCLD_REG_FBA_WIDTH(nCAddr) = 12;
					OCLD_REG_DBS_DFS_WIDTH(nCAddr) = 0;
					astONLDMemAddr[nDev].nDFSDBSMask = 0;
				}
				astONLDMemAddr[nDev].nFBAShift = 12;
				astONLDMemAddr[nDev].nFPAShift = 6;
				astONLDMemAddr[nDev].nFSAShift = 4;
				astONLDMemAddr[nDev].nFBAMask  = 0xFFF;
				astONLDMemAddr[nDev].nFPAMask  = 0x3F;
				astONLDMemAddr[nDev].nFSAMask  = 0x3;
				break;
		default :
				break;
	}
}

//////////
// Function Name : ONENAND_EnableECCCorrection
// Function Description : Set the ECC Error Correction Operation
// Input : 	Controller - OneNand Controller Port Number 
//			uEnable -ONENAND_WITH_CORRECT :  ECC Error Correction enable
//					ONENAND_WITHOUT_CORRECT : ECC Error Correction disable
// Version : v0.1
void ONENAND_EnableECCCorrection(UINT32 nDev, BOOL32 bEnable)
{
	UINT32 uEnableECC;
	UINT32 nBAddr;
	UINT32 nCAddr;
	UINT32 temp = 0xffffffff;

	nBAddr = GET_DEV_BADDR(nDev);
	nCAddr = GET_ONENANDCON_BADDR(nBAddr);

	uEnableECC = OCLD_REG_MEM_CFG(nCAddr);

	if(bEnable == TRUE32)
		uEnableECC &= ~BIT_ECC;
	else
		uEnableECC |= BIT_ECC;
	
	OCLD_REG_MEM_CFG(nCAddr) = uEnableECC;
    temp = ONLD_READ_DIRECT(nBAddr, ONLD_REG_SYS_CONF1(0x0));
}

//////////
// Function Name : ONENAND_EnableIOBE
// Function Description : Set the I/O Buffer enable for INT and RDY signals
// Input : 	Controller - OneNand Controller Port Number 
//			uEnable - IOBE Enable/Disable
// Version : v0.1
void ONENAND_EnableIOBE(UINT32 nDev, BOOL32 bEnable)
{
	UINT32 uEnableIOBE;
	UINT32 nBAddr;
	UINT32 nCAddr;
	UINT32 temp = 0xffffffff;

	nBAddr = GET_DEV_BADDR(nDev);
	nCAddr = GET_ONENANDCON_BADDR(nBAddr);

	uEnableIOBE = OCLD_REG_MEM_CFG(nCAddr);
	uEnableIOBE &= ~(0x7<<5);

	uEnableIOBE |= BIT_RDYPOL | BIT_INTPOL | (bEnable<<5);
	
	OCLD_REG_MEM_CFG(nCAddr) = uEnableIOBE;
    temp = ONLD_READ_DIRECT(nBAddr, ONLD_REG_SYS_CONF1(0x0));
}

//////////
// Function Name : ONENAND_SetBurstLatency
// Function Description : Sets the burst read latency in cycles 
// Input : 	Controller - OneNand Controller Port Number 
//			eLatency - (OneNAND_eLATENCY)latency cycle
// Version : v0.1
void ONENAND_SetBurstLatency(UINT32 nDev, OneNAND_eLATENCY eLatency)
{
	UINT32 uBurstReadLatency;
	UINT32 nBAddr;
	UINT32 nCAddr;
	UINT32 temp = 0xffffffff;

	nBAddr = GET_DEV_BADDR(nDev);
	nCAddr = GET_ONENANDCON_BADDR(nBAddr);

	uBurstReadLatency = OCLD_REG_MEM_CFG(nCAddr);
	uBurstReadLatency &= ~(0x7<<12);

	uBurstReadLatency |= (eLatency<<12);
	
	OCLD_REG_MEM_CFG(nCAddr) = uBurstReadLatency;
    temp = ONLD_READ_DIRECT(nBAddr, ONLD_REG_SYS_CONF1(0x0));

}

//////////
// Function Name : ONENAND_SyncMode
// Function Description : Set the OneNand Transfer Mode include burst length 
// Input : 	Controller - OneNand Controller Port Number 
//			uMode - 	Read&Write Transfer Mode
// Version : v0.1
void ONENAND_SetSyncMode(UINT32 nDev, OneNAND_eMODE eMode)
{
	UINT32 uSyncMode;
	UINT32 nBAddr;
	UINT32 nCAddr;
	UINT32 temp = 0xffffffff;

	nBAddr = GET_DEV_BADDR(nDev);
	nCAddr = GET_ONENANDCON_BADDR(nBAddr);

	uSyncMode = OCLD_REG_MEM_CFG(nCAddr);
	uSyncMode &= ~((1<<15)|(0x7<<9)|(1<<1));
	
	switch (eMode)
	{
		case eOND_SYNC_CONT:
			uSyncMode |= (0x1<<15)|(0x0<<9)|(0x1<<1);
			OCLD_REG_BURST_LEN(nCAddr) = BL_16WORDS;
			OCLD_REG_MEM_CFG(nCAddr) = uSyncMode;		//sync, burst:incr
			break;

		case eOND_SYNC_BURST4:
			uSyncMode |= (0x1<<15)|(0x1<<9)|(0x1<<1);
			OCLD_REG_BURST_LEN(nCAddr) = BL_4WORDS;
			OCLD_REG_MEM_CFG(nCAddr) = uSyncMode;		//sync, burst:4
			break;

		case eOND_SYNC_BURST8:
			uSyncMode |= (0x1<<15)|(0x2<<9)|(0x1<<1);
			OCLD_REG_BURST_LEN(nCAddr) = BL_8WORDS;
			OCLD_REG_MEM_CFG(nCAddr) = uSyncMode;		//sync, burst:8
			break;

		case eOND_SYNC_BURST16:
			uSyncMode |= (0x1<<15)|(0x3<<9)|(0x1<<1);
			OCLD_REG_BURST_LEN(nCAddr) = BL_16WORDS;
			OCLD_REG_MEM_CFG(nCAddr) = uSyncMode;		//sync, burst:16
			break;

		case eOND_SYNC_BURST32:
			uSyncMode |= (0x1<<15)|(0x4<<9)|(0x1<<1);
			OCLD_REG_BURST_LEN(nCAddr) = BL_32WORDS;
			OCLD_REG_MEM_CFG(nCAddr) = uSyncMode;		//sync, burst:16
			break;

		case eOND_RM_SYNC_WM_ASYNC_BURST16:
			uSyncMode |= (0x1<<15)|(0x3<<9)|(0x0<<1);
			OCLD_REG_BURST_LEN(nCAddr) = BL_16WORDS;
			OCLD_REG_MEM_CFG(nCAddr) = uSyncMode;	    //rm sync, wm async, burst:16
			break;

		case eOND_ASYNC:
		default:
			uSyncMode |= (0x0<<15)|(0x0<<9)|(0x0<<1);
			OCLD_REG_BURST_LEN(nCAddr) = 0;
			OCLD_REG_MEM_CFG(nCAddr) = uSyncMode;		//rm async, burst:4
			break;
	}
    temp = ONLD_READ_DIRECT(nBAddr, ONLD_REG_SYS_CONF1(0x0));
}

//////////
// Function Name : ONENAND_EnableIntPin
// Function Description : Interrupt Pin Enable&Disable
// Input : 	Controller - OneNand Controller Port Number 
//			Enable - 1:Enable, 0: Disable
// Version : v0.1
void ONENAND_EnableIntPin(UINT32 nDev, UINT32 nFlag)
{
	UINT32 nBAddr;
	UINT32 nCAddr;

	nBAddr = GET_DEV_BADDR(nDev);
	nCAddr = GET_ONENANDCON_BADDR(nBAddr);

	OCLD_REG_INT_PIN_ENABLE(nCAddr) = nFlag & 0x1;
}

void ONENAND_EnableSpareTransfer(UINT32 nDev, UINT32 nFlag)
{
	UINT32 nBAddr;
	UINT32 nCAddr;

	nBAddr = GET_DEV_BADDR(nDev);
	nCAddr = GET_ONENANDCON_BADDR(nBAddr);

	OCLD_REG_TRANS_SPARE(nCAddr) = nFlag & 0x1;
}

#if (OND_TRANS_MODE == OND_DMA)
BOOL MapDMABuffers()
{
	BOOL bRet = TRUE;

    ONLD_DBG_PRINT((TEXT("[ONLD:MSG] ++MapDMABuffers()\r\n")));

	g_nDMABufferPhyPage = (UINT32)ONLD_PAGEDATA_PA_BASEADDR;
	g_nDMABufferVirPage = (UINT32)(ONLD_PAGEDATA_VA_BASEADDR | CACHED_TO_UNCACHED_OFFSET);  // uncached area
//	g_nDMABufferVirPage = (UINT32)ONLD_PAGEDATA_VA_BASEADDR;  // cached area

	return bRet;
}

BOOL DMAInitialize()
{
#ifndef USE_SDMA
	g_pSYSCONReg->HCLK_GATE |= (1<<12); // DMAC0 HCLK Pass
#else
	g_pSYSCONReg->HCLK_GATE |= (1<<26); // SDMAC0 HCLK Pass
#endif

	if (!(g_pDMAC0Reg->DMACC3Control0 & TCINT_ENABLE))	// Check channel in use with TC Int Enable Bit !!!
	{
		g_pDMAC0Reg->DMACC3Control0 |= TCINT_ENABLE;	// Set TC Int Enable Bit to reserve this channel!!!
	}

	if (!(g_pDMAC0Reg->DMACConfiguration & DMAC_ENABLE))		// DMAC0 is Disabled
	{
		// Enable DMAC0
		g_pDMAC0Reg->DMACConfiguration = M1_LITTLE_ENDIAN | M2_LITTLE_ENDIAN | DMAC_ENABLE;
		ONLD_DBG_PRINT((TEXT("[ONLD:MSG] DMAC0 Enabled\r\n")));
	}

	return TRUE;
}

BOOL DMASetOneNAND(UINT32 nOneNANDMode, UINT32 nTransUnit, UINT32 nBurstSize)
{
	g_pDMAC0Reg->DMACC3LLI = 0;		// Disable LLI
	g_pDMAC0Reg->DMACC3Configuration = ALLOW_REQUEST | UNLOCK | FLOWCTRL(MEM_TO_MEM) | DEST_PERI(0) | SRC_PERI(0);

	// setting source
	g_pDMAC0Reg->DMACC3Control0 = (g_pDMAC0Reg->DMACC3Control0 & ~((1<<26)|(1<<24)|SRC_UNIT_MASK|SRC_BURST_MASK))
						|(INCREASE<<26) |(AHB_M1<<24)|(nTransUnit<<18)|(nBurstSize<<12);

	// setting destination
	g_pDMAC0Reg->DMACC3Control0 = (g_pDMAC0Reg->DMACC3Control0 & ~((1<<27)|(1<<25)|DEST_UNIT_MASK|DEST_BURST_MASK))
						|(INCREASE<<27) |(AHB_M1<<25)|(nTransUnit<<21)|(nBurstSize<<15);

	// setting OneNAND readpage
	g_pDMAC0Reg->DMACC3Configuration &= ~(ONENANDMODEDST|ONENANDMODESRC);
	g_pDMAC0Reg->DMACC3Configuration |= nOneNANDMode;

	// Clear Interrupt Pending
	g_pDMAC0Reg->DMACIntTCClear |= (1<<3);
	g_pDMAC0Reg->DMACIntErrClear |= (1<<3);
	g_pDMAC0Reg->DMACC3Configuration &= ~(TCINT_UNMASK|ERRINT_UNMASK);		// mask interrupt, polling DMA

	return TRUE;
}

BOOL DMASetChannelTransSize_Read(UINT32 uSrcAddr, UINT32 uDstAddr, UINT32 uByteCount)
{
	g_pDMAC0Reg->DMACC3SrcAddr = (UINT32)(uSrcAddr - CACHED_TO_UNCACHED_OFFSET - ONLD_PHYSICAL_TO_VIRTUAL_OFFSET);
	g_pDMAC0Reg->DMACC3DestAddr = (UINT32)uDstAddr;

	// setting transter size
	g_pDMAC0Reg->DMACC3Control1 = uByteCount;

	return TRUE;
}

BOOL DMASetChannelTransSize_Write(UINT32 uSrcAddr, UINT32 uDstAddr, UINT32 uByteCount)
{
	g_pDMAC0Reg->DMACC3SrcAddr = (UINT32)uSrcAddr;
	g_pDMAC0Reg->DMACC3DestAddr = (UINT32)(uDstAddr - CACHED_TO_UNCACHED_OFFSET - ONLD_PHYSICAL_TO_VIRTUAL_OFFSET);

	// setting transter size
	g_pDMAC0Reg->DMACC3Control1 = uByteCount;

	return TRUE;
}

BOOL DMASetChannelTransSize(UINT32 uSrcAddr, UINT32 uDstAddr, UINT32 uByteCount)
{
	if (g_pDMAC0Reg->DMACC3Configuration&ONENANDMODESRC)
	{
		g_pDMAC0Reg->DMACC3SrcAddr = (UINT32)(uSrcAddr - CACHED_TO_UNCACHED_OFFSET - ONLD_PHYSICAL_TO_VIRTUAL_OFFSET);
		g_pDMAC0Reg->DMACC3DestAddr = (UINT32)uDstAddr;
	}
	else if (g_pDMAC0Reg->DMACC3Configuration&ONENANDMODEDST)
	{
		g_pDMAC0Reg->DMACC3SrcAddr = (UINT32)uSrcAddr;
		g_pDMAC0Reg->DMACC3DestAddr = (UINT32)(uDstAddr - CACHED_TO_UNCACHED_OFFSET - ONLD_PHYSICAL_TO_VIRTUAL_OFFSET);
	}
	else
	{
		ONLD_ERR_PRINT((TEXT("[ONLD:ERR] DMACh is not set\r\n")));
	}

	// setting transter size
	g_pDMAC0Reg->DMACC3Control1 = uByteCount;

	return TRUE;
}

BOOL DMAChannelStart()
{
	// Clear Halt Bit
	g_pDMAC0Reg->DMACC3Configuration &= ~HALT;

	// Enable Channel
	g_pDMAC0Reg->DMACC3Configuration |= CHANNEL_ENABLE;

	return TRUE;
}
#endif  // OND_TRANS_MODE

/*****************************************************************************/
/* Code Implementation                                                       */
/*****************************************************************************/
static VOID
_WriteEmptyData(UINT32 pAddr, UINT32 nScts, UINT32 nSize)
{
    UINT32 nBytes;

    while (nScts-- > 0)
    {
        for (nBytes = nSize; nBytes > 0; nBytes -= sizeof(UINT32))
        {
            *(volatile UINT32 *)pAddr = 0xffffffff;
        }
    }
}

static VOID
_WriteData(UINT32 pAddr, UINT8 *pBuf, UINT32 nScts, UINT32 nSize)
{
    UINT32 *pBuffer = (UINT32 *)pBuf;

#if (OND_TRANS_MODE == OND_POL)
    UINT32 nBytes;

    while (nScts-- > 0)
    {
        for (nBytes = nSize; nBytes > 0; nBytes -= sizeof(UINT32))
        {
            *(volatile UINT32 *)pAddr = *pBuffer++;
        }
    }
#elif (OND_TRANS_MODE == OND_LDM)
	//OneNand4burstPageWrite((UINT32)pBuffer, pAddr, (UINT32)((nSize * nScts)/16));
	OneNand8burstPageWrite((UINT32)pBuffer, pAddr, (UINT32)((nSize * nScts)/32));
#endif  // OND_TRANS_MODE
}

⌨️ 快捷键说明

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