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 + -
显示快捷键?