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

📄 cspiutil.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
字号:
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
//  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:  cspiutil.c
//
//  This file contains the utility function for accessing perpherials via CSPI.
//  The code is currently used for accessing PMIC.  We assume 32 bit access.
//
//-----------------------------------------------------------------------------

#include <windows.h>
#include <Devload.h>
#include <ceddk.h>
#include "cspiutil.h"

//-----------------------------------------------------------------------------
// External Functions
extern BOOL   BSPPmicCSPIGetSysIntr(int index, DWORD *cspiSysIntr);
extern BOOL   BSPPmicCSPIMapIoSpace(int index);
extern void   BSPPmicCSPIWriteTXFIFO(unsigned int data);
extern UINT32 BSPPmicCSPIReadRXFIFO(void);
extern void   BSPPmicCSPIExchange(void);
extern void   BSPPmicCPSIWaitTransactionComplete(void);
extern void   BSPPmicCSPIWaitReadReady(void);
extern void   BSPPmicCSPIEnable(void);
extern void   BSPPmicCSPIDisable(void);
extern void   BSPPmicCSPIRXIRQEnable(void);
extern void   BSPPmicCSPIIRQDisable(void);
extern UINT32 BSPPmicGetSpiFreqIn(void);
extern BOOL   BSPPmicSetSpiClockGating(BOOL bEnable);

//-----------------------------------------------------------------------------
// External Variables
extern BOOL g_bPmicUseCspiPolling;

//-----------------------------------------------------------------------------
// Defines
#define CSPI_READ               0
#define CSPI_WRITE              1

#define CSPI_TIMEOUT            1000

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

#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)

#endif

//-----------------------------------------------------------------------------
// Global Variables

//-----------------------------------------------------------------------------
// Local Variables
static HANDLE g_hCspiIntrEvent;
static HANDLE g_hCspiWaitEvent;
static HANDLE g_hCspiIntrServThread;
static DWORD g_cspiSysIntr;
static BOOL g_bUsePolling;
static volatile BOOL g_bSync;
static HANDLE g_hCspiMutex;


//-----------------------------------------------------------------------------
// Local Functions
static DWORD WaitForInterruptEvent(HANDLE hIntrEvent, DWORD dwMilliseconds);
static DWORD WINAPI CspiIntrServThread (LPVOID lpParam);

//-----------------------------------------------------------------------------
//
// Function: cspiInitialize
//
// Initializes the CSPI interface and data structures.
//
// Parameters:
//      index
//          [in] CSPI instance (1 = CSPI1, 2 = CSPI2) to initialize.
//
//      dwFrequency
//          [in] Frequency requested.
//
// Returns:
//      TRUE is CSPI is initialized successfully.
//
//-----------------------------------------------------------------------------
BOOL cspiInitialize(int index, UINT32 dwFrequency)
{
    if (!BSPPmicCSPIGetSysIntr(index, &g_cspiSysIntr))
    {
        DEBUGMSG(ZONE_ERROR, 
            (TEXT("cspiInitialize: Failed to obtain SYSINTR value.\r\n")));
        goto Error;
    }

    if (!BSPPmicCSPIMapIoSpace(index))
    {
        DEBUGMSG(ZONE_ERROR, 
            (TEXT("cspiInitialize: MmMapIoSpace failed for CSP_CSPI_REG.\r\n")));
        goto Error;
    }

    // Create event for CSPI interrupt signaling
    g_hCspiIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (g_hCspiIntrEvent == NULL)
    {
        DEBUGMSG(ZONE_ERROR, 
            (TEXT("cspiInitialize: CreateEvent failed for g_hCspiIntrEvent.\r\n")));
        goto Error;
    }
    
    // Register CSPI interrupt
    if (!InterruptInitialize(g_cspiSysIntr, g_hCspiIntrEvent, NULL, 0))
    {
        DEBUGMSG(ZONE_ERROR, 
            (TEXT("cspiInitialize: InterruptInitialize failed.\r\n")));
        goto Error;
    }

    // Create event for CSPI thread wait signaling
    g_hCspiWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (g_hCspiWaitEvent == NULL)
    {
        DEBUGMSG(ZONE_ERROR, 
            (TEXT("cspiInitialize: CreateEvent failed for g_hCspiWaitEvent.\r\n")));
        goto Error;
    }

    g_hCspiMutex = CreateMutex(NULL, FALSE, L"MUTEX_PMIC");

    // Create IST for CSPI interrupts
    g_hCspiIntrServThread = CreateThread(NULL, 0, CspiIntrServThread, NULL, 0, NULL);      
    if (!g_hCspiIntrServThread) 
    {
        DEBUGMSG(ZONE_ERROR, 
            (TEXT("cspiInitialize: CreateThread failed for CSPI IST\r\n")));
        goto Error;
    }

    // Initialize global for sync with threads blocked on CSPI transfer
    g_bSync = FALSE;
    
    // Configure for interrupt-driven communication
    cspiConfigPolling(g_bPmicUseCspiPolling);

    return TRUE;

Error:
    return FALSE;
}


//-----------------------------------------------------------------------------
//
// Function: cspiRelease
//
// Frees allocated memory, closes reference to handles, and resets the state
// of global member variables.
//
// Parameters:
//      index
//          [in] CSPI instance (1 = CSPI1, 2 = CSPI2) to initialize
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
VOID cspiRelease(int index)
{
    return;
}

//-----------------------------------------------------------------------------
//
// Function: cspiConfigPolling
//
// Configures polled or interrupt-driven communication for the CSPI interface.
//
// Parameters:
//      bPoll
//          [in] Set to TRUE to forced polled communication.  Set to FALSE for
//          interrupt-driven communication.
//
// Returns:
//      None.
//
//-----------------------------------------------------------------------------
VOID cspiConfigPolling(BOOL bPoll)
{
    g_bUsePolling = bPoll;
}


//-----------------------------------------------------------------------------
//
// Function: cspiAddWritePacket
//
// Add a CSPI write packet.
//
// Parameters:
//      addr
//          [in] address
//      data
//          [in] data to write
//
// Returns:
//      TRUE if CSPI writing is successful.
//
//-----------------------------------------------------------------------------
BOOL cspiAddWritePacket(UINT32 addr, UINT32 data)
{
    CSPI_PACKET32 packet;

    // Format the packet
    packet.reg.data = data;
    packet.reg.null = 0;
    packet.reg.address = addr;
    packet.reg.rw = CSPI_WRITE;

    // Write the packet to the TXFIFO
    BSPPmicCSPIWriteTXFIFO(packet.data);
    DEBUGMSG(ZONE_INFO, (_T("write 0x%x = 0x%x\r\n"), addr, data));

    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: cspiAddReadPacket
//
// Add a CSPI read packet.
//
// Parameters:
//      addr
//          [in] address
//
// Returns:
//      TRUE if CSPI reading is successful.
//
//-----------------------------------------------------------------------------
BOOL cspiAddReadPacket(UINT32 addr)
{
    CSPI_PACKET32 packet;

    // Format the packet
    packet.reg.data = 0;
    packet.reg.null = 0;
    packet.reg.address = addr;
    packet.reg.rw = CSPI_READ;

    // Write the packet to the TXFIFO
    BSPPmicCSPIWriteTXFIFO(packet.data);

    DEBUGMSG(ZONE_INFO, (_T("read addr = 0x%x\r\n"), addr));

    return TRUE;
}

//-----------------------------------------------------------------------------
//
// Function: cspiDataExchange
//
// Initiate CSPI data exchange.
//
// Parameters:
//      None.
//
// Returns:
//      TRUE if data exchange is successful.
//
//-----------------------------------------------------------------------------
BOOL cspiDataExchange()
{
    BSPPmicCSPIExchange();

#ifdef VPMX31
    // wait until transaction is complete
    BSPPmicCSPIWaitTransactionComplete();
#endif

    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: cspiReceiveData
//
// Read a packet from CSPI RXDATA.
//
// Parameters:
//      data
//          [out] data read from CSPI RXDATA
//
// Returns:
//      TRUE if CSPI reading is successful.
//
//-----------------------------------------------------------------------------
BOOL cspiReceiveData(UINT32* data)
{
#ifdef VPMX31
    *data = BSPPmicCSPIReadRXFIFO();
    *data &= 0xFFFFFF;
    DEBUGMSG(ZONE_INFO, (_T("Receive data = 0x%x\r\n"), *data));

    return TRUE;
#else
    BOOL rc = FALSE;
    
    // If polled communication is requested
    if (g_bUsePolling)
    {
        // Wait until transaction is complete
	BSPPmicCSPIWaitReadReady();
    }

    // Else use interrupt-driven communication
    else
    {

        // Set a global to indicate we are about to block on the CSPI
        // transfer.  This will be used during a suspend procedure
        // to see if we need to wait until the transfer is complete
        g_bSync = TRUE;
        
        // NOTE: Can't use WaitForSingleObject directly on an event
        // registered with InterruptInitialize as the kernel faults
        // on priority inversion!
        if (WaitForSingleObject(g_hCspiWaitEvent, CSPI_TIMEOUT) != WAIT_OBJECT_0)
        {
            DEBUGMSG(ZONE_ERROR, (_T("cspiReceiveData failed\r\n")));
            *data = 0;
            goto cleanUp;
        }
    }


    *data = BSPPmicCSPIReadRXFIFO();
    *data &= 0xFFFFFF;
    DEBUGMSG(ZONE_INFO, (_T("Receive data = 0x%x\r\n"), *data));

    rc = TRUE;


cleanUp:
    g_bSync = FALSE;
    InterruptDone(g_cspiSysIntr);
    return rc;
#endif
}


//-----------------------------------------------------------------------------
//
// Function: cspiDiscardData
//
// Discard all data in CSPI RXDATA.
//
// Parameters:
//      None.
//
// Returns:
//      TRUE.
//
//-----------------------------------------------------------------------------
BOOL cspiDiscardData()
{
    UINT data;

    return cspiReceiveData(&data);
}


//-----------------------------------------------------------------------------
//
// Function: cspiPowerDown
//
// Power down the CSPI interface.
//
// Parameters:
//      None.
//
// Returns:
//      TRUE.
//
//-----------------------------------------------------------------------------
VOID cspiPowerDown(void)
{
}


//-----------------------------------------------------------------------------
//
// Function: cspiSync
//
// Waits for pending interrupt-driven SPI transfers to complete so that the
// system can properly suspend.
//
// Parameters:
//      None.
//
// Returns:
//      TRUE.
//
//-----------------------------------------------------------------------------
VOID cspiSync(void)
{
    // Wait for pending interrupt-driven transfers to complete.  The g_bSync
    // global is set prior to blocking on the CSPI transfer and will be cleared
    // by CspiIntrServThread or completion of cspiReceiveData
    while (g_bSync);
        
}


//-----------------------------------------------------------------------------
//
//  Function: cspiLock
//
//  Obtains a lock for the CSPI hardware so that the OAL and PMIC core driver
//  can safely share access.
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
void cspiLock(void)
{    
    WaitForSingleObject(g_hCspiMutex, INFINITE);

    BSPPmicSetSpiClockGating(TRUE);
    BSPPmicCSPIEnable();
   
    // Configure the CSPI for polled/interrupt-driven mode                                                 
    if (g_bUsePolling)
    {
        // Disable all CSPI interrupts
	BSPPmicCSPIIRQDisable();
    }
    else
    {
        // Enable RX FIFO ready interrupt
	BSPPmicCSPIRXIRQEnable();
    }
}


//-----------------------------------------------------------------------------
//
//  Function: cspiUnlock
//
//  Release the lock previously obtained by cspiLock.
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
void cspiUnlock(void)
{    
    BSPPmicCSPIDisable();
    BSPPmicSetSpiClockGating(FALSE);
    ReleaseMutex(g_hCspiMutex);
}


//-----------------------------------------------------------------------------
//
//  Function:  CspiIntrServThread
//
//  This is the interrupt service thread for CSPI interrupts.  
//
//  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 CspiIntrServThread (LPVOID lpParam)
{
    DWORD rc = TRUE;

    // Bump up our priority to the highest level available to CE drivers. 
    // This will make surewe have a chance to signal threads blocked on a 
    // CSPI transfer before starting the suspend procedure.
    CeSetThreadPriority(GetCurrentThread(), 97);
    
    while(TRUE)
    {
        if(WaitForSingleObject(g_hCspiIntrEvent, INFINITE) == WAIT_OBJECT_0)
        {
            // Disable CSPI interrupts, so we can call InterruptDone.  The
            // thread signaled with g_hCspiWaitEvent will perform the acutal
            // CSPI servicing
	    BSPPmicCSPIIRQDisable();
            g_bSync = FALSE;
            InterruptDone(g_cspiSysIntr);
            SetEvent(g_hCspiWaitEvent);
        }
        else 
        {
            // Abnormal signal
            rc = FALSE;
            break;
        }
    }

    return rc;
}

⌨️ 快捷键说明

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