📄 marathon.c
字号:
HostUnMapPhysToLin(pui32ClkCtrl, CLK_REG_MAP_SIZE / HOST_PAGESIZE());
}
PVR_DPF((PVR_DBG_MESSAGE, "MARATHON: XScale MemClk believed to be %dHz.\n", pMSysData->ui32MemClk));
/* Calculate tSYSPW (see figure 56 of IAS) in terms of XScale memclk */
/* 2*marathon_sysclk/xcale_memclk, rounding up */
// ui32SYSPW = (2*pMSysData->ui32MemClk+ui32Freq-1)/pMSysData->ui32SysClk;
ui32SYSPW = (2*pMSysData->ui32MemClk+ui32Freq-1)/ui32Freq;
if (pMSysData->bCotulla)
{
IMG_UINT32 ui32RDFMap[16] =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 18, 23};
/* VLIO: tSYSPW = RRR*2 + 1 */
ui32RRR = ui32SYSPW/2;
/* VLIO: tSYSPW = RDN + 2 */
ui32RDN = ui32SYSPW - 2;
/* VLIO: tSYSPW = RDF + 1 */
ui32RDF = ui32SYSPW - 1;
/* SRAM: tSYSPW = RRR*2 + 4 */
ui32SramRRR = (ui32SYSPW - 2)/2;
/* SRAM: tSYSPW = RDN + 1 */
ui32SramRDN = ui32SYSPW - 1;
if (ui32RDN < 2)
ui32RDN = 2;
if (ui32SramRDN <2)
ui32SramRDN = 2;
ui32RDF = Remap(ui32RDFMap, ui32RDF);
if (ui32RDF < 3)
ui32RDF = 3;
}
else
{
#ifdef BULVERDE_B_STEPPING
IMG_UINT32 ui32RDNMap[16] =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 20, 26, 30};
IMG_UINT32 ui32RDFMap[16] =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 18, 23};
#else
IMG_UINT32 ui32RDFMap[16] =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 20, 26, 30};
#endif
/* VLIO: tSYSPW = RRR*2 + 1 */
ui32RRR = ui32SYSPW/2;
/* VLIO: tSYSPW = RDN*2 */
ui32RDN = (ui32SYSPW + 1)/2;
/* VLIO: tSYSPW = RDF + 1 */
ui32RDF = ui32SYSPW - 1;
/* SRAM: tSYSPW = RRR*2 + 4 */
if(ui32SYSPW >= 3)
{
ui32SramRRR = (ui32SYSPW - 3)/2;
}
else
{
ui32SramRRR = 0;
}
/* SRAM: tSYSPW = RDN + 1 */
ui32SramRDN = ui32SYSPW - 1;
#ifdef BULVERDE_B_STEPPING
ui32RDN = Remap(ui32RDNMap, ui32RDN);
ui32SramRDN = Remap(ui32RDNMap, ui32SramRDN);
#endif
if (ui32RDN < 2)
ui32RDN = 2;
ui32RDF = Remap(ui32RDFMap, ui32RDF);
if (ui32RDF < 3)
ui32RDF = 3;
}
if (ui32RRR > 7)
{
PVR_DPF((PVR_DBG_WARNING,"XScaleMMCSetup: VLIO RRR out of spec (want %d, programming 7)", ui32RRR));
ui32RRR = 7;
}
if (ui32SramRRR > 7)
{
PVR_DPF((PVR_DBG_WARNING,"XScaleMMCSetup: SRAM RRR out of spec (want %d, programming 7)", ui32SramRRR));
ui32SramRRR = 7;
}
if (ui32RDN > 15)
{
PVR_DPF((PVR_DBG_WARNING, "XScaleMMCSetup: VLIO RDN out of spec"));
ui32RDN = 15;
}
if (ui32SramRDN > 15)
{
PVR_DPF((PVR_DBG_WARNING,"XScaleMMCSetup: SRAM RDN out of spec"));
ui32SramRDN = 15;
}
if (ui32RDF > 15)
{
PVR_DPF((PVR_DBG_WARNING,"XScaleMMCSetup: VLIO RDF out of spec"));
ui32RDF = 15;
}
ui32Val = (ui32RRR << 12) | (ui32RDN << 8) | (ui32RDF << 4) | 0x4;
ConfigureChipSelect(pMSysData->ui32VLIOChipSelect, ui32Val, pMSysData);
if(pMSysData->ui32SRAMChipSelect != -1)
{
ui32Val = (ui32SramRRR << 12) | (ui32SramRDN << 8) | (0xf << 4) | 0x1;
ConfigureChipSelect(pMSysData->ui32SRAMChipSelect, ui32Val, pMSysData);
}
PVR_DPF((PVR_DBG_MESSAGE,"MARATHON: XScaleMMCSetup exited.\n"));
return(TRUE);
}
/*****************************************************************************
FUNCTION : ConfigureChipSelect
PURPOSE : Identify which MSCx register must be written to configure the
specified chip select. Copy the configuration bits (ui32MemoryConfig)
to either the upper or lower 16-bits of the MSCx register as
appropriate.
PARAMETERS : IMG_UINT32 ui32ChipSelect
IMG_UINT32 ui32MemoryConfig
PSYS_SPECIFIC_DATA pMSysData
RETURNS :
*****************************************************************************/
static void ConfigureChipSelect(IMG_UINT32 ui32ChipSelect, IMG_UINT32 ui32MemoryConfig, PSYS_SPECIFIC_DATA pMSysData)
{
volatile IMG_UINT32 *pui32Reg = 0;
IMG_UINT32 ui32MSC;
/* Make sure that the chip select is within the permitted range. */
PVR_ASSERT((ui32ChipSelect >= 0));
PVR_ASSERT((ui32ChipSelect <= 5));
/* Find the MSCx register corresponding to the requested chip select. */
pui32Reg = (pMSysData->pui32MemCtrl)+2+(ui32ChipSelect/2);
/* Read contents of the MSCx register. */
ui32MSC = *pui32Reg;
if(ui32ChipSelect % 2)
{
/* If ChipSelect is an odd number, prepare to write to the upper 16 bits of the MSCx register. */
ui32MSC = (ui32MSC & 0x0000ffff) | (ui32MemoryConfig << 16);
}
else
{
/* If ChipSelect is an even number, prepare to write to the lower 16 bits of the MSCx register. */
ui32MSC = (ui32MSC & 0xffff0000) | ui32MemoryConfig;
}
/* Write back to the MSCx register. */
*pui32Reg = ui32MSC;
}
#if REDUCE_FREQ_IN_DISP_REFRESH
/*****************************************************************************
FUNCTION : SysQuickChangeSYSCLK
PURPOSE : Change Marathon System Clock while entering
: and exiting Display Refresh
PARAMETERS : PSYS_SPECIFIC_DATA pMSysData
: BOOL bSlow
****************************************************************************/
void SysQuickChangeSYSCLK(PSYS_SPECIFIC_DATA pMSysData, BOOL bSlow)
{ //---------- Quick Core Clock Switch
DWORD dwPLL;
DWORD dwODFBModeVal = (pMSysData->bODFBPowerModeActiveLow) ?
MAR_ODFB_POWERMODE_MODE_ACTIVE_LOW :
MAR_ODFB_POWERMODE_MODE_ACTIVE;
if (bSlow)
{
dwODFBModeVal |= MAR_ODFB_POWERMODE_SLOW_LOW;
dwPLL = MAR_SYSCLK_SELECT_PLL1; // Use PLL1 (PixClk) as SysClk Source
}
else
{
dwODFBModeVal |= (pMSysData->ui32SysClk < MAR_ODFB_FREQ_THRESHOLD) ?
MAR_ODFB_POWERMODE_SLOW_LOW :
MAR_ODFB_POWERMODE_SLOW_HIGH;
dwPLL = MAR_SYSCLK_SELECT_PLL0; // Use PLL0 (Full Speed) as SysClk Source
}
// Start Switch Over ---- This section should complete within ~200uS to avoid user-seen flash
SysPreChangePll(TRUE); // Waits for VSync, so the next steps are not seen by user
// SET ODFB (on-chip RAM) Mode (required prior to chaning SYSCLK PLL
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_ODFB_POWERMODE, MAR_ODFB_POWERMODE_MODE_SLEEP);
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_SYSCLK_SELECT, dwPLL);
HostWaitus(3); // Need to wait after switching SysClk Source for more than 2.5us
// Wake ODFB (on-chip RAM)
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_ODFB_POWERMODE, dwODFBModeVal);
SysPostChangePll(TRUE);
// End Switch Over ------------
} //---------- End Quick Core Clock Switch
/*****************************************************************************
FUNCTION : SysSDRAMSetStateWithFreqChanges
PURPOSE : Set SDRAM power mode and change Marathon core frequency
PARAMETERS : ui32Mode - mode to set
RETURNS :
*****************************************************************************/
void SysSDRAMSetStateWithFreqChanges(IMG_UINT32 ui32Mode)
{
IMG_UINT32 ui32Val;
PSYS_SPECIFIC_DATA pMSysData;
GET_MARATHON_SYS_DATA(pMSysData);
switch (ui32Mode)
{
case SYS_SDRAM_POWER_SLEEP:
WriteHWReg(pMSysData->pvLinRegBaseAddr,
MC_POWERDOWN_CONTROL,
MC_POWERDOWN_CONTROL_SELF_REFRESH);
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_SDCLK_CONFIG, MAR_SDCLK_CONFIG_OFF); /* wt: Hardware say invalid */
SysQuickChangeSYSCLK(pMSysData, TRUE);
#ifdef LOCAL_MEMORY_SELF_REFRESH
#ifdef LOCAL_MEMORY_SELF_REFRESH_TESTING
SysWriteLEDData(0x22);
#endif // LOCAL_MEMORY_SELF_REFRESH_TESTING
#endif // LOCAL_MEMORY_SELF_REFRESH
pMSysData->ui32SDRAMMode = SYS_SDRAM_POWER_SLEEP;
break;
case SYS_SDRAM_POWER_ACTIVE:
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_SDCLK_CONFIG, MAR_SDCLK_CONFIG_ON);
WriteHWReg(pMSysData->pvLinRegBaseAddr, MC_POWERDOWN_CONTROL, MC_POWERDOWN_CONTROL_ACTIVE);
SysQuickChangeSYSCLK(pMSysData, FALSE);
pMSysData->ui32SDRAMMode = SYS_SDRAM_POWER_ACTIVE;
/* Dummy read access to the SDRAM address space to trigger the statechange to ACTIVE */
ui32Val = *pMSysData->pui32SDRAMDummyArea;
#ifdef LOCAL_MEMORY_SELF_REFRESH
#ifdef LOCAL_MEMORY_SELF_REFRESH_TESTING
SysWriteLEDData(0x11);
#endif // LOCAL_MEMORY_SELF_REFRESH_TESTING
#endif // LOCAL_MEMORY_SELF_REFRESH
break;
default:
PVR_DPF((PVR_DBG_ERROR, "SysSDRAMSetStateWithFreqChanges - Invalid state - Only Active and Sleep are supported"));
break;
}
}
#endif //REDUCE_FREQ_IN_DISP_REFRESH
/*****************************************************************************
FUNCTION : SysSDRAMSetState
PURPOSE : Set SDRAM power mode
PARAMETERS : ui32Mode - mode to set
RETURNS :
*****************************************************************************/
void SysSDRAMSetState(IMG_UINT32 ui32Mode)
{
IMG_UINT32 ui32Val;
PSYS_SPECIFIC_DATA pMSysData;
GET_MARATHON_SYS_DATA(pMSysData);
PDUMPSCRIPT("---- SetSDRAMSetState");
PDUMPREGTAG(PDUMPTAGS_REG_MSOC, 0);
switch (ui32Mode)
{
case SYS_SDRAM_POWER_SLEEP:
PVR_DPF((PVR_DBG_MESSAGE, "SysSDRAMSetState - SLEEP"));
WriteHWReg(pMSysData->pvLinRegBaseAddr,
MC_POWERDOWN_CONTROL,
MC_POWERDOWN_CONTROL_SELF_REFRESH);
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_SDCLK_CONFIG, MAR_SDCLK_CONFIG_OFF);
#ifdef LOCAL_MEMORY_SELF_REFRESH
#ifdef LOCAL_MEMORY_SELF_REFRESH_TESTING
SysWriteLEDData(0x22);
#endif // LOCAL_MEMORY_SELF_REFRESH_TESTING
#endif // LOCAL_MEMORY_SELF_REFRESH
pMSysData->ui32SDRAMMode = SYS_SDRAM_POWER_SLEEP;
break;
case SYS_SDRAM_POWER_SHUTDOWN:
PVR_DPF((PVR_DBG_MESSAGE, "SysSDRAMSetState - SHUTDOWN"));
WriteHWReg(pMSysData->pvLinRegBaseAddr, MC_POWERDOWN_CONTROL, MC_POWERDOWN_CONTROL_SHUTDOWN);
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_SDCLK_CONFIG, MAR_SDCLK_CONFIG_OFF);
pMSysData->ui32SDRAMMode = SYS_SDRAM_POWER_SHUTDOWN;
break;
case SYS_SDRAM_POWER_ACTIVE:
PVR_DPF((PVR_DBG_MESSAGE, "SysSDRAMSetState - ACTIVE"));
WriteHWReg(pMSysData->pvLinRegBaseAddr, MAR_SDCLK_CONFIG, MAR_SDCLK_CONFIG_ON);
WriteHWReg(pMSysData->pvLinRegBaseAddr, MC_POWERDOWN_CONTROL, MC_POWERDOWN_CONTROL_ACTIVE);
pMSysData->ui32SDRAMMode = SYS_SDRAM_POWER_ACTIVE;
//FIXME, do we need to snsure that the following line is not optimised out on a release build
/* Dummy read access to the SDRAM address space to trigger the statechange to ACTIVE */
ui32Val = *pMSysData->pui32SDRAMDummyArea;
#ifdef LOCAL_MEMORY_SELF_REFRESH
#ifdef LOCAL_MEMORY_SELF_REFRESH_TESTING
SysWriteLEDData(0x11);
#endif // LOCAL_MEMORY_SELF_REFRESH_TESTING
#endif // LOCAL_MEMORY_SELF_REFRESH
break;
default:
PVR_DPF((PVR_DBG_ERROR, "SysSDRAMSetState - *UNKNOWN*"));
break;
}
PDUMPREGMBX;
}
/*****************************************************************************
FUNCTION : SysPostChangePll
PURPOSE : Restore the PDP address generator and sync control regs to their
State before the prechange pll call
PARAMETERS :
RETURNS :
*****************************************************************************/
IMG_VOID SysPostChangePll()
{
PSYS_SPECIFIC_DATA pMSysData;
GET_MARATHON_SYS_DATA(pMSysData);
/* Reenable the address generators */
WriteHWReg(pMSysData->pvLinRegBaseAddr, PDP_STR1BASE + DISPLAY_REG_OFFSET,pMSysData->ui32Str1);
WriteHWReg(pMSysData->pvLinRegBaseAddr, PDP_STR2BASE + DISPLAY_REG_OFFSET,pMSysData->ui32Str2);
WriteHWReg(pMSysData->pvLinRegBaseAddr, PDP_CURBASE + DISPLAY_REG_OFFSET,pMSysData->ui32Str3);
}
/*****************************************************************************
FUNCTION : SysPreChangePll
PURPOSE : Store the PDP address generator and sync control regs to allow
recovery after we have done pll setting stuff
PARAMETERS :
RETURNS :
*****************************************************************************/
IMG_VOID SysPreChangePll()
{
IMG_UINT32 ui32FrontPorch , ui32ActiveLine;
PSYS_SPECIFIC_DATA pMSysData;
GET_MARATHON_SYS_DATA(pMSysData);
/*---------------------------------------------------------------------------------------------------------------------------------------------------------**
** Ok we are moving the DAC pre and post pll behaviour into here so as to minimize the amount of time that the address generator is turned off **
** We want to wait until the end of the display i.e. wait for the current line to be >= front porch start this will give us maximum time to do the change **
** Obviously we only need to do this if any of the sync gens are active. **
**---------------------------------------------------------------------------------------------------------------------------------------------------------*/
pMSysData->ui32Str1=ReadHWReg(pMSysData->pvLinRegBaseAddr,PDP_STR1BASE + DISPLAY_REG_OFFSET);
pMSysData->ui32Str2=ReadHWReg(pMSysData->pvLinRegBaseAddr,PDP_STR2BASE + DISPLAY_REG_OFFSET);
pMSysData->ui32Str3=ReadHWReg(pMSysData->pvLinRegBaseAddr,PDP_CURBASE + DISPLAY_REG_OFFSET);
pMSysData->ui32Sync=ReadHWReg(pMSysData->pvLinRegBaseAddr,PDP_SYNCCTRL + DISPLAY_REG_OFFSET);
ui32FrontPorch = ReadHWReg(pMSysData->pvLinRegBaseAddr,PDP_VT3 + DISPLAY_REG_OFFSET) >>16;
if((pMSysData->ui32Sync & 0x80000000)&&(( pMSysData->ui32Str1 & 0x80000000)||(pMSysData->ui32Str2 & 0x80000000)||(pMSysData->ui32Str3 & 0x80000000)))
{
// first wait until we are less than the front porch start
do
{
ui32ActiveLine = ReadHWReg(pMSysData->pvLinRegBaseAddr,PDP_LINECOUNT + DISPLAY_REG_OFFSET);
}while(ui32ActiveLine>ui32FrontPorch);
// Then wait for it becoming greater, this gives us the most time for a flicker free update
do
{
ui32ActiveLine = ReadHWReg(pMSysData->pvLinRegBaseAddr,PDP_LINECOUNT + DISPLAY_REG_OFFSET);
}while(ui32ActiveLine<ui32FrontPorch);
/* turn off the address generators */
WriteHWReg(pMSysData->pvLinRegBaseAddr, PDP_STR1BASE + DISPLAY_REG_OFFSET, pMSysData->ui32Str1&~0x80000000);
WriteHWReg(pMSysData->pvLinRegBaseAddr, PDP_STR2BASE + DISPLAY_REG_OFFSET, pMSysData->ui32Str2&~0x80000000);
WriteHWReg(pMSysData->pvLinRegBaseAddr, PDP_CURBASE + DISPLAY_REG_OFFSET, pMSysData->ui32Str3&~0x80000000);
}
}
#endif /* SUPPORT_MARATHON */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -