📄 intr.c
字号:
//------------------------------------------------------------------------------
//
// 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 + -