📄 dvm_dfm_api.c
字号:
/**************************************************************************
** INTEL CONFIDENTIAL
** Copyright 2000-2003 Intel Corporation. All Rights Reserved.
**
** The source code contained or described herein and all documents
** related to the source code (Material) are owned by Intel Corporation
** or its suppliers or licensors. Title to the Material remains with
** Intel Corporation or its suppliers and licensors. The Material contains
** trade secrets and proprietary and confidential information of Intel
** or its suppliers and licensors. The Material is protected by worldwide
** copyright and trade secret laws and treaty provisions. No part of the
** Material may be used, copied, reproduced, modified, published, uploaded,
** posted, transmitted, distributed, or disclosed in any way without Intel抯
** prior express written permission.
** No license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise. Any license under such intellectual property rights
** must be express and approved by Intel in writing.
Module Name:
DVM_DFM_API.c
Abstract:
This file implements the DVM/DFM APIs that are exposed for dynamically
varying BULVERDE's operating voltage and frequencies. Try.
**************************************************************************/
#include <windows.h>
#include <oal.h>
#include "ipm_dvfm.h"
#include "xllp_lcd.h"
#include "xllp_memctrl.h"
#include "xllp_dvm.h"
#include "xllp_dmac.h"
#include "xllp_gpio.h"
#include <pkfuncs.h>
#include "intcbits.h"
#include "bulverde_base_regs.h"
#include "bulverde_ost.h"
#include "mainstoneii.h"
volatile XLLP_PWRMGR_T *v_pPwrReg =NULL;
volatile XLLP_OST_T *v_pOSTReg =NULL;
volatile I2C_REG *v_pI2CReg = NULL;
volatile XLLP_CLKMGR_T *v_pClkReg = NULL;
volatile LCDRegs *v_pLCDRegs =NULL;
volatile XLLP_DMAC_T *v_pDMARegs = NULL;
XLLP_GPIO_T *v_pGPIOReg = NULL;
volatile XLLP_MEMORY_CONTROL_REGISTER_T *memc_reg = NULL;
static unsigned long gLastVoltage= MAX_VOLTAGE;
HANDLE hIPM_LCDEvent = NULL;
/************************************************************************************
//Function Name: IPMRegisterMapping()
//Functionality: return the content from CCSR
//Argument:
//Return: content of CCSR
//Comment: For later use in OS, it needs v_pClkReg as one argument
/************************************************************************************/
void IPMRegisterMapping()
{
v_pClkReg = (volatile XLLP_CLKMGR_T*)OALPAtoVA(BULVERDE_BASE_REG_PA_CLKMGR, FALSE);
v_pPwrReg = (volatile XLLP_PWRMGR_T*)OALPAtoVA(BULVERDE_BASE_REG_PA_PWR, FALSE);
v_pI2CReg = (I2C_REG *)((char*)v_pPwrReg + 0x180);
memc_reg = (volatile XLLP_MEMORY_CONTROL_REGISTER_T *)OALPAtoVA(BULVERDE_BASE_REG_PA_MEMC, FALSE);
v_pOSTReg = (volatile XLLP_OST_T*)OALPAtoVA(BULVERDE_BASE_REG_PA_OST, FALSE);
v_pLCDRegs =(volatile LCDRegs*)OALPAtoVA(BULVERDE_BASE_REG_PA_LCD, FALSE);
v_pDMARegs =(volatile XLLP_DMAC_T*)OALPAtoVA(BULVERDE_BASE_REG_PA_DMAC, FALSE);
v_pGPIOReg =(XLLP_GPIO_T*)OALPAtoVA(BULVERDE_BASE_REG_PA_GPIO, FALSE);
}
/************************************************************************************
//Function Name: GetCurrentFrequencyStatus
//Functionality: return the content from CCSR
//Argument:
//Return: content of CCSR
//Comment: For later use in OS, it needs v_pClkReg as one argument
/************************************************************************************/
FREQ_VOLT_STATUS GetCurrentFrequencyStatus( )
{
FREQ_VOLT_STATUS temp;
unsigned long CLKCFGValue = XllpXSC1ReadCLKCFG();
temp.CPDIS = (v_pClkReg->ccsr & 0x80000000)>>31;
temp.PPDIS = (v_pClkReg->ccsr & 0x40000000)>>30;
temp.LCD_26 = (v_pClkReg->cccr & 0x08000000)>>27; // LCD_26 ccsr np
temp.PLL_EARLY = (v_pClkReg->cccr & 0x04000000)>>26; // PLL_EARLY ccsr np
temp.A_Bit = (v_pClkReg->cccr & 0x02000000)>>25; // A ccsr np
temp.NMulti = (v_pClkReg->ccsr & 0x00000380)>>7;
temp.LMulti = v_pClkReg->ccsr & 0x0000001F;
temp.fastbus_mode = (CLKCFGValue & 0x8)>>3;
temp.turbo_mode = (CLKCFGValue & 0x1);
temp.Volts = gLastVoltage;
// Volts: 2 ways to deal with this: 1) rip the dacvalue from the pmic 2) simply keep a soft copy when we set it
return temp;
}
/************************************************************************************
//Function Name: SetCoreFrequency
//Functionality: Set core frequency
//Argument: LMult - Multiplier of Run Mode
// NMult - Multiplier of Turbo Mode
// mode - Run mode or turbo mode or fast-bus mode
//Return: None
//Comment:For the time being, I am not sure whether mode change and frequency change
// could happen simultaneously, we assum it. If it doesn't, we update it later
// According to the SPECS, if you do the frequency change, system bus clock
// will be stopped for a while, but in turbo mode, system bus clcok doesn't stop,
// you don't need to concern about the LCD controller and memory controller
//Core frequency change sequence
/************************************************************************************/
void SetCoreFrequency(int LMult, int NMult, int run_mode_flag, int fastbus_mode_flag)
{
int newCLKCFGValue = 0;
unsigned long CLKCFGValue = 0;
int turbo_mode, i = 0;
turbo_mode = (CLKCFGValue & 0x1);
v_pClkReg->cccr = (NMult<<7) | LMult;
//NKDbgPrintfW(TEXT("before initiate new frequency cccr 0x%x\r\n"), v_pClkReg->cccr);
//set up the new CLKCFG value, for an new frequency
newCLKCFGValue =(0x2 | (fastbus_mode_flag<<3) | run_mode_flag);
// Gracefully suspend LCD controller if in RUN mode or fast_bus mode
// it is not necssary for Turbo mode because system bus is not disabled
// for Turbo mode
if (LMult > 15)
{
newCLKCFGValue = 0x2; // B= 0 (Normal), F=1
}
//Program the CLKCFG (CP14, reigster 6) for frequency change
//parameter is mask to use for CLKCFG register
// NKDbgPrintfW(TEXT("after initiate new frequency ccsr 0x%x\r\n"), v_pClkReg->ccsr);
}
#ifdef EBOOT_BLD
extern msWait(unsigned msVal);
#endif
//#define DBG 1
/********************************************************************************
//Function Name: SetCoreVoltage
//Functionality: Sets core voltage via PMIC on PI2C bus
//Argument: DacValue: command data sent to PMIC.
//Return: none
//Comment:
/********************************************************************************/
void SetCoreVoltage(DWORD dacValue)
{
v_pPwrReg->PCFR |= (0x60); // enable Pwr I2C
v_pI2CReg->ISAR = 0x0; // Set Slave address
v_pI2CReg->ICR = 0x0; // Clear interrupts in ICR
v_pI2CReg->ICR = (I2C_IUE | I2C_SCLE); // Enable I2C unit, and enable clock output
v_pI2CReg->IDBR = 0x40; // Set D/A's slave address and enable write mode
v_pI2CReg->ICR = (I2C_IUE | I2C_SCLE | I2C_START | I2C_TB); // Send START and then TRANSMIT the byte.
while ((v_pI2CReg->ISR & I2C_ITE) != I2C_ITE); // Wait for ITE to go high. bman: never gets out of this loop. <<--|
v_pI2CReg->ISR = I2C_ITE; // Write the ITE bit to clear it.
v_pI2CReg->IDBR = 0x0; // Command
v_pI2CReg->ICR = (I2C_IUE | I2C_SCLE | I2C_TB); // Clear START, STOP, set TB
while ((v_pI2CReg->ISR & I2C_ITE) != I2C_ITE); // Wait for ITE to go high
v_pI2CReg->ISR = I2C_ITE; // Write the ITE bit to clear it.
v_pI2CReg->IDBR = dacValue & 0x000000FF; // LSB
v_pI2CReg->ICR = (I2C_IUE | I2C_SCLE | I2C_TB); // Clear START, STOP, set TB
while ((v_pI2CReg->ISR & I2C_ITE) != I2C_ITE); // Wait for ITE to go high
v_pI2CReg->ISR = I2C_ITE; // Write the ITE bit to clear it.
v_pI2CReg->IDBR = (dacValue & 0x0000FF00) >> 8; // MSB
v_pI2CReg->ICR = (I2C_IUE | I2C_SCLE | I2C_TB); // Clear START, STOP, set TB
while ((v_pI2CReg->ISR & I2C_ITE) != I2C_ITE); // Wait for ITE to go high
v_pI2CReg->ISR = I2C_ITE; // Write the ITE bit to clear it.
v_pI2CReg->ICR = (I2C_IUE | I2C_SCLE | I2C_STOP | I2C_TB);
while ((v_pI2CReg->ISR & I2C_ITE) != I2C_ITE); // Wait for ITE to go high
v_pI2CReg->ISR = I2C_ITE; // Write the ITE bit to clear it.
while (( (v_pPwrReg->PVCR) & PVCR_VCSA) !=0); // set means busy
}
void ClearAllSQC(void)
{
int i =0;
for (i=0; i<32; i++)
(v_pPwrReg->PCMDn[4*i]) &= ~PCMD_SQC;
}
void ClearAllMBC(void)
{
int i =0;
for (i=0; i<32; i++)
(v_pPwrReg->PCMDn[4*i]) &= ~PCMD_MBC;
}
void ClearAllDCE(void)
{
int i =0;
for (i=0; i<32; i++)
(v_pPwrReg->PCMDn[4*i]) &= ~PCMD_DCE;
}
void SetMBCBit(int ReadPointer, int NumOfBytes)
{
v_pPwrReg->PCMDn[0] |= PCMD_MBC;
v_pPwrReg->PCMDn[1] |= PCMD_MBC;
}
void SetLCBit(int ReadPointer, int NumOfBytes)
{
v_pPwrReg->PCMDn[0] |= PCMD_LC;
v_pPwrReg->PCMDn[1] |= PCMD_LC;
v_pPwrReg->PCMDn[2] |= PCMD_LC;
}
void SetCommandData(unsigned char *DataArray, int StartPoint, int size)
{
v_pPwrReg->PCMDn[0] &= 0xFFFFFF00;
v_pPwrReg->PCMDn[0] |= DataArray[0];
v_pPwrReg->PCMDn[1] &= 0xFFFFFF00;
v_pPwrReg->PCMDn[1] |= DataArray[1];
v_pPwrReg->PCMDn[2] &= 0xFFFFFF00;
v_pPwrReg->PCMDn[2] |= DataArray[2];
}
BOOL VSetPCMDRange_LC(UINT iFrom, UINT iTo)
{
UINT i;
if (iTo < iFrom || iTo < 0 || iFrom < 0 || iTo > 31 || iFrom > 31)
{
return FALSE;
}
for (i = iFrom ; i <= iTo ; i++)
{
// set commands, this is not the last one
v_pPwrReg->PCMDn[4 * i] &= ~PCMD_LC;
}
// set last command
v_pPwrReg->PCMDn[4 * iTo] |= PCMD_LC;
return TRUE;
}
void VM_SingleByte_Command(DWORD data, int ReadPointer)
{
int i = 0;
v_pPwrReg->PVCR = 0;
v_pPwrReg->PCFR &= ~PCFR_FVC;
v_pPwrReg->PVCR &=~ PVCR_CommandDelay; // no delay is necessary
v_pPwrReg->PVCR |= 0xFFFFFF80; // clear slave address
v_pPwrReg->PVCR |= 0x20; // set slave address
v_pPwrReg->PVCR &= ~(0x1f<<20); // clear read pointer 0
v_pPwrReg->PVCR |= (ReadPointer<<20);
ClearAllSQC();
ClearAllMBC(); // single byte command
ClearAllDCE(); // Clear DCE bit
//through ReadPointer to find the command register which needs to send byte
//fill the data with command register
for (i=0; i<32; i++)
{
if (i == ReadPointer)
{
v_pPwrReg->PCMDn[4 * i] = data;
break;
}
else
v_pPwrReg->PCMDn[4 * i] &= 0xFFFFFF00;
}
//Set last command to read pointer also so we only send one command
VSetPCMDRange_LC(0, ReadPointer);
v_pPwrReg->PCFR |= 0x60; // enable Pwr I2C
while (( (v_pPwrReg->PVCR) & PVCR_VCSA))
{
}
}
void VM_MulitByte_Command(unsigned char *dataArray, int ReadPointer, int NumOfBytes)
{
while (v_pPwrReg->PVCR & PVCR_VCSA); // set means busy. Consider using a timeout here.
v_pPwrReg->PVCR = 0; // no command delay is necessary
//*PVCR &= 0xFFFFF07F;
//*PVCR &= 0xFFFFFF80; // clear slave address
v_pPwrReg->PVCR |= 0x20; // set slave address
//*PVCR &= 0xFE0FFFFF; // clear read pointer 0
v_pPwrReg->PVCR |= (ReadPointer << 20); // PCMD[ReadPointer] contains the first command
ClearAllSQC(); // Sequence configuration is not necessary
ClearAllDCE(); // Clear DCE bit
ClearAllMBC();
SetMBCBit (ReadPointer, NumOfBytes); // set MBC for all but the last command byte
// indicate this is the first command and last command also (?)
//
SetLCBit(ReadPointer, NumOfBytes);
//
// program the command data
//
SetCommandData(dataArray, ReadPointer, NumOfBytes);
v_pPwrReg->PCFR |= PCFR_FVC; // enable VCS on FCS
v_pPwrReg->PCFR |= (0x60); // enable Pwr I2C
}
//
// Needs to be plat-specific
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -