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

📄 xllp_suspendresume.c

📁 Intel PXA270底层设备驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    crsa_sp = pSVC_regs;

    pSYS_regs = Xllp_SaveMSARMRegs(crsa_sp, XLLP_CPSR_Mode_SYS);
    SYS_words = (crsa_sp - pSYS_regs);
    //DBGMSG(("Xllp_SuspendResume: SYS(x%x) saved: x%08x-x%08x, (%d)\r\n",
    //        XLLP_CPSR_Mode_SYS, crsa_sp, pSYS_regs, SYS_words));
    crsa_sp = pSYS_regs;

    DBGMSG(("Xllp_SuspendResume: mode specific core registers saved\r\n"));
#if 0 // ENABLE_DEBUG_MESSAGES // debug code
    {
        int i;
        unsigned long *p;
        unsigned long words;

    p = (unsigned long *)pFIQ_regs;
    words = FIQ_words;
    DBGMSG(("Xllp_SuspendResume: FIQ@x%08x (%d)\r\n", p, words));
    for (i = words-1; i>=0; i--)
        DBGMSG(("    x%08x:x%08x\r\n", &p[i], p[i]));
    
    p = (unsigned long *)pIRQ_regs;
    words = IRQ_words;
    DBGMSG(("Xllp_SuspendResume: IRQ@x%08x (%d)\r\n", p, words));
    for (i = words-1; i>=0; i--)
        DBGMSG(("    x%08x:x%08x\r\n", &p[i], p[i]));
    
    p = (unsigned long *)pUND_regs;
    words = UND_words;
    DBGMSG(("Xllp_SuspendResume: UND@x%08x (%d)\r\n", p, words));
    for (i = words-1; i>=0; i--)
        DBGMSG(("    x%08x:x%08x\r\n", &p[i], p[i]));
    
    p = (unsigned long *)pABT_regs;
    words = ABT_words;
    DBGMSG(("Xllp_SuspendResume: ABT@x%08x (%d)\r\n", p, words));
    for (i = words-1; i>=0; i--)
        DBGMSG(("    x%08x:x%08x\r\n", &p[i], p[i]));
    
    p = (unsigned long *)pSVC_regs;
    words = SVC_words;
    DBGMSG(("Xllp_SuspendResume: SVC@x%08x (%d)\r\n", p, words));
    for (i = words-1; i>=0; i--)
        DBGMSG(("    x%08x:x%08x\r\n", &p[i], p[i]));
    
    p = (unsigned long *)pSYS_regs;
    words = SYS_words;
    DBGMSG(("Xllp_SuspendResume: SYS@x%08x (%d)\r\n", p, words));
    for (i = words-1; i>=0; i--)
        DBGMSG(("    x%08x:x%08x\r\n", &p[i], p[i]));
    }
    DBGMSG(("Xllp_SuspendResume: After Core Save: ResumePhase2Data=x%08x->x%08x\r\n",
                  pResumePhase2Data, ResumePhase2DataPA));
#endif // debug code

    pMEMCRegs->MDREFR &= ~(0x00080000u );/*xlli_MDREFR_K2DB2*/

	pPWRRegs->PSPR   = ResumePhase2DataPA;
//----------------------------------------------------------------------------------------------
#ifdef BSP_MAINSTONE
    // PGSRn values will most likely be platform dependent.
#if 0
    // The following PGSR defined values are what was used in WinCE Ozone (which seemed to work well).
#define PMGR_PGSR0_vals_DFLT    ((0x00008800u)| 0xC0000000u)   // xlli_GPSR0_value 
#define PMGR_PGSR1_vals_DFLT    (0x00000002u)  // xlli_GPSR1_value 
#define PMGR_PGSR2_vals_DFLT    (0x0001FC00u)  // xlli_GPSR2_value 
            // Must set AC97 reset line high (deasserted) in PGSR for ACUNIT to work after sleep
            // Force all reserved GPIO control bits low
