📄 intr.c
字号:
//
// 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.
//
//------------------------------------------------------------------------------
//
// File: intr.h
//
// This file contains MainstoneII board specific interrupt code.
//
#include <bsp.h>
#include <intr_fpga.h>
#include <RTConfig.h>
static UINT32 FPGAInterruptHandler(UINT32 ra);
static void EnableGPIO1Irq(void);
static void DisableGPIO1Irq(void);
static void ClearGPIO1Irq(void);
static volatile MAINSTONEII_BLR_REGS *g_pBLRegs = NULL;
static volatile BULVERDE_GPIO_REG *g_pGPIORegs = NULL;
#if USE_RESET_PIN_AS_PENDOWN
#define IRQ_GPIOXX_2_RESET_TO_PENDOWN IRQ_GPIO0_PENIRQ
static UINT32 GPIOXX_2_InterruptHandler(UINT32 irq);
#endif
//------------------------------------------------------------------------------
//
// Function: BSPIntrInit
//
BOOL BSPIntrInit()
{
volatile BULVERDE_INTR_REG *pIntrRegs = NULL;
OALMSG(OAL_INTR&&OAL_FUNC, (L"+BSPIntrInit\r\n"));
pIntrRegs = (volatile BULVERDE_INTR_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_INTC, FALSE);
g_pBLRegs = (volatile MAINSTONEII_BLR_REGS *) OALPAtoVA(MAINSTONEII_BASE_REG_PA_FPGA, FALSE);
g_pGPIORegs = (volatile BULVERDE_GPIO_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_GPIO, FALSE);
// Mask and clear all FPGA interrupts.
//
g_pBLRegs->int_msk_en = 0;
g_pBLRegs->int_set_clr = 0;
// Enable USB Cable detection interrupts
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, FPGA_INT_BIT(IRQ_GPIO0_USBCD));
// Enable GPIO 0 for falling edge (Active Low) to signal the FPGA interrupts.
//
SETREG32((PULONG)&g_pGPIORegs->GFER0, XLLP_GPIO_BIT_0);
SETREG32((PULONG)&pIntrRegs->icmr, (1 << IRQ_GPIO0));
#if USE_RESET_PIN_AS_PENDOWN
SETREG32((PULONG)&pIntrRegs->icmr, (1 << IRQ_GPIOXX_2));
#endif
// Set up static interrupt mappings
OALIntrStaticTranslate(SYSINTR_OHCI, IRQ_USBOHCI);
#if USE_RESET_PIN_AS_PENDOWN
OALIntrStaticTranslate(SYSINTR_TOUCH,IRQ_GPIOXX_2_RESET_TO_PENDOWN);
#else
OALIntrStaticTranslate(SYSINTR_TOUCH, IRQ_GPIO0_UCB1400);
#endif
OALIntrStaticTranslate(SYSINTR_TOUCH_CHANGED, IRQ_OSMR1);
OALIntrStaticTranslate(SYSINTR_KEYPAD, IRQ_KEYPAD);
OALIntrStaticTranslate(SYSINTR_FFUART, IRQ_FFUART);
OALIntrStaticTranslate(SYSINTR_BFUART, IRQ_BTUART);
OALIntrStaticTranslate(SYSINTR_SFUART, IRQ_STUART);
OALIntrStaticTranslate(SYSINTR_PCCARD_CSC_S0, IRQ_GPIO0_PCMCIA_S0_CSC);
OALIntrStaticTranslate(SYSINTR_PCCARD_CD_S0, IRQ_GPIO0_PCMCIA_S0_CD);
OALIntrStaticTranslate(SYSINTR_PCCARD_CSC_S1, IRQ_GPIO0_PCMCIA_S1_CSC);
OALIntrStaticTranslate(SYSINTR_PCCARD_CD_S1, IRQ_GPIO0_PCMCIA_S1_CD);
OALIntrStaticTranslate(SYSINTR_AUDIO, IRQ_DMAC);
OALIntrStaticTranslate(SYSINTR_USBFN, IRQ_USBFN);
OALIntrStaticTranslate(SYSINTR_PWRBTN, IRQ_GPIO1);
OALMSG(OAL_INTR&&OAL_FUNC, (L"-BSPIntrInit\r\n"));
return TRUE;
}
//------------------------------------------------------------------------------
BOOL BSPIntrRequestIrqs(DEVICE_LOCATION *pDevLoc, UINT32 *pCount, UINT32 *pIrqs)
{
BOOL rc = FALSE;
OALMSG(OAL_INTR&&OAL_FUNC, (
L"+BSPIntrRequestIrq(0x%08x->%d/%d/0x%08x/%d, 0x%08x, 0x%08x)\r\n",
pDevLoc, pDevLoc->IfcType, pDevLoc->BusNumber, pDevLoc->LogicalLoc,
pDevLoc->Pin, pCount, pIrqs
));
// Check for input params
if (pIrqs == NULL || pCount == NULL || *pCount < 1) goto Done;
switch (pDevLoc->IfcType) {
case Internal:
switch ((ULONG)pDevLoc->LogicalLoc) {
case (MAINSTONEII_BASE_REG_PA_SMSC_ETHERNET + 0x300):
pIrqs[0] = IRQ_GPIO0_ETHERNET;
*pCount = 1;
rc = TRUE;
break;
}
break;
}
Done:
OALMSG(OAL_INTR&&OAL_FUNC, (L"-BSPIntrRequestIrq(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: BSPIntrEnableIrq
//
// This function is called from OALIntrEnableIrq to enable interrupt on
// secondary interrupt controller.
//
UINT32 BSPIntrEnableIrq(UINT32 irq)
{
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+BSPIntrEnableIrq(%d)\r\n", irq));
// Valid board-level interrupt?
if (g_pBLRegs && (irq >= IRQ_MAINSTONEII_GPIO0_MIN) && (irq <= IRQ_MAINSTONEII_GPIO0_MAX))
{
UINT32 TempVal = (INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS);
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, (TempVal | FPGA_INT_BIT(irq)));
// Enabling the interrupt at the FPGA controller is enough - no need to enable the Bulverde GPIO0 interrupt.
irq = OAL_INTR_IRQ_UNDEFINED;
}
else if(irq == IRQ_GPIO1)
{
EnableGPIO1Irq();
}
#if USE_RESET_PIN_AS_PENDOWN
if ( g_pGPIORegs && ( IRQ_GPIOXX_2_RESET_TO_PENDOWN == irq ) )
{
g_pGPIORegs->GRER3 |= (XLLP_GPIO_BIT_AC97_RESET_n);
}
#endif
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-BSPIntrEnableIrq(irq = %d)\r\n", irq));
return irq;
}
//------------------------------------------------------------------------------
//
// Function: BSPIntrDisableIrq
//
// This function is called from OALIntrDisableIrq to disable interrupt on
// secondary interrupt controller.
//
UINT32 BSPIntrDisableIrq(UINT32 irq)
{
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+BSPIntrDisableIrq(%d)\r\n", irq));
// Valid board-level interrupt?
if (g_pBLRegs && (irq >= IRQ_MAINSTONEII_GPIO0_MIN) && (irq <= IRQ_MAINSTONEII_GPIO0_MAX))
{
UINT32 TempVal = (INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS);
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, (TempVal & ~FPGA_INT_BIT(irq)));
// Masking the interrupt at the FPGA controller is enough - no need to mask the Bulverde GPIO0 interrupt.
irq = OAL_INTR_IRQ_UNDEFINED;
}
else if(irq == IRQ_GPIO1)
{
DisableGPIO1Irq();
}
#if USE_RESET_PIN_AS_PENDOWN
if ( g_pGPIORegs && ( IRQ_GPIOXX_2_RESET_TO_PENDOWN == irq ) )
{
g_pGPIORegs->GRER3 &= ~(XLLP_GPIO_BIT_AC97_RESET_n);
}
#endif
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-BSPIntrDisableIrq(irq = %d\r\n", irq));
return irq;
}
//------------------------------------------------------------------------------
//
// Function: BSPIntrDoneIrq
//
// This function is called from OALIntrDoneIrq to finish interrupt on
// secondary interrupt controller.
//
UINT32 BSPIntrDoneIrq(UINT32 irq)
{
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+BSPIntrDoneIrq(%d)\r\n", irq));
// Valid board-level interrupt?
if (g_pBLRegs && (irq >= IRQ_MAINSTONEII_GPIO0_MIN) && (irq <= IRQ_MAINSTONEII_GPIO0_MAX))
{
UINT32 TempVal;
TempVal = INREG32((PULONG)&g_pBLRegs->int_set_clr) & ~INTSETCLR_RESERVED_BITS;
OUTREG32((PULONG)&g_pBLRegs->int_set_clr, (TempVal & ~FPGA_INT_BIT(irq)));
TempVal = (INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS);
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, (TempVal | FPGA_INT_BIT(irq)));
// Masking the interrupt at the FPGA controller is enough - no need to mask the Bulverde GPIO0 interrupt.
irq = OAL_INTR_IRQ_UNDEFINED;
}
#if USE_RESET_PIN_AS_PENDOWN
if ( g_pGPIORegs && ( IRQ_GPIOXX_2_RESET_TO_PENDOWN == irq ) )
{
g_pGPIORegs->GRER3 |= (XLLP_GPIO_BIT_AC97_RESET_n);
}
#endif
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-BSPIntrDoneIrq(irq = %d)\r\n", irq));
return irq;
}
//------------------------------------------------------------------------------
//
// Function: BSPIntrActiveIrq
//
// This function is called from interrupt handler to give BSP chance to
// translate IRQ in case of secondary interrupt controller.
//
UINT32 BSPIntrActiveIrq(UINT32 irq)
{
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+BSPIntrActiveIrq(%d)\r\n", irq));
switch(irq)
{
case IRQ_GPIO0:
irq = FPGAInterruptHandler(irq);
break;
case IRQ_GPIO1:
ClearGPIO1Irq();
break;
case IRQ_GPIOXX_2:
#if USE_RESET_PIN_AS_PENDOWN
irq = GPIOXX_2_InterruptHandler(irq);
break;
#endif
default:
break;
}
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-BSPIntrActiveIrq(%d)\r\n", irq));
return irq;
}
//------------------------------------------------------------------------------
//
// Function: FPGAInterruptHandler
//
// This function is called from the BSP ISR to handle an FPGA interrupt.
//
static UINT32 FPGAInterruptHandler(UINT32 irq)
{
UINT8 nInt;
UINT32 TempVal;
// Read the pending FPGA interrupts and ignore masked/reserved interrupts.
TempVal = INREG32((PULONG)&g_pBLRegs->int_set_clr);
TempVal &= (INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS);
// Scan through the pending interrupts and look for a match.
for (nInt = IRQ_MAINSTONEII_GPIO0_MIN ; nInt <= IRQ_MAINSTONEII_GPIO0_MAX ; nInt++)
{
if (TempVal & FPGA_INT_BIT(nInt))
{
// Mask and clear the interrupt (note that we must write 0's to the reserved bits).
// Interrupt acknowledge occurs in the SMC ISR routine
TempVal = INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS;
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, (TempVal & ~FPGA_INT_BIT(nInt)));
TempVal = INREG32((PULONG)&g_pBLRegs->int_set_clr) & ~INTSETCLR_RESERVED_BITS;
OUTREG32((PULONG)&g_pBLRegs->int_set_clr, (TempVal & ~FPGA_INT_BIT(nInt)));
break;
}
}
// If we see the PCCARD client IRQ asserted, look to see if the card is present in the
// slot. The MainstoneII PCCARD FPGA implementation is asserting the client IRQ upon
// card removal which can cause problems down the line when we try to read from the card.
//
if (nInt == IRQ_GPIO0_PCMCIA_S0)
{
if (g_pBLRegs->pcmcia0_srcr & PCMCIA_S0_nCD_MASK) nInt = IRQ_GPIO0;
}
if (nInt == IRQ_GPIO0_PCMCIA_S1)
{
if (g_pBLRegs->pcmcia1_srcr & PCMCIA_S1_nCD_MASK) nInt = IRQ_GPIO0;
}
// *** The following is to work around a problem in the MainstoneII FPGA ***
//
// Bulverde requires a minimum GPIO0 deassertion period before the GPIO0
// signal can be reasserted. Failure to comply can lead to problems with
// GPIO0 interrupt detection. As well, because the FPGA interrupt masking
// operation is a non-atomic read-modify-write operation, it's possible
// that an async FPGA interrupt can assert during that sequence which
// in turn violates Bulverde's GPIO0 timing requirements.
//
// 1. First, we'll save off the current interrupt mask (it will be later restored).
TempVal = (INREG32((PULONG)&g_pBLRegs->int_msk_en) & ~INTMSK_RESERVED_BITS);
// 2. Disable all FPGA interrupts (disable FPGA GPIO0 assertion to Bulverde).
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, 0);
// 3. Clear the Bulverde GPIO0 falling edge detection.
OUTREG32((PULONG)&g_pGPIORegs->GEDR0, XLLP_GPIO_BIT_0);
// 4. Wait...
OALStall(1);
// 5. Restore the FPGA mask (this will cause any pending interrupts to assert
// to the Bulverde).
OUTREG32((PULONG)&g_pBLRegs->int_msk_en, TempVal);
return((nInt <= IRQ_MAINSTONEII_GPIO0_MAX) ? nInt : irq);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// Function: Enables the GPIO1 Irq by setting the corresponding GFERx and GRERx bits
//
static void EnableGPIO1Irq(void)
{
SETREG32((PULONG)&g_pGPIORegs->GFER0, XLLP_GPIO_BIT_1);
SETREG32((PULONG)&g_pGPIORegs->GRER0, XLLP_GPIO_BIT_1);
}
//------------------------------------------------------------------------------
//
// Function: disables the GPIO1 Irq by clearing the corresponding GFERx and GRERx bits
//
static void DisableGPIO1Irq(void)
{
CLRREG32((PULONG)&g_pGPIORegs->GFER0, XLLP_GPIO_BIT_1);
CLRREG32((PULONG)&g_pGPIORegs->GRER0, XLLP_GPIO_BIT_1);
}
//------------------------------------------------------------------------------
//
// Function: clears the GPIO1 Irq by clearing the GEDRx bit
//
static void ClearGPIO1Irq(void)
{
g_pGPIORegs->GEDR0 = XLLP_GPIO_BIT_1;
}
#if USE_RESET_PIN_AS_PENDOWN
static UINT32 GPIOXX_2_InterruptHandler(UINT32 irq)
{
UINT32 retval = 0;
volatile BULVERDE_INTR_REG *pIntrRegs = NULL;
pIntrRegs = (volatile BULVERDE_INTR_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_INTC, FALSE);
g_pGPIORegs = (volatile BULVERDE_GPIO_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_GPIO, FALSE);
// Disable GPIOXX_2 interrupts
pIntrRegs->icmr &= ~XLLP_INTC_GPIOXX_2;
// Check have pendown status of the reset-to-pendown pin
if ( g_pGPIORegs->GEDR3 & (XLLP_GPIO_BIT_AC97_RESET_n))
{
//Clear the edge detect status of the reset-to-pendown pin.
g_pGPIORegs->GEDR3 |=(XLLP_GPIO_BIT_AC97_RESET_n);
// Disable the Rising-Edge detect of the reset-to-pendown pin
g_pGPIORegs->GRER3 &= ~(XLLP_GPIO_BIT_AC97_RESET_n);
//return pendown IRQ
retval = IRQ_GPIOXX_2_RESET_TO_PENDOWN;
}
// Enable GPIOXX_2 interrupts.
pIntrRegs->icmr |= XLLP_INTC_GPIOXX_2;
//RETAILMSG (1, (TEXT("GPIOXX_2_InterruptHandler,retval=%d\r\n"),retval));
return(retval);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -