Do better job with UIE_VECTOR.
[Rockbox.git] / firmware / target / arm / imx31 / gigabeat-s / avic-imx31.c
blobfa74d3bb9f6945c4a5ca716ca16ab988e7590c36
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
19 #include <stdio.h>
20 #include "system.h"
21 #include "imx31l.h"
22 #include "avic-imx31.h"
23 #include "panic.h"
24 #include "debug.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)
48 int mode;
49 long offset;
51 asm volatile (
52 "mrs %0, cpsr \n" /* Mask core IRQ/FIQ */
53 "orr %0, %0, #0xc0 \n"
54 "msr cpsr_c, %0 \n"
55 "and %0, %0, #0x1f \n" /* Get mode bits */
56 : "=&r"(mode)
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>");
66 /* We use the AVIC */
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)
76 asm volatile (
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 */
85 void avic_init(void)
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 */
100 asm volatile (
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"
104 : : : "r0");
106 /* Enable normal interrupts at all priorities */
107 NIMASK = 16;
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,
114 IRQ_FIQ_STATUS);
116 if (ints != ALL) /* No mass-enable allowed */
118 avic_set_int_type(ints, intstype);
119 VECTOR(ints) = (long)handler;
120 INTENNUM = ints;
123 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
126 void avic_disable_int(enum IMX31_INT_LIST ints)
128 long i;
130 if (ints == ALL)
132 for (i = 0; i < 64; i++)
134 INTDISNUM = i;
135 VECTOR(i) = (long)UIE_VECTOR;
138 else
140 INTDISNUM = ints;
141 VECTOR(ints) = (long)UIE_VECTOR;
145 static void set_int_type(int i, enum INT_TYPE intstype)
147 volatile unsigned long *reg;
148 long val;
150 if (i >= 32)
152 reg = &INTTYPEH;
153 val = 1L << (i - 32);
155 else
157 reg = &INTTYPEL;
158 val = 1L << i;
161 if (intstype == IRQ)
162 val = *reg & ~val;
163 else
164 val = *reg | val;
166 *reg = val;
169 void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype)
171 int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED,
172 IRQ_FIQ_STATUS);
174 if (ints == ALL)
176 int i;
177 for (i = 0; i < 64; i++)
178 set_int_type(i, intstype);
180 else
182 set_int_type(ints, intstype);
185 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);