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

📄 idle.c

📁 Intel DBPXA27X评估板OAL层代码.
💻 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.
*/


#include <windows.h>
#include <nkintr.h>
#include <oal.h>
#include <bsp.h>
#include <types.h>
#include <bulverde.h>
#include "xllp_dvm.h"
#include "xllp_lcd.h"
#include "xllp_ost.h"
#include "xllp_intc.h"
#include "xllp_rtc.h"
#include "ipm_dvfm.h"
#include "bulverde_keypad.h"
#include "xllp_dmac.h"
#include "bsp_cfg.h"
#include "bulverde_base_regs.h"
#include "bulverde_ost.h"
#include "mainstoneii.h"

#define	CKEN16_LCD	(0x1<<16)
#define CCCR_CPDIS_BIT_ON	(0x1<<31)
#define CCCR_PPDIS_BIT_ON	(0x1<<30)
#define CCCR_LCD_26_BIT_ON	(0x1<<27)
#define	CCCR_PLL_EARLY_EN_BIT_ON	(0x1<<26)

extern void XllpCpuIdle();
extern void XllpCpuStandby();
extern BOOL	ComboChange(COMBO_PARAM );
static void IPM_Enter_13M(void);
static void IPM_Exit_13M( );
static void IPMWait(unsigned Microscont);
static void IPMmsWait(unsigned msVal);
static void IPMusWait(unsigned msVal);
static void BulverdeEnterStandby(void);
static void USecWait(UINT32 usec);
#define SENSE_PCD_CHG_EN (1 << 25)
#define SENSE_MD_PCD(x) ((x) << 17)

extern volatile XLLP_PWRMGR_T  *v_pPwrReg;
extern volatile XLLP_OST_T     *v_pOSTReg;
extern volatile I2C_REG        *v_pI2CReg;
extern volatile XLLP_CLKMGR_T  *v_pClkReg;
extern volatile LCDRegs        *v_pLCDRegs;
extern volatile XLLP_DMAC_T    *v_pDMARegs;
extern XLLP_GPIO_T    *v_pGPIOReg;

BOOL deep_idle_enabled = 0;

unsigned int clkcfg_save = 0;
int g_13MEnable = FALSE;
int g_SkipEnable = FALSE;
//------------------------------------------------------------------------------
//
//  Function:   IPMCPUIdle
//
//  This Idle function implements a cpu idle. 
//  it enters 13M idle if BSP_NODEEPIDLE defined 
//  and g_13MEnable is true.
//



extern UINT32 idle_msec;

// James Lai suggest to stay in deep idle for at least 40 msec to avoid
// LCD flicker.
// But we conservatively select 5 msec
#define IDLE_MSEC_MIN 5

void IPMCPUIdle()
{
#ifndef BSP_NOIPM       
#ifndef BSP_NODEEPIDLE          
	if( (deep_idle_enabled ==1) && (idle_msec >= IDLE_MSEC_MIN))
	
		IPM_Enter_13M();
#endif		
#endif		
        XllpCpuIdle();
	
#ifndef BSP_NOIPM       
#ifndef BSP_NODEEPIDLE        
	if( (deep_idle_enabled ==1) && (idle_msec >= IDLE_MSEC_MIN))
		IPM_Exit_13M();
#endif		
#endif		
}


#ifdef BSP_STANDBY_AS_IDLE
extern UINT32 OALTimerIntrHandler();


// setup ost4 and enter standby, return the duration of standby
UINT32 Standby(UINT32 idleMSec)
{
	UINT32 time_before;
	UINT32 time_match;

	extern void ost4_set_compare(UINT32);

	/* setup ost4 */
	time_before = v_pOSTReg->oscr4;
	time_match = v_pOSTReg->oscr4 + idleMSec;
	ost4_set_compare(time_match);
	BulverdeEnterStandby();

	/* ost4 or something else get the cpu out of standby */
	TIMER_M4_INT_CLR(v_pOSTReg->ossr);
	TIMER_M4_INT_DIS(v_pOSTReg->oier);
	return v_pOSTReg->oscr4 - time_before;
}

void BulverdeEnterStandby()
{
 
   unsigned long           SavedFDADR0;
   unsigned int            KeySnoop=0;
   BOOL                    DMABusy = FALSE;
	UINT32 i = 100000;



   // Setup the Wakeup enable registers for all the wakeup sources
   v_pPwrReg->PWER  =   0xC0000003u;
   v_pPwrReg->PRER  =   3u;
   v_pPwrReg->PFER  =   3u;

   // Clear the PEDR Edge Detects register
   v_pPwrReg->PEDR = 0xCE00FE1B;

   // Setup the keypad wakeups ( platform dependant )
   v_pPwrReg->PKWR = 0x000FD000;

   // Setting the OPDE bit so 13 Mhz OSC will still be powered.
   v_pPwrReg->PCFR = ((0x1 << 6) | (0x1u << 14) | (0x1u << 15) | 0x1);
   v_pPwrReg->PSTR = 0xF08;
   v_pPwrReg->PSSR = 0x10;

   // Clear the keypad status register.
   v_pPwrReg->PKSR = 0x000FFFFF;
   //  FIXME: Check to see if any DMA Activity is in Progress.
   // (takes care of Audio and MMC since they are DMA clients)

   for(i=0; i<32; i++) {
       if(v_pDMARegs->DCSR[i] & (0x1u << 31)) {
           DMABusy = TRUE;
           break;
       }
   }


   //  Check to see if any key press is in progress.
   //  FIXME: temply disabled to check this keypad events.
      KeySnoop = XllpKpKeypressIsInProgress(v_pGPIOReg);

   // if(KeySnoop || (v_pDriverGlobals->ipm.SkipLowPower) || (DMABusy)) {
   if( DMABusy || g_SkipEnable || KeySnoop) {
       XllpCpuIdle();
   } else  {
	   		SavedFDADR0 = v_pLCDRegs->FDADR0;
			v_pLCDRegs->LCSR0 = 1;
			while(v_pLCDRegs->LCSR0 & 1);			
			v_pLCDRegs->LCCR0 = ((v_pLCDRegs->LCCR0 & 0x07FFFFFF) | 0x448);				
			while(!(v_pLCDRegs->LCSR0 & 1));

			XllpCpuStandby();							// Beam me up Scotty !!

			// set ENB to restart the LCD again
			v_pLCDRegs->FDADR0 = SavedFDADR0;
			v_pLCDRegs->LCCR0 = ((v_pLCDRegs->LCCR0 & 0x07FFFBFF) | 0x1);  
 
   }
   v_pPwrReg->PSSR = 0x10;
   // NKDbgPrintfW(TEXT("Leaving Standby from kernel\r\n"));
}
#endif

BOOL OALIoCtlSetFreqVolt(UINT32 code, VOID *pInpBuffer, 
						 UINT32 inpSize, VOID *pOutBuffer,
                         UINT32 outSize, UINT32 *pOutSize)
{
	COMBO_PARAM  *combo_param;
		combo_param = (COMBO_PARAM *)pInpBuffer; 
	    //NKDbgPrintfW(TEXT("FV\r\n"));	
		ComboChange(*combo_param);

		return TRUE;

}

BOOL OALIoCtlEnable13MIDLE(UINT32 code, VOID *pInpBuffer, 
						 UINT32 inpSize, VOID *pOutBuffer,
                         UINT32 outSize, UINT32 *pOutSize)
{
	  	deep_idle_enabled = 1;

		return TRUE;

}

BOOL OALIoCtlDisable13MIDLE(UINT32 code, VOID *pInpBuffer, 
						 UINT32 inpSize, VOID *pOutBuffer,
                         UINT32 outSize, UINT32 *pOutSize)
{
	  	deep_idle_enabled = 0;

		return TRUE;

}


#define CLKCFG_DEFAULT 0
// return the clkcfg value before entering 13M mode

static void IPM_Enter_13M(void)
{
	int cccr;
	int clkcfg;
	

	int tmp;
    //NKDbgPrintfW(TEXT("13M Enab\r\n"));
	if( v_pClkReg->cccr & (1<<31) )
		return;

	/* LCD senses 13M mode and sets PCD to SENSE_MD_PCD automatically */
	v_pLCDRegs->LCCR4 |= SENSE_PCD_CHG_EN | SENSE_MD_PCD(0);

	clkcfg_save = clkcfg = XllpXSC1ReadCLKCFG() & XLLP_CLKCFG_MODE_MASK;

	
	cccr = v_pClkReg->cccr;

	cccr |= CCCR_CPDIS_BIT_ON;
	cccr &= ~CCCR_PPDIS_BIT_ON;
//	cccr |= CCCR_LCD_26_BIT_ON;

	v_pClkReg->cccr = cccr;
    cccr = v_pClkReg->cccr;
	// Using one-step write to clkcfg to resolve the LCD flicker
	clkcfg &= ~(XLLP_CLKCFG_T | XLLP_CLKCFG_HT);
	clkcfg |= XLLP_CLKCFG_F;

	XllpXSC1WriteCLKCFG(clkcfg);
	tmp = v_pClkReg->cccr;
	while (XllpXSC1ReadCLKCFG() != clkcfg);
	
	//NKDbgPrintfW(TEXT("Done 13M En\r\n"));
}

#ifndef BSP_NODEEPIDLE          
static void IPM_Exit_13M(void)
{
	int cccr, ccsr;

	int tmp;
   // NKDbgPrintfW(TEXT("13M disab\r\n"));
	cccr = v_pClkReg->cccr;
	
	cccr |= (CCCR_CPDIS_BIT_ON | CCCR_PLL_EARLY_EN_BIT_ON);
	
	v_pClkReg->cccr = cccr;
	
	cccr = v_pClkReg->cccr;
	
	if ((cccr & 0x84000000) != 0x84000000) { /* CPDIS, pll_early_en */
		NKDbgPrintfW(TEXT("Warning: CPDIS or PLL_EARLY_EN not on.\r\n"));
	}
	
	    IPMusWait(120); 
	//	USecWait(100); 
		{
	          long volatile int i=0;
	
	          for (i=0; i<999999 /* arbitrary big value to prevent
	                                  looping forever */; i++) {
	                   ccsr = v_pClkReg->ccsr;

	                   if ((ccsr & 0x30000000) == 0x30000000) {
	                            break;
	                   }
	          }
	}
	
	cccr &= ~(CCCR_CPDIS_BIT_ON | CCCR_PPDIS_BIT_ON); /* Not ON */
	//cccr |= CCCR_PLL_EARLY_EN_BIT_ON;

	v_pClkReg->cccr = cccr;
    tmp = v_pClkReg->cccr;

	// restore the previous saved B, HT, T bits of clkcfg
	// according to the spec, we can't do this in 13M mode

	clkcfg_save = (XLLP_CLKCFG_F |XLLP_CLKCFG_B |XLLP_CLKCFG_T);

	// Using one-step write to clkcfg to reslove the LCD flicker
	XllpXSC1WriteCLKCFG(clkcfg_save);
	// as required in the spec, read cccr, 
	// read clkcfg and compare to the written value until matched
//	tmp = v_pClkReg->cccr;
	while (XllpXSC1ReadCLKCFG() != clkcfg_save);
//	NKDbgPrintfW(TEXT("Done 13M disab\r\n"));
	return;	
}
#endif

#define OSCR_OFFSET 0x10

static void IPMWait(unsigned Microscont)
{
	volatile unsigned *lTimerOSCRAddress;
    unsigned lValue,Time;

     lTimerOSCRAddress = (unsigned *)((char*)v_pOSTReg + OSCR_OFFSET);
    

    Time=*lTimerOSCRAddress;

    lValue = Time + (Microscont*4);
    if (lValue < Time)
    {  // test for wrap
        while (Time < *lTimerOSCRAddress);
    }
    while(*lTimerOSCRAddress <= lValue);
}

static void IPMmsWait(unsigned msVal)
{
    IPMWait(msVal*1000);
}

static void IPMusWait(unsigned msVal)
{
    IPMWait(msVal);
}



//------------------------------------------------------------------------------



int g_StandbyEnable = FALSE;

BOOL OALIoCtlStandbyIdleGetStatus(
    UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
    UINT32 outSize, UINT32 *pOutSize)
{
    // Validate caller's arguments.
    //
    if (!pOutBuffer || (outSize < sizeof(g_StandbyEnable)))
    {
        NKSetLastError(ERROR_INSUFFICIENT_BUFFER);
        return(FALSE);
    }

    // Copy the cache information into the caller's buffer.
    //
    memcpy(pOutBuffer, &g_StandbyEnable, sizeof(g_StandbyEnable));
    if (pOutSize) 
		*pOutSize = sizeof(g_StandbyEnable);

	
    return(TRUE);
}

BOOL OALIoCtlStandbyIdleSetStatus(
    UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
    UINT32 outSize, UINT32 *pOutSize)
{
	int input;

    // Validate caller's arguments.
    //
    if (!pInpBuffer || (inpSize < sizeof(g_StandbyEnable)))
    {
        NKSetLastError(ERROR_INVALID_PARAMETER);
        return(FALSE);
    }

	input = *(int*)pInpBuffer;

	if (input != TRUE && input != FALSE)
	{
        NKSetLastError(ERROR_INVALID_PARAMETER);
        return(FALSE);
    }

	g_StandbyEnable = input;
//	NKDbgPrintfW(TEXT("Standby -- is %d\r\n"), g_StandbyEnable);
    return(TRUE);
}



static void USecWait(UINT32 usec)
{
	
    UINT32 countBegin = v_pOSTReg->oscr0;
    UINT32 countEnd;

    /* replace 3.25 with 4 for no float in kernel mode, 
     * optimize it when necessary. 
     */    
    countEnd = countBegin + usec * 4;

    if (countEnd < v_pOSTReg->oscr0)
        while (countEnd < v_pOSTReg->oscr0);

    while(v_pOSTReg->oscr0 <= countEnd);
}

BOOL OALIoCtlSkipLowPowerSetStatus(
    UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
    UINT32 outSize, UINT32 *pOutSize)
{
	int input;

    // Validate caller's arguments.
    //
    if (!pInpBuffer || (inpSize < sizeof(g_SkipEnable)))
    {
        NKSetLastError(ERROR_INVALID_PARAMETER);
        return(FALSE);
    }

	input = *(int*)pInpBuffer;

	if (input != TRUE && input != FALSE)
	{
        NKSetLastError(ERROR_INVALID_PARAMETER);
        return(FALSE);
    }

	g_SkipEnable = input;

//	NKDbgPrintfW(TEXT("skip enable is %d\r\n"), g_SkipEnable);
    return(TRUE);
}

⌨️ 快捷键说明

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