📄 dvm.c
字号:
/* these are DVM APIs. They are being used to set voltage and frequency dynamically
Get the current frequency state and voltage level, another very important thing
is to implement DVM policy which takes information from system and decides when
and how to change frequency and voltage to minimze the power consumption on the
fly, but still meet performance requirement. Current code refers Joe's PWR_I2C
code and Beth's frequency change code
*/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "systypes.h"
#include "dm_errors.h"
#include "dm_edit.h"
#include "xsuart.h"
#include "dm_serialInOut.h"
#include "xllp_clkmgr.h"
#include "xllp_gpio.h"
#include "xllp_pm.h"
#include "xllp_intc.h"
#include "xllp_memctrl.h"
#include "boardControl.h"
#include "i2c.h"
#include "DVM.h"
P_XLLP_INTC_T intReg = (P_XLLP_INTC_T)0x40D00000;
P_XLLP_CLKMGR_T clkReg = (P_XLLP_CLKMGR_T)0x41300000;
P_XLLP_GPIO_T gpioReg = (P_XLLP_GPIO_T ) 0x40E00000;
P_POST_I2C_T PI2C = (P_POST_I2C_T)PWR_I2C_BASE;
P_XLLP_PWRMGR_T pwrMgr = (P_XLLP_PWRMGR_T)0x40F00000;
XLLP_MEMORY_CONTROL_REGISTER_T * memContrl = (XLLP_MEMORY_CONTROL_REGISTER_T * )0x48000000;
/***********************************************************************************
//function Name: DVM_Init
//Functionality: Initialize PWR I2C and allocate memory for the I2C structure
//Argument: None
//Return: void
//Comment: This format is just for bare metal test, later for OS, it is not necessary
***********************************************************************************/
void DVMInit(void)
{
//Enable PWERI2C clock
clkReg->cken |=XLLP_CLKEN_PWRI2C; //XLLP_CLKEN_PWRI2C;
pwrMgr->PCFR |= PCFR_PI2C;
}
/***********************************************************************************
//function Name: DVM_Init
//Functionality: Initialize PWR I2C and allocate memory for the I2C structure
//Argument: None
//Return: void
//Comment: This format is just for bare metal test, later for OS, it is not necessary
***********************************************************************************/
void DVMPwrdwn(void)
{
//disable PWERI2C clock
clkReg->cken &=~XLLP_CLKEN_PWRI2C; //XLLP_CLKEN_PWRI2C;
pwrMgr->PCFR &= ~PCFR_PI2C;
}
/********************************************************************************
//Function Name: SetCoreVoltage
//Functionality: Report the value of core voltage
//Argument: None
//Return: the core voltage value
//Comment:
********************************************************************************/
UINT SetCoreVoltage(UINT16 dacValue)
{
UINT errorLog=0;
I2C_TX seq;
XLLP_UINT8_T voltageChange[3];
XLLP_UINT32_T returnVal=0;
PI2C->ISAR = 0x0; // Set Slave address
PI2C->ICR = 0x0; // Clear interrupts in ICR
PI2C->ICR = (POST_ICR_UIE | POST_ICR_SCLEA); // Enable I2C unit, and enable clock output
voltageChange[0] = 0x0;
voltageChange[1] = dacValue & 0xff;
voltageChange[2] = (dacValue & 0xff00) >> 8;
seq.dev_id = 0x40;
seq.data_len = sizeof(voltageChange);
seq.data = voltageChange;
if((returnVal = i2c_write(PI2C, intReg, &seq))!= ERR_T_NONE)
{
XllpUtilityOutputError(returnVal);
LOGERRORX(errorLog,
ERR_L_DVM, ERR_TS_I2C_WRITE, DAC_VAL, ERR_T_NOTRANSMIT,
0, 0, 0);
return(errorLog);
}
return 0;
}
UINT8 AsciiToDecTrans(char d)
{
if((d > 47)&&(d < 58))
return(d - 48);
return 0;
}
UINT16 GetInput(INT keyCount)
{
CHAR key;
INT32 newVolt=0;
INT placeSpot;
UartContextT * ctxP = GetPointerToSystemUart();
volatile UartRegsT * uartP = (UartRegsT *)ctxP->regsP;
ctxP->clearRxUartFnP(ctxP);
if(keyCount== 3)
placeSpot=100;
else
if(keyCount== 2)
placeSpot=10;
else
if(keyCount== 1)
placeSpot=1;
while (keyCount--)
{
while (ctxP->readUartFnP(ctxP, (PCHAR)&key, 1) == 0);
// Toggle RTS signal
uartP->MCR ^= MCR_RTS;
// Translate the key
key &= 0xff;
printf("%c", key);
newVolt += (AsciiToDecTrans(key) * placeSpot);
placeSpot = placeSpot/10;
}
return newVolt;
}
/********************************************************************************
//Function Name: DVMSetVolt
//Functionality: Report the value of core voltage
//Argument: None
//Return: the core voltage value
//Comment:
********************************************************************************/
void KDVMSetVolt(PVOID arg, PCHAR param)
{
CHAR string[80];
PCHAR tokenP;
INT32 newVoltage=0;
INT i, placeSpot=100;
if (param)
{
// Copy the arguments so not to alter the original string.
strcpy(string, param);
// Get first token.
tokenP = strtok(string, " ,\n");
for(i=0;i<3;i++)
{
newVoltage += (AsciiToDecTrans(tokenP[i]) * placeSpot);
placeSpot = placeSpot/10;
}
}
else
{
printf (" User! Enter a new voltage >>");
newVoltage = GetInput(3);
}
DVMSetVolt(newVoltage);
}
void DVMSetVolt(UINT16 newVoltage)
{
DVMInit();
SetCoreVoltage(newVoltage);
DVMPwrdwn();
}
void KDVMSetVoltFreq(PVOID arg, PCHAR param)
{
CHAR string[80];
PCHAR tokenP;
INT32 newVoltage=0;
INT i, placeSpot=100;
UINT32 newFreq=0;
UINT16 lMultipler=0;
if (param)
{
// Copy the arguments so not to alter the original string.
strcpy(string, param);
// Get first token.
tokenP = strtok(string, " ,\n");
for(i=0;i<3;i++)
{
newVoltage += (AsciiToDecTrans(tokenP[i]) * placeSpot);
placeSpot = placeSpot/10;
}
placeSpot=100;
tokenP = strtok(NULL, " ,\n");
for(i=0;i<3;i++)
{
newFreq += (AsciiToDecTrans(tokenP[i]) * placeSpot);
placeSpot = placeSpot/10;
}
}
else
{
printf (" User! Enter a new voltage >>");
newVoltage = GetInput(3);
printf ("\r\n User! Enter a new freqency >>");
newFreq = GetInput(3);
}
lMultipler = newFreq/13;
ComboChange(lMultipler,0x2, newVoltage, 0);
}
void ComboChange(INT LMult, INT TMult, UINT16 DACValue, UINT fBus)
{
UINT8 dataArray[3];
UINT ReadPointer = 0;
dataArray[0] = 0; //Command 0
dataArray[1] = (DACValue & 0x000000FF);
dataArray[2] = (DACValue & 0x0000FF00)>>8;
//set up the new frequency mulitipliers, N and L
clkReg->cken |=XLLP_CLKEN_PWRI2C; //XLLP_CLKEN_PWRI2C;
clkReg->cccr = (((TMult & 0x7)<<7) | (LMult & 0x1f));
//votlage change configureation
pwrMgr->PVCR = 0;
// pwrMgr->PCFR = 0;
pwrMgr->PCFR &= ~PCFR_FVC;
pwrMgr->PVCR &= 0xFFFFF07F; //no delay is necessary
pwrMgr->PVCR &= 0xFFFFFF80; //clear slave address
pwrMgr->PVCR |= 0x20; //set slave address
pwrMgr->PVCR &= 0xFE0FFFFF; //clear read pointer 0
pwrMgr->PVCR |= (ReadPointer<<20);
//DCE and SQC are not necessary for single command
ClearAllSQC(); //Sequence configuration is not necessary
ClearAllDCE(); //Clear DCE bit
ClearAllMBC( ); //Clear all MBC bit first
//indicate the last byte of this command is holded in this register
pwrMgr->PCMDn[2] &= ~PCMDn_MBC;
//programming the command data bit
pwrMgr->PCMDn[0] &= 0xFFFFFF00;
pwrMgr->PCMDn[0] |= (dataArray[0] | PCMDn_MBC | PCMDn_LC);
pwrMgr->PCMDn[1] &= 0xFFFFFF00;
pwrMgr->PCMDn[1] |= ( dataArray[1] | PCMDn_MBC | PCMDn_LC);
pwrMgr->PCMDn[2] &= 0xFFFFFF00;
pwrMgr->PCMDn[2] |= ( dataArray[2] | PCMDn_LC);
pwrMgr->PCFR |= (PCFR_PI2C|PCFR_FVC); //PCFR_PI2C_EN; //enable Pwr I2C
if(fBus == 1)
InitiateFcs(1, 1);
else
InitiateFcs(1, 0);
clkReg->cken &=~XLLP_CLKEN_PWRI2C; //XLLP_CLKEN_PWRI2C;
WriteHexLeds(clkReg->ccsr);
}
void ClearAllSQC(void)
{
int i =0;
for(i=0; i<32; i++)
pwrMgr->PCMDn[i] &= ~PCMDn_SQC;
}
void ClearAllMBC(void)
{
int i =0;
for(i=0; i<32; i++)
pwrMgr->PCMDn[i] &= ~PCMDn_MBC;
}
void ClearAllDCE(void)
{
int i =0;
for(i=0; i<32; i++)
pwrMgr->PCMDn[i] &= ~PCMDn_DCE;
}
void KDVMTFreqChange(PVOID arg, PCHAR param)
{
CHAR string[80];
PCHAR tokenP;
UINT16 newVoltage=0;
UINT32 newFreq=0;
UINT16 lMultipler=0;
UINT16 tMultipler=0;
UINT fastBus=0, memclkdivtwo=0;
int i=0, placeSpot=100;;
// Check for parameters.
if (param)
{
// Copy the arguments so not to alter the original string.
strcpy(string, param);
// Get first token for new voltage.
tokenP = strtok(string, " ,\n");
for(i=0;i<3;i++)
{
newVoltage += (AsciiToDecTrans(tokenP[i]) * placeSpot);
placeSpot = placeSpot/10;
}
placeSpot=100;
tokenP = strtok(NULL, " ,\n");
// Get next token for new frequency.
for(i=0;i<3;i++)
{
newFreq += (AsciiToDecTrans(tokenP[i]) * placeSpot);
placeSpot = placeSpot/10;
}
i=0;
// Get next token for turbo multiplier.
tokenP = strtok(NULL, " ,\n");
tMultipler = (AsciiToDecTrans(tokenP[i]));
// Get next token for fast bus.
tokenP = strtok(NULL, " ,\n");
fastBus = (AsciiToDecTrans(tokenP[i]));
// Get next token for setting memclk / 2 or not.
tokenP = strtok(NULL, " ,\n");
memclkdivtwo = (AsciiToDecTrans(tokenP[i]));
}
else
{
printf (" User! Enter a new voltage >>");
newVoltage = GetInput(3);
printf ("\r\n User! Enter a new freqency >>");
newFreq = GetInput(3);
printf ("\r\n User! Enter a Turbo Multipler (ex. 2 - 6) >>");
tMultipler = GetInput(1);
printf ("\r\n User! Set FastBus?\r\n");
if(GetUserResponse(YESNO))
fastBus = 1;
printf (" User! Set SDClk (CLK_MEM/2) freqency?\r\n");
if(GetUserResponse(YESNO))
memclkdivtwo=1;
}
lMultipler = newFreq/13;
ComboChange(lMultipler, tMultipler, newVoltage, fastBus);
if(memclkdivtwo)
memContrl->MDREFR |= 0x4000;
else
memContrl->MDREFR &= ~0x4000;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -