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

📄 dvfc.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
字号:
//------------------------------------------------------------------------------
//
//  Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved
//  THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
//  BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
//  FREESCALE SEMICONDUCTOR, INC.
//
//------------------------------------------------------------------------------
//
//  File:  dvfc.c
//
//  This file contains driver support for the DVFS and DPTC power
//  management features of the SoC.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>
#include "csp.h"

//-----------------------------------------------------------------------------
// External Functions
extern BOOL BSPDvfcInit(void);
extern BOOL BSPDvfcDeinit(void);
extern void BSPDvfcIntrServ(void);
extern BOOL BSPDvfcPowerSet(CEDEVICE_POWER_STATE dx);
extern int BSPDvfcGetThreadPriority(void);


//-----------------------------------------------------------------------------
// External Variables


//-----------------------------------------------------------------------------
// Defines


//-----------------------------------------------------------------------------
// Types


//-----------------------------------------------------------------------------
// Global Variables
PCSP_CCM_REGS g_pCCM;

//-----------------------------------------------------------------------------
// Local Variables
static DWORD g_dwDvfcSysIntr;
static HANDLE g_hDvfcIntrEvent;
static HANDLE g_hDvfcIntrServThread;
static CEDEVICE_POWER_STATE g_dxCurrent = D0;

//-----------------------------------------------------------------------------
// Local Functions
static DWORD WINAPI DvfcIntrServThread (LPVOID lpParam);

//-----------------------------------------------------------------------------
//
//  Function:  DllEntry
//
//  This function is an optional method of entry into a DLL. If the function
//  is used, it is called by the system when processes and threads are
//  initialized and terminated, or on calls to the LoadLibrary and
//  FreeLibrary functions.
//
//  Parameters:
//      hinstDLL
//          [in] Handle to the DLL. The value is the base address of the DLL.
//
//      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.
//          If dwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for
//          dynamic loads and nonnull for static loads. If dwReason is
//          DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain is called
//          by using FreeLibrary and nonnull if DllMain is called during
//          process termination.
//
//  Returns:
//      When the system calls the DllMain function with the
//      DLL_PROCESS_ATTACH value, the function returns TRUE if it
//      succeeds or FALSE if initialization fails.
//
//      If the return value is FALSE when DllMain is called because the
//      process uses the LoadLibrary function, LoadLibrary returns NULL.
//
//      If the return value is FALSE when DllMain is called during
//      process initialization, the process terminates with an error.
//
//      When the system calls the DllMain function with a value other
//      than DLL_PROCESS_ATTACH, the return value is ignored.
//
//-----------------------------------------------------------------------------
BOOL WINAPI DllEntry(HINSTANCE hDllHandle, DWORD  dwReason,
                           LPVOID lpreserved)
{
    switch (dwReason)
    {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls((HMODULE) hDllHandle);
        break;

    case DLL_PROCESS_DETACH:
        break;

    default:
        break;
    }
    
    return TRUE;
}
       

//-----------------------------------------------------------------------------
//
//  Function:  Init
//
//  This function initializes the DVFC driver.  Called by the Device Manager to
//  initialize a device.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DVF_Init(void)
{
    BOOL rc = FALSE;
    PHYSICAL_ADDRESS phyAddr;
    DWORD irq;
    
    // Map CCM for access to DCVR and PMCR registers
    if (g_pCCM == NULL)
    {
        phyAddr.QuadPart = CSP_BASE_REG_PA_CCM;

        // Map peripheral physical address to virtual address
        g_pCCM = (PCSP_CCM_REGS) MmMapIoSpace(phyAddr, sizeof(CSP_CCM_REGS),
            FALSE);

        // Check if virtual mapping failed
        if (g_pCCM == NULL)
        {
            ERRORMSG(TRUE, (_T("MmMapIoSpace failed!\r\n")));
            goto cleanUp;
        }

    }

    // Disable the DPTC
    CLRREG32(&g_pCCM->PMCR0, CSP_BITFMASK(CCM_PMCR0_DPTEN));

    // Translate IRQ into SYSINTR
    irq = IRQ_CCM;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irq, sizeof(irq),
        &g_dwDvfcSysIntr, sizeof(g_dwDvfcSysIntr), NULL))
    {
        ERRORMSG(TRUE, (_T("IOCTL_HAL_REQUEST_SYSINTR failed for IRQ_CCM!\r\n")));
        goto cleanUp;
    }

    // Create event for IST signaling
    g_hDvfcIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!g_hDvfcIntrEvent)
    {
        ERRORMSG(TRUE, (_T("CreateEvent failed for DVFC IST signal!\r\n")));
        goto cleanUp;
    }
    
    // Register interrupt
    if (!InterruptInitialize(g_dwDvfcSysIntr, g_hDvfcIntrEvent, NULL, 0))
    {
        ERRORMSG(TRUE, (_T("InterruptInitialize failed for DVFC SYSINTR!\r\n")));
        goto cleanUp;
    }

    // Allow platform-specific DVFC initialization
    if (!BSPDvfcInit())
    {
        ERRORMSG(TRUE, (_T("BSPDvfcInit failed!\r\n")));
        goto cleanUp;
    }
    
    // Create IST for DVFC interrupts
    g_hDvfcIntrServThread = CreateThread(NULL, 0, DvfcIntrServThread, NULL, 0, NULL);      
    if (!g_hDvfcIntrServThread) 
    {
        ERRORMSG(TRUE, (_T("CreateThread failed for DVFC IST!\r\n")));
        goto cleanUp;
    }

    // Route DVFC interrupts to MCU
    INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_PTVIS, CCM_PMCR0_PTVIS_MCU_DPTC_REQ);
    INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFIS, CCM_PMCR0_DVFIS_MCU_DVFS_REQ);        

    RETAILMSG(TRUE, (_T("PMCR0 = 0x%x\r\n"), INREG32(&g_pCCM->PMCR0)));
    
    rc = TRUE;

cleanUp:

    return rc;

}


//-----------------------------------------------------------------------------
//
//  Function:  Deinit
//
//  This function deinitializes the DPTC.  Called by the Device Manager to
//  deinitialize a device.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE.
//
//-----------------------------------------------------------------------------
BOOL DVF_Deinit(void)
{
    BOOL rc;

    rc = BSPDvfcDeinit();

    return rc;
}

//-----------------------------------------------------------------------------
//
//  Function: Open
//
//  This function opens a device for reading, writing, or both.  An application 
//  indirectly invokes this function when it calls the CreateFile function to 
//  open special device file names.
//
//  Parameters:
//      hDeviceContext
//          [in] Handle to the device context. The XXX_Init function creates
//                and returns this handle.
//      AccessCode
//          [in] Access code for the device. The access is a combination of
//                read and write access from CreateFile.
//      ShareMode
//          [in] File share mode of the device. The share mode is a
//                combination of read and write access sharing from CreateFile.
//
//  Returns:
//      This function returns a handle that identifies the open context of
//      the device to the calling application.
//
//-----------------------------------------------------------------------------
DWORD DVF_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
    return hDeviceContext;
}


//-----------------------------------------------------------------------------
//
//  Function: Close
//
//  This function closes a device context created by the hOpenContext 
//  parameter.
//
//  Parameters:
//      hOpenContext
//          [in] Handle returned by the XXX_Open function, used to identify
//                the open context of the device.
//
//  Returns:
//      TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL DVF_Close(DWORD hOpenContext)
{
    return TRUE;
}


//-----------------------------------------------------------------------------
//
//  Function:  IOControl
//
//  This function sends a command to the DVFC driver.
//
//  Parameters:
//      hOpenContext 
//          [in] Handle to the open context of the device. The XXX_Open 
//              (Device Manager) function creates and returns this identifier. 
//
//      dwCode 
//          [in] I/O control operation to perform.
//
//      pBufIn 
//          [in] Pointer to the buffer containing data to transfer to the 
//          device. 
//
//      dwLenIn 
//          [in] Number of bytes of data in the buffer specified for pBufIn. 
//
//      pBufOut 
//          [out] Pointer to the buffer used to transfer the output data from 
//          the device. 
//
//      dwLenOut 
//          [in] Maximum number of bytes in the buffer specified by pBufOut. 
//
//      pdwActualOut 
//          [out] Pointer to the DWORD buffer that this function uses to 
//          return the actual number of bytes received from the device. 
//
//  Returns:
//      TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL DVF_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn,
    PBYTE pBufOut,  DWORD dwLenOut, PDWORD pdwActualOut)
{
    BOOL rc;
    DWORD  dwErr = ERROR_INVALID_PARAMETER;
    PPOWER_CAPABILITIES ppc;
    CEDEVICE_POWER_STATE dx;

    switch (dwCode) 
    {
        
    case IOCTL_POWER_CAPABILITIES:
        // Tell the power manager about ourselves.
        if (pBufOut != NULL 
            && dwLenOut >= sizeof(POWER_CAPABILITIES) 
            && pdwActualOut != NULL) 
        {
            __try 
            {
                ppc = (PPOWER_CAPABILITIES) pBufOut;
                memset(ppc, 0, sizeof(*ppc));              
                ppc->DeviceDx = DX_MASK(D0) | DX_MASK(D4);
                *pdwActualOut = sizeof(*ppc);
                dwErr = ERROR_SUCCESS;
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                ERRORMSG(TRUE, (_T("Exception in DVFC IOCTL_POWER_CAPABILITIES\r\n")));
            }
        }

        break;
        
        
    case IOCTL_POWER_SET: 
        if(pBufOut != NULL 
            && dwLenOut == sizeof(CEDEVICE_POWER_STATE) 
            && pdwActualOut != NULL) 
        {
            __try 
            {
                dx = *(PCEDEVICE_POWER_STATE) pBufOut;
                if(VALID_DX(dx)) 
                {
                    // Any request that is not D0 becomes a D4 request
                    if(dx != D0) 
                    {
                        dx = D4;
                    }
                    
                    *(PCEDEVICE_POWER_STATE) pBufOut = dx;
                    *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
                    if (BSPDvfcPowerSet(dx))
                    {
                        g_dxCurrent = dx;
                        dwErr = ERROR_SUCCESS;
                    }
                }
            } 
            __except(EXCEPTION_EXECUTE_HANDLER) 
            {
                ERRORMSG(TRUE, (_T("Exception in DVFC IOCTL_POWER_SET\r\n")));
            }
        }
        break;
        
    case IOCTL_POWER_GET: 
        if(pBufOut != NULL 
            && dwLenOut == sizeof(CEDEVICE_POWER_STATE) 
            && pdwActualOut != NULL) {
            // Just return our current Dx value
            __try 
            {
                *(PCEDEVICE_POWER_STATE) pBufOut = g_dxCurrent;
                *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
                dwErr = ERROR_SUCCESS;
            }
            __except(EXCEPTION_EXECUTE_HANDLER) 
            {
                ERRORMSG(TRUE, (_T("Exception in DVFC IOCTL_POWER_SET\r\n")));
            }
        }
        break;
        
    default:
        ERRORMSG(TRUE, (_T("%s: Unsupported DVFC IOCTL code %u\r\n"), dwCode));
        dwErr = ERROR_NOT_SUPPORTED;
        break;
    }
    
    // Pass back appropriate response codes
    SetLastError(dwErr);

    if(dwErr != ERROR_SUCCESS) 
    {
        rc = FALSE;
    } 

    else 
    {
        rc = TRUE;
    }
    
    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function:  DvfcIntrServThread
//
//  This is the interrupt service thread for DPTC interrupts.  
//  deinitialize a device.
//
//  Parameters:
//      lpParam
//          [in] Thread data passed to the function using the 
//          lpParameter parameter of the CreateThread function. Not used.
//
//  Returns:
//      Returns thread exit code.
//
//-----------------------------------------------------------------------------
static DWORD WINAPI DvfcIntrServThread (LPVOID lpParam)
{
    DWORD rc = TRUE;

    CeSetThreadPriority(GetCurrentThread(), BSPDvfcGetThreadPriority());

    while(TRUE)
    {
        if(WaitForSingleObject(g_hDvfcIntrEvent, INFINITE) == WAIT_OBJECT_0)
        {
            BSPDvfcIntrServ();
            InterruptDone(g_dwDvfcSysIntr);
        }
        else 
        {
            // Abnormal signal
            rc = FALSE;
            break;
        }
    }

    return rc;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -