intr.c
来自「SAMSUNG S3C6410 CPU BSP for winmobile6」· C语言 代码 · 共 934 行 · 第 1/2 页
C
934 行
//
// 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.
//
//------------------------------------------------------------------------------
//
// File: interrupt.c
//
// This file implement major part of interrupt module for S3C3210X SoC.
//
#include <windows.h>
#include <ceddk.h>
#include <Nkintr.h>
#include <oal.h>
#include <bsp_cfg.h>
#include <s3c6410.h>
#include <intr.h>
#define VIC_MASK
static const UINT32 g_VirIrq2PhyIrq[IRQ_MAX_S3C6410] =
{
PHYIRQ_EINT0, // 0 // 0
PHYIRQ_EINT0, // 1 // 0
PHYIRQ_EINT0, // 2 // 0
PHYIRQ_EINT0, // 3 // 0
PHYIRQ_EINT1, // 4 // 1
PHYIRQ_EINT1, // 5 // 1
PHYIRQ_EINT1, // 6 // 1
PHYIRQ_EINT1, // 7 // 1
PHYIRQ_EINT1, // 8 // 1
PHYIRQ_EINT1, // 9 // 1
PHYIRQ_EINT1, // 10 // 1
PHYIRQ_EINT1, // 11 // 1
PHYIRQ_RTC_TIC, // 12 // 2
PHYIRQ_CAMIF_C, // 13 // 3
PHYIRQ_CAMIF_P, // 14 // 4
#if (CPU_NAME == S3C6410)
PHYIRQ_I2C1, // 15 // 5
PHYIRQ_I2S_V40, // 16 // 6
PHYIRQ_GPS, // 17 // 7
PHYIRQ_3D, // 18 // 8
#elif (CPU_NAME == S3C6400)
PHYIRQ_CAMIF_MC, // 15 // 5
PHYIRQ_CAMIF_MP, // 16 // 6
PHYIRQ_CAMIF_WE_C, // 17 // 7
PHYIRQ_CAMIF_WE_P, // 18 // 8
#endif
PHYIRQ_POST , // 19 // 9
PHYIRQ_ROTATOR, // 20 // 10
PHYIRQ_2D, // 21 // 11
PHYIRQ_TVENC, // 22 // 12
PHYIRQ_TVSCALER, // 23 // 13
PHYIRQ_BATF, // 24 // 14
PHYIRQ_JPEG, // 25 // 15
PHYIRQ_MFC, // 26 // 16
PHYIRQ_SDMA0, // 27 // 17
PHYIRQ_SDMA1, // 28 // 18
PHYIRQ_ARM_DMAERR, // 29 // 19
PHYIRQ_ARM_DMA, // 30 // 20
PHYIRQ_ARM_DMAS, // 31 // 21
PHYIRQ_KEYPAD, // 32 // 22
PHYIRQ_TIMER0, // 33 // 23
PHYIRQ_TIMER1, // 34 // 24
PHYIRQ_TIMER2, // 35 // 25
PHYIRQ_WDT, // 36 // 26
PHYIRQ_TIMER3, // 37 // 27
PHYIRQ_TIMER4, // 38 // 28
PHYIRQ_LCD0_FIFO, // 39 // 29
PHYIRQ_LCD1_FRAME, // 40 // 30
PHYIRQ_LCD2_SYSIF, // 41 // 31
PHYIRQ_EINT2, // 42 // 32
PHYIRQ_EINT2, // 43 // 32
PHYIRQ_EINT2, // 44 // 32
PHYIRQ_EINT2, // 45 // 32
PHYIRQ_EINT2, // 46 // 32
PHYIRQ_EINT2, // 47 // 32
PHYIRQ_EINT2, // 48 // 32
PHYIRQ_EINT2, // 49 // 32
PHYIRQ_EINT3, // 50 // 33
PHYIRQ_EINT3, // 51 // 33
PHYIRQ_EINT3, // 52 // 33
PHYIRQ_EINT3, // 53 // 33
PHYIRQ_EINT3, // 54 // 33
PHYIRQ_EINT3, // 55 // 33
PHYIRQ_EINT3, // 56 // 33
PHYIRQ_EINT3, // 57 // 33
PHYIRQ_PCM0 , // 58 // 34
PHYIRQ_PCM1 , // 59 // 35
PHYIRQ_AC97, // 60 // 36
PHYIRQ_UART0, // 61 // 37
PHYIRQ_UART1, // 62 // 38
PHYIRQ_UART2, // 63 // 39
PHYIRQ_UART3, // 64 // 40
PHYIRQ_DMA0, // 65 // 41
PHYIRQ_DMA0, // 66 // 41
PHYIRQ_DMA0, // 67 // 41
PHYIRQ_DMA0, // 68 // 41
PHYIRQ_DMA0, // 69 // 41
PHYIRQ_DMA0, // 70 // 41
PHYIRQ_DMA0, // 71 // 41
PHYIRQ_DMA0, // 72 // 41
PHYIRQ_DMA1, // 73 // 42
PHYIRQ_DMA1, // 74 // 42
PHYIRQ_DMA1, // 75 // 42
PHYIRQ_DMA1, // 76 // 42
PHYIRQ_DMA1, // 77 // 42
PHYIRQ_DMA1, // 78 // 42
PHYIRQ_DMA1, // 79 // 42
PHYIRQ_DMA1, // 80 // 42
PHYIRQ_ONENAND0, // 81 // 43
PHYIRQ_ONENAND1, // 82 // 44
PHYIRQ_NFC, // 83 // 45
PHYIRQ_CFC, // 84 // 46
PHYIRQ_UHOST, // 85 // 47
PHYIRQ_SPI0, // 86 // 48
PHYIRQ_SPI1, // 87 // 49
PHYIRQ_I2C, // 88 // 50
PHYIRQ_HSITX, // 89 // 51
PHYIRQ_HSIRX, // 90 // 52
PHYIRQ_RESERVED, // 91 // 53
PHYIRQ_MSM, // 92 // 54
PHYIRQ_HOSTIF, // 93 // 55
PHYIRQ_HSMMC0, // 94 // 56
PHYIRQ_HSMMC1, // 95 // 57
PHYIRQ_OTG, // 96 // 58
PHYIRQ_IRDA, // 97 // 59
PHYIRQ_RTC_ALARM, // 98 // 60
PHYIRQ_SEC, // 99 // 61
PHYIRQ_PENDN, // 100 // 62
PHYIRQ_ADC // 101 // 63
};
static const UINT32 g_PhyIrq2VirIrq[PHYIRQ_MAX_S3C6410] =
{
// VIC0
IRQ_EINT0, // 0 (IRQ_EINT0~IRQ_EINT3)
IRQ_EINT4, // 1 (IRQ_EINT4~IRQ_EINT11)
IRQ_RTC_TIC, // 2
IRQ_CAMIF_C, // 3
IRQ_CAMIF_P, // 4
#if (CPU_NAME == S3C6410)
IRQ_I2C1, // 5
IRQ_I2S_V40, // 6
IRQ_GPS, // 7
IRQ_3D, // 8
#elif (CPU_NAME == S3C6400)
IRQ_CAMIF_MC, // 5
IRQ_CAMIF_MP, // 6
IRQ_CAMIF_WE_C, // 7
IRQ_CAMIF_WE_P, // 8
#endif
IRQ_POST, // 9
IRQ_ROTATOR, // 10
IRQ_2D, // 11
IRQ_TVENC, // 12
IRQ_TVSCALER, // 13
IRQ_BATF, // 14
IRQ_JPEG, // 15
IRQ_MFC, // 16
IRQ_SDMA0, // 17
IRQ_SDMA1, // 18
IRQ_ARM_DMAERR, // 19
IRQ_ARM_DMA, // 20
IRQ_ARM_DMAS, // 21
IRQ_KEYPAD, // 22
IRQ_TIMER0, // 23
IRQ_TIMER1, // 24
IRQ_TIMER2, // 25
IRQ_WDT, // 26
IRQ_TIMER3, // 27
IRQ_TIMER4, // 28
IRQ_LCD0_FIFO, // 29
IRQ_LCD1_FRAME, // 30
IRQ_LCD2_SYSIF, // 31
// VIC1
IRQ_EINT12, // 32 (IRQ_EINT12~IRQ_EINT19)
IRQ_EINT20, // 33 (IRQ_EINT20~IRQ_EINT27)
IRQ_PCM0, // 34
IRQ_PCM1, // 35
IRQ_AC97, // 36
IRQ_UART0, // 37
IRQ_UART1, // 38
IRQ_UART2, // 39
IRQ_UART3, // 40
IRQ_DMA0_CH0, // 41 (IRQ_DMA0_CH0~IRQ_DMA0_CH7)
IRQ_DMA1_CH0, // 42 (IRQ_DMA1_CH0~IRQ_DMA1_CH7)
IRQ_ONENAND0, // 43
IRQ_ONENAND1, // 44
IRQ_NFC, // 45
IRQ_CFC, // 46
IRQ_UHOST, // 47
IRQ_SPI0, // 48
IRQ_SPI1, // 49
IRQ_I2C, // 50
IRQ_HSITX, // 51
IRQ_HSIRX, // 52
IRQ_RESERVED, // 53
IRQ_MSM , // 54
IRQ_HOSTIF, // 55
IRQ_HSMMC0, // 56
IRQ_HSMMC1, // 57
IRQ_OTG , // 58
IRQ_IRDA, // 59
IRQ_RTC_ALARM, // 60
IRQ_SEC, // 61
IRQ_PENDN, // 62
IRQ_ADC // 63
};
//------------------------------------------------------------------------------
//
// Globals: g_pIntrRegs/g_pPortRegs
//
// The global variables are storing virual address for interrupt and port
// registers for use in interrupt handling to avoid possible time consumig
// call to OALPAtoVA function.
//
static volatile S3C6410_VIC_REG *g_pVIC0Reg;
static volatile S3C6410_VIC_REG *g_pVIC1Reg;
static volatile S3C6410_GPIO_REG *g_pGPIOReg;
static volatile S3C6410_DMAC_REG *g_pDMAC0Reg;
static volatile S3C6410_DMAC_REG *g_pDMAC1Reg;
// Function pointer to profiling timer ISR routine.
//
PFN_PROFILER_ISR g_pProfilerISR = NULL;
static void PrepareEINTIntr(void);
static void PrepareDMACIntr(void);
static void InitializeVIC(void);
void VICTableInit(void); // Reference by OEMPowerOff() in "Off.c"
extern volatile BOOL g_bOalInterruptFlag; // in "\common\timer\timer.c"
//------------------------------------------------------------------------------
//
// Function: OALIntrInit
//
// This function initialize interrupt mapping, hardware and call platform
// specific initialization.
//
BOOL OALIntrInit()
{
BOOL rc = FALSE;
OALMSG( OAL_FUNC&&OAL_INTR, (L"+OALInterruptInit\r\n") );
// First get uncached virtual addresses
g_pVIC0Reg = (S3C6410_VIC_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_VIC0, FALSE);
g_pVIC1Reg = (S3C6410_VIC_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_VIC1, FALSE);
g_pGPIOReg = (S3C6410_GPIO_REG*)OALPAtoVA(S3C6410_BASE_REG_PA_GPIO, FALSE);
g_pDMAC0Reg = (S3C6410_DMAC_REG*)OALPAtoVA(S3C6410_BASE_REG_PA_DMA0, FALSE);
g_pDMAC1Reg = (S3C6410_DMAC_REG*)OALPAtoVA(S3C6410_BASE_REG_PA_DMA1, FALSE);
// Initialize interrupt mapping
OALIntrMapInit();
PrepareEINTIntr();
PrepareDMACIntr();
// Initialize VIC
InitializeVIC();
#ifdef OAL_BSP_CALLBACKS
// Give BSP change to initialize subordinate controller
rc = BSPIntrInit();
#else
rc = TRUE;
#endif
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));
// This shouldn't happen
if (*pCount < 1) goto cleanUp;
#ifdef OAL_BSP_CALLBACKS
rc = BSPIntrRequestIrqs(pDevLoc, pCount, pIrqs);
#endif
cleanUp:
OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrRequestIrqs(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALIntrEnableIrqs
//
BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
{
BOOL bRet = TRUE;
UINT32 VirtualIRQ;
UINT32 PhysicalIRQ;
UINT32 i;
OALMSG(OAL_INTR&&OAL_FUNC, (L"+OALIntrEnableIrqs(%d, 0x%08x)\r\n", count, pIrqs));
for (i = 0; i < count; i++)
{
#ifndef OAL_BSP_CALLBACKS
VirtualIRQ = pIrqs[i];
#else
// Give BSP chance to enable irq on subordinate interrupt controller
VirtualIRQ = BSPIntrEnableIrq(pIrqs[i]);
#endif
if (VirtualIRQ == OAL_INTR_IRQ_UNDEFINED) continue;
// Translate to Physical IRQ
PhysicalIRQ = g_VirIrq2PhyIrq[VirtualIRQ];
if (PhysicalIRQ < VIC1_BIT_OFFSET)
{
g_pVIC0Reg->VICINTENABLE = (0x1<<PhysicalIRQ);
}
else if (PhysicalIRQ < PHYIRQ_MAX_S3C6410)
{
g_pVIC1Reg->VICINTENABLE = (0x1<<(PhysicalIRQ-VIC1_BIT_OFFSET));
}
else
{
bRet = FALSE;
}
}
OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrEnableIrqs(rc = %d)\r\n", bRet));
return bRet;
}
//------------------------------------------------------------------------------
//
// Function: OALIntrDisableIrqs
//
VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs)
{
UINT32 VirtualIRQ;
UINT32 PhysicalIRQ;
UINT32 i;
OALMSG(OAL_INTR&&OAL_FUNC, (L"+OALIntrDisableIrqs(%d, 0x%08x)\r\n", count, pIrqs));
for (i = 0; i < count; i++)
{
#ifndef OAL_BSP_CALLBACKS
VirtualIRQ = pIrqs[i];
#else
// Give BSP chance to disable irq on subordinate interrupt controller
VirtualIRQ = BSPIntrDisableIrq(pIrqs[i]);
#endif
if (VirtualIRQ == OAL_INTR_IRQ_UNDEFINED) continue;
// Translate to Physical IRQ
PhysicalIRQ = g_VirIrq2PhyIrq[VirtualIRQ];
if (PhysicalIRQ == PHYIRQ_EINT0)
{
// IRQ_EINT0 ~ IRQ_EINT3
g_pGPIOReg->EINT0MASK |= (1<<VirtualIRQ); // Mask Sub Interrupt
g_pGPIOReg->EINT0PEND |= (1<<VirtualIRQ); // Clear Sub Pending
// Do not Mask PHYIRQ_EINT0 Interrupt !!!
}
else if (PhysicalIRQ == PHYIRQ_EINT1)
{
// IRQ_EINT4 ~ IRQ_EINT11
g_pGPIOReg->EINT0MASK |= (1<<VirtualIRQ); // Mask Sub Interrupt
g_pGPIOReg->EINT0PEND |= (1<<VirtualIRQ); // Clear Sub Pending
// Do not Mask PHYIRQ_EINT1 Interrupt !!!
}
else if (PhysicalIRQ == PHYIRQ_EINT2)
{
// IRQ_EINT12 ~ IRQ_EINT19
g_pGPIOReg->EINT0MASK |= (1<<(VirtualIRQ-30)); // Mask Sub Interrupt
g_pGPIOReg->EINT0PEND |= (1<<(VirtualIRQ-30)); // Clear Sub Pending
// Do not Mask PHYIRQ_EINT2 Interrupt !!!
}
else if (PhysicalIRQ == PHYIRQ_EINT3)
{
// IRQ_EINT20 ~ IRQ_EINT27
g_pGPIOReg->EINT0MASK |= (1<<(VirtualIRQ-30)); // Mask Sub Interrupt
g_pGPIOReg->EINT0PEND |= (1<<(VirtualIRQ-30)); // Clear Sub Pending
// Do not Mask PHYIRQ_EINT3 Interrupt !!!
}
else if (PhysicalIRQ == PHYIRQ_DMA0)
{
// Do not Mask PHYIRQ_DMA0 Interrupt !!!
}
else if (PhysicalIRQ == PHYIRQ_DMA1)
{
// Do not Mask PHYIRQ_DMA1 Interrupt !!!
}
else if (PhysicalIRQ < VIC1_BIT_OFFSET)
{
g_pVIC0Reg->VICINTENCLEAR = (0x1<<PhysicalIRQ);
}
else if (PhysicalIRQ < PHYIRQ_MAX_S3C6410)
{
g_pVIC1Reg->VICINTENCLEAR = (0x1<<(PhysicalIRQ-VIC1_BIT_OFFSET));
}
}
OALMSG(OAL_INTR&&OAL_FUNC, (L"-OALIntrDisableIrqs\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: OALIntrDoneIrqs
//
VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
UINT32 VirtualIRQ;
UINT32 PhysicalIRQ;
UINT32 i;
OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALIntrDoneIrqs(%d, 0x%08x)\r\n", count, pIrqs));
for (i = 0; i < count; i++)
{
#ifndef OAL_BSP_CALLBACKS
VirtualIRQ = pIrqs[i];
#else
// Give BSP chance to finish irq on subordinate interrupt controller
VirtualIRQ = BSPIntrDoneIrq(pIrqs[i]);
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?