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

📄 intr.c

📁 三星2440原版bsp
💻 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.
//
//------------------------------------------------------------------------------
//
//  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 <s3c2440x.h>
#include <s3c2440x_intr.h>
#include <intr.h>
#ifdef DVS_EN
#include <bsp_cfg.h>
#endif
 

//------------------------------------------------------------------------------
//
//  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 S3C2440X_INTR_REG *g_pIntrRegs; 
static S3C2440X_IOPORT_REG *g_pPortRegs;
#ifdef DVS_EN
static S3C2440X_LCD_REG	*g_pLCDRegs;
#endif

extern volatile BOOL b_oalInterruptFlag;
#ifdef DVS_EN
	BOOL	VSYNCINTR;
	BOOL	CurrStateIdle;
	extern volatile BOOL IDLEflag;
	extern DWORD dwCurrentidle;

	volatile int CurrentState = Active;

	extern DWORD dwPrevTotalTick1000;
	extern DWORD dwPrevTotalTick100;

	extern DWORD dwPrevIdleTick1000;
	extern DWORD dwPrevIdleTick100;

	extern DWORD dwPercentIdle1000;
	extern DWORD dwPercentIdle100;

	extern void DVS_ON(void);
	extern void DVS_OFF(void);
	extern void ChangeVoltage(int);
	extern int GetCurrentVoltage(void);
	extern void CLKDIV124();
	extern void CLKDIV144();
	extern void CLKDIV136();
	extern void CLKDIV166();
	extern void CLKDIV148();
	extern void CLKDIV188();
#endif
//  Function pointer to profiling timer ISR routine.
//
PFN_PROFILER_ISR g_pProfilerISR = NULL;
 

//------------------------------------------------------------------------------
//
//  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") );

    // Initialize interrupt mapping
    OALIntrMapInit();

    // First get uncached virtual addresses
    g_pIntrRegs = (S3C2440X_INTR_REG*)OALPAtoVA(
        S3C2440X_BASE_REG_PA_INTR, FALSE
    );
    g_pPortRegs = (S3C2440X_IOPORT_REG*)OALPAtoVA(
        S3C2440X_BASE_REG_PA_IOPORT, FALSE
    );

#ifdef DVS_EN    
    g_pLCDRegs = (S3C2440X_LCD_REG *)OALPAtoVA(
    S3C2440X_BASE_REG_PA_LCD, FALSE
    );
#endif    
    
    // Mask and clear external interrupts
    OUTREG32(&g_pPortRegs->EINTMASK, 0xFFFFFFFF);
    OUTREG32(&g_pPortRegs->EINTPEND, 0xFFFFFFFF);

    // Mask and clear internal interrupts
    OUTREG32(&g_pIntrRegs->INTMSK, 0xFFFFFFFF);
    OUTREG32(&g_pIntrRegs->SRCPND, 0xFFFFFFFF);

    // S3C2440X developer notice (page 4) warns against writing a 1 to any
    // 0 bit field in the INTPND register.  Instead we'll write the INTPND
    // value itself.
    OUTREG32(&g_pIntrRegs->INTPND, INREG32(&g_pIntrRegs->INTPND));

    // Unmask the system tick timer interrupt
    CLRREG32(&g_pIntrRegs->INTMSK, 1 << IRQ_TIMER4);

#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;

    RETAILMSG(1, (
        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 rc = TRUE;
    UINT32 i, mask, irq;

    RETAILMSG(0, (
        L"+OALIntrEnableIrqs(%d, 0x%08x[%d])\r\n", count, pIrqs, *pIrqs
    ));

    for (i = 0; i < count; i++) {
#ifndef OAL_BSP_CALLBACKS
        irq = pIrqs[i];
#else
        // Give BSP chance to enable irq on subordinate interrupt controller
        irq = BSPIntrEnableIrq(pIrqs[i]);
#endif
        if (irq == OAL_INTR_IRQ_UNDEFINED) continue;
        // Depending on IRQ number use internal or external mask register
        if (irq <= IRQ_ADC) {
            // Use interrupt mask register
            CLRREG32(&g_pIntrRegs->INTMSK, 1 << irq);
        } else if (irq <= IRQ_EINT7) {
            // Use external mask register
            CLRREG32(&g_pIntrRegs->INTMSK, 1 << IRQ_EINT4_7);
            CLRREG32(&g_pPortRegs->EINTMASK, 1 << (irq - IRQ_EINT4 + 4));
        } else if (irq <= IRQ_EINT23) {
            // Use external mask register
            mask = 1 << (irq - IRQ_EINT4 + 4);
            OUTREG32(&g_pPortRegs->EINTPEND, mask);
            CLRREG32(&g_pPortRegs->EINTMASK, mask);
            mask = 1 << IRQ_EINT8_23;
            if ((INREG32(&g_pIntrRegs->INTPND) & mask) != 0) {
                OUTREG32(&g_pIntrRegs->INTPND, mask);
            }
            CLRREG32( &g_pIntrRegs->INTMSK, 1 << IRQ_EINT8_23);
        } else {
            rc = FALSE;
        }
    }        

    RETAILMSG(FALSE, (L"-OALIntrEnableIrqs(rc = %d)\r\n", rc));
    return rc;    
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrDisableIrqs
//
VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 i, mask, irq;

    RETAILMSG(1, (
        L"+OALIntrDisableIrqs(%d, 0x%08x[%d])\r\n", count, pIrqs, *pIrqs
    ));

    for (i = 0; i < count; i++) {
#ifndef OAL_BSP_CALLBACKS
        irq = pIrqs[i];
#else
        // Give BSP chance to disable irq on subordinate interrupt controller
        irq = BSPIntrDisableIrq(pIrqs[i]);
        if (irq == OAL_INTR_IRQ_UNDEFINED) continue;
#endif
        // Depending on IRQ number use internal or external mask register
        if (irq <= IRQ_ADC) {
            // Use interrupt mask register
            mask = 1 << irq;
            SETREG32(&g_pIntrRegs->INTMSK, mask);
        } else if (irq <= IRQ_EINT23) {
            // Use external mask register
            mask = 1 << (irq - IRQ_EINT4 + 4);
            SETREG32(&g_pPortRegs->EINTMASK, mask);
        }
    }

    RETAILMSG(1, (L"-OALIntrDisableIrqs\r\n"));
}


//------------------------------------------------------------------------------
//
//  Function:  OALIntrDoneIrqs
//
VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 i, mask, irq;
    S3C2440X_INTR_REG *pIntr = (S3C2440X_INTR_REG*)OALPAtoVA(S3C2440X_BASE_REG_PA_INTR, FALSE);

//	RETAILMSG(1, (TEXT("\r\n\r\n")));
//	RETAILMSG(1, (TEXT("pIntr->INTMOD = 0x%x \r\n"), pIntr->INTMOD));
//	RETAILMSG(1, (TEXT("pIntr->INTMSK = 0x%x \r\n"), pIntr->INTMSK));
//	RETAILMSG(1, (TEXT("pIntr->INTSUBMSK = 0x%x \r\n"), pIntr->INTSUBMSK));

//	RETAILMSG(1, (
//		L"+OALIntrDoneIrqs(%d, 0x%08x[%d])\r\n", count, pIrqs, *pIrqs
//	));

    for (i = 0; i < count; i++) {
#ifndef OAL_BSP_CALLBACKS
        irq = pIrqs[i];
#else
        // Give BSP chance to finish irq on subordinate interrupt controller
        irq = BSPIntrDoneIrq(pIrqs[i]);
#endif    
        // Depending on IRQ number use internal or external mask register
        if (irq <= IRQ_ADC) {
            // Use interrupt mask register
            mask = 1 << irq;
            OUTREG32(&g_pIntrRegs->SRCPND, mask);
            CLRREG32(&g_pIntrRegs->INTMSK, mask);
        } else if (irq <= IRQ_EINT23) {
            // Use external mask register
            mask = 1 << (irq - IRQ_EINT4 + 4);
            OUTREG32(&g_pPortRegs->EINTPEND, mask);
            CLRREG32(&g_pPortRegs->EINTMASK, mask);
        }    
    }

//	RETAILMSG(1, (L"-OALIntrDoneIrqs\r\n"));
}


//------------------------------------------------------------------------------
//
//  Function:  OEMInterruptHandler
//
ULONG OEMInterruptHandler(ULONG ra)
{
    UINT32 sysIntr = SYSINTR_NOP;
    UINT32 irq, irq2, mask;
#ifdef DVS_EN
#if (DVS_METHOD == 1 || DVS_METHOD == 3)
    unsigned int clkval_calc;
	unsigned int i;
#endif //(DVS_METHOD == 1 || DVS_METHOD == 3)
#endif //DVS_EN
    
	static DWORD HeartBeatCnt, HeartBeatStat;  //LED4 is used for heart beat
	
	b_oalInterruptFlag = TRUE;

    // for forbidding to miss interrupt by noise
	while(!((1<<INREG32(&g_pIntrRegs->INTOFFSET))&INREG32(&g_pIntrRegs->INTPND)))
		INREG32(&g_pIntrRegs->INTOFFSET);
    // Get pending interrupt(s)
    irq = INREG32(&g_pIntrRegs->INTOFFSET);
    
#if 0
     if(irq == IRQ_SDI)
    RETAILMSG(1,(TEXT("IRQ_SDI interrupt is occured!!\r\n")));
    if(irq == IRQ_DMA0)
    RETAILMSG(1,(TEXT("IRQ_DMA0 interrupt is occured!!\r\n")));


    if(irq == IRQ_USBD)
    RETAILMSG(1,(TEXT("IRQ_USBD interrupt is occured!!\r\n")));
    if(irq == IRQ_USBH)    
    RETAILMSG(1,(TEXT("IRQ_USBH interrupt is occured!!\r\n")));   
#endif
	if(irq == IRQ_RTC)
    RETAILMSG(1,(TEXT("IRQ_RTC ALARM interrupt is occured!!\r\n")));
    
#ifdef DVS_EN
#if (DVS_METHOD == 2)
	if ( GetCurrentVoltage() != HIGHVOLTAGE )
	{
		ChangeVoltage(HIGHVOLTAGE);
		for(i=0;i<VOLTAGEDELAY;i++)
		{
			INREG32(&g_pPortRegs->GPFDAT);  // for loop operation, just read.
		}
		DVS_OFF();
	}
#elif (DVS_METHOD == 3)
	if ( CurrentState == Active )
	{
		if( irq != IRQ_LCD )
		{
			if ( GetCurrentVoltage() != HIGHVOLTAGE )
			{
				ChangeVoltage(HIGHVOLTAGE);
				for(i=0;i<VOLTAGEDELAY;i++)
				{
					INREG32(&g_pPortRegs->GPFDAT);  // for loop operation, just read.
				}
				DVS_OFF();
			}
		}

	}
#endif //(DVS_METHOD == 3)

#endif //DEV_EN

    // System timer interrupt?
    if (irq == IRQ_TIMER4) {

		if (++HeartBeatCnt > 100)
			{
				HeartBeatCnt   = 0;
				HeartBeatStat ^= 1;

				if (HeartBeatStat)                        
					g_pPortRegs->GPFDAT &= ~(1 << 4); // LED 4 On

⌨️ 快捷键说明

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