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

📄 powerbutton.c

📁 2443 wince5.0 bsp, source code
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//

/* ++

    PCF50606 Power Supply Controller & Battery Management

    Notes:
    ======
    o) I2c client
	
	
	Updates:
	======
	1) 2443 EVT1 revision point is applied. External interrupt setting is modified
-- */

#include <windows.h>
#include <nkintr.h>
#include <windev.h>
#include <winbase.h>
#include <S3C2443REF_GPIO.h>

#include "pwr.h"
#include <bsp.h>



static DWORD PWR_IST(LPVOID Context);

// Make sure the driver builds OK in tinykern configuration
HMODULE g_hMod = NULL;
typedef void (*PFN_GwesPowerOffSystem)(void);
PFN_GwesPowerOffSystem g_pfnGwesPowerOffSystem = NULL;

#define TICKTEST	0

#if TICKTEST
UINT32 g_PwrButtonIrq = IRQ_TICK;	// Determined by SMDK2443 board layout.
#else
UINT32 g_PwrButtonIrq = IRQ_EINT0;	// Determined by SMDK2443 board layout.
#endif

UINT32 g_PwrButtonSysIntr = SYSINTR_UNDEFINED;

UINT32 g_ResetButtonIrq = IRQ_EINT11;	// Determined by SMDK2443 board layout.
UINT32 g_ResetButtonSysIntr = SYSINTR_UNDEFINED;
HANDLE g_ResetThread;
HANDLE g_ResetEvent;
static DWORD RESET_IST();

volatile S3C2443_IOPORT_REG *v_pIOPregs;
volatile S3C2443_RTC_REG *v_pRTCregs;
volatile S3C2443_INTR_REG	*v_pIntrRegs;

#define ENABLE  TRUE
#define DISABLE FALSE
#define SWRST_BTN 1


DWORD
HW_InitRegisters(
    PPWR_CONTEXT pPWR
    )
{
    DWORD retry = 0;

#if TICKTEST
	v_pRTCregs = (volatile S3C2443_RTC_REG *)VirtualAlloc(0, sizeof(S3C2443_RTC_REG), MEM_RESERVE, PAGE_NOACCESS);
	VirtualCopy((PVOID)v_pRTCregs, (PVOID)(S3C2443_BASE_REG_PA_RTC >> 8), sizeof(S3C2443_RTC_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE );	
	v_pRTCregs->TICNT0 = (1<<7);
	v_pRTCregs->TICNT1 = (3<<0);
	v_pRTCregs->RTCCON = (5<<5)|(1<<0);
	
#else

	v_pIOPregs = (volatile S3C2443_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2443_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
	VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2443_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2443_IOPORT_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE );	
	
   v_pIntrRegs = (volatile S3C2443_INTR_REG *)VirtualAlloc(0, sizeof(S3C2443_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
   VirtualCopy((PVOID)v_pIntrRegs, (PVOID)(S3C2443_BASE_REG_PA_INTR >> 8), sizeof(S3C2443_INTR_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE );	
   
#ifdef EVT1
	v_pIOPregs->GPFDAT  &= ~(0x1 << 0);		
	v_pIOPregs->EXTINT0 = (READEXTINT0(v_pIOPregs->EXTINT0) & ~(0xf<<0)) | (0x1 << 3)|(0x2 << 0);		/* Configure EINT0 as Falling Edge Mode				*/	
#else
	v_pIOPregs->GPFUDP &= ~(3<<0);   // Pull up down disable
	v_pIOPregs->GPFUDP |= (2<<0);   // Pull up down disable
	v_pIOPregs->EXTINT0 = (v_pIOPregs->EXTINT0 & ~(0xf<<0)) | (0x1 << 3)|(0x2 << 0);		/* Configure EINT0 as Falling Edge Mode				*/	
#endif

	v_pIOPregs->GPFCON  &= ~(0x3 << 0);		/* Set EINT0(GPF0) as EINT0							*/
	v_pIOPregs->GPFCON  |=  (0x2 << 0);


#endif


#if SWRST_BTN    //- ksk dbg
	v_pIOPregs->GPGDAT  &= ~(0x1 << 3);		/* Set EINT11(GPG3) as EINT11							*/

#ifdef EVT1
	v_pIOPregs->EXTINT1 = (READEXTINT1(v_pIOPregs->EXTINT1) & ~(0xf<<12)) | (0xa << 12); 	
#else
	v_pIOPregs->GPGUDP &= ~(3<<6);   // Pull up down disable
	v_pIOPregs->GPGUDP |= (2<<6);   // Pull up down disable	
    v_pIOPregs->EXTINT1 = (v_pIOPregs->EXTINT1 & ~(0xf<<12)) | (0xa << 12); 	
#endif


	v_pIOPregs->GPGCON  &= ~(0x3 << 6);		/* Set EINT11(GPG3) as EINT11							*/
	v_pIOPregs->GPGCON  |=  (0x2 << 6);

    // clear soure pending register for sharing EINT8_23 button(Cleaning hive-based register and Reset button)
#endif


    return 0;
}


/* ++

    The reset value of the PCF50606 INTxM registers is 0: Interrupt enabled.
    Once we enable the interrupt they start firing unless we mask them _before_
    enabeling the interrupt(s).
    
-- */
DWORD
HW_Init(
    PPWR_CONTEXT pPWR
    )
{
    DWORD dwErr = ERROR_SUCCESS;

    if ( !pPWR )
        return ERROR_INVALID_PARAMETER;

    // Init H/W
    pPWR->State = INITIALIZE;
    
    RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters \r\n")));
	dwErr = HW_InitRegisters(pPWR);
    if ( dwErr ) {
	    RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters  Error (0x%x) \r\n"), dwErr));
        goto _error_exit;
    }

    RETAILMSG(1, (TEXT("HW_Init : CreateEvent \r\n")));
	pPWR->ISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    // Request a SYSINTR value from the OAL.
    //
    RETAILMSG(1, (TEXT("HW_Init : IOCTL_HAL_REQUEST_SYSINTR \r\n")));
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_PwrButtonIrq, sizeof(UINT32), &g_PwrButtonSysIntr, sizeof(UINT32), NULL))
    {
        RETAILMSG(1, (TEXT("ERROR: PwrButton: Failed to request sysintr value for power button interrupt.\r\n")));
        return(0);
    }
    RETAILMSG(1,(TEXT("INFO: PwrButton: Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_PwrButtonIrq, g_PwrButtonSysIntr));

	if (!(InterruptInitialize(g_PwrButtonSysIntr, pPWR->ISTEvent, 0, 0))) 
	{
		RETAILMSG(1, (TEXT("ERROR: PwrButton: Interrupt initialize failed.\r\n")));
	}

    RETAILMSG(1, (TEXT("HW_Init : CreateThread \r\n"), dwErr));
    if ( (pPWR->IST = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PWR_IST, pPWR, 0, NULL)) == NULL) {
        dwErr = GetLastError();
        RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to create IST: %u\r\n"), dwErr));
        goto _error_exit;
    }
    
    RETAILMSG(1, (TEXT("HW_Init : CeSetThreadPriority \r\n"), dwErr));
    // TODO: registry override
    if ( !CeSetThreadPriority(pPWR->IST, POWER_THREAD_PRIORITY)) {
        dwErr = GetLastError();
        RETAILMSG(1, (TEXT("PCF50606 ERROR: CeSetThreadPriority ERROR:%d \r\n"), dwErr));
        goto _error_exit;
    }

    pPWR->State = RUN;

    RETAILMSG(1, (TEXT("HW_Init : Done \r\n"), dwErr));    
#if SWRST_BTN    //- ksk dbg
	g_ResetEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_ResetButtonIrq, sizeof(UINT32), &g_ResetButtonSysIntr, sizeof(UINT32), NULL))
    {
        RETAILMSG(1, (TEXT("ERROR: ResetButton: Failed to request sysintr value for reset button interrupt.\r\n")));
        return(0);
    }  
    RETAILMSG(1,(TEXT("INFO: ResetButton: Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_ResetButtonIrq, g_ResetButtonSysIntr));
	if (!(InterruptInitialize(g_ResetButtonSysIntr, g_ResetEvent, 0, 0))) 
	{
		RETAILMSG(1, (TEXT("ERROR: ResetButton: Interrupt initialize failed.\r\n")));
	}
    if ( (g_ResetThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) RESET_IST, 0, 0, NULL)) == NULL) {
        dwErr = GetLastError();
        RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to create IST: %u\r\n"), dwErr));
        goto _error_exit;
    }	
    if ( !CeSetThreadPriority(g_ResetThread, POWER_THREAD_PRIORITY)) {
        dwErr = GetLastError();
        RETAILMSG(1, (TEXT("PCF50606 ERROR: CeSetThreadPriority ERROR:%d \r\n"), dwErr));
        goto _error_exit;
    }    
#endif    
    


_error_exit:
    return dwErr;
}


DWORD
HW_Deinit(
    PPWR_CONTEXT pPWR
    )
{
    if ( !pPWR )
        return ERROR_INVALID_PARAMETER;
    
    RETAILMSG(1,(TEXT("+PWR_Deinit \r\n")));

    pPWR->State = UNINITIALIZED;

    if (pPWR->hADC && CloseHandle(pPWR->hADC))
        pPWR->hADC = NULL;

    if (pPWR->hTSCPRES && CloseHandle(pPWR->hTSCPRES))
        pPWR->hTSCPRES = NULL;

    if (pPWR->hI2C && pPWR->hI2C != INVALID_HANDLE_VALUE && CloseHandle(pPWR->hI2C))
        pPWR->hI2C = INVALID_HANDLE_VALUE;
    
    InterruptDisable(g_PwrButtonSysIntr);

    if (pPWR->ISTEvent && CloseHandle(pPWR->ISTEvent))
        pPWR->ISTEvent = NULL;
    
    if (pPWR->IST && CloseHandle(pPWR->IST))
        pPWR->IST = NULL;  

    //  Free the coredll instance if we have allocated one
    if(g_hMod) {
        FreeLibrary(g_hMod);
        g_hMod = NULL;
    }

	VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
	// EINT0, GPF0 Port Init Done
	VirtualFree((PVOID) v_pRTCregs, 0, MEM_RELEASE);	

    RETAILMSG(1,(TEXT("-PWR_Deinit \r\n")));

    return ERROR_SUCCESS;
}


DWORD 
HW_Open(
    PPWR_CONTEXT pPWR
    )
{
    RETAILMSG(1, (TEXT("PCF: HW_Open \r\n")));
    return ERROR_SUCCESS;
}


DWORD 
HW_Close(
    PPWR_CONTEXT pPWR
    )
{
    RETAILMSG(1, (TEXT("PCF: HW_Close \r\n")));
    return ERROR_SUCCESS;
}


BOOL
HW_PowerUp(
    PPWR_CONTEXT pPWR
   )
{
    RETAILMSG(1, (TEXT("PCF: HW_PowerUp \r\n")));
    pPWR->State = RESUME;
//    pPWR->State = RUN;
//    SetInterruptEvent(g_PwrButtonSysIntr);
    return TRUE;
}


BOOL
HW_PowerDown(
    PPWR_CONTEXT pPWR
   )
{
    RETAILMSG(1, (TEXT("PCF: HW_PowerDown \r\n")));
    pPWR->State = SUSPEND;
    return TRUE;
}


BOOL
HW_PowerCapabilities(
    PPWR_CONTEXT pPWR,
    PPOWER_CAPABILITIES ppc
    )
{
    return TRUE;
}


BOOL
HW_PowerSet(
    PPWR_CONTEXT pPWR,
    PCEDEVICE_POWER_STATE pDx   // IN, OUT
   )
{   
    CEDEVICE_POWER_STATE NewDx = *pDx;

    if ( VALID_DX(NewDx) ) 
    {
        // We only support D0, so do nothing.
        // Just return current state.
        pPWR->Dx = *pDx = D0;
        RETAILMSG(1, (TEXT("PCF: IOCTL_POWER_SET: D%u => D%u \r\n"), NewDx, pPWR->Dx));
        return TRUE;
    }

    return FALSE;
}


BOOL
HW_PowerGet(
    PPWR_CONTEXT pPWR,
    PCEDEVICE_POWER_STATE pDx
   )
{   
    // return our Current Dx value
    *pDx = pPWR->Dx;
    RETAILMSG(1, (TEXT("PCF: IOCTL_POWER_GET: D%u \r\n"), pPWR->Dx));

    return TRUE;
}


static DWORD 
PWR_IST(
    PPWR_CONTEXT pPWR
    )
{
    DWORD we;
	WCHAR  state[1024] = {0};
	LPWSTR pState = &state[0];
	DWORD dwBufChars = (sizeof(state) / sizeof(state[0]));
	DWORD  dwStateFlags = 0;
	DWORD dwErr;
    DWORD dwTimeout = 1000;
    
    if (!pPWR)
        return ERROR_INVALID_PARAMETER;

    while (1) {
        __try {
            we = WaitForSingleObject(pPWR->ISTEvent, INFINITE);
			RETAILMSG(1,(TEXT("\r\nPWR_IST: pPWR->State = 0x%x \r\n"), pPWR->State));

			InterruptDone(g_PwrButtonSysIntr);

            
			if ((pPWR->State == RUN))
			{
#if TICKTEST
				v_pRTCregs->TICNT0 = (1<<7);
				v_pRTCregs->TICNT1 = (3<<0);
				v_pRTCregs->RTCCON = (5<<5)|(1<<0);
#endif
				SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE );
			}
			else///APR if ( pPWR->State == 0x2 )
			{
#if TICKTEST
				v_pRTCregs->TICNT0 = (1<<7);
				v_pRTCregs->TICNT1 = (3<<0);
				v_pRTCregs->RTCCON = (5<<5)|(1<<0);
#endif				
				SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
				pPWR->State = RUN;
			}
        } _except(EXCEPTION_EXECUTE_HANDLER) {
            RETAILMSG(1,(TEXT("!!! PWR_IST EXCEPTION: 0x%X !!!\r\n"), GetExceptionCode() ));
        }
	}
}


static DWORD 
RESET_IST()
{
    while (1) {
        __try {
            WaitForSingleObject(g_ResetEvent, INFINITE);
			RETAILMSG(1,(TEXT("\r\nReset Button pressed \r\n")));
			InterruptDone(g_ResetButtonSysIntr);
			KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);

        } _except(EXCEPTION_EXECUTE_HANDLER) {
            RETAILMSG(1,(TEXT("!!! RESET_IST EXCEPTION: 0x%X !!!\r\n"), GetExceptionCode() ));
        }
	}
	
	return 0;
}
/* ++

 Get/Set the PCF RTC.
 
 One neat PCF feature is the stand alone RTC.
 You could power the ARM core to full off and maintin the RTC & ALARM on the PCF.
 This is not a required feature for PPC2002 release, but OEMs are 
 free to add this as desired. You should sync the ARM & PCF RTC
 and update as appropriate. If you choose to implement this it would
 be good to power as much of the PCF off as possible to maintin it's RTC
 for much longer time.

-- */
BOOL 
PWR_GetRealTime(
    PPWR_CONTEXT pPWR,
    LPSYSTEMTIME lpst
    )
{
    return TRUE;
}


BOOL
PWR_SetRealTime(
    PPWR_CONTEXT pPWR,
    LPSYSTEMTIME lpst
    ) 
{
    return TRUE;
}


BOOL
HW_IOControl(
    PPWR_CONTEXT pPWR,
    DWORD dwCode,
    PBYTE pBufIn,
    DWORD dwLenIn,
    PBYTE pBufOut,
    DWORD dwLenOut,
    PDWORD pdwActualOut
   )
{
	return FALSE;
}


⌨️ 快捷键说明

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