summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/avic-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/avic-imx31.c305
1 files changed, 131 insertions, 174 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
index 8236a38014..99a52e56d5 100644
--- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
@@ -20,204 +20,161 @@
20#include "system.h" 20#include "system.h"
21#include "imx31l.h" 21#include "imx31l.h"
22#include "avic-imx31.h" 22#include "avic-imx31.h"
23#include "panic.h"
23#include "debug.h" 24#include "debug.h"
24 25
26static const char * avic_int_names[64] =
27{
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"
44};
45
46static void UIE_VECTOR(void)
47{
48 set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
49 long offset = FIVECSR;
50 long offsetn = (long)NIVECSR >> 16;
51
52 if (offsetn == -1)
53 offset = offsetn; /* Could be FIQ */
54
55 panicf("Unhandled %s %ld: %s",
56 offsetn >= 0 ? "IRQ" : "FIQ", offset,
57 offset >= 0 ? avic_int_names[offset] : "");
58}
59
60/* We use the AVIC */
61void __attribute__((naked)) irq_handler(void)
62{
63 panicf("Unhandled IRQ");
64}
65
66/* Accoring to section 9.3.5 of the UM, the AVIC doesn't accelerate
67 * fast interrupts and they must be dispatched */
68void __attribute__((naked)) fiq_handler(void)
69{
70 asm volatile (
71 "mov r10, #0x6c000000 \n" /* load AVIC base address */
72 "ldr r9, [r10, #0x44] \n" /* read FIVECSR of AVIC */
73 "add r10, r10, #100 \n" /* move pointer to base of VECTOR table */
74 "ldr r8, [r10, r9, lsl #2] \n" /* read FIQ vector from VECTOR table */
75 "bx r8 \n" /* jump to FIQ service routine */
76 );
77}
78
25void avic_init(void) 79void avic_init(void)
26{ 80{
27 /*following the steps in the AVIC setup in imx31 man*/ 81 /* Disable all interrupts and set to unhandled */
82 avic_disable_int(ALL);
28 83
29 /*Initialize interrupt structures*/ 84 /* Init all interrupts to type IRQ */
30 int i,avicstart; 85 avic_set_int_type(ALL, IRQ);
31 /*get start of avic_init section for address calculation*/
32 __asm__ ("ldr %0,=_avicstart\n\t"
33 :"=r"(avicstart):);
34 86
35 for(i=0; i < 64;i++) 87 /* Set NM bit to enable VIC */
36 { 88 INTCNTL |= INTCNTL_NM;
37 imx31_int[i].name = (char *)&imx31_int_names[i];
38 imx31_int[i].int_type=IRQ;
39 /*integer i MUST be multiplied by 8 b/c gnu as
40 generates 2 instructions for each vector instruction
41 in vector_init(). Hence the value of 8 byte intervals
42 between each vector start address*/
43 imx31_int[i].addr=(avicstart+(i*8));
44 imx31_int[i].priority=0;
45 imx31_int[i].pInt_Handler=Unhandled_Int;
46 }
47
48 /*enable all Interrupts*/
49 avic_enable_int(ALL,IRQ,0);
50
51 /*Setup all interrupt type IRQ*/
52 avic_set_int_type(ALL,IRQ);
53
54 /*Set NM bit to enable VIC*/
55 INTCNTL |= (1 << 18);
56 89
57 /*Setup Registers Vector0-Vector63 for interrupt handler functions*/ 90 /* Enable IRQ/FIQ in imx31 INTCNTL reg */
58 for(i=0; i < 64;i++) 91 INTCNTL &= ~(INTCNTL_ABFEN | INTCNTL_NIDIS | INTCNTL_FIDIS);
59 writel(imx31_int[i].addr,(VECTOR_BASE_ADDR+(i*8))); 92
60 93 /* Enable VE bit in CP15 Control reg to enable VIC */
61 /*disable FIQ for now until the interrupt handlers are more mature...*/ 94 asm volatile (
62 disable_fiq(); 95 "mrc p15, 0, r0, c1, c0, 0 \n"
63 /*enable_fiq();*/ 96 "orr r0, r0, #(1 << 24) \n"
64 97 "mcr p15, 0, r0, c1, c0, 0 \n"
65 /*enable IRQ in imx31 INTCNTL reg*/ 98 : : : "r0");
66 INTCNTL &= ~(NIDIS); 99
67 /*disable FIQ in imx31 INTCNTL reg*/ 100 /* Enable normal interrupts at all priorities */
68 INTCNTL |= FIDIS; 101 NIMASK = 16;
69
70 /*enable IRQ in ARM11 core, enable VE bit in CP15 Control reg to enable VIC*/
71 __asm__ ("mrs r0,cpsr\t\n"
72 "bic r0,r0,#0x80\t\n"
73 "msr cpsr,r0\t\n"
74 "mrc p15,0,r0,c1,c0,0\n\t"
75 "orr r0,r0,#0x1000000\n\t"
76 "mcr p15,0,r0,c1,c0,0\n\t":::
77 "r0");
78} 102}
79 103
80void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype, 104void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype,
81 void (*pInt_Handler) (void)) 105 void (*handler)(void))
82{ 106{
83 int i; 107 int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED,
108 IRQ_FIQ_STATUS);
84 109
85 if(ints == ALL) 110 if (ints != ALL) /* No mass-enable allowed */
86 { 111 {
87 avic_set_int_type(ALL,intstype); 112 avic_set_int_type(ints, intstype);
88 for(i=0;i<64;i++) 113 VECTOR(ints) = (long)handler;
89 INTENNUM= (long)i; 114 INTENNUM = ints;
90 if(!(*pInt_Handler)) 115 }
91 pInt_Handler=Unhandled_Int; 116
92 return; 117 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
93 }
94
95 imx31_int[ints].int_type=intstype;
96 imx31_int[ints].pInt_Handler=pInt_Handler;
97 avic_set_int_type(ints,intstype);
98 INTENNUM=(long)ints;
99} 118}
100 119
101void avic_disable_int(enum IMX31_INT_LIST ints) 120void avic_disable_int(enum IMX31_INT_LIST ints)
102{ 121{
103 int i; 122 long i;
104 123
105 if(ints == ALL) 124 if (ints == ALL)
106 { 125 {
107 for(i=0;i<64;i++) 126 for (i = 0; i < 64; i++)
108 INTDISNUM=(long)i; 127 {
109 imx31_int[ints].pInt_Handler=Unhandled_Int; 128 INTDISNUM = i;
110 return; 129 VECTOR(i) = (long)UIE_VECTOR;
130 }
111 } 131 }
112 132 else
113 INTDISNUM=(long)ints; 133 {
134 INTDISNUM = ints;
135 VECTOR(ints) = (long)UIE_VECTOR;
136 }
114} 137}
115 138
116void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype) 139static void set_int_type(int i, enum INT_TYPE intstype)
117{ 140{
118 int i; 141 volatile unsigned long *reg;
119 if(ints == ALL) 142 long val;
120 {
121 imx31_int[ints].int_type=intstype;
122 for(i=0;i<64;i++)
123 {
124 if(intstype > CCM_DVFS)
125 INTTYPEH=(long)(intstype-32);
126 else INTTYPEL=(long)intstype;
127 }
128 return;
129 }
130
131 imx31_int[ints].int_type=intstype;
132 if(intstype > CCM_DVFS)
133 INTTYPEH=(long)(intstype-32);
134 else INTTYPEL=(long)intstype;
135}
136 143
137void Unhandled_Int(void) 144 if (i >= 32)
138{ 145 {
139 enum IMX31_INT_LIST ints = 0; 146 reg = &INTTYPEH;
140 DEBUGF("Unhandled Interrupt:\n"); 147 val = 1L << (i - 32);
141 DEBUGF("Name : %s\n",imx31_int[ints].name); 148 }
142 DEBUGF("Interrupt Type : "); 149 else
143 if(imx31_int[ints].int_type==IRQ) 150 {
144 DEBUGF("IRQ\n"); 151 reg = &INTTYPEL;
145 else DEBUGF("FIQ\n"); 152 val = 1L << i;
146 DEBUGF("Handler Address : 0x%x\n",imx31_int[ints].addr); 153 }
147 DEBUGF("Priority : %d",imx31_int[ints].priority); 154
155 if (intstype == IRQ)
156 val = *reg & ~val;
157 else
158 val = *reg | val;
159
160 *reg = val;
148} 161}
149 162
150void vector_init(void) 163void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype)
151{ 164{
152 165 int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED,
153 /*64 branch instructions, one for every vector in avic 166 IRQ_FIQ_STATUS);
154 A better idea would to calculate the shellcode for each of these 167
155 instructions...*/ 168 if (ints == ALL)
156 169 {
157 170 int i;
158 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED0].pInt_Handler)); 171 for (i = 0; i < 64; i++)
159 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED1].pInt_Handler)); 172 set_int_type(i, intstype);
160 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED2].pInt_Handler)); 173 }
161 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[I2C3].pInt_Handler)); 174 else
162 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[I2C2].pInt_Handler)); 175 {
163 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[MPEG4_ENCODER].pInt_Handler)); 176 set_int_type(ints, intstype);
164 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RTIC].pInt_Handler)); 177 }
165 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[FIR].pInt_Handler)); 178
166 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[MMC_SDHC2].pInt_Handler)); 179 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
167 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[MMC_SDHC1].pInt_Handler));
168 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[I2C1].pInt_Handler));
169 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[SSI2].pInt_Handler));
170 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[SSI1].pInt_Handler));
171 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[CSPI2].pInt_Handler));
172 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[CSPI1].pInt_Handler));
173 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[ATA].pInt_Handler));
174 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[MBX].pInt_Handler));
175 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[CSPI3].pInt_Handler));
176 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART3].pInt_Handler));
177 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[IIM].pInt_Handler));
178 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[SIM1].pInt_Handler));
179 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[SIM2].pInt_Handler));
180 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RNGA].pInt_Handler));
181 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EVTMON].pInt_Handler));
182 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[KPP].pInt_Handler));
183 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RTC].pInt_Handler));
184 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[PWN].pInt_Handler));
185 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EPIT2].pInt_Handler));
186 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EPIT1].pInt_Handler));
187 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPT].pInt_Handler));
188 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[PWR_FAIL].pInt_Handler));
189 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[CCM_DVFS].pInt_Handler));
190 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART2].pInt_Handler));
191 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[NANDFC].pInt_Handler));
192 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[SDMA].pInt_Handler));
193 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[USB_HOST1].pInt_Handler));
194 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[USB_HOST2].pInt_Handler));
195 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[USB_OTG].pInt_Handler));
196 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED3].pInt_Handler));
197 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[MSHC1].pInt_Handler));
198 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[MSHC2].pInt_Handler));
199 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[IPU_ERR].pInt_Handler));
200 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[IPU].pInt_Handler));
201 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED4].pInt_Handler));
202 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED5].pInt_Handler));
203 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART1].pInt_Handler));
204 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART4].pInt_Handler));
205 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[UART5].pInt_Handler));
206 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[ETC_IRQ].pInt_Handler));
207 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[SCC_SCM].pInt_Handler));
208 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[SCC_SMN].pInt_Handler));
209 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPIO2].pInt_Handler));
210 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPIO1].pInt_Handler));
211 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[CCM_CLK].pInt_Handler));
212 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[PCMCIA].pInt_Handler));
213 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[WDOG].pInt_Handler));
214 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[GPIO3].pInt_Handler));
215 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[RESERVED6].pInt_Handler));
216 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_PWMG].pInt_Handler));
217 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_TEMP].pInt_Handler));
218 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_SENS1].pInt_Handler));
219 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_SENS2].pInt_Handler));
220 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_WDOG].pInt_Handler));
221 __asm__("ldr pc, %0\n\t"::"g"(imx31_int[EXT_TV].pInt_Handler));
222
223} 180}