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.c53
1 files changed, 24 insertions, 29 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
index 6b64bfad77..ce2932a13f 100644
--- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
@@ -74,9 +74,9 @@ void __attribute__((naked)) irq_handler(void)
74void __attribute__((naked)) fiq_handler(void) 74void __attribute__((naked)) fiq_handler(void)
75{ 75{
76 asm volatile ( 76 asm volatile (
77 "mov r10, #0x6c000000 \n" /* load AVIC base address */ 77 "mov r10, #0x68000000 \n" /* load AVIC base address */
78 "ldr r9, [r10, #0x44] \n" /* read FIVECSR of AVIC */ 78 "ldr r9, [r10, #0x44] \n" /* read FIVECSR of AVIC */
79 "add r10, r10, #100 \n" /* move pointer to base of VECTOR table */ 79 "add r10, r10, #0x100 \n" /* move pointer to base of VECTOR table */
80 "ldr r8, [r10, r9, lsl #2] \n" /* read FIQ vector from 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 */ 81 "bx r8 \n" /* jump to FIQ service routine */
82 ); 82 );
@@ -84,23 +84,24 @@ void __attribute__((naked)) fiq_handler(void)
84 84
85void avic_init(void) 85void avic_init(void)
86{ 86{
87 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
87 int i; 88 int i;
88 89
89 /* Disable all interrupts and set to unhandled */ 90 /* Disable all interrupts and set to unhandled */
90 avic_disable_int(ALL); 91 avic_disable_int(ALL);
91 92
92 /* Reset AVIC control */ 93 /* Reset AVIC control */
93 INTCNTL = 0; 94 avic->intcntl = 0;
94 95
95 /* Init all interrupts to type IRQ */ 96 /* Init all interrupts to type IRQ */
96 avic_set_int_type(ALL, IRQ); 97 avic_set_int_type(ALL, IRQ);
97 98
98 /* Set all normal to lowest priority */ 99 /* Set all normal to lowest priority */
99 for (i = 0; i < 8; i++) 100 for (i = 0; i < 8; i++)
100 NIPRIORITY(i) = 0; 101 avic->nipriority[i] = 0;
101 102
102 /* Set NM bit to enable VIC */ 103 /* Set NM bit to enable VIC */
103 INTCNTL |= INTCNTL_NM; 104 avic->intcntl |= INTCNTL_NM;
104 105
105 /* Enable VE bit in CP15 Control reg to enable VIC */ 106 /* Enable VE bit in CP15 Control reg to enable VIC */
106 asm volatile ( 107 asm volatile (
@@ -110,28 +111,30 @@ void avic_init(void)
110 : : : "r0"); 111 : : : "r0");
111 112
112 /* Enable normal interrupts at all priorities */ 113 /* Enable normal interrupts at all priorities */
113 NIMASK = 0x1f; 114 avic->nimask = 0x1f;
114} 115}
115 116
116void avic_set_int_priority(enum IMX31_INT_LIST ints, 117void avic_set_int_priority(enum IMX31_INT_LIST ints,
117 unsigned long ni_priority) 118 unsigned long ni_priority)
118{ 119{
119 volatile unsigned long *reg = &NIPRIORITY((63 - ints) / 8); 120 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
120 unsigned int shift = 4*(ints % 8); 121 volatile uint32_t *reg = &avic->nipriority[7 - (ints >> 3)];
121 unsigned long mask = 0xful << shift; 122 unsigned int shift = (ints & 0x7) << 2;
123 uint32_t mask = 0xful << shift;
122 *reg = (*reg & ~mask) | ((ni_priority << shift) & mask); 124 *reg = (*reg & ~mask) | ((ni_priority << shift) & mask);
123} 125}
124 126
125void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype, 127void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype,
126 unsigned long ni_priority, void (*handler)(void)) 128 unsigned long ni_priority, void (*handler)(void))
127{ 129{
130 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
128 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS); 131 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
129 132
130 if (ints != ALL) /* No mass-enable allowed */ 133 if (ints != ALL) /* No mass-enable allowed */
131 { 134 {
132 avic_set_int_type(ints, intstype); 135 avic_set_int_type(ints, intstype);
133 VECTOR(ints) = (long)handler; 136 avic->vector[ints] = (long)handler;
134 INTENNUM = ints; 137 avic->intennum = ints;
135 avic_set_int_priority(ints, ni_priority); 138 avic_set_int_priority(ints, ni_priority);
136 } 139 }
137 140
@@ -140,38 +143,30 @@ void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype,
140 143
141void avic_disable_int(enum IMX31_INT_LIST ints) 144void avic_disable_int(enum IMX31_INT_LIST ints)
142{ 145{
143 long i; 146 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
147 uint32_t i;
144 148
145 if (ints == ALL) 149 if (ints == ALL)
146 { 150 {
147 for (i = 0; i < 64; i++) 151 for (i = 0; i < 64; i++)
148 { 152 {
149 INTDISNUM = i; 153 avic->intdisnum = i;
150 VECTOR(i) = (long)UIE_VECTOR; 154 avic->vector[i] = (long)UIE_VECTOR;
151 } 155 }
152 } 156 }
153 else 157 else
154 { 158 {
155 INTDISNUM = ints; 159 avic->intdisnum = ints;
156 VECTOR(ints) = (long)UIE_VECTOR; 160 avic->vector[ints] = (long)UIE_VECTOR;
157 } 161 }
158} 162}
159 163
160static void set_int_type(int i, enum INT_TYPE intstype) 164static void set_int_type(int i, enum INT_TYPE intstype)
161{ 165{
162 volatile unsigned long *reg; 166 /* INTTYPEH: vectors 63-32, INTTYPEL: vectors 31-0 */
163 long val; 167 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
164 168 volatile uint32_t *reg = &avic->inttype[1 - (i >> 5)];
165 if (i >= 32) 169 uint32_t val = 1L << (i & 0x1f);
166 {
167 reg = &INTTYPEH;
168 val = 1L << (i - 32);
169 }
170 else
171 {
172 reg = &INTTYPEL;
173 val = 1L << i;
174 }
175 170
176 if (intstype == IRQ) 171 if (intstype == IRQ)
177 val = *reg & ~val; 172 val = *reg & ~val;