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

📄 pcf50606.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -