1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 by James Espinoza
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
22 #include "avic-imx31.h"
26 static const char * avic_int_names
[64] =
28 "RESERVED0", "RESERVED1", "RESERVED2", "I2C3",
29 "I2C2", "MPEG4_ENCODER", "RTIC", "FIR",
30 "MMC/SDHC2", "MMC/SDHC1", "I2C1", "SSI2",
31 "SSI1", "CSPI2", "CSPI1", "ATA",
32 "MBX", "CSPI3", "UART3", "IIM",
33 "SIM1", "SIM2", "RNGA", "EVTMON",
34 "KPP", "RTC", "PWN", "EPIT2",
35 "EPIT1", "GPT", "PWR_FAIL", "CCM_DVFS",
36 "UART2", "NANDFC", "SDMA", "USB_HOST1",
37 "USB_HOST2", "USB_OTG", "RESERVED3", "MSHC1",
38 "MSHC2", "IPU_ERR", "IPU", "RESERVED4",
39 "RESERVED5", "UART1", "UART4", "UART5",
40 "ETC_IRQ", "SCC_SCM", "SCC_SMN", "GPIO2",
41 "GPIO1", "CCM_CLK", "PCMCIA", "WDOG",
42 "GPIO3", "RESERVED6", "EXT_PWMG", "EXT_TEMP",
43 "EXT_SENS1", "EXT_SENS2", "EXT_WDOG", "EXT_TV"
46 static void UIE_VECTOR(void)
52 "mrs %0, cpsr \n" /* Mask core IRQ/FIQ */
53 "orr %0, %0, #0xc0 \n"
55 "and %0, %0, #0x1f \n" /* Get mode bits */
59 offset
= mode
== 0x11 ? (long)FIVECSR
: ((long)NIVECSR
>> 16);
61 panicf("Unhandled %s %ld: %s",
62 mode
== 0x11 ? "FIQ" : "IRQ", offset
,
63 offset
>= 0 ? avic_int_names
[offset
] : "<Unknown>");
67 void __attribute__((naked
)) irq_handler(void)
69 panicf("Unhandled IRQ in irq_handler");
72 /* Accoring to section 9.3.5 of the UM, the AVIC doesn't accelerate
73 * fast interrupts and they must be dispatched */
74 void __attribute__((naked
)) fiq_handler(void)
77 "mov r10, #0x6c000000 \n" /* load AVIC base address */
78 "ldr r9, [r10, #0x44] \n" /* read FIVECSR of AVIC */
79 "add r10, r10, #100 \n" /* move pointer to base of VECTOR table */
80 "ldr r8, [r10, r9, lsl #2] \n" /* read FIQ vector from VECTOR table */
81 "bx r8 \n" /* jump to FIQ service routine */
87 /* Disable all interrupts and set to unhandled */
88 avic_disable_int(ALL
);
90 /* Init all interrupts to type IRQ */
91 avic_set_int_type(ALL
, IRQ
);
93 /* Set NM bit to enable VIC */
94 INTCNTL
|= INTCNTL_NM
;
96 /* Enable IRQ/FIQ in imx31 INTCNTL reg */
97 INTCNTL
&= ~(INTCNTL_ABFEN
| INTCNTL_NIDIS
| INTCNTL_FIDIS
);
99 /* Enable VE bit in CP15 Control reg to enable VIC */
101 "mrc p15, 0, r0, c1, c0, 0 \n"
102 "orr r0, r0, #(1 << 24) \n"
103 "mcr p15, 0, r0, c1, c0, 0 \n"
106 /* Enable normal interrupts at all priorities */
110 void avic_enable_int(enum IMX31_INT_LIST ints
, enum INT_TYPE intstype
,
111 void (*handler
)(void))
113 int oldstatus
= set_interrupt_status(IRQ_FIQ_DISABLED
,
116 if (ints
!= ALL
) /* No mass-enable allowed */
118 avic_set_int_type(ints
, intstype
);
119 VECTOR(ints
) = (long)handler
;
123 set_interrupt_status(oldstatus
, IRQ_FIQ_STATUS
);
126 void avic_disable_int(enum IMX31_INT_LIST ints
)
132 for (i
= 0; i
< 64; i
++)
135 VECTOR(i
) = (long)UIE_VECTOR
;
141 VECTOR(ints
) = (long)UIE_VECTOR
;
145 static void set_int_type(int i
, enum INT_TYPE intstype
)
147 volatile unsigned long *reg
;
153 val
= 1L << (i
- 32);
169 void avic_set_int_type(enum IMX31_INT_LIST ints
, enum INT_TYPE intstype
)
171 int oldstatus
= set_interrupt_status(IRQ_FIQ_DISABLED
,
177 for (i
= 0; i
< 64; i
++)
178 set_int_type(i
, intstype
);
182 set_int_type(ints
, intstype
);
185 set_interrupt_status(oldstatus
, IRQ_FIQ_STATUS
);