📄 pmicpdk.cpp
字号:
//-----------------------------------------------------------------------------
//
// Copyright (C) 2004-2005, Motorola Inc. All Rights Reserved
//
/*---------------------------------------------------------------------------
* Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
* THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
* AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
*--------------------------------------------------------------------------*/
// File: pmicpdk.cpp
//
// This file contains the PMIC chip specific functions that provide control
// over the Power Management IC.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <cmnintrin.h>
#include <Devload.h>
#include <ceddk.h>
#include "cspiutil.h"
#include "pmic_ioctl.h"
#include "pmic_lla.h"
#include "pmic_adc.h"
#include "regs_adc.h"
#include "regs.h"
#include "regs_battery.h"
#include "regs_connectivity.h"
#include "pmic_connectivity.h"
#include "pmic_convity_priv.h"
//-----------------------------------------------------------------------------
// External Functions
extern "C" int BSPPmicGetSpiPort(void);
extern "C" UINT32 BSPPmicGetSpiFreqOut();
extern "C" DWORD BSPPmicGetIrq(void);
extern "C" BOOL BSPPmicInit(HANDLE *phIntrHdlr);
extern "C" BOOL BSPPmicDeinit(void);
extern "C" BOOL BSPPmicClearIrq(void);
extern "C" BOOL BSPPmicGetIrqStatus(UINT32 *status);
extern "C" VOID BSPPmicPowerNotifySuspend(void);
extern "C" VOID BSPPmicPowerNotifyResume(void);
extern "C" VOID BSPPmicReadIntrStatus(void);
extern "C" VOID BSPPmicSignalOALRTC(void);
//-----------------------------------------------------------------------------
// External Variables
extern "C" BOOL g_bPmicUseCspiPolling;
//-----------------------------------------------------------------------------
// Defines
#define PMIC_INTS0_TO_AP 0xFFFFFF // all interrupts to AP.
#define PMIC_INTS1_TO_AP 0xFFFFFF
#define PMIC_ALL_BITS 0xFFFFFF
#define MC13783_ADC_DEFAULT_ATO_SETTING 0x01
#define MC13783_ADC_REGISTER_MASK_ALL 0xFFFFFF
#define ADC_OPERATION_TIMEOUT 5000
#ifdef DEBUG
// Debug zone bit positions
#define ZONEID_ERROR 0
#define ZONEID_WARN 1
#define ZONEID_INIT 2
#define ZONEID_FUNC 3
#define ZONEID_INFO 4
// Debug zone masks
#define ZONEMASK_ERROR (1 << ZONEID_ERROR)
#define ZONEMASK_WARN (1 << ZONEID_WARN)
#define ZONEMASK_INIT (1 << ZONEID_INIT)
#define ZONEMASK_FUNC (1 << ZONEID_FUNC)
#define ZONEMASK_INFO (1 << ZONEID_INFO)
// Debug zone args to DEBUGMSG
#define ZONE_ERROR DEBUGZONE(ZONEID_ERROR)
#define ZONE_WARN DEBUGZONE(ZONEID_WARN)
#define ZONE_INIT DEBUGZONE(ZONEID_INIT)
#define ZONE_FUNC DEBUGZONE(ZONEID_FUNC)
#define ZONE_INFO DEBUGZONE(ZONEID_INFO)
DBGPARAM dpCurSettings = {
_T("PMICPDK"),
{
TEXT("Errors"), TEXT("Warnings"), TEXT("Init"), TEXT("Func"),
TEXT("Info"), TEXT(""), TEXT(""), TEXT(""),
TEXT(""),TEXT(""),TEXT(""),TEXT(""),
TEXT(""),TEXT(""),TEXT(""),TEXT("")
},
ZONEMASK_ERROR | ZONEMASK_WARN // | ZONEMASK_INIT | ZONEMASK_FUNC | ZONEMASK_INFO // ulZoneMask
};
#endif // DEBUG
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
// Local Variables
static CRITICAL_SECTION pmicCs;
static CRITICAL_SECTION adcCs;
static CRITICAL_SECTION intRegCs;
static HANDLE hIntrEventPmic;
static HANDLE hPmicISTThread;
static DWORD dwSysIntrPmic;
static BOOL bISTTerminate;
static HANDLE phIntrHdlr[PMIC_INT_MAX_ID];
static volatile BOOL g_bAdcPolled = FALSE;
static CEDEVICE_POWER_STATE g_dxCurrent = D0;
//-----------------------------------------------------------------------------
// Local Functions
static BOOL InitializePMIC();
static VOID CleanupPMIC();
static PMIC_STATUS PmicADCGetSettings(UINT16 channel, UINT32 *group,
UINT32 *chann, UINT32 *ena);
static PMIC_STATUS PmicADCConvert();
static VOID PmicADCDisable();
static VOID PmicReadEightValues(UINT16* pReturnVal);
static BOOL CheckIntIdValid(UINT32 IntID);
static BOOL PMICAdcSetMode(PMIC_TOUCH_MODE mode);
static BOOL PmicIsrThreadProc();
static DWORD WINAPI PmicPowerNotificationThread(LPVOID lpParam);
extern "C" BOOL PMICIoctlIntEnable(UINT32 IntID, BOOL EnableFlag);
extern "C" VOID SetRegister(UINT32 addr, UINT32 data, UINT32 mask);
extern "C" VOID GetRegister(UINT32 addr, UINT32* content);
//-----------------------------------------------------------------------------
//
// Function: DllEntry
//
// This is the entry and exit point for the PMIC control module. This
// function is called when processed and threads attach and detach from this
// module.
//
// Parameters:
// hInstDll
// [in] The handle to this module.
//
// dwReason
// [in] Specifies a flag indicating why the DLL entry-point function
// is being called.
//
// lpvReserved
// [in] Specifies further aspects of DLL initialization and cleanup.
//
// Returns:
// TRUE if the PMIC is initialized; FALSE if an error occurred during
// initialization.
//
//-----------------------------------------------------------------------------
extern "C"
BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
DEBUGREGISTER((HMODULE)hInstDll);
DisableThreadLibraryCalls((HMODULE) hInstDll);
DEBUGMSG(ZONE_INIT,
(_T("***** DLL PROCESS ATTACH TO PMIC PDK *****\r\n")));
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT,
(_T("***** DLL PROCESS DETACH FROM PMIC PDK *****\r\n")));
break;
}
// Return TRUE for success
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: InitializePMIC
//
// Initializes the PMIC module.
//
// Parameters:
// None.
//
// Returns:
// TRUE if the PMIC is initialized or FALSE if an error occurred during
// initialization. The reason for the failure can be retrieved by the
// GetLastError().
//
//-----------------------------------------------------------------------------
static BOOL
InitializePMIC(void)
{
// These definitions must match what is documented in the MC13783 L3 DTS
// document and are used to check if the MC13783 is actually present or
// not at the beginning of the driver initialization process.
static const UINT32 MC13783_ICID_MASK = 0x1C0; // ICID[2:0] corresponds to
// bits [8:6] of the ID
// register.
static const UINT32 MC13783_ICID_VALUE = 0x80; // This corresponds to
// ICID[2:0] = 010.
BOOL initializedPMIC = FALSE;
DWORD irq;
int i;
UINT32 isr;
UINT32 temp_data;
DEBUGMSG(ZONE_INIT || ZONE_FUNC, (TEXT("+%s()\r\n"), __WFUNCTION__));
// Create critical sections.
InitializeCriticalSection(&pmicCs);
InitializeCriticalSection(&adcCs);
InitializeCriticalSection(&intRegCs);
// Initialize CSPI interface to communicate with the PMIC.
initializedPMIC = cspiInitialize(BSPPmicGetSpiPort(),
BSPPmicGetSpiFreqOut());
if (!initializedPMIC)
{
ERRORMSG(TRUE, (TEXT("%s(): cspiInitialize() failed.\r\n"),
__WFUNCTION__));
goto Error;
}
// Check to see if the MC13783 PMIC is actually present. We do that by
// trying to read the Revision ID register. According to the MC13783
// Level 3 Detailed Technical Specifications document, the ICID[2:0]
// bits are hardwired to be 010 for the MC13783.
//
// If we fail to detect the presence of an MC13783 PMIC here, we should
// immediately abort any further initialization steps.
GetRegister(MC13783_REV_ADDR, &temp_data);
if ((temp_data & MC13783_ICID_MASK) != MC13783_ICID_VALUE)
{
DEBUGMSG(TRUE, (TEXT("%s(): failed to detect MC17383 PMIC.\r\n"),
__WFUNCTION__));
goto Error;
}
DEBUGMSG(TRUE, (TEXT("%s(): successfully detected MC17383 PMIC.\r\n"),
__WFUNCTION__));
// Reset Interrupt registration table
for (i = PMIC_INT_MAX_ID - 1; i>=0; i--)
{
phIntrHdlr[i] = NULL;
}
// Initialize the PMIC interrupt. Start by masking all interrupts.
SetRegister(MC13783_INT_MSK0_ADDR, PMIC_ALL_BITS, PMIC_ALL_BITS);
SetRegister(MC13783_INT_MSK1_ADDR, PMIC_ALL_BITS, PMIC_ALL_BITS);
// Then clear all existing interrupts.
GetRegister(MC13783_INT_STAT0_ADDR, &isr);
SetRegister(MC13783_INT_STAT0_ADDR, (isr & PMIC_INTS0_TO_AP),
PMIC_ALL_BITS);
GetRegister(MC13783_INT_STAT1_ADDR, &isr);
SetRegister(MC13783_INT_STAT1_ADDR, (isr & PMIC_INTS1_TO_AP),
PMIC_ALL_BITS);
// Initialize platform-specific configuration
BSPPmicInit(phIntrHdlr);
// Create an event for signalling PMIC interrupts.
//
// pEventAttributes = NULL (must be NULL)
// bManualReset = FALSE => resets automatically to nonsignaled
// state after waiting thread released
// bInitialState = FALSE => initial state is non-signaled
// lpName = NULL => object created without a name
//
hIntrEventPmic = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hIntrEventPmic == NULL)
{
ERRORMSG(TRUE, (TEXT("%s(): CreateEvent() failed.\r\n"),
__WFUNCTION__));
goto Error;
}
irq = BSPPmicGetIrq();
// Call the OAL to translate the IRQ into a SysIntr value.
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irq, sizeof(DWORD),
&dwSysIntrPmic, sizeof(DWORD), NULL))
{
ERRORMSG(TRUE, (TEXT("%s(): IOCTL_HAL_REQUEST_SYSINTR failed.\r\n"),
__WFUNCTION__));
goto Error;
}
// Register PMIC interrupt
if (!InterruptInitialize(dwSysIntrPmic, hIntrEventPmic, NULL, 0))
{
ERRORMSG(TRUE, (TEXT("%s(): InterruptInitialize() failed!\r\n"),
__WFUNCTION__));
goto Error;
}
// Ask the OAL to enable our interrupt to wake the system from suspend
KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &dwSysIntrPmic,
sizeof(dwSysIntrPmic), NULL, 0, NULL);
bISTTerminate = FALSE;
hPmicISTThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)PmicIsrThreadProc,
0, 0, NULL);
if (!hPmicISTThread)
{
ERRORMSG(TRUE, (TEXT("%s(): CreateThread() failed\r\n"),
__WFUNCTION__));
goto Error;
}
// Create event for blocking on ADC conversions to complete
phIntrHdlr[PMIC_MC13783_INT_ADCDONEI] =
CreateEvent(NULL, FALSE, FALSE, _T("EVENT_ADCDONE"));
// Check if CreateEvent failed
if (phIntrHdlr[PMIC_MC13783_INT_ADCDONEI] == NULL)
{
ERRORMSG(TRUE, (TEXT("%s(): CreateEvent() failed!\r\n"),
__WFUNCTION__));
goto Error;
}
// Unmask ADC complete interrupt
SetRegister(MC13783_INT_MSK0_ADDR, PMIC_ALL_BITS, PMIC_ALL_BITS);
SetRegister(MC13783_INT_MSK0_ADDR, 0, (1 << PMIC_MC13783_INT_ADCDONEI));
// Unmask TOD interrupts
SetRegister(MC13783_INT_MSK1_ADDR, 0, MC13783_TODAM_MASK);
DEBUGMSG(ZONE_INIT || ZONE_FUNC, (TEXT("-%s returning %d\r\n"),
__WFUNCTION__, initializedPMIC));
return initializedPMIC;
Error:
CleanupPMIC();
return FALSE;
}
//-----------------------------------------------------------------------------
//
// Function: CleanupPMIC
//
// This function unmaps the registry space for the PMIC registers.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
static VOID
CleanupPMIC(void)
{
DEBUGMSG(ZONE_FUNC, (TEXT("+%s\r\n"), __WFUNCTION__));
cspiRelease(BSPPmicGetSpiPort());
// Release SYSINTR
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &dwSysIntrPmic, sizeof(DWORD),
NULL, 0, NULL);
dwSysIntrPmic = SYSINTR_UNDEFINED;
// If PMIC no longer needs service
// Clear the gpio interrupt flag(w1c)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -