📄 pwrbtn_pcf.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
-- */
#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 \r\n"), 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 \r\n")));
if ( !pPWR )
return ERROR_INVALID_PARAMETER;
RETAILMSG(1, (TEXT("HW_Init : InitializeCriticalSection \r\n")));
InitializeCriticalSection(&pPWR->RegCS);
RETAILMSG(1, (TEXT("HW_Init : VirtualAlloc \r\n")));
// 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!\r\n")) );
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!\r\n")) );
goto _error_exit;
}
}
RETAILMSG(1, (TEXT("HW_Init : pPWR->State \r\n")));
// Init H/W
pPWR->State = INITIALIZE;
RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters \r\n"), dwErr));
dwErr = HW_InitRegisters(pPWR);
if ( dwErr ) {
RETAILMSG(1, (TEXT("HW_Init : HW_InitRegisters Error \r\n"), dwErr));
goto _error_exit;
}
//
// create PWR_IST
//
RETAILMSG(1, (TEXT("HW_Init : CreateEvent \r\n"), dwErr));
if ( (pPWR->ISTEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
dwErr = GetLastError();
RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to create IST event: %u \r\n"), dwErr));
goto _error_exit;
}
RETAILMSG(1, (TEXT("HW_Init : InterruptInitialize \r\n"), dwErr));
if( !InterruptInitialize(SYSINTR_POWER, pPWR->ISTEvent, NULL, 0) ) {
dwErr = GetLastError();
RETAILMSG(1,(TEXT("PCF50606 ERROR: Unable to initialize interrupt: %u\r\n"), dwErr));
goto _error_exit;
}
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;
// 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%.2x\r\n"), pPWR->ResetReg[0] ));
RETAILMSG(1,(TEXT("HW_Init INT1: 0x%.2x\r\n"), pPWR->ResetReg[1]));
RETAILMSG(1,(TEXT("HW_Init INT2: 0x%.2x\r\n"), pPWR->ResetReg[2]));
RETAILMSG(1,(TEXT("HW_Init INT3: 0x%.2x\r\n"), pPWR->ResetReg[3]));
// pPWR->ResetRegReady = TRUE;
// SetEvent(pPWR->ISTEvent);
}
RETAILMSG(1, (TEXT("HW_Init : Donw \r\n"), dwErr));
_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(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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -