PWRBTN_PCF.c
资源名称:SMDK2440.rar [点击查看]
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:16k
源码类别:
Windows CE
开发平台:
Windows_Unix
- //
- // 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
- -- */
- #include <windows.h>
- #include <nkintr.h>
- #include <windev.h>
- #include <winbase.h>
- #include "oalintr.h"
- #include "pwr.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;
- //
- // Write PCF50606 registers directly from our cache
- //
- DWORD
- HW_WriteRegisters(
- PPWR_CONTEXT pPWR,
- PUCHAR pBuff, // Optional buffer
- UCHAR StartReg, // start register
- DWORD nRegs // number of registers
- )
- {
- return 1;
- }
- /* ++
- Setup the regulators/converters.
- Currenly uses default settings.
- TODO: determine if we can lower anything.
- -- */
- DWORD
- HW_InitRegulators(
- PPWR_CONTEXT pPWR
- )
- {
- return 1;
- }
- #define ENABLE TRUE
- #define DISABLE FALSE
- DWORD
- HW_InitCharger(
- PPWR_CONTEXT pPWR,
- UCHAR ucMode,
- UCHAR ucFlags,
- BOOL bEnable
- )
- {
- return 1;
- }
- DWORD
- HW_InitRegisters(
- PPWR_CONTEXT pPWR
- )
- {
- DWORD retry = 0;
- // EINT0, GPF0 Port Init
- IOPreg * v_pIOPregs;
- v_pIOPregs = (volatile IOPreg *)VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS);
- VirtualCopy((PVOID)v_pIOPregs, (PVOID)(IOP_BASE), sizeof(IOPreg), PAGE_READWRITE | PAGE_NOCACHE);
- v_pIOPregs->rGPFCON &= ~(0x3 << 0); /* Set EINT0(GPF0) as EINT0 */
- v_pIOPregs->rGPFCON |= (0x2 << 0);
- v_pIOPregs->rEXTINT0 &= ~(0x7 << 0); /* Configure EINT0 as Falling Edge Mode */
- v_pIOPregs->rEXTINT0 |= (0x4 << 0);
- VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE);
- // EINT0, GPF0 Port Init Done
- EnterCriticalSection(&pPWR->RegCS);
- // init DRV_GLOBAL
- pPWR->pDriverGlobals->power.State = PCF50606_STATE_IDLE;
- pPWR->pDriverGlobals->power.Error = ERROR_SUCCESS;
- pPWR->pDriverGlobals->power.ACLineStatus = 0;
- pPWR->pDriverGlobals->power.ACLineStatus |= AC_LINE_BACKUP_POWER;
- pPWR->pDriverGlobals->power.ACLineStatus |= AC_LINE_ONLINE;
- pPWR->pDriverGlobals->power.BatteryFlag = 0;
- pPWR->pDriverGlobals->power.BatteryFlag |= BATTERY_FLAG_CHARGING;
- pPWR->pDriverGlobals->power.bADCC1 = 0;
- pPWR->pDriverGlobals->power.bADCC2 = 0;
- pPWR->pDriverGlobals->power.bADCDAT1 = 0;
- pPWR->pDriverGlobals->power.bADCDAT2 = 0;
- pPWR->pDriverGlobals->power.bADCDAT3 = 0;
- LeaveCriticalSection(&pPWR->RegCS);
- 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;
- BOOL Ret;
- pPWR->pDriverGlobals = NULL;
- RETAILMSG(1, (TEXT("HW_Init : GetProcAddress rn"), dwErr));
- // Load GwesPowerOffSystem from coredll
- g_hMod = LoadLibraryEx(L"coredll.dll", NULL, DONT_RESOLVE_DLL_REFERENCES);
- if(g_hMod) {
- g_pfnGwesPowerOffSystem = (PFN_GwesPowerOffSystem) GetProcAddress(g_hMod, L"GwesPowerOffSystem");
- if(!g_pfnGwesPowerOffSystem) {
- FreeLibrary(g_hMod);
- g_hMod = NULL;
- }
- }
- RETAILMSG(1, (TEXT("HW_Init : ERROR_INVALID_PARAMETER rn")));
- if ( !pPWR )
- return ERROR_INVALID_PARAMETER;
- RETAILMSG(1, (TEXT("HW_Init : InitializeCriticalSection rn")));
- InitializeCriticalSection(&pPWR->RegCS);
- RETAILMSG(1, (TEXT("HW_Init : VirtualAlloc rn")));
- // map in DRV_GLOB
- if ( pPWR->pDriverGlobals == NULL )
- {
- pPWR->pDriverGlobals =
- (PDRIVER_GLOBALS)
- VirtualAlloc( 0,
- DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
- MEM_RESERVE,
- PAGE_NOACCESS
- );
- if ( pPWR->pDriverGlobals == NULL )
- {
- RETAILMSG( 1, (TEXT( "pPWR->pDriverGlobals: VirtualAlloc failed!rn")) );
- goto _error_exit;
- }
- Ret = VirtualCopy( (LPVOID)pPWR->pDriverGlobals,
- (LPVOID)DRIVER_GLOBALS_PHYSICAL_MEMORY_START,
- DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
- PAGE_READWRITE | PAGE_NOCACHE
- );
- if ( Ret == FALSE )
- {
- RETAILMSG( 1, (TEXT( "pPWR->pDriverGlobals: VirtualCopy failed!rn")) );
- goto _error_exit;
- }
- }
- RETAILMSG(1, (TEXT("HW_Init : pPWR->State rn")));
- // Init H/W
- pPWR->State = INITIALIZE;
- RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters rn"), dwErr));
- dwErr = HW_InitRegisters(pPWR);
- if ( dwErr ) {
- RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters Error rn"), dwErr));
- goto _error_exit;
- }
- //
- // create PWR_IST
- //
- RETAILMSG(1, (TEXT("HW_Init : CreateEvent rn"), dwErr));
- if ( (pPWR->ISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
- dwErr = GetLastError();
- RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to create IST event: %u rn"), dwErr));
- goto _error_exit;
- }
- RETAILMSG(1, (TEXT("HW_Init : InterruptInitialize rn"), dwErr));
- if( !InterruptInitialize(SYSINTR_POWER, pPWR->ISTEvent, NULL, 0) ) {
- dwErr = GetLastError();
- RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to initialize interrupt: %urn"), dwErr));
- goto _error_exit;
- }
- RETAILMSG(1, (TEXT("HW_Init : CreateThread rn"), 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: %urn"), dwErr));
- goto _error_exit;
- }
- RETAILMSG(1, (TEXT("HW_Init : CeSetThreadPriority rn"), dwErr));
- // TODO: registry override
- if ( !CeSetThreadPriority(pPWR->IST, POWER_THREAD_PRIORITY)) {
- dwErr = GetLastError();
- RETAILMSG(1, (TEXT("PCF50606 ERROR: CeSetThreadPriority ERROR:%d rn"), dwErr));
- goto _error_exit;
- }
- pPWR->State = RUN;
- // Finally, after we are initialized dispatch any unmasked interrupts
- // we may have missed during system start up. We do this because the INTx
- // registers are cleared on read.
- if ( !dwErr )
- {
- RETAILMSG(1,(TEXT("HW_Init OOCS: 0x%.2xrn"), pPWR->ResetReg[0] ));
- RETAILMSG(1,(TEXT("HW_Init INT1: 0x%.2xrn"), pPWR->ResetReg[1]));
- RETAILMSG(1,(TEXT("HW_Init INT2: 0x%.2xrn"), pPWR->ResetReg[2]));
- RETAILMSG(1,(TEXT("HW_Init INT3: 0x%.2xrn"), pPWR->ResetReg[3]));
- // pPWR->ResetRegReady = TRUE;
- // SetEvent(pPWR->ISTEvent);
- }
- RETAILMSG(1, (TEXT("HW_Init : Donw rn"), dwErr));
- _error_exit:
- return dwErr;
- }
- DWORD
- HW_Deinit(
- PPWR_CONTEXT pPWR
- )
- {
- if ( !pPWR )
- return ERROR_INVALID_PARAMETER;
- RETAILMSG(1,(TEXT("+PWR_Deinit rn")));
- 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(SYSINTR_POWER);
- if (pPWR->ISTEvent && CloseHandle(pPWR->ISTEvent))
- pPWR->ISTEvent = NULL;
- if (pPWR->IST && CloseHandle(pPWR->IST))
- pPWR->IST = NULL;
- if (pPWR->pDriverGlobals) {
- VirtualFree( pPWR->pDriverGlobals,
- DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE ,
- MEM_RELEASE
- );
- pPWR->pDriverGlobals = NULL;
- }
- // Free the coredll instance if we have allocated one
- if(g_hMod) {
- FreeLibrary(g_hMod);
- g_hMod = NULL;
- }
- DeleteCriticalSection(&pPWR->RegCS);
- RETAILMSG(1,(TEXT("-PWR_Deinit rn")));
- return ERROR_SUCCESS;
- }
- DWORD
- HW_Open(
- PPWR_CONTEXT pPWR
- )
- {
- return ERROR_SUCCESS;
- }
- DWORD
- HW_Close(
- PPWR_CONTEXT pPWR
- )
- {
- return ERROR_SUCCESS;
- }
- BOOL
- HW_PowerUp(
- PPWR_CONTEXT pPWR
- )
- {
- RETAILMSG(1, (TEXT("PCF: HW_PowerUp rn")));
- pPWR->State = RESUME;
- SetInterruptEvent(SYSINTR_POWER);
- return TRUE;
- }
- BOOL
- HW_PowerDown(
- PPWR_CONTEXT pPWR
- )
- {
- 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 rn"), 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 rn"), pPWR->Dx));
- return TRUE;
- }
- static DWORD
- PWR_IST(
- PPWR_CONTEXT pPWR
- )
- {
- int CurrStatus = RUN;
- DWORD we;
- WCHAR state[1024] = {0};
- LPWSTR pState = &state[0];
- DWORD dwBufChars = (sizeof(state) / sizeof(state[0]));
- DWORD dwStateFlags = 0;
- DWORD dwErr;
- if (!pPWR)
- return ERROR_INVALID_PARAMETER;
- while (1) {
- __try {
- we = WaitForSingleObject(pPWR->ISTEvent, INFINITE);
- RETAILMSG(1,(TEXT("rnPWR_IST: pPWR->State = 0x%x rn"), pPWR->State));
- dwErr = GetSystemPowerState(pState, dwBufChars, &dwStateFlags);
- if (ERROR_SUCCESS != dwErr) {
- RETAILMSG(1, (TEXT("PMGET!GetSystemPowerState:ERROR:%dn"), dwErr));
- } else {
- RETAILMSG(1, (TEXT("PMGET! System Power state is '%s', flags 0x%08xn"), state, dwStateFlags));
- switch (POWER_STATE(dwStateFlags)) {
- case POWER_STATE_ON:
- RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_ONn")));
- break;
- case POWER_STATE_OFF:
- RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_OFFn")));
- break;
- case POWER_STATE_CRITICAL:
- RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_CRITICALn")));
- break;
- case POWER_STATE_BOOT:
- RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_BOOTn")));
- break;
- case POWER_STATE_IDLE:
- RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_IDLEn")));
- break;
- case POWER_STATE_SUSPEND:
- RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_SUSPENDn")));
- break;
- case POWER_STATE_RESET:
- RETAILMSG(1, (TEXT("PMGET!tPOWER_STATE_RESETn")));
- break;
- case 0:
- break;
- default:
- RETAILMSG(1,(TEXT("PMGET!tUnknown Power State Flags:0x%xn"),dwStateFlags));
- ASSERT(0);
- break;
- }
- }
- switch (pPWR->State) {
- case RUN:
- RETAILMSG(1, (TEXT("PWR_IST: RUNrn")));
- if (CurrStatus == SUSPEND)
- {
- RETAILMSG(1, (TEXT("CurrStatus == SUSPENDrn")));
- pPWR->State = RUN;
- CurrStatus = RUN;
- // clear any potential pending ADC interrupt
- InterruptDone(SYSINTR_POWER);
- SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
- continue;
- }
- else if (CurrStatus == RESUME)
- {
- RETAILMSG(1, (TEXT("CurrStatus == RESUMErn")));
- if ( wcscmp(state,TEXT("unattended")) == 0 )
- {
- RETAILMSG(1, (TEXT("Unattended Power Off Modern")));
- pPWR->State = RUN;
- CurrStatus = SUSPEND;
- continue;
- }
- // else if ( wcscmp(state,TEXT("resuming")) == 0 )
- // {
- // RETAILMSG(1, (TEXT("Still resuming...rn")));
- // Sleep(1000);
- // SetEvent(pPWR->ISTEvent);
- // continue;
- // }
- else
- {
- RETAILMSG(1, (TEXT("Power Onrn")));
- pPWR->State = RUN;
- CurrStatus = RUN;
- // clear any potential pending ADC interrupt
- InterruptDone(SYSINTR_POWER);
- SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
- continue;
- }
- }
- break;
- case INITIALIZE:
- // Keep from reading our clear on read INTx registers
- // during init.
- RETAILMSG(1, (TEXT("PWR_IST: INITIALIZErn")));
- Sleep(10);
- continue;
- break;
- case SUSPEND:
- RETAILMSG(1, (TEXT("PWR_IST: SUSPENDrn")));
- // continue;
- break;
- case RESUME:
- case ADC_ERROR:
- RETAILMSG(1,(TEXT("PWR_IST: %s rn"), pPWR->State == RESUME ? L"RESUME" : L"ADC_ERROR" ));
- pPWR->State = RUN;
- CurrStatus = RESUME;
- // clear any potential pending ADC interrupt
- InterruptDone(SYSINTR_POWER);
- Sleep(200);
- SetEvent(pPWR->ISTEvent);
- // SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
- continue;
- break;
- case UNINITIALIZED:
- RETAILMSG(1,(TEXT("PWR_IST: ExitThread rn")));
- ExitThread(ERROR_SUCCESS);
- return ERROR_SUCCESS;
- default:
- RETAILMSG(1,(TEXT("PWR_IST: unknown state: %urn"), pPWR->State));
- TEST_TRAP;
- continue;
- break;
- }
- //
- // get status
- //
- // EnterCriticalSection(&pPWR->RegCS);
- //
- // if ( !pPWR->ResetRegReady ) {
- // } else {
- // // get & restore the cleared registers
- // pPWR->ResetRegReady = FALSE;
- // }
- LeaveCriticalSection(&pPWR->RegCS);
- // clear the interrupt before power off
- InterruptDone(SYSINTR_POWER);
- CurrStatus = SUSPEND;
- SetSystemPowerState( NULL, POWER_STATE_SUSPEND, POWER_FORCE );
- } _except(EXCEPTION_EXECUTE_HANDLER) {
- RETAILMSG(1,(TEXT("!!! PWR_IST EXCEPTION: 0x%X !!!rn"), GetExceptionCode() ));
- }
- }
- }
- /* ++
- 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;
- }