diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/avic-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/avic-imx31.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c index fa74d3bb9f..b04b22911a 100644 --- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c | |||
@@ -84,18 +84,24 @@ void __attribute__((naked)) fiq_handler(void) | |||
84 | 84 | ||
85 | void avic_init(void) | 85 | void avic_init(void) |
86 | { | 86 | { |
87 | int i; | ||
88 | |||
87 | /* Disable all interrupts and set to unhandled */ | 89 | /* Disable all interrupts and set to unhandled */ |
88 | avic_disable_int(ALL); | 90 | avic_disable_int(ALL); |
89 | 91 | ||
92 | /* Reset AVIC control */ | ||
93 | INTCNTL = 0; | ||
94 | |||
90 | /* Init all interrupts to type IRQ */ | 95 | /* Init all interrupts to type IRQ */ |
91 | avic_set_int_type(ALL, IRQ); | 96 | avic_set_int_type(ALL, IRQ); |
92 | 97 | ||
98 | /* Set all normal to lowest priority */ | ||
99 | for (i = 0; i < 8; i++) | ||
100 | NIPRIORITY(i) = 0; | ||
101 | |||
93 | /* Set NM bit to enable VIC */ | 102 | /* Set NM bit to enable VIC */ |
94 | INTCNTL |= INTCNTL_NM; | 103 | INTCNTL |= INTCNTL_NM; |
95 | 104 | ||
96 | /* Enable IRQ/FIQ in imx31 INTCNTL reg */ | ||
97 | INTCNTL &= ~(INTCNTL_ABFEN | INTCNTL_NIDIS | INTCNTL_FIDIS); | ||
98 | |||
99 | /* Enable VE bit in CP15 Control reg to enable VIC */ | 105 | /* Enable VE bit in CP15 Control reg to enable VIC */ |
100 | asm volatile ( | 106 | asm volatile ( |
101 | "mrc p15, 0, r0, c1, c0, 0 \n" | 107 | "mrc p15, 0, r0, c1, c0, 0 \n" |
@@ -104,11 +110,20 @@ void avic_init(void) | |||
104 | : : : "r0"); | 110 | : : : "r0"); |
105 | 111 | ||
106 | /* Enable normal interrupts at all priorities */ | 112 | /* Enable normal interrupts at all priorities */ |
107 | NIMASK = 16; | 113 | NIMASK = 0x1f; |
114 | } | ||
115 | |||
116 | void avic_set_int_priority(enum IMX31_INT_LIST ints, | ||
117 | unsigned long ni_priority) | ||
118 | { | ||
119 | volatile unsigned long *reg = &NIPRIORITY((63 - ints) / 8); | ||
120 | unsigned int shift = 4*(ints % 8); | ||
121 | unsigned long mask = 0xful << shift; | ||
122 | *reg = (*reg & ~mask) | ((ni_priority << shift) & mask); | ||
108 | } | 123 | } |
109 | 124 | ||
110 | void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype, | 125 | void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype, |
111 | void (*handler)(void)) | 126 | unsigned long ni_priority, void (*handler)(void)) |
112 | { | 127 | { |
113 | int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, | 128 | int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, |
114 | IRQ_FIQ_STATUS); | 129 | IRQ_FIQ_STATUS); |
@@ -118,6 +133,7 @@ void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype, | |||
118 | avic_set_int_type(ints, intstype); | 133 | avic_set_int_type(ints, intstype); |
119 | VECTOR(ints) = (long)handler; | 134 | VECTOR(ints) = (long)handler; |
120 | INTENNUM = ints; | 135 | INTENNUM = ints; |
136 | avic_set_int_priority(ints, ni_priority); | ||
121 | } | 137 | } |
122 | 138 | ||
123 | set_interrupt_status(oldstatus, IRQ_FIQ_STATUS); | 139 | set_interrupt_status(oldstatus, IRQ_FIQ_STATUS); |