rt-thread/bsp/allwinner/libraries/sunxi-hal/hal/source/intc/intc.c

203 lines
6.0 KiB
C

/*
*********************************************************************************************************
* AR100 SYSTEM
* AR100 Software System Develop Kits
* interrupt module
*
* (c) Copyright 2012-2016, Sunny China
* All Rights Reserved
*
* File : intc.c
* By : Sunny
* Version : v1.0
* Date : 2012-5-3
* Descript: interrupt controller module.
* Update : date auther ver notes
* 2012-5-3 13:25:40 Sunny 1.0 Create this file.
*********************************************************************************************************
*/
#include "intc_i.h"
#include "platform-intc.h"
struct intc_regs *pintc_regs;
/*
*********************************************************************************************************
* INTERRUPT INIT
*
* Description: initialize interrupt.
*
* Arguments : none.
*
* Returns : OK if initialize succeeded, others if failed.
*
* Note :
*********************************************************************************************************
*/
s32 intc_init(void)
{
pintc_regs = (struct intc_regs *)(SUNXI_R_INTC_PBASE);
/*initialize interrupt controller */
pintc_regs->enable = 0x0;
pintc_regs->mask = 0x0;
pintc_regs->pending = 0xffffffff;
pintc_regs->enable1 = 0x0;
pintc_regs->mask1 = 0x0;
pintc_regs->pending1 = 0xffffffff;
pintc_regs->enable2 = 0x0;
pintc_regs->mask2 = 0x0;
pintc_regs->pending2 = 0xffffffff;
return OK;
}
/*
*********************************************************************************************************
* INTERRUPT EXIT
*
* Description: exit interrupt.
*
* Arguments : none.
*
* Returns : OK if exit succeeded, others if failed.
*
* Note :
*********************************************************************************************************
*/
s32 intc_exit(void)
{
pintc_regs = NULL;
return OK;
}
/*
*********************************************************************************************************
* ENABLE INTERRUPT
*
* Description: enable a specific interrupt.
*
* Arguments : intno : the source number of interrupt to which we want to enable.
*
* Returns : OK if enable interrupt succeeded, others if failed.
*
* Note :
*********************************************************************************************************
*/
s32 intc_enable_interrupt(u32 intno)
{
/*intno can't beyond then IRQ_SOURCE_MAX */
/* ASSERT(intno < IRQ_SOUCE_MAX); */
/*
* NMI interrupt should clear before enable.
* by sunny at 2012-6-12 19:30:22.
*/
if (intno == SUNXI_RINTC_IRQ_NMI) {
pintc_regs->pending = (1 << intno);
}
/*enable interrupt which number is intno */
if (intno <= 31)
pintc_regs->enable |= (1 << intno);
else if (intno > 31 && intno <= 63)
pintc_regs->enable1 |= (1 << (intno - 32));
else
pintc_regs->enable2 |= (1 << (intno - 64));
return OK;
}
/*
*********************************************************************************************************
* DISABLE INTERRUPT
*
* Description: disable a specific interrupt.
*
* Arguments : intno : the source number of interrupt which we want to disable.
*
* Returns : OK if disable interrupt succeeded, others if failed.
*
* Note :
*********************************************************************************************************
*/
s32 intc_disable_interrupt(u32 intno)
{
/*intno can't beyond then IRQ_SOURCE_MAX */
/* ASSERT(intno < IRQ_SOUCE_MAX); */
/*enable interrupt which number is intno */
if (intno <= 31)
pintc_regs->enable &= ~(1 << intno);
else if (intno > 31 && intno <= 63)
pintc_regs->enable1 &= ~(1 << (intno - 32));
else
pintc_regs->enable2 &= ~(1 << (intno - 64));
return OK;
}
/*
*********************************************************************************************************
* GET CURRENT INTERRUPT
*
* Description: get the source number of current interrupt.
*
* Arguments : none.
*
* Returns : the source number of current interrupt.
*
* Note :
*********************************************************************************************************
*/
u32 intc_get_current_interrupt(void)
{
volatile u32 interrupt;
interrupt = (u32) ((pintc_regs->vector) >> 2);
return interrupt;
}
s32 intc_set_mask(u32 intno, u32 mask)
{
/* intno can't beyond then IRQ_SOURCE_MAX */
/* ASSERT(intno < IRQ_SOUCE_MAX); */
/* enable interrupt which number is intno */
if (intno <= 31) {
pintc_regs->mask &= ~(1 << intno);
pintc_regs->mask |= (mask << intno);
} else if (intno > 31 && intno <= 63) {
pintc_regs->mask1 &= ~(1 << (intno - 32));
pintc_regs->mask1 |= (mask << intno);
} else {
pintc_regs->mask2 &= ~(1 << (intno - 64));
pintc_regs->mask2 |= (mask << intno);
}
return OK;
}
s32 intc_set_group_config(u32 grp_irq_num, u32 mask)
{
if (grp_irq_num <= 31) {
pintc_regs->group_config0 &= ~(1 << grp_irq_num);
pintc_regs->group_config0 |= (mask << grp_irq_num);
} else if (grp_irq_num > 31 && grp_irq_num <= 63) {
pintc_regs->group_config1 &= ~(1 << (grp_irq_num - 32));
pintc_regs->group_config1 |= (mask << grp_irq_num);
} else if (grp_irq_num > 63 && grp_irq_num <= 95) {
pintc_regs->group_config2 &= ~(1 << (grp_irq_num - 64));
pintc_regs->group_config2 |= (mask << grp_irq_num);
} else {
pintc_regs->group_config3 &= ~(1 << (grp_irq_num - 64));
pintc_regs->group_config3 |= (mask << grp_irq_num);
}
return OK;
}