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

📄 intr.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  Copyright (C) 2004, 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: intr.c
//
//  This file implements the major part of interrupt support for the 
//  MX31 SoC.
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <cmnintrin.h>
#include <oal.h>
#include "csp.h"
#include <intr.h>



//------------------------------------------------------------------------------
// External Functions


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


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

#ifdef VERBOSE_INTENABLE
#define TRACE_INTENABLE \
    OALMSG(OAL_INFO, (L"g_oalIrqMask.HighPart = 0x%x\r\n", g_oalIrqMask[irq].HighPart)); \
    OALMSG(OAL_INFO, (L"g_oalIrqMask.LowPart = 0x%x\r\n", g_oalIrqMask[irq].LowPart)); \
    OALMSG(OAL_INFO, (L"g_oalGpioMask[0] = 0x%x\r\n", g_oalGpioMask[0][irq])); \
    OALMSG(OAL_INFO, (L"g_oalGpioMask[1] = 0x%x\r\n", g_oalGpioMask[1][irq])); \
    OALMSG(OAL_INFO, (L"g_oalGpioMask[2] = 0x%x\r\n", g_oalGpioMask[2][irq])); \
    OALMSG(OAL_INFO, (L"INTENABLEH = 0x%x\r\n", INREG32(&g_pAVIC->INTENABLEH))); \
    OALMSG(OAL_INFO, (L"INTENABLEL = 0x%x\r\n", INREG32(&g_pAVIC->INTENABLEL))); \
    OALMSG(OAL_INFO, (L"GPIO1_IMR = 0x%x\r\n", INREG32(&g_pGPIO1->IMR))); \
    OALMSG(OAL_INFO, (L"GPIO2_IMR = 0x%x\r\n", INREG32(&g_pGPIO2->IMR))); \
    OALMSG(OAL_INFO, (L"GPIO3_IMR = 0x%x\r\n", INREG32(&g_pGPIO3->IMR))); 
#else
#define TRACE_INTENABLE
#endif // VERBOSE_INTENABLE


#define OAL_IRQ_ENABLE(irq) \
    if (g_oalGpioMask[0][irq]) SETREG32(&g_pGPIO1->IMR, g_oalGpioMask[0][irq]); \
    if (g_oalGpioMask[1][irq]) SETREG32(&g_pGPIO2->IMR, g_oalGpioMask[1][irq]); \
    if (g_oalGpioMask[2][irq]) SETREG32(&g_pGPIO3->IMR, g_oalGpioMask[2][irq]); \
    if (g_oalIrqMask[irq].HighPart) SETREG32(&g_pAVIC->INTENABLEH, g_oalIrqMask[irq].HighPart); \
    if (g_oalIrqMask[irq].LowPart) SETREG32(&g_pAVIC->INTENABLEL, g_oalIrqMask[irq].LowPart); \
    TRACE_INTENABLE;

#define OAL_IRQ_DISABLE(irq) \
    if (g_oalIrqMask[irq].HighPart) CLRREG32(&g_pAVIC->INTENABLEH, g_oalIrqMask[irq].HighPart); \
    if (g_oalIrqMask[irq].LowPart) CLRREG32(&g_pAVIC->INTENABLEL, g_oalIrqMask[irq].LowPart); \
    if (g_oalGpioMask[0][irq]) CLRREG32(&g_pGPIO1->IMR, g_oalGpioMask[0][irq]); \
    if (g_oalGpioMask[1][irq]) CLRREG32(&g_pGPIO2->IMR, g_oalGpioMask[1][irq]); \
    if (g_oalGpioMask[2][irq]) CLRREG32(&g_pGPIO3->IMR, g_oalGpioMask[2][irq]); \
    TRACE_INTENABLE;


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


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

UINT32 g_oalIrqTranslate[OAL_INTR_IRQ_MAXIMUM];
ULARGE_INTEGER g_oalIrqMask[OAL_INTR_IRQ_MAXIMUM];
UINT32 g_oalGpioTranslate[DDK_GPIO_PORT3+1][GPIO_INTR_SOURCES_MAX];
UINT32 g_oalSdmaTranslate[SDMA_NUM_CHANNELS];
UINT32 g_oalGpioMask[DDK_GPIO_PORT3+1][OAL_INTR_IRQ_MAXIMUM];
PCSP_AVIC_REGS g_pAVIC;

const UINT32 g_IRQ_RTC = IRQ_RTC; // Create a global variable for the
                                  // SOC-specific IRQ that is used by
				  // the RTC.

//  Function pointer to profiling timer ISR routine.
//
PFN_PROFILER_ISR g_pProfilerISR = NULL;


//------------------------------------------------------------------------------
// Local Variables

PCSP_GPIO_REGS g_pGPIO1;
PCSP_GPIO_REGS g_pGPIO2;
PCSP_GPIO_REGS g_pGPIO3;
PCSP_SDMA_REGS g_pSDMA;


//------------------------------------------------------------------------------
// Local Functions


//------------------------------------------------------------------------------
//
//  Function:  OALIntrInit
//
//  This function initialize interrupt mapping, hardware and call platform
//  specific initialization.
//
BOOL OALIntrInit()
{
    BOOL rc = FALSE;
    UCHAR i;
    UINT32 irq;

    OALMSG( OAL_FUNC&&OAL_INTR, (L"+OALInterruptInit\r\n") );

    // Initialize interrupt mapping
    OALIntrMapInit();

    // Get uncached virtual addresses for AVIC
    g_pAVIC = (PCSP_AVIC_REGS) OALPAtoUA(CSP_BASE_REG_PA_AVIC);
    if (g_pAVIC == NULL)
    {
        OALMSG(OAL_ERROR, (L"OALIntrInit:  AVIC null pointer!\r\n"));
        goto cleanUp;
    }

    // Get uncached virtual addresses for GPIO modules
    g_pGPIO1 = (PCSP_GPIO_REGS) OALPAtoUA(CSP_BASE_REG_PA_GPIO1);
    if (g_pGPIO1 == NULL)
    {
        OALMSG(OAL_ERROR, (L"OALIntrInit:  GPIO1 null pointer!\r\n"));
        goto cleanUp;
    }

    g_pGPIO2 = (PCSP_GPIO_REGS) OALPAtoUA(CSP_BASE_REG_PA_GPIO2);
    if (g_pGPIO2 == NULL)
    {
        OALMSG(OAL_ERROR, (L"OALIntrInit:  GPIO2 null pointer!\r\n"));
        goto cleanUp;
    }

    g_pGPIO3 = (PCSP_GPIO_REGS) OALPAtoUA(CSP_BASE_REG_PA_GPIO3);
    if (g_pGPIO3 == NULL)
    {
        OALMSG(OAL_ERROR, (L"OALIntrInit:  GPIO3 null pointer!\r\n"));
        goto cleanUp;
    }

    // Get uncached virtual addresses for SDMA
    g_pSDMA = (PCSP_SDMA_REGS) OALPAtoUA(CSP_BASE_REG_PA_SDMA);
    if (g_pSDMA == NULL)
    {
        OALMSG(OAL_ERROR, (L"OALIntrInit:  SDMA null pointer!\r\n"));
        goto cleanUp;
    }

    // Initialize SoC-specific translation tables
    for (i = 0; i < OAL_INTR_IRQ_MAXIMUM; i++)
    {
        g_oalIrqTranslate[i] = i;
        g_oalIrqMask[i].QuadPart = CSP_IRQMASK(i);
    }

    memset(g_oalGpioTranslate, OAL_INTR_IRQ_UNDEFINED,
        sizeof(g_oalGpioTranslate));
    memset(g_oalSdmaTranslate, OAL_INTR_IRQ_UNDEFINED,
        sizeof(g_oalSdmaTranslate));
    memset(g_oalGpioMask, 0, sizeof(g_oalGpioMask));

    // Mask and clear all GPIO IRQs
    OUTREG32(&g_pGPIO1->IMR, 0);
    OUTREG32(&g_pGPIO1->ISR, 0xFFFFFFFF);
    OUTREG32(&g_pGPIO2->IMR, 0);
    OUTREG32(&g_pGPIO2->ISR, 0xFFFFFFFF);
    OUTREG32(&g_pGPIO3->IMR, 0);
    OUTREG32(&g_pGPIO3->ISR, 0xFFFFFFFF);

    // Translation table above maps provides a one-to-one mapping
    // between AVIC IRQs and the IRQ table maintained for SYSINTR 
    // mapping.  For peripherals that have multiple IRQs that we want 
    // to be reported as a single SYSINTR, we can "slam" them by
    // overriding the corresponding table values.  This translation
    // is required since PQOAL assumes one-to-one mapping between
    // SYSINTR and IRQ.
    //
    // NOTE:  Maintain consistency with slammed IRQs and the
    //        IRQs returned from OALIntrRequestIrqs

    // Slam SIM IRQs to IRQ_SIM_COMMON
    g_oalIrqMask[IRQ_SIM_COMMON].QuadPart = 
        CSP_IRQMASK(IRQ_SIM_COMMON) | CSP_IRQMASK(IRQ_SIM_DATA);
    g_oalIrqTranslate[IRQ_SIM_DATA] = IRQ_SIM_COMMON;

    // Slam IPU IRQs to IRQ_IPU_GENERAL
    g_oalIrqMask[IRQ_IPU_GENERAL].QuadPart = 
        CSP_IRQMASK(IRQ_IPU_ERROR) | CSP_IRQMASK(IRQ_IPU_GENERAL);
    g_oalIrqTranslate[IRQ_IPU_ERROR] = IRQ_IPU_GENERAL;

    // Slam CCM DVFS interrupt to CCM DPTC interrupt
    g_oalIrqMask[IRQ_CCM].QuadPart = 
        CSP_IRQMASK(IRQ_CCM) | CSP_IRQMASK(IRQ_DVFS);
    g_oalIrqTranslate[IRQ_DVFS] = IRQ_CCM;
    

#ifdef OAL_BSP_CALLBACKS
    // Give BSP chance to initialize subordinate controller
    rc = BSPIntrInit();
#else
    rc = TRUE;
#endif

    // Enable the SDMA IRQ
    irq = IRQ_SDMA;
    if (!OALIntrEnableIrqs(1, &irq))
    {
        OALMSG(OAL_WARN, 
            (L"OALIntrInit: can't enable IRQ_SDMA\r\n"));
    }

    // Enable GPIO1 IRQ
    irq = IRQ_GPIO1;
    if (!OALIntrEnableIrqs(1, &irq))
    {
        OALMSG(OAL_WARN, 
            (L"OALIntrInit: can't enable IRQ_GPIO1\r\n"));
    }

    // Enable GPIO2 IRQ
    irq = IRQ_GPIO2;
    if (!OALIntrEnableIrqs(1, &irq))
    {
        OALMSG(OAL_WARN, 
            (L"OALIntrInit: can't enable IRQ_GPIO2\r\n"));
    }

    // Enable GPIO3 IRQ
    irq = IRQ_GPIO3;
    if (!OALIntrEnableIrqs(1, &irq))
    {
        OALMSG(OAL_WARN, 
            (L"OALIntrInit: can't enable IRQ_GPIO3\r\n"));
    }
    
cleanUp:
    OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALInterruptInit(rc = %d)\r\n", rc));
    return rc;
}



//------------------------------------------------------------------------------
//
//  Function:  OALIntrRequestIrqs
//
//  This function returns IRQs for CPU/SoC devices based on their
//  physical address.
//
BOOL OALIntrRequestIrqs(DEVICE_LOCATION *pDevLoc, UINT32 *pCount, UINT32 *pIrqs)
{
    BOOL rc = FALSE;

    OALMSG(OAL_INTR&&OAL_FUNC, (
        L"+OALIntrRequestIrqs(0x%08x->%d/%d/0x%08x/%d, 0x%08x, 0x%08x)\r\n",
        pDevLoc, pDevLoc->IfcType, pDevLoc->BusNumber, pDevLoc->LogicalLoc,
        pDevLoc->Pin, pCount, pIrqs
    ));

    if (pIrqs == NULL || pCount == NULL || *pCount < 1) goto cleanUp;

    switch (pDevLoc->IfcType) 
    {
    case Internal:

        switch (pDevLoc->LogicalLoc)
        {
        case CSP_BASE_REG_PA_I2C3:
            pIrqs[0] = IRQ_I2C3;
            *pCount = 1;
            rc = TRUE;
            break;
                
        case CSP_BASE_REG_PA_I2C2:
            pIrqs[0] = IRQ_I2C2;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_MPEG4_ENCODER:
            pIrqs[0] = IRQ_MPEG4_ENCODE;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_RTIC:
            pIrqs[0] = IRQ_RTIC;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_FIRI:
            pIrqs[0] = IRQ_FIRI;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_SDHC2:
            pIrqs[0] = IRQ_SDHC2;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_SDHC1:
            pIrqs[0] = IRQ_SDHC1;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_I2C:
            pIrqs[0] = IRQ_I2C;
            *pCount = 1;
            rc = TRUE;
            break;
            
        case CSP_BASE_REG_PA_SSI2:
            pIrqs[0] = IRQ_SSI2;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_SSI1:
            pIrqs[0] = IRQ_SSI1;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_CSPI2:
            pIrqs[0] = IRQ_CSPI2;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_CSPI1:
            pIrqs[0] = IRQ_CSPI1;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_ATA_CTRL:
            pIrqs[0] = IRQ_ATA_CTRL;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_MEM_PA_GACC:
            pIrqs[0] = IRQ_GACC;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_CSPI3:
            pIrqs[0] = IRQ_CSPI3;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_UART3:
            pIrqs[0] = IRQ_UART3;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_IIM:
            pIrqs[0] = IRQ_IIM;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_SIM:
            pIrqs[0] = IRQ_SIM_COMMON;  // Slammed SIM IRQ
            *pCount = 1;
            rc = TRUE;
            break;
            
        case CSP_BASE_REG_PA_RNGA:
            pIrqs[0] = IRQ_RNGA;
            *pCount = 1;
            rc = TRUE;
            break;
            
        case CSP_BASE_REG_PA_EVTMON:
            pIrqs[0] = IRQ_EVTMON;
            *pCount = 1;
            rc = TRUE;
            break;
            
        case CSP_BASE_REG_PA_KPP:
            pIrqs[0] = IRQ_KPP;
            *pCount = 1;
            rc = TRUE;
            break;
            
        case CSP_BASE_REG_PA_RTC:
            pIrqs[0] = IRQ_RTC;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_PWM:
            pIrqs[0] = IRQ_PWM;
            *pCount = 1;
            rc = TRUE;
            break;

        case CSP_BASE_REG_PA_EPIT2:
            pIrqs[0] = IRQ_EPIT2;
            *pCount = 1;
            rc = TRUE;
            break;

⌨️ 快捷键说明

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