#define PMGR_PGSR3_vals_DFLT    (0x00000000u|XLLP_GPIO_BIT_AC97_RESET_n)  // xlli_GPSR3_value 
#endif
#if 1
    // I haven't figured out what all these bits do exactly but they work.
    // The alternative used in WinCE Ozone don't work (platform won't wake up)
    pPWRRegs->PGSR0  = 0xd02c861b;
    pPWRRegs->PGSR1  = 0x03cf5746;
    pPWRRegs->PGSR2  = 0x173d4000;
    pPWRRegs->PGSR3  = 0x0073ff81;
#else
    pPWRRegs->PGSR0  = (0x00008800 | 0xC0000000);                 // 0xd02c861b;
    pPWRRegs->PGSR1  = (0x00000002);                              //0x03cf5746;
    pPWRRegs->PGSR2  = (0x0001FC00);                              //0x173d4000;
    pPWRRegs->PGSR3  = (0x00000000 | XLLP_GPIO_BIT_AC97_RESET_n); //0x0073ff81;
#endif
#endif // BSP_MAINSTONE
    
    pPWRRegs->PWER   = 0x80000000; // wake on RTC
    // Wakeup sources will eventually be set based on values passed in via the RESTART_DATA structure
    // For now they are hardcoded to keypad, touch, RTC alarm, and GPIO0 (card or cable insert/remove)
#ifdef BSP_MAINSTONE
    pPWRRegs->PWER  |= 0x00000001;   // wake on GPIO 0
	pPWRRegs->PRER   = 0x1;          // GPIO0 rising edge enable
	pPWRRegs->PFER   = 0x1;          // GPIO0 falling edge enable
    pPWRRegs->PKWR   = 0x000FD000;   // Enable wake on keypad activity
    DBGMSG(("Xllp_SuspendResume: PWER=x%08x->x%08x, PRER=x%08x->x%08x, PFER=x%08x->x%08x, PKWR=x%08x->x%08x\r\n",
                  PWRSave.PWER, pPWRRegs->PWER
                 ,PWRSave.PRER, pPWRRegs->PRER
                 ,PWRSave.PFER, pPWRRegs->PFER
                 ,PWRSave.PKWR, pPWRRegs->PKWR
            ));

    //pPWRRegs->PCFR  = 0x71;
    //pPWRRegs->PCFR  = 0x61;
    pPWRRegs->PSLR  |= 0x00100000;   // nResetOut prevents FPGA triggered wakeup so set SL_ROD
    //pPWRRegs->PSLR  = 0xff100008;
    DBGMSG(("Xllp_SuspendResume: PCFR=x%08x->x%08x, PSLR=x%08x->x%08x\r\n",
                  PWRSave.PCFR, pPWRRegs->PCFR, PWRSave.PSLR, pPWRRegs->PSLR));
    
    // For FPGA interrupts to cause wakeup, pending interrupts must be cleared before sleeping.
    pBCRegs->PSCR1   = 0;            // clear all pending FPGA interrupts
    pBCRegs->PIMER1  = (0x25);       // enable FPGA interrupt for pen, USB cable, MMC card detect
    DBGMSG(("Xllp_SuspendResume: PSCR1=x%08x->x%08x, PIMER1=x%08x->x%08x\r\n",
                  BCRSave.PSCR1, pBCRegs->PSCR1, BCRSave.PIMER1, pBCRegs->PIMER1));
#else
#endif // BSP_MAINSTONE
//----------------------------------------------------------------------------------------------
    SetHexLeds(0xce055555);   // won't be visible unless disable fails
    DisableHexLeds();

        // Allow log messages to be sent before power off
#if (ENABLE_DEBUG_MESSAGES || ENABLE_LOG_MESSAGES)
    {
        unsigned long t1 = pOSTRegs->oscr0;
    while (DIFF_UL(pOSTRegs->oscr0, t1) < (500 * XLLP_OST_TICKS_MS))
        ;
    }
#endif    
//========================================================================
    Xllp_SuspendAndResumeA(pResumePhase2Data);   // goodnight!
//========================================================================
    // At this point we've woken up again.
	// NOTE!!! 
    // No log messages should be output until platform restore is complete.
    // Attempting to do so will probably crash the system.
    // SETHEXLEDS seems to be safe (probably because the boot code inits them).
	
    SetHexLeds(0xce05aaaa);

	// Restore CPU Core registers.
    // Note that although the regs for all modes were saved prior to power off above,
    // we don't restore the core regs for the mode we're currently in (probably SVC).
    // Restoring the mode we're in would screw up our current context (particularly SP, LR, and SPSR)
    // However SPSR does need to be restored to it's value on entry prior to returning from this function.
    {
        XLLP_UINT32_T mode = Xllp_Get_ARM_CPSR() & XLLP_CPSR_Mode_Mask;
    // We'de better be in the same mode as when we saved state or things will get rather confusing.
    if (mode != (entry_CPSR & XLLP_CPSR_Mode_Mask))
        {
        while(1)
            ;
        }
    // Note that although we saved mode specific registers for all modes above,
    // we only restore them for modes other than the current mode.
    // Current mode registers are restored from the stack just before we return.
    if (mode != XLLP_CPSR_Mode_FIQ)
        Xllp_RestoreMSARMRegs(pFIQ_regs, XLLP_CPSR_Mode_FIQ);
    if (mode != XLLP_CPSR_Mode_IRQ)
        Xllp_RestoreMSARMRegs(pIRQ_regs, XLLP_CPSR_Mode_IRQ);
    if (mode != XLLP_CPSR_Mode_UND)
        Xllp_RestoreMSARMRegs(pUND_regs, XLLP_CPSR_Mode_UND);
    if (mode != XLLP_CPSR_Mode_ABT)
        Xllp_RestoreMSARMRegs(pABT_regs, XLLP_CPSR_Mode_ABT);
    if (mode != XLLP_CPSR_Mode_SVC)
        Xllp_RestoreMSARMRegs(pSVC_regs, XLLP_CPSR_Mode_SVC);
    if (mode != XLLP_CPSR_Mode_SYS)
        Xllp_RestoreMSARMRegs(pSYS_regs, XLLP_CPSR_Mode_SYS);
    }
    
    SetHexLeds(0xce05fffe);
    
    // save information so we can (eventually) determine wakeup source.
    resume_PWR_PEDR       = pPWRRegs->PEDR;
    resume_PWR_PKSR       = pPWRRegs->PKSR;
#ifdef BSP_MAINSTONE
    resume_FPGA_ISCR      = pBCRegs->PSCR1;
    resume_FPGA_IER       = pBCRegs->PIMER1;
#endif // BSP_MAINSTONE

	XllpPWRRestore(pPWRRegs, &PWRSave);
	XllpCLKRestore(pCLKRegs, &CLKSave);
	XllpGPIORestore(pGPIORegs, &GPIOSave);
    XllpINTCRestore(pINTCRegs, &INTCSave);
#ifdef BSP_MAINSTONE
    {
        XLLP_UINT32_T ISCReg;
    // FPGA interrupts need to be handled specially because FPGA is powered during suspend.
    // If one or more FPGA interrupts is asserted while in suspend mode, 
    // the interrupt handler will not be called after resume 
    // unless the interrupts are cleared and re-asserted.
    
    // Save current active interrupts (this will indicate any interrupts that happened while suspended)
    ISCReg = pBCRegs->PSCR1;
    // clear any active interrupts so they don't fire when IMER1 is restored
    pBCRegs->PSCR1 = 0;
    // Restore all saved regs except interrupt set/clear reg
    XllpBCRRestore(pBCRegs, &BCRSave);
    // Re-assert any interrupts active prior to or that occurred while suspended
    pBCRegs->PSCR1 = BCRSave.PSCR1 | ISCReg;
    }
#endif // BSP_MAINSTONE

	SetHexLeds(0xce05fffd);
	
    // XllpIMRestore(IMAddr, IMSave, IMSize);
	
	OSD_ExecuteAfterAllResets();
    
    OSD_DebugCommsResume();
    // Log messages should be OK from here on.

	SetHexLeds(0xce05fffc);
	
    LOGMSG(("Xllp_SuspendResume: State Restored: ResumePhase2Data=x%08x->x%08x\r\n",
                  pResumePhase2Data, ResumePhase2DataPA));

    // XllpI2cInit((XLLP_I2C_T*)pI2CRegs, (XLLP_GPIO_T*)pGPIORegs, (XLLP_CLKMGR_T*)pCLKRegs, 0);

	// XllpOSTRestore(pOSTRegs, &OSTSave);
    // WinCE seems to need a timer interrupt to make it's timers work after resume.
    if ((entry_OIER & 1) && (entry_OSMR0 != 0))
        {
        pOSTRegs->osmr0 = entry_OSMR0;
        pOSTRegs->oscr0 = entry_OSMR0 - 5;
        pOSTRegs->oier |= 1;
        while (DIFF_UL(pOSTRegs->osmr0, pOSTRegs->oscr0) >= 0) // wait for match to occur
            ;
        }

	SetHexLeds(0xce05fffb);
    
    DBGMSG(("Xllp_SuspendResume: Wake Reason: PEDR=x%08x, PKSR=x%08x, ISCR=x%08x, IER=x%08x\r\n",
                  resume_PWR_PEDR, resume_PWR_PKSR, resume_FPGA_ISCR, resume_FPGA_IER));
    
	DBGMSG(("Xllp_SuspendResume: Exit: (entry_CPSR=x%08x)\r\n", entry_CPSR));
    DBGMSG(("Xllp_SuspendResume: Exit: RCNR=x%08x, RTAR=x%08x, RTSR=x%08x, PICR=x%08x\r\n",
                  pRTCRegs->rcnr, pRTCRegs->rtar, pRTCRegs->rtsr, pRTCRegs->picr));
    DBGMSG(("Xllp_SuspendResume: Exit: RYAR1=x%08x, RDAR1=x%08x\r\n",
                  pRTCRegs->ryar1, pRTCRegs->rdar1));
    DBGMSG(("Xllp_SuspendResume: Exit: OSCR0=x%08x, OSMR0=x%08x, OIER=x%08x\r\n",
                  pOSTRegs->oscr0, pOSTRegs->osmr0, pOSTRegs->oier));
    DBGMSG(("Xllp_SuspendResume: Exit: OMCR4=x%08x, OMCR5=x%08x, OMCR6=x%08x, OMCR7=x%08x\r\n",
                  pOSTRegs->omcr4, pOSTRegs->omcr5, pOSTRegs->omcr6, pOSTRegs->omcr7));

    SetHexLeds(entry_hexleds);
    Xllp_Set_ARM_SPSR(entry_SPSR);
    Xllp_Set_ARM_CPSR(entry_CPSR);
    return(0);                      // eventually we'll return the wakeup reason
    } // Xllp_SuspendAndResume

#if 0
void RtcWakeupSet(UINT32 sec)
{
	XLLP_INTC_T *pINTCRegs = (XLLP_INTC_T*)OSD_MapPAtoVA(BULVERDE_BASE_REG_PA_INTC);

	XLLP_RTC_T *pRTCRegs = (XLLP_RTC_T*)OSD_MapPAtoVA(BULVERDE_BASE_REG_PA_RTC);

    pINTCRegs->icmr &= ~XLLP_INTC_RTCALARM;
    
    // Setup the RTC controller to have the alarm interrupt enabled.
    // Testing with current (C0 Bulverde) silicon suggests this isn't essential (RCNR == RTAR seems to cause wakeup anyway).
    // ie. wakeup occurs even if the line commented out below is used.
    // However, doing this seems intuitive and it does work with current hardware as well.
    pRTCRegs->rtsr = (pRTCRegs->rtsr & ~(XLLP_RTSR_MASK | XLLP_RTSR_RESERVED_BITS)) | XLLP_RTSR_ALE;
    // v_pRTCReg->rtsr = (v_pRTCReg->rtsr & ~(XLLP_RTSR_ALE));

	// Set RTC match register to wake up almost immediately.
    pRTCRegs->rtar  =  pRTCRegs->rcnr + sec ;
}
#endif
//------------------------------------------------------------------------------

⌨️ 快捷键说明

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