📄 pcf50606.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#include <windows.h>
#include <windev.h>
#include <types.h>
#include <memory.h>
#include <string.h>
#include <nkintr.h>
#include <ceddk.h>
#include <pmimpl.h>
#include <pmpolicy.h>
#include <nled.h>
#include <bulverde_base_regs.h>
#include <plato.h>
#include <xllp_gpio.h>
#include <xllp_clkmgr.h>
#include <xllp_ost.h>
#include <xllp_i2c.h>
#include "bsp_cfg.h"
#include "pcf50606.h"
#include "pmdriver.h"
#ifndef SHIP_BUILD
#define DBG_ERROR 1
#define DBG_WARNING 2
#define DBG_VERBOSE 4
#define DBG_STATECHANGE 8
DBGPARAM dpCurSettings = {
TEXT("Philips PCF50606 PMIC Driver"),
{
TEXT("Errors"), TEXT("Warnings"), TEXT("Verbose"), TEXT("StateChange"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"),
TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined"), TEXT("Undefined")
},
DBG_ERROR | DBG_WARNING | DBG_STATECHANGE
};
#endif
extern BOOL gfACOnline;
BOOL g_FlagExitThrd = FALSE;
HANDLE g_PwrMonThread = NULL;
HANDLE m_hReadMsgQ = NULL;
#define QUEUE_ENTRIES 16
#define MAX_NAMELEN 64
#define QUEUE_SIZE (QUEUE_ENTRIES*(sizeof(POWER_BROADCAST)+MAX_NAMELEN))
INT WINAPI PwrMonThread(void);
INT WINAPI PCF50606IntrThread(void);
void PCF50606Initialize(PPCF50606 pPCF50606);
XLLP_BOOL_T XllpPI2CInit(volatile P_XLLP_PI2C_T I2C_regs,
volatile P_XLLP_GPIO_T gpio,
volatile P_XLLP_CLKMGR_T clkMgr,
XLLP_UINT32_T dev_id);
//times in micro seconds
const LONG g_PcfLedPeriodOptions[] =
{
400000,
1000000,
1200000,
2000000,
2600000,
4000000,
6000000,
8000000
};
#define NUM_PERIOD_OPTIIONS (sizeof(g_PcfLedPeriodOptions)/sizeof(g_PcfLedPeriodOptions[0]))
const LONG g_PcfLedOnTimeOptions[] =
{
50000,
100000,
200000,
500000
};
#define NUM_ON_TIME_OPTIIONS (sizeof(g_PcfLedOnTimeOptions)/sizeof(g_PcfLedOnTimeOptions[0]))
void CleanUp(PPCF50606 pPCF50606)
{
if (NULL != pPCF50606)
{
// Unmap any memory areas that we may have mapped.
if (pPCF50606->v_pGPIORegs != NULL)
{
MmUnmapIoSpace((VOID*)pPCF50606->v_pGPIORegs, sizeof(XLLP_GPIO_T));
}
if (pPCF50606->v_pClkRegs != NULL)
{
MmUnmapIoSpace((VOID*)pPCF50606->v_pClkRegs, sizeof(XLLP_CLKMGR_T));
}
if (pPCF50606->v_pOstRegs != NULL)
{
MmUnmapIoSpace((VOID*)pPCF50606->v_pOstRegs, sizeof(XLLP_OST_T));
}
if (pPCF50606->v_pIntcRegs != NULL)
{
MmUnmapIoSpace((VOID*)pPCF50606->v_pIntcRegs, sizeof(XLLP_INTC_T));
}
if (pPCF50606->v_pPI2CRegs != NULL)
{
MmUnmapIoSpace((VOID*)pPCF50606->v_pPI2CRegs, sizeof(XLLP_PI2C_T));
}
if (pPCF50606->v_pI2CRegs != NULL)
{
MmUnmapIoSpace((VOID*)pPCF50606->v_pI2CRegs, sizeof(XLLP_I2C_T));
}
// Delete open contexts if any
if (pPCF50606->pOpenContextHead != NULL)
{
PPCF50606OPEN pContext = (PPCF50606OPEN)pPCF50606->pOpenContextHead;
PPCF50606OPEN pDeleteContext = NULL;
while (pContext != NULL)
{
pDeleteContext = pContext;
pContext = (PPCF50606OPEN)pContext->next;
CloseMsgQueue(pDeleteContext->msgQueuePCFRead);
LocalFree(pDeleteContext);
pDeleteContext = NULL;
}
}
// Delete message queues
if (pPCF50606->msgQueuePCFWrite)
{
CloseMsgQueue(pPCF50606->msgQueuePCFWrite);
}
if (pPCF50606->msgQueuePMPOLICY)
{
CloseMsgQueue(pPCF50606->msgQueuePMPOLICY);
}
// Close handles
if (pPCF50606->hevPCF50606Event)
{
CloseHandle(pPCF50606->hevPCF50606Event);
}
// Free any critical sections we have allocated
DeleteCriticalSection(&pPCF50606->csI2CAccess);
// Finally, free device structure
LocalFree(pPCF50606);
}
if (g_PwrMonThread != NULL)
{
// Signal PwrMonThread to finish (closing the handle will force ReadMsgQueue to return)
g_FlagExitThrd = TRUE;
if ( m_hReadMsgQ )
{
CloseMsgQueue(m_hReadMsgQ);
m_hReadMsgQ = NULL;
}
// Wait for thread to finish
WaitForSingleObject(g_PwrMonThread, 3000);
if(g_PwrMonThread)
CloseHandle(g_PwrMonThread);
}
}
BOOL
PCF_Deinit(
DWORD hDeviceContext)
{
CleanUp((PPCF50606)hDeviceContext);
return(TRUE);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
DWORD
PCF_Init(
LPCTSTR pContext,
LPCVOID lpvBusContext)
{
MSGQUEUEOPTIONS msgQueueOptions;
PHYSICAL_ADDRESS PA;
HANDLE hThread = NULL;
PPCF50606 pPCF50606 = NULL;
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF_Init(%s)(%x)\r\n"), pContext,lpvBusContext));
// Allocate for device structure
pPCF50606 = (PPCF50606)LocalAlloc( LPTR, sizeof(PCF50606));
if (NULL == pPCF50606)
{
goto Error;
}
//////
// Initialize device structure
//////
// Initialize critical section protection for power I2C bus
InitializeCriticalSection(&pPCF50606->csI2CAccess);
// Initialize message queue options
memset(&msgQueueOptions, 0, sizeof(msgQueueOptions));
msgQueueOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
msgQueueOptions.dwFlags = 0;
msgQueueOptions.dwMaxMessages = MAX_QUEUE_MESSAGES;
msgQueueOptions.cbMaxMessage = sizeof(DWORD);
msgQueueOptions.bReadAccess = FALSE;
// Create PCF50606 msgQueue
pPCF50606->msgQueuePCFWrite = CreateMsgQueue(TEXT("PCF50606"), &msgQueueOptions);
if(pPCF50606->msgQueuePCFWrite == NULL)
{
RETAILMSG(ZONE_ERROR, (_T("CreateMsgQueue() failed %d\r\n"),GetLastError()));
goto Error;
}
// Initialize message queue options
memset(&msgQueueOptions, 0, sizeof(msgQueueOptions));
msgQueueOptions.dwSize = sizeof(msgQueueOptions);
msgQueueOptions.dwFlags = MSGQUEUE_ALLOW_BROKEN;
msgQueueOptions.dwMaxMessages = 10;
msgQueueOptions.cbMaxMessage = sizeof(POWERPOLICYMESSAGE);
msgQueueOptions.bReadAccess = FALSE;
// Create PMPOLICY msgQueue
pPCF50606->msgQueuePMPOLICY = CreateMsgQueue(PMPOLICY_NOTIFICATION_QUEUE, &msgQueueOptions);
if(pPCF50606->msgQueuePMPOLICY == NULL)
{
RETAILMSG(ZONE_ERROR, (_T("CreateMsgQueue() failed %d\r\n"),GetLastError()));
goto Error;
}
// Perform memory mapping of hardware registers
PA.QuadPart = BULVERDE_BASE_REG_PA_GPIO;
pPCF50606->v_pGPIORegs =
(volatile XLLP_GPIO_T *) MmMapIoSpace(PA, sizeof(XLLP_GPIO_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_CLKMGR;
pPCF50606->v_pClkRegs =
(volatile XLLP_CLKMGR_T *) MmMapIoSpace(PA, sizeof(XLLP_CLKMGR_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_OST;
pPCF50606->v_pOstRegs =
(volatile XLLP_OST_T *) MmMapIoSpace(PA, sizeof(XLLP_OST_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_INTC;
pPCF50606->v_pIntcRegs =
(volatile XLLP_INTC_T *) MmMapIoSpace(PA, sizeof(XLLP_INTC_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_PWR;
pPCF50606->v_pPI2CRegs =
(volatile XLLP_PI2C_T *) MmMapIoSpace(PA, sizeof(XLLP_PI2C_T), FALSE);
PA.QuadPart = BULVERDE_BASE_REG_PA_PWR + 0x180;
pPCF50606->v_pI2CRegs =
(volatile XLLP_I2C_T *) MmMapIoSpace(PA, sizeof(XLLP_I2C_T), FALSE);
if (NULL == pPCF50606->v_pGPIORegs ||
NULL == pPCF50606->v_pClkRegs ||
NULL == pPCF50606->v_pOstRegs ||
NULL == pPCF50606->v_pIntcRegs ||
NULL == pPCF50606->v_pPI2CRegs ||
NULL == pPCF50606->v_pI2CRegs )
{
RETAILMSG(ZONE_ERROR, (_T("Mapping of hardware registers failed\r\n")));
goto Error;
}
// Initial low level I2C processor registers;
XllpPI2CInit((P_XLLP_PI2C_T)pPCF50606->v_pPI2CRegs,
(P_XLLP_GPIO_T)pPCF50606->v_pGPIORegs,
(P_XLLP_CLKMGR_T)pPCF50606->v_pClkRegs,
(XLLP_UINT32_T)0);
// Initialize the PCF50606 controller
PCF50606Initialize(pPCF50606);
// Create PCF50606 interrupt event
pPCF50606->hevPCF50606Event = CreateEvent(NULL,FALSE,FALSE,NULL);
if (NULL == pPCF50606->hevPCF50606Event)
{
RETAILMSG(ZONE_ERROR, (TEXT("Failed to create interrupt event. Err = %d\r\n"), GetLastError()));
goto Error;
}
// Turn on falling edge detection
pPCF50606->v_pGPIORegs->GFER0 |= XLLP_BIT_0;
// Clear pending edge interrupt
pPCF50606->v_pGPIORegs->GEDR0 &= ~(XLLP_BIT_0);
// Associate system interrupt to irq
if(!(InterruptInitialize(SYSINTR_PCF50606, pPCF50606->hevPCF50606Event , NULL, 0)))
{
RETAILMSG(ZONE_ERROR, (TEXT("InterruptInitialize(SYSINTR_PCF50606) Failed!! %d\r\n"), GetLastError()));
goto Error;
}
else
{
DEBUGMSG(ZONE_VERBOSE, (TEXT("InterruptInitialize(SYSINTR_PCF50606) Complete!!\r\n")));
}
// Spawn device interrupt thread
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PCF50606IntrThread, (LPVOID)pPCF50606, 0, NULL);
if (NULL == hThread)
{
goto Error;
}
g_PwrMonThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PwrMonThread, NULL, 0, NULL);
if ( g_PwrMonThread == NULL )
{
goto Error;
}
return((DWORD)pPCF50606);
Error:
RETAILMSG(ZONE_ERROR, (TEXT("ERROR in PCF_Init\r\n")));
CleanUp(pPCF50606);
return ((DWORD)NULL);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
DWORD
PCF_Open(
DWORD hDeviceContext,
DWORD AccessCode,
DWORD ShareMode)
{
DWORD retval = 0;
MSGQUEUEOPTIONS msgOptions;
PPCF50606OPEN pOpenContext = NULL;
PPCF50606OPEN pContext = NULL;
PPCF50606 pPCF50606 = (PPCF50606)hDeviceContext;
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF_Open()\r\n")));
pPCF50606->dwOpenCount++;
// Allocate space for open structure
pContext = (PPCF50606OPEN)LocalAlloc(LPTR, sizeof(PCF50606OPEN));
if (!pContext)
{
goto Error;
}
// Fill out open structure
pContext->pPCF50606Device = (DWORD*)pPCF50606;
pContext->dwIndex = pPCF50606->dwOpenCount;
// Initialize message queue options
msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
msgOptions.dwFlags = 0;
msgOptions.dwMaxMessages = MAX_QUEUE_MESSAGES;
msgOptions.cbMaxMessage = sizeof(DWORD);
msgOptions.bReadAccess = TRUE;
// Create PCF50606 msgQueue
pContext->msgQueuePCFRead = CreateMsgQueue(TEXT("PCF50606"), &msgOptions);
if(pContext->msgQueuePCFRead == NULL)
{
RETAILMSG(ZONE_ERROR, (_T("CreateMsgQueue() failed %d\r\n"),GetLastError()));
goto Error;
}
// Add the new open context to the head of open contexts list
pContext->next = (DWORD*)pPCF50606->pOpenContextHead;
pPCF50606->pOpenContextHead = pContext;
// Hand off memory on success.
retval = (DWORD)pContext;
pContext = NULL;
Error:
// Cleanup on error
if (NULL != pContext)
{
if (pContext->msgQueuePCFRead)
{
CloseMsgQueue(pOpenContext->msgQueuePCFRead);
}
// And free the context data structure
LocalFree(pContext);
}
return retval;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -