⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysc.c

📁 s3c6410基于USB OTG下载内核至NORFLASH的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************************
* 
*	Project Name : S3C6410 Validation
*
*	Copyright 2006 by Samsung Electronics, Inc.
*	All rights reserved.
*
*	Project Description :
*		This software is only for validating functions of the S3C6410.
*		Anybody can use this software without our permission.
*  
*--------------------------------------------------------------------------------------
* 
*	File Name : sysc.c
*  
*	File Description : This file implements the API functons for system controller.
*
*	Author : Haksoo,Kim
*	Dept. : AP Development Team
*	Created Date : 2006/11/08
*	Version : 0.1 
* 
*	History
*	- Created(Haksoo,Kim 2006/11/08)
*	- Added sfr (Wonjoon.Jang 2007/01/08)
*  
**************************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "option.h"
#include "library.h"
#include "sfr6410.h"
#include "system.h"

#include "gpio.h"
#include "sysc.h"


//
#define rAPLL_LOCK			(SYSCON_BASE+0x000)
#define rMPLL_LOCK			(SYSCON_BASE+0x004)
#define rEPLL_LOCK			(SYSCON_BASE+0x008)
#define rAPLL_CON			(SYSCON_BASE+0x00c)
#define rMPLL_CON			(SYSCON_BASE+0x010)
#define rEPLL_CON0			(SYSCON_BASE+0x014)
#define rEPLL_CON1			(SYSCON_BASE+0x018)
#define rCLK_SRC				(SYSCON_BASE+0x01c)
#define rCLK_DIV0			(SYSCON_BASE+0x020)
#define rCLK_DIV1			(SYSCON_BASE+0x024)
#define rCLK_DIV2			(SYSCON_BASE+0x028)
#define rCLK_OUT				(SYSCON_BASE+0x02c)
#define rHCLK_GATE			(SYSCON_BASE+0x030)
#define rPCLK_GATE			(SYSCON_BASE+0x034)
#define rSCLK_GATE			(SYSCON_BASE+0x038)
//
#define rAHB_CON0			(SYSCON_BASE+0x100)
#define rAHB_CON1			(SYSCON_BASE+0x104)
#define rAHB_CON2			(SYSCON_BASE+0x108)
#define rSDMA_SEL			(SYSCON_BASE+0x110)
#define rSW_RST				(SYSCON_BASE+0x114)
#define rSYS_ID				(SYSCON_BASE+0x118)
#define rMEM_SYS_CFG		(SYSCON_BASE+0x120)
#define rQOS_OVERRIDE0		(SYSCON_BASE+0x124)
#define rQOS_OVERRIDE1		(SYSCON_BASE+0x128)
#define rMEM_CFG_STAT		(SYSCON_BASE+0x12c)
//
#define rPWR_CFG			(SYSCON_BASE+0x804)
#define rEINT_MASK			(SYSCON_BASE+0x808)
#define rNORMAL_CFG			(SYSCON_BASE+0x810)
#define rSTOP_CFG			(SYSCON_BASE+0x814)
#define rSLEEP_CFG			(SYSCON_BASE+0x818)
#define rOSC_FREQ			(SYSCON_BASE+0x820)
#define rOSC_STABLE			(SYSCON_BASE+0x824)
#define rPWR_STABLE			(SYSCON_BASE+0x828)
#define rFPC_STABLE			(SYSCON_BASE+0x82c)
#define rMTC_STABLE			(SYSCON_BASE+0x830)
// 
#define rOTHERS				(SYSCON_BASE+0x900)
#define rRST_STAT			(SYSCON_BASE+0x904)
#define rWAKEUP_STAT		(SYSCON_BASE+0x908)
#define rBLK_PWR_STAT		(SYSCON_BASE+0x90c)
#define rINFORM0			(SYSCON_BASE+0xA00)
#define rINFORM1			(SYSCON_BASE+0xA04)
#define rINFORM2			(SYSCON_BASE+0xA08)
#define rINFORM3			(SYSCON_BASE+0xA0c)
#define rINFORM4			(SYSCON_BASE+0xA10)
#define rINFORM5			(SYSCON_BASE+0xA14)
#define rINFORM6			(SYSCON_BASE+0xA18)
#define rINFORM7			(SYSCON_BASE+0xA1c)


u32	g_System_ID; 
u8	g_System_Revision, g_System_Pass, g_SYNCACK;
u32	g_APLL, g_MPLL, g_ARMCLK, g_HCLKx2, g_HCLK, g_PCLK;




//////////
// Function Name : SYSC_ReadSystemID
// Function Description : This function reads system ID register
// Input : NONE 
// Output : NONE
// Version : 
void SYSC_ReadSystemID(void)
{
	u32 temp;

	temp = Inp32(rSYS_ID);

	g_System_ID = (temp>>8)&0xffffff;
	g_System_Revision	=	(temp>>4)&0xf;
	g_System_Pass 	=	(temp)&0xf;

	return;
}

//////////
// Function Name : SYSC_GetClkInform
// Function Description : This function gets common clock information
// Input : NONE 
// Output : NONE
// Version : 
void SYSC_GetClkInform( void)
{
	u8 muxApll, muxMpll, muxSync;
	u8 divApll, divHclkx2, divHclk, divPclk;
	u16 pllM, pllP, pllS;
	u32 temp;
	
	////
	// clock division ratio	
	temp = Inp32(rCLK_DIV0);
	divApll = temp & 0xf;
	divHclkx2 = (temp>>9) & 0x7;
	divHclk = (temp>>8) & 0x1;
	divPclk = (temp>>12) & 0xf;

	////
	// Operating Mode
	temp = Inp32(rOTHERS);
	temp = (temp>>8)&0xf;
	if(temp)
	{
		g_SYNCACK = 1;
	}
	else
	{
		g_SYNCACK = 0;
	}
	
	////
	// ARMCLK
	muxApll = Inp32(rCLK_SRC) & 0x1;
	if(muxApll)	//FOUT
	{			
		temp = Inp32(rAPLL_CON);
		pllM = (temp>>16)&0x3ff;
		pllP = (temp>>8)&0x3f;
		pllS = (temp&0x7);

		g_APLL = ((FIN>>pllS)/pllP)*pllM;
	}
	else	//FIN
	{
		g_APLL = FIN;
	}
	
	g_ARMCLK = g_APLL/(divApll+1);
	
	////
	// HCLK
	muxSync = (Inp32(rOTHERS)>>7) & 0x1;
	if(muxSync)	//synchronous mode
	{
		g_HCLKx2 = g_APLL/(divHclkx2+1);
		
		temp = Inp32(rMPLL_CON);
		pllM = (temp>>16)&0x3ff;
		pllP = (temp>>8)&0x3f;
		pllS = (temp&0x7);

		g_MPLL = ((FIN>>pllS)/pllP)*pllM;
	}
	else
	{
		muxMpll = (Inp32(rCLK_SRC)>>1) & 0x1;
		if(muxMpll)	//FOUT
		{						
			temp = Inp32(rMPLL_CON);
			pllM = (temp>>16)&0x3ff;
			pllP = (temp>>8)&0x3f;
			pllS = (temp&0x7);

			g_MPLL = ((FIN>>pllS)/pllP)*pllM;
		}
		else	//FIN
		{
			g_MPLL = FIN;
		}
		g_HCLKx2 = g_MPLL/(divHclkx2+1);		
	}
	
	g_HCLK = g_HCLKx2/(divHclk+1);
	
	////
	// PCLK
	g_PCLK = g_HCLKx2/(divPclk+1);

	return;
	
}


//////////
// Function Name : SYSC_SetPLL
// Function Description : This function control PLL Output Frequency (APLL, MPLL:PLL9025X, EPLL:PLL9024X)
//				  Fout = (mdiv * Fin) / (pdiv x 2^sdiv),   Fout = ((mdiv+k/2^16) * Fin) / (pdiv x 2^sdiv)
// Input : 				ePLL  : APLL, MPLL, EPLL	
//						uMdiv : Mdiv Value ( 56 ~ 1023), ( 13 ~ 255)
//						uPdiv :  Pdiv Value ( 1~63)
//						uSdiv : Sdiv Value ( 0~5 )
//						uKdiv : PLL9025X (Not Used, 0), PLL9024X(0~65535)
// Output : NONE
// Version : 
void SYSC_SetPLL(PLL_eTYPE  ePLL, u32 uMdiv, u32 uPdiv, u32 uSdiv, u32 uKdiv)
{
	u32 temp, uRegValue;


	switch(ePLL)
	{
		case eAPLL: 
			// Check the Divider Value.
			if( uMdiv < 56 || uMdiv > 1023)
			{
				printf(" Wrong  Mdiv Value, Correct Value Range = (56 ~ 1023) (%d)\n", uMdiv);
			}
			if( uPdiv < 1 || uPdiv > 63)
			{
				printf(" Wrong  Pdiv Value, Correct Value Range = (1 ~ 63) (%d)\n", uPdiv);
			}
			if( uSdiv > 5)
			{
				printf(" Wrong  Sdiv Value, Correct Value Range = (0 ~ 5) (%d)\n", uSdiv);
			}
      			// Check the Fvco Range

      			temp = ((FIN/uPdiv)*uMdiv)/1000000;
			if( temp <1000 || temp > 2000)
			{
				printf(" Please select the proper M,P,S divider value\n");
				printf(" Fvco Range = (1000MHz ~ 2000MHz),  Current Value is (%d)MHz\n", temp);
			}

			uRegValue = (u32)(((u32)(0x1<<31))|(uMdiv<<16)|(uPdiv<<8)|(uSdiv<<0));
			Outp32(rAPLL_CON, uRegValue);
			break;

		case eMPLL: 
			// Check the Divider Value.
			if( uMdiv < 56 || uMdiv > 1023)
			{
				printf(" Wrong  Mdiv Value, Correct Value Range = (56 ~ 1023) (%d)\n", uMdiv);
			}
			if( uPdiv < 1 || uPdiv > 63)
			{
				printf(" Wrong  Pdiv Value, Correct Value Range = (1 ~ 63) (%d)\n", uPdiv);
			}
			if( uSdiv > 5)
			{
				printf(" Wrong  Sdiv Value, Correct Value Range = (0 ~ 5) (%d)\n", uSdiv);
			}
      			// Check the Fvco Range

      			temp = ((FIN/uPdiv)*uMdiv)/1000000;
			if( temp <1000 || temp > 2000)
			{
				printf(" Please select the proper M,P,S divider value\n");
				printf(" Fvco Range = (1000MHz ~ 2000MHz),  Current Value is (%d)MHz\n", temp);
			}

			uRegValue = (u32)(((u32)(0x1<<31))|(uMdiv<<16)|(uPdiv<<8)|(uSdiv<<0));
			Outp32(rMPLL_CON, uRegValue);	
			break;

		case eEPLL: 
			// Check the Divider Value.
			if( uMdiv < 13 || uMdiv > 255)
			{
				printf(" Wrong  Mdiv Value, Correct Value Range = (56 ~ 1023) (%d)\n", uMdiv);
			}
			if( uPdiv < 1 || uPdiv > 63)
			{
				printf(" Wrong  Pdiv Value, Correct Value Range = (1 ~ 63) (%d)\n", uPdiv);
			}
			if( uSdiv > 5)
			{
				printf(" Wrong  Sdiv Value, Correct Value Range = (0 ~ 5) (%d)\n", uSdiv);
			}
			if( uKdiv >65535)
			{
				printf(" Wrong  Kdiv Value, Correct Value Range = (0 ~ 65535) (%d)\n", uKdiv);
			}
		      // Check the Fvco Range

		       temp = ((FIN/uPdiv)*(uMdiv+uKdiv>>16))/1000000;
			if( temp <60 || temp > 250)
			{
				printf(" Please select the proper M,P,S divider value\n");
				printf(" Fvco Range = (60MHz ~ 250MHz),  Current Value is (%d)MHz\n", temp);
			}

			Outp32(rEPLL_CON1, uKdiv);
			uRegValue = (u32)(((u32)(0x1<<31))|(uMdiv<<16)|(uPdiv<<8)|(uSdiv<<0));
			Outp32(rEPLL_CON0, uRegValue);
			break;
		}

	// Get Information
	SYSC_GetClkInform();
}

//////////
// Function Name : SYSC_StopPLL
// Function Description : This function stop PLL.
//				  Fout = (mdiv * Fin) / (pdiv x 2^sdiv),   Fout = ((mdiv+k/2^16) * Fin) / (pdiv x 2^sdiv)
// Input : 				ePLL  : eAPLL,eMPLL, eEPLL
//
//						
// Output : NONE
// Version : 
void SYSC_StopPLL(PLL_eTYPE  ePLL)
{
	u32  uRegValue;


	switch(ePLL)
	{
		case eAPLL: 

			uRegValue = Inp32(rAPLL_CON);
			uRegValue = (uRegValue & ~(0x1<<31)); 
			Outp32(rAPLL_CON, uRegValue);
			break;

		case eMPLL: 
			uRegValue = Inp32(rMPLL_CON);
			uRegValue = (uRegValue & ~(0x1<<31)); 
			Outp32(rMPLL_CON, uRegValue);	
			break;

		case eEPLL: 
			uRegValue = Inp32(rEPLL_CON0);
			uRegValue = (uRegValue & ~(0x1<<31)); 
			Outp32(rEPLL_CON0, uRegValue);
			break;
		}

	
}

/////////
// Function Name : SYSC_RdLockDetect
// Function Description : This function reads Lock Detect bit of the A/MPLL (Hidden)
// Input : 		ePLL  : eAPLL, eMPLL
// Output :            TRUE/FALSE
// Version : 

bool  SYSC_RdLockDetect(PLL_eTYPE  ePLL)
{
	u32 uRegValue, uLockDetect;

	switch(ePLL)
	{
		case eAPLL: 

			uRegValue = Inp32(rAPLL_CON);
			uLockDetect = (uRegValue >>30)&(0x1); 
			break;

		case eMPLL: 
			uRegValue = Inp32(rMPLL_CON);
			uLockDetect = (uRegValue >>30)&(0x1); 
			break;

	}

	if(uLockDetect == 1)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}

	
}

//////////
// Function Name : SYSC_ChangeSYSCLK
// Function Description : This function control System Clock  
//				  Fout = (mdiv * Fin) / (pdiv x 2^sdiv),   Fout = ((mdiv+k/2^16) * Fin) / (pdiv x 2^sdiv)
// Input : 				eAPLLMPS  : APLL M,P,S Value
//						eMPLLMPS  : MPLL M,P,S Value  ( using at Async Mode )
//						uARM_Ratio : ARM Divider
//						uHCLKx2_Ratio : HCLKx2 Divider
//						uPCLK_Ratio : PCLK Divider
//						Other values are retained
// Output : NONE
// Version : 
void SYSC_ChangeSYSCLK(APLL_eOUT  eAPLLMPS, APLL_eOUT eMPLLMPS, u32 uARM_Ratio, u32 uHCLKx2_Ratio, u32 uPCLK_Ratio)
{
	u32 uRegValue, uRegValue_A;
	u32 uRegValue_M, uRegValue_E;
	u32 uMVAL, uPVAL, uSVAL;
	u32 uMVAL_M, uPVAL_M, uSVAL_M;
	u32 uTemp;
	
	uMVAL = (eAPLLMPS&0x3FF0000)>>16;
	uPVAL = (eAPLLMPS&0xFF00)>>8;
	uSVAL = eAPLLMPS&0x00FF;
	uRegValue_A = (u32)(((u32)(0x1<<31))|(uMVAL<<16)|(uPVAL<<8)|(uSVAL<<0));

	uMVAL_M = (eMPLLMPS&0x3FF0000)>>16;
	uPVAL_M = (eMPLLMPS&0xFF00)>>8;
	uSVAL_M = eMPLLMPS&0x00FF;


	uTemp = (Inp32(rOTHERS)>>8)&0xF;


	if(uTemp==0xF )		// Sync Mode
	{
	
		uRegValue_M = Inp32(rMPLL_CON);

	}
	else			// ASync Mode
	{
		uRegValue_M = (u32)(((u32)(0x1<<31))|(uMVAL_M<<16)|(uPVAL_M<<8)|(uSVAL_M<<0));
		uRegValue_E = Inp32(rEPLL_CON0);
	}
	
	
	// Divider Change
	uRegValue = Inp32(rCLK_DIV0);
	uRegValue = (uRegValue & ~(0xFE07)) | ((uPCLK_Ratio<<12)|(uHCLKx2_Ratio<<9)|(uARM_Ratio<<0));
	Outp32(rCLK_DIV0, uRegValue);
	
	// EVT0 W.A 
	Outp32(rMPLL_CON, uRegValue_M);

	if(uTemp == 0)
	{
		Outp32(rEPLL_CON0, uRegValue_E);
	}
	// APLL Set
	
	Outp32(rAPLL_CON, uRegValue_A);
	Delay(1000);

	
	SYSC_GetClkInform();
	UART_InitDebugCh(0, 115200);
	Delay(1000);

	printf("============================ \n");
	printf("Current Clock Information \n");
	printf("ARMCLK: %.2fMHz  HCLKx2: %.2fMHz  HCLK: %.2fMHz  PCLK: %.2fMHz\n",(float)g_ARMCLK/1.0e6, (float)g_HCLKx2/1.0e6, (float)g_HCLK/1.0e6, (float)g_PCLK/1.0e6);
	printf("============================ \n");
	

}



//////////
// Function Name : SYSC_ChangeSYSCLK_1
// Function Description : This function control System Clock  
//				  Fout = (mdiv * Fin) / (pdiv x 2^sdiv),   Fout = ((mdiv+k/2^16) * Fin) / (pdiv x 2^sdiv)
// Input : 				eAPLLMPS  : APLL M,P,S Value
//						eMPLLMPS  : MPLL M,P,S Value  ( using at Async Mode )
//						uARM_Ratio : ARM Divider
//						uHCLKx2_Ratio : HCLKx2 Divider
//						uPCLK_Ratio : PCLK Divider
//						Other values are retained
// Output : NONE
// Version : 
void SYSC_ChangeSYSCLK_1(APLL_eOUT  eAPLLMPS, APLL_eOUT eMPLLMPS, u32 uARM_Ratio, u32 uHCLKx2_Ratio, u32 uPCLK_Ratio)
{
	u32 uRegValue_A;
	u32 uRegValue_M;
	u32 uMVAL, uPVAL, uSVAL;
	u32 uMVAL_M, uPVAL_M, uSVAL_M;
	u32 uSYNCMODE;
	u32 uRegValue_DIV0, uRegValue_SRC, uTemp, uTemp1;
	
	uMVAL = (eAPLLMPS&0x3FF0000)>>16;
	uPVAL = (eAPLLMPS&0xFF00)>>8;
	uSVAL = eAPLLMPS&0x00FF;
	uRegValue_A = (u32)(((u32)(0x1<<31))|(uMVAL<<16)|(uPVAL<<8)|(uSVAL<<0));

	uMVAL_M = (eMPLLMPS&0x3FF0000)>>16;
	uPVAL_M = (eMPLLMPS&0xFF00)>>8;
	uSVAL_M = eMPLLMPS&0x00FF;


	uSYNCMODE = (Inp32(rOTHERS)>>8)&0xF;


	if(uSYNCMODE==0xF )		// Sync Mode
	{
	
		uRegValue_M = Inp32(rMPLL_CON);

	}
	else			// ASync Mode
	{
		uRegValue_M = (u32)(((u32)(0x1<<31))|(uMVAL_M<<16)|(uPVAL_M<<8)|(uSVAL_M<<0));
	}


	// Clock Divider Change 1:2:2
	uRegValue_DIV0 = Inp32(rCLK_DIV0);
	uTemp = (uRegValue_DIV0&~(0xFFFF))|(1<<12)|((0<<9)|(1<<8)|(1<<4)|(0<<0));		// ARM:HCLKx2:HCLK:PCLK = 1:1:2:2

	// Set-up Divider Value
	uRegValue_DIV0 = (uRegValue_DIV0 & ~(0xFE07)) | ((uPCLK_Ratio<<12)|(uHCLKx2_Ratio<<9)|(uARM_Ratio<<0));

	uRegValue_SRC = Inp32(rCLK_SRC);
	uTemp1 = (uRegValue_SRC&~(0x7))|0x0;

	Outp32(rCLK_SRC, uTemp1);	// Clock Source Change
	Outp32(rCLK_DIV0, uTemp);	// Change Clock Divider
	
	
	// PLL Change
	if(uSYNCMODE == 0)
	{
		Outp32(rMPLL_CON, uRegValue_M);
	}

	Outp32(rAPLL_CON, uRegValue_A);

	while(((Inp32(rAPLL_CON)>>30)&0x1)==0);


	// Change Divider Value
	Outp32(rCLK_DIV0, uRegValue_DIV0);
	// Change Clock SRC
	Outp32(rCLK_SRC, uRegValue_SRC);

	
	Delay(1000);
	SYSC_GetClkInform();
	UART_InitDebugCh(0, 115200);

	printf("============================ \n");
	printf("Current Clock Information \n");
	printf("ARMCLK: %.2fMHz  HCLKx2: %.2fMHz  HCLK: %.2fMHz  PCLK: %.2fMHz\n",(float)g_ARMCLK/1.0e6, (float)g_HCLKx2/1.0e6, (float)g_HCLK/1.0e6, (float)g_PCLK/1.0e6);
	printf("============================ \n");
	

}


#define uTIME_OF_XTAL	(1.0e6/(float)FIN)	

//////////
// Function Name : SYSC_SetLockTime
// Function Description : This function control APLL Lock Time (PLL9025X), Max 100us
//				  Fout = (mdiv * Fin) / (pdiv x 2^sdiv)
// Input : 				uLockTime : Max 100us, us order
//						ePLL		  : PLL Type
// Output : NONE
// Version : 
void SYSC_SetLockTime( PLL_eTYPE  ePLL, u32 uLockTime)
{
	u32 uLockCount;
	
	uLockCount = (unsigned int)((float)uLockTime/((float)uTIME_OF_XTAL));
	printf("uLockCount : 0x%x\n", uLockCount);

	switch(ePLL)

⌨️ 快捷键说明

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