diff options
Diffstat (limited to 'arch/blackfin/mach-common/ints-priority.c')
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 137 |
1 files changed, 54 insertions, 83 deletions
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 1bba6030dce9..a7d7b2dd4059 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c | |||
@@ -161,11 +161,15 @@ static void bfin_core_unmask_irq(unsigned int irq) | |||
161 | 161 | ||
162 | static void bfin_internal_mask_irq(unsigned int irq) | 162 | static void bfin_internal_mask_irq(unsigned int irq) |
163 | { | 163 | { |
164 | unsigned long flags; | ||
165 | |||
164 | #ifdef CONFIG_BF53x | 166 | #ifdef CONFIG_BF53x |
167 | local_irq_save_hw(flags); | ||
165 | bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & | 168 | bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & |
166 | ~(1 << SIC_SYSIRQ(irq))); | 169 | ~(1 << SIC_SYSIRQ(irq))); |
167 | #else | 170 | #else |
168 | unsigned mask_bank, mask_bit; | 171 | unsigned mask_bank, mask_bit; |
172 | local_irq_save_hw(flags); | ||
169 | mask_bank = SIC_SYSIRQ(irq) / 32; | 173 | mask_bank = SIC_SYSIRQ(irq) / 32; |
170 | mask_bit = SIC_SYSIRQ(irq) % 32; | 174 | mask_bit = SIC_SYSIRQ(irq) % 32; |
171 | bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & | 175 | bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & |
@@ -175,15 +179,20 @@ static void bfin_internal_mask_irq(unsigned int irq) | |||
175 | ~(1 << mask_bit)); | 179 | ~(1 << mask_bit)); |
176 | #endif | 180 | #endif |
177 | #endif | 181 | #endif |
182 | local_irq_restore_hw(flags); | ||
178 | } | 183 | } |
179 | 184 | ||
180 | static void bfin_internal_unmask_irq(unsigned int irq) | 185 | static void bfin_internal_unmask_irq(unsigned int irq) |
181 | { | 186 | { |
187 | unsigned long flags; | ||
188 | |||
182 | #ifdef CONFIG_BF53x | 189 | #ifdef CONFIG_BF53x |
190 | local_irq_save_hw(flags); | ||
183 | bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | | 191 | bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | |
184 | (1 << SIC_SYSIRQ(irq))); | 192 | (1 << SIC_SYSIRQ(irq))); |
185 | #else | 193 | #else |
186 | unsigned mask_bank, mask_bit; | 194 | unsigned mask_bank, mask_bit; |
195 | local_irq_save_hw(flags); | ||
187 | mask_bank = SIC_SYSIRQ(irq) / 32; | 196 | mask_bank = SIC_SYSIRQ(irq) / 32; |
188 | mask_bit = SIC_SYSIRQ(irq) % 32; | 197 | mask_bit = SIC_SYSIRQ(irq) % 32; |
189 | bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) | | 198 | bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) | |
@@ -193,6 +202,7 @@ static void bfin_internal_unmask_irq(unsigned int irq) | |||
193 | (1 << mask_bit)); | 202 | (1 << mask_bit)); |
194 | #endif | 203 | #endif |
195 | #endif | 204 | #endif |
205 | local_irq_restore_hw(flags); | ||
196 | } | 206 | } |
197 | 207 | ||
198 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM |
@@ -390,7 +400,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, | |||
390 | static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) | 400 | static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) |
391 | { | 401 | { |
392 | #ifdef CONFIG_IPIPE | 402 | #ifdef CONFIG_IPIPE |
393 | _set_irq_handler(irq, handle_edge_irq); | 403 | _set_irq_handler(irq, handle_level_irq); |
394 | #else | 404 | #else |
395 | struct irq_desc *desc = irq_desc + irq; | 405 | struct irq_desc *desc = irq_desc + irq; |
396 | /* May not call generic set_irq_handler() due to spinlock | 406 | /* May not call generic set_irq_handler() due to spinlock |
@@ -1055,13 +1065,18 @@ int __init init_arch_irq(void) | |||
1055 | #endif | 1065 | #endif |
1056 | default: | 1066 | default: |
1057 | #ifdef CONFIG_IPIPE | 1067 | #ifdef CONFIG_IPIPE |
1058 | /* | 1068 | /* |
1059 | * We want internal interrupt sources to be masked, because | 1069 | * We want internal interrupt sources to be |
1060 | * ISRs may trigger interrupts recursively (e.g. DMA), but | 1070 | * masked, because ISRs may trigger interrupts |
1061 | * interrupts are _not_ masked at CPU level. So let's handle | 1071 | * recursively (e.g. DMA), but interrupts are |
1062 | * them as level interrupts. | 1072 | * _not_ masked at CPU level. So let's handle |
1063 | */ | 1073 | * most of them as level interrupts, except |
1064 | set_irq_handler(irq, handle_level_irq); | 1074 | * the timer interrupt which is special. |
1075 | */ | ||
1076 | if (irq == IRQ_SYSTMR || irq == IRQ_CORETMR) | ||
1077 | set_irq_handler(irq, handle_simple_irq); | ||
1078 | else | ||
1079 | set_irq_handler(irq, handle_level_irq); | ||
1065 | #else /* !CONFIG_IPIPE */ | 1080 | #else /* !CONFIG_IPIPE */ |
1066 | set_irq_handler(irq, handle_simple_irq); | 1081 | set_irq_handler(irq, handle_simple_irq); |
1067 | #endif /* !CONFIG_IPIPE */ | 1082 | #endif /* !CONFIG_IPIPE */ |
@@ -1101,10 +1116,9 @@ int __init init_arch_irq(void) | |||
1101 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | | 1116 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | |
1102 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; | 1117 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; |
1103 | 1118 | ||
1104 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \ | 1119 | #ifdef SIC_IWR0 |
1105 | || defined(BF538_FAMILY) || defined(CONFIG_BF51x) | ||
1106 | bfin_write_SIC_IWR0(IWR_DISABLE_ALL); | 1120 | bfin_write_SIC_IWR0(IWR_DISABLE_ALL); |
1107 | #if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) | 1121 | # ifdef SIC_IWR1 |
1108 | /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which | 1122 | /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which |
1109 | * will screw up the bootrom as it relies on MDMA0/1 waking it | 1123 | * will screw up the bootrom as it relies on MDMA0/1 waking it |
1110 | * up from IDLE instructions. See this report for more info: | 1124 | * up from IDLE instructions. See this report for more info: |
@@ -1114,10 +1128,8 @@ int __init init_arch_irq(void) | |||
1114 | bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); | 1128 | bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); |
1115 | else | 1129 | else |
1116 | bfin_write_SIC_IWR1(IWR_DISABLE_ALL); | 1130 | bfin_write_SIC_IWR1(IWR_DISABLE_ALL); |
1117 | #else | 1131 | # endif |
1118 | bfin_write_SIC_IWR1(IWR_DISABLE_ALL); | 1132 | # ifdef SIC_IWR2 |
1119 | #endif | ||
1120 | # ifdef CONFIG_BF54x | ||
1121 | bfin_write_SIC_IWR2(IWR_DISABLE_ALL); | 1133 | bfin_write_SIC_IWR2(IWR_DISABLE_ALL); |
1122 | # endif | 1134 | # endif |
1123 | #else | 1135 | #else |
@@ -1126,9 +1138,8 @@ int __init init_arch_irq(void) | |||
1126 | 1138 | ||
1127 | #ifdef CONFIG_IPIPE | 1139 | #ifdef CONFIG_IPIPE |
1128 | for (irq = 0; irq < NR_IRQS; irq++) { | 1140 | for (irq = 0; irq < NR_IRQS; irq++) { |
1129 | struct irq_desc *desc = irq_desc + irq; | 1141 | struct irq_desc *desc = irq_to_desc(irq); |
1130 | desc->ic_prio = __ipipe_get_irq_priority(irq); | 1142 | desc->ic_prio = __ipipe_get_irq_priority(irq); |
1131 | desc->thr_prio = __ipipe_get_irqthread_priority(irq); | ||
1132 | } | 1143 | } |
1133 | #endif /* CONFIG_IPIPE */ | 1144 | #endif /* CONFIG_IPIPE */ |
1134 | 1145 | ||
@@ -1211,76 +1222,21 @@ int __ipipe_get_irq_priority(unsigned irq) | |||
1211 | return IVG15; | 1222 | return IVG15; |
1212 | } | 1223 | } |
1213 | 1224 | ||
1214 | int __ipipe_get_irqthread_priority(unsigned irq) | ||
1215 | { | ||
1216 | int ient, prio; | ||
1217 | int demux_irq; | ||
1218 | |||
1219 | /* The returned priority value is rescaled to [0..IVG13+1] | ||
1220 | * with 0 being the lowest effective priority level. */ | ||
1221 | |||
1222 | if (irq <= IRQ_CORETMR) | ||
1223 | return IVG13 - irq + 1; | ||
1224 | |||
1225 | /* GPIO IRQs are given the priority of the demux | ||
1226 | * interrupt. */ | ||
1227 | if (IS_GPIOIRQ(irq)) { | ||
1228 | #if defined(CONFIG_BF54x) | ||
1229 | u32 bank = PINT_2_BANK(irq2pint_lut[irq - SYS_IRQS]); | ||
1230 | demux_irq = (bank == 0 ? IRQ_PINT0 : | ||
1231 | bank == 1 ? IRQ_PINT1 : | ||
1232 | bank == 2 ? IRQ_PINT2 : | ||
1233 | IRQ_PINT3); | ||
1234 | #elif defined(CONFIG_BF561) | ||
1235 | demux_irq = (irq >= IRQ_PF32 ? IRQ_PROG2_INTA : | ||
1236 | irq >= IRQ_PF16 ? IRQ_PROG1_INTA : | ||
1237 | IRQ_PROG0_INTA); | ||
1238 | #elif defined(CONFIG_BF52x) | ||
1239 | demux_irq = (irq >= IRQ_PH0 ? IRQ_PORTH_INTA : | ||
1240 | irq >= IRQ_PG0 ? IRQ_PORTG_INTA : | ||
1241 | IRQ_PORTF_INTA); | ||
1242 | #else | ||
1243 | demux_irq = irq; | ||
1244 | #endif | ||
1245 | return IVG13 - PRIO_GPIODEMUX(demux_irq) + 1; | ||
1246 | } | ||
1247 | |||
1248 | /* The GPIO demux interrupt is given a lower priority | ||
1249 | * than the GPIO IRQs, so that its threaded handler | ||
1250 | * unmasks the interrupt line after the decoded IRQs | ||
1251 | * have been processed. */ | ||
1252 | prio = PRIO_GPIODEMUX(irq); | ||
1253 | /* demux irq? */ | ||
1254 | if (prio != -1) | ||
1255 | return IVG13 - prio; | ||
1256 | |||
1257 | for (ient = 0; ient < NR_PERI_INTS; ient++) { | ||
1258 | struct ivgx *ivg = ivg_table + ient; | ||
1259 | if (ivg->irqno == irq) { | ||
1260 | for (prio = 0; prio <= IVG13-IVG7; prio++) { | ||
1261 | if (ivg7_13[prio].ifirst <= ivg && | ||
1262 | ivg7_13[prio].istop > ivg) | ||
1263 | return IVG7 - prio; | ||
1264 | } | ||
1265 | } | ||
1266 | } | ||
1267 | |||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | /* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */ | 1225 | /* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */ |
1272 | #ifdef CONFIG_DO_IRQ_L1 | 1226 | #ifdef CONFIG_DO_IRQ_L1 |
1273 | __attribute__((l1_text)) | 1227 | __attribute__((l1_text)) |
1274 | #endif | 1228 | #endif |
1275 | asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) | 1229 | asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) |
1276 | { | 1230 | { |
1231 | struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr(); | ||
1232 | struct ipipe_domain *this_domain = ipipe_current_domain; | ||
1277 | struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop; | 1233 | struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop; |
1278 | struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst; | 1234 | struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst; |
1279 | int irq; | 1235 | int irq, s; |
1280 | 1236 | ||
1281 | if (likely(vec == EVT_IVTMR_P)) { | 1237 | if (likely(vec == EVT_IVTMR_P)) { |
1282 | irq = IRQ_CORETMR; | 1238 | irq = IRQ_CORETMR; |
1283 | goto handle_irq; | 1239 | goto core_tick; |
1284 | } | 1240 | } |
1285 | 1241 | ||
1286 | SSYNC(); | 1242 | SSYNC(); |
@@ -1322,24 +1278,39 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs) | |||
1322 | irq = ivg->irqno; | 1278 | irq = ivg->irqno; |
1323 | 1279 | ||
1324 | if (irq == IRQ_SYSTMR) { | 1280 | if (irq == IRQ_SYSTMR) { |
1281 | #ifdef CONFIG_GENERIC_CLOCKEVENTS | ||
1282 | core_tick: | ||
1283 | #else | ||
1325 | bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */ | 1284 | bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */ |
1285 | #endif | ||
1326 | /* This is basically what we need from the register frame. */ | 1286 | /* This is basically what we need from the register frame. */ |
1327 | __raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend; | 1287 | __raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend; |
1328 | __raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc; | 1288 | __raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc; |
1329 | if (!ipipe_root_domain_p) | 1289 | if (this_domain != ipipe_root_domain) |
1330 | __raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10; | ||
1331 | else | ||
1332 | __raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10; | 1290 | __raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10; |
1291 | else | ||
1292 | __raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10; | ||
1333 | } | 1293 | } |
1334 | 1294 | ||
1335 | handle_irq: | 1295 | #ifndef CONFIG_GENERIC_CLOCKEVENTS |
1296 | core_tick: | ||
1297 | #endif | ||
1298 | if (this_domain == ipipe_root_domain) { | ||
1299 | s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status); | ||
1300 | barrier(); | ||
1301 | } | ||
1336 | 1302 | ||
1337 | ipipe_trace_irq_entry(irq); | 1303 | ipipe_trace_irq_entry(irq); |
1338 | __ipipe_handle_irq(irq, regs); | 1304 | __ipipe_handle_irq(irq, regs); |
1339 | ipipe_trace_irq_exit(irq); | 1305 | ipipe_trace_irq_exit(irq); |
1340 | 1306 | ||
1341 | if (ipipe_root_domain_p) | 1307 | if (this_domain == ipipe_root_domain) { |
1342 | return !test_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status)); | 1308 | set_thread_flag(TIF_IRQ_SYNC); |
1309 | if (!s) { | ||
1310 | __clear_bit(IPIPE_SYNCDEFER_FLAG, &p->status); | ||
1311 | return !test_bit(IPIPE_STALL_FLAG, &p->status); | ||
1312 | } | ||
1313 | } | ||
1343 | 1314 | ||
1344 | return 0; | 1315 | return 0; |
1345 | } | 1316 | } |