?? sysc.c
字號(hào):
/**************************************************************************************
*
* Project Name : S3C6400 Validation
*
* Copyright 2006 by Samsung Electronics, Inc.
* All rights reserved.
*
* Project Description :
* This software is only for validating functions of the S3C6400.
* 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 "sfr6400.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)
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_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)
{
#if 0 //EVT1
printf(" Please select the proper M,P,S divider value\n");
printf(" Fvco Range = (1000MHz ~ 2000MHz), Current Value is (%d)MHz\n", temp);
#endif
}
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)
{
#if 0 //EVT1
printf(" Please select the proper M,P,S divider value\n");
printf(" Fvco Range = (1000MHz ~ 2000MHz), Current Value is (%d)MHz\n", temp);
#endif
}
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);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -