rockbox/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c

224 lines
8.1 KiB
C
Raw Normal View History

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 by James Espinoza
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdio.h>
#include "system.h"
#include "imx31l.h"
#include "avic-imx31.h"
#include "debug.h"
void avic_init(void)
{
/*following the steps in the AVIC setup in imx31 man*/
/*Initialize interrupt structures*/
int i,avicstart;
/*get start of avic_init section for address calculation*/
__asm__ ("ldr %0,=_avicstart\n\t"
:"=r"(avicstart):);
for(i=0; i < 64;i++)
{
imx31_int[i].name = (char *)&imx31_int_names[i];
imx31_int[i].int_type=IRQ;
/*integer i MUST be multiplied by 8 b/c gnu as
generates 2 instructions for each vector instruction
in vector_init(). Hence the value of 8 byte intervals
between each vector start address*/
imx31_int[i].addr=(avicstart+(i*8));
imx31_int[i].priority=0;
imx31_int[i].pInt_Handler=Unhandled_Int;
}
/*enable all Interrupts*/
avic_enable_int(ALL,IRQ,0);
/*Setup all interrupt type IRQ*/
avic_set_int_type(ALL,IRQ);
/*Set NM bit to enable VIC*/
INTCNTL |= (1 << 18);
/*Setup Registers Vector0-Vector63 for interrupt handler functions*/
for(i=0; i < 64;i++)
writel(imx31_int[i].addr,(VECTOR_BASE_ADDR+(i*8)));
/*disable FIQ for now until the interrupt handlers are more mature...*/
disable_fiq();
/*enable_fiq();*/
/*enable IRQ in imx31 INTCNTL reg*/
INTCNTL &= ~(NIDIS);
/*disable FIQ in imx31 INTCNTL reg*/
INTCNTL |= FIDIS;
/*enable IRQ in ARM11 core, enable VE bit in CP15 Control reg to enable VIC*/
__asm__ ("mrs r0,cpsr\t\n"
"bic r0,r0,#0x80\t\n"
"msr cpsr,r0\t\n"
"mrc p15,0,r0,c1,c0,0\n\t"
"orr r0,r0,#0x1000000\n\t"
"mcr p15,0,r0,c1,c0,0\n\t":::
"r0");
}
void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype,
void (*pInt_Handler) (void))
{
int i;
if(ints == ALL)
{
avic_set_int_type(ALL,intstype);
for(i=0;i<64;i++)
INTENNUM= (long)i;
if(!(*pInt_Handler))
pInt_Handler=Unhandled_Int;
return;
}
imx31_int[ints].int_type=intstype;
imx31_int[ints].pInt_Handler=pInt_Handler;
avic_set_int_type(ints,intstype);
INTENNUM=(long)ints;
}
void avic_disable_int(enum IMX31_INT_LIST ints)
{
int i;
if(ints == ALL)
{
for(i=0;i<64;i++)
INTDISNUM=(long)i;
imx31_int[ints].pInt_Handler=Unhandled_Int;
return;
}
INTDISNUM=(long)ints;
}
void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype)
{
int i;
if(ints == ALL)
{
imx31_int[ints].int_type=intstype;
for(i=0;i<64;i++)
{
if(intstype > CCM_DVFS)
INTTYPEH=(long)(intstype-32);
else INTTYPEL=(long)intstype;
}
return;
}
imx31_int[ints].int_type=intstype;
if(intstype > CCM_DVFS)
INTTYPEH=(long)(intstype-32);
else INTTYPEL=(long)intstype;
}
void Unhandled_Int(void)
{
enum IMX31_INT_LIST ints = 0;
DEBUGF("Unhandled Interrupt:\n");
DEBUGF("Name : %s\n",imx31_int[ints].name);
DEBUGF("Interrupt Type : ");
if(imx31_int[ints].int_type==IRQ)
DEBUGF("IRQ\n");
else DEBUGF("FIQ\n");
DEBUGF("Handler Address : 0x%x\n",imx31_int[ints].addr);
DEBUGF("Priority : %d",imx31_int[ints].priority);
}
void vector_init(void)
{
/*64 branch instructions, one for every vector in avic
A better idea would to calculate the shellcode for each of these
instructions...*/
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED0].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[I2C3].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[I2C2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[MPEG4_ENCODER].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RTIC].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[FIR].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[MMC_SDHC2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[MMC_SDHC1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[I2C1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[SSI2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[SSI1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[CSPI2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[CSPI1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[ATA].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[MBX].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[CSPI3].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART3].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[IIM].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[SIM1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[SIM2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RNGA].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EVTMON].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[KPP].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RTC].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[PWN].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EPIT2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EPIT1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPT].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[PWR_FAIL].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[CCM_DVFS].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[NANDFC].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[SDMA].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[USB_HOST1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[USB_HOST2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[USB_OTG].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED3].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[MSHC1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[MSHC2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[IPU_ERR].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[IPU].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED4].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED5].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART4].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART5].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[ETC_IRQ].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[SCC_SCM].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[SCC_SMN].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPIO2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPIO1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[CCM_CLK].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[PCMCIA].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[WDOG].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPIO3].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED6].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_PWMG].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_TEMP].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_SENS1].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_SENS2].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_WDOG].pInt_Handler));
__asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_TV].pInt_Handler));
}