aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/jmr3927/rbhma3100/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/jmr3927/rbhma3100/irq.c')
-rw-r--r--arch/mips/jmr3927/rbhma3100/irq.c106
1 files changed, 56 insertions, 50 deletions
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index 722174481467..39a0243bed9a 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -46,6 +46,7 @@
46#include <linux/smp_lock.h> 46#include <linux/smp_lock.h>
47#include <linux/bitops.h> 47#include <linux/bitops.h>
48 48
49#include <asm/irq_regs.h>
49#include <asm/io.h> 50#include <asm/io.h>
50#include <asm/mipsregs.h> 51#include <asm/mipsregs.h>
51#include <asm/system.h> 52#include <asm/system.h>
@@ -239,45 +240,80 @@ struct tb_irq_space jmr3927_ioc_irqspace = {
239 .space_id = 0, 240 .space_id = 0,
240 can_share : 1 241 can_share : 1
241}; 242};
243
242struct tb_irq_space jmr3927_irc_irqspace = { 244struct tb_irq_space jmr3927_irc_irqspace = {
243 .next = NULL, 245 .next = NULL,
244 .start_irqno = JMR3927_IRQ_IRC, 246 .start_irqno = JMR3927_IRQ_IRC,
245 nr_irqs : JMR3927_NR_IRQ_IRC, 247 .nr_irqs = JMR3927_NR_IRQ_IRC,
246 .mask_func = mask_irq_irc, 248 .mask_func = mask_irq_irc,
247 .unmask_func = unmask_irq_irc, 249 .unmask_func = unmask_irq_irc,
248 .name = "on-chip", 250 .name = "on-chip",
249 .space_id = 0, 251 .space_id = 0,
250 can_share : 0 252 .can_share = 0
251}; 253};
252 254
253void jmr3927_spurious(struct pt_regs *regs) 255
256#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
257static int tx_branch_likely_bug_count = 0;
258static int have_tx_branch_likely_bug = 0;
259
260static void tx_branch_likely_bug_fixup(void)
261{
262 struct pt_regs *regs = get_irq_regs();
263
264 /* TX39/49-BUG: Under this condition, the insn in delay slot
265 of the branch likely insn is executed (not nullified) even
266 the branch condition is false. */
267 if (!have_tx_branch_likely_bug)
268 return;
269 if ((regs->cp0_epc & 0xfff) == 0xffc &&
270 KSEGX(regs->cp0_epc) != KSEG0 &&
271 KSEGX(regs->cp0_epc) != KSEG1) {
272 unsigned int insn = *(unsigned int*)(regs->cp0_epc - 4);
273 /* beql,bnel,blezl,bgtzl */
274 /* bltzl,bgezl,blezall,bgezall */
275 /* bczfl, bcztl */
276 if ((insn & 0xf0000000) == 0x50000000 ||
277 (insn & 0xfc0e0000) == 0x04020000 ||
278 (insn & 0xf3fe0000) == 0x41020000) {
279 regs->cp0_epc -= 4;
280 tx_branch_likely_bug_count++;
281 printk(KERN_INFO
282 "fix branch-likery bug in %s (insn %08x)\n",
283 current->comm, insn);
284 }
285 }
286}
287#endif
288
289static void jmr3927_spurious(void)
254{ 290{
255#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND 291#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
256 tx_branch_likely_bug_fixup(regs); 292 tx_branch_likely_bug_fixup();
257#endif 293#endif
258 printk(KERN_WARNING "spurious interrupt (cause 0x%lx, pc 0x%lx, ra 0x%lx).\n", 294 printk(KERN_WARNING "spurious interrupt (cause 0x%lx, pc 0x%lx, ra 0x%lx).\n",
259 regs->cp0_cause, regs->cp0_epc, regs->regs[31]); 295 regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
260} 296}
261 297
262asmlinkage void plat_irq_dispatch(struct pt_regs *regs) 298asmlinkage void plat_irq_dispatch(void)
263{ 299{
264 int irq; 300 int irq;
265 301
266#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND 302#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
267 tx_branch_likely_bug_fixup(regs); 303 tx_branch_likely_bug_fixup();
268#endif 304#endif
269 if ((regs->cp0_cause & CAUSEF_IP7) == 0) { 305 if ((regs->cp0_cause & CAUSEF_IP7) == 0) {
270#if 0 306#if 0
271 jmr3927_spurious(regs); 307 jmr3927_spurious();
272#endif 308#endif
273 return; 309 return;
274 } 310 }
275 irq = (regs->cp0_cause >> CAUSEB_IP2) & 0x0f; 311 irq = (regs->cp0_cause >> CAUSEB_IP2) & 0x0f;
276 312
277 do_IRQ(irq + JMR3927_IRQ_IRC, regs); 313 do_IRQ(irq + JMR3927_IRQ_IRC);
278} 314}
279 315
280static irqreturn_t jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *regs) 316static irqreturn_t jmr3927_ioc_interrupt(int irq, void *dev_id)
281{ 317{
282 unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR); 318 unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR);
283 int i; 319 int i;
@@ -285,7 +321,7 @@ static irqreturn_t jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *
285 for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) { 321 for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) {
286 if (istat & (1 << i)) { 322 if (istat & (1 << i)) {
287 irq = JMR3927_IRQ_IOC + i; 323 irq = JMR3927_IRQ_IOC + i;
288 do_IRQ(irq, regs); 324 do_IRQ(irq);
289 } 325 }
290 } 326 }
291 return IRQ_HANDLED; 327 return IRQ_HANDLED;
@@ -295,7 +331,7 @@ static struct irqaction ioc_action = {
295 jmr3927_ioc_interrupt, 0, CPU_MASK_NONE, "IOC", NULL, NULL, 331 jmr3927_ioc_interrupt, 0, CPU_MASK_NONE, "IOC", NULL, NULL,
296}; 332};
297 333
298static irqreturn_t jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs *regs) 334static irqreturn_t jmr3927_isac_interrupt(int irq, void *dev_id)
299{ 335{
300 unsigned char istat = jmr3927_isac_reg_in(JMR3927_ISAC_INTS2_ADDR); 336 unsigned char istat = jmr3927_isac_reg_in(JMR3927_ISAC_INTS2_ADDR);
301 int i; 337 int i;
@@ -303,7 +339,7 @@ static irqreturn_t jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs
303 for (i = 0; i < JMR3927_NR_IRQ_ISAC; i++) { 339 for (i = 0; i < JMR3927_NR_IRQ_ISAC; i++) {
304 if (istat & (1 << i)) { 340 if (istat & (1 << i)) {
305 irq = JMR3927_IRQ_ISAC + i; 341 irq = JMR3927_IRQ_ISAC + i;
306 do_IRQ(irq, regs); 342 do_IRQ(irq);
307 } 343 }
308 } 344 }
309 return IRQ_HANDLED; 345 return IRQ_HANDLED;
@@ -314,7 +350,7 @@ static struct irqaction isac_action = {
314}; 350};
315 351
316 352
317static irqreturn_t jmr3927_isaerr_interrupt(int irq, void * dev_id, struct pt_regs * regs) 353static irqreturn_t jmr3927_isaerr_interrupt(int irq, void *dev_id)
318{ 354{
319 printk(KERN_WARNING "ISA error interrupt (irq 0x%x).\n", irq); 355 printk(KERN_WARNING "ISA error interrupt (irq 0x%x).\n", irq);
320 356
@@ -324,7 +360,7 @@ static struct irqaction isaerr_action = {
324 jmr3927_isaerr_interrupt, 0, CPU_MASK_NONE, "ISA error", NULL, NULL, 360 jmr3927_isaerr_interrupt, 0, CPU_MASK_NONE, "ISA error", NULL, NULL,
325}; 361};
326 362
327static irqreturn_t jmr3927_pcierr_interrupt(int irq, void * dev_id, struct pt_regs * regs) 363static irqreturn_t jmr3927_pcierr_interrupt(int irq, void *dev_id)
328{ 364{
329 printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq); 365 printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq);
330 printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n", 366 printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n",
@@ -439,33 +475,3 @@ void jmr3927_irq_init(u32 irq_base)
439 475
440 jmr3927_irq_base = irq_base; 476 jmr3927_irq_base = irq_base;
441} 477}
442
443#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
444static int tx_branch_likely_bug_count = 0;
445static int have_tx_branch_likely_bug = 0;
446void tx_branch_likely_bug_fixup(struct pt_regs *regs)
447{
448 /* TX39/49-BUG: Under this condition, the insn in delay slot
449 of the branch likely insn is executed (not nullified) even
450 the branch condition is false. */
451 if (!have_tx_branch_likely_bug)
452 return;
453 if ((regs->cp0_epc & 0xfff) == 0xffc &&
454 KSEGX(regs->cp0_epc) != KSEG0 &&
455 KSEGX(regs->cp0_epc) != KSEG1) {
456 unsigned int insn = *(unsigned int*)(regs->cp0_epc - 4);
457 /* beql,bnel,blezl,bgtzl */
458 /* bltzl,bgezl,blezall,bgezall */
459 /* bczfl, bcztl */
460 if ((insn & 0xf0000000) == 0x50000000 ||
461 (insn & 0xfc0e0000) == 0x04020000 ||
462 (insn & 0xf3fe0000) == 0x41020000) {
463 regs->cp0_epc -= 4;
464 tx_branch_likely_bug_count++;
465 printk(KERN_INFO
466 "fix branch-likery bug in %s (insn %08x)\n",
467 current->comm, insn);
468 }
469 }
470}
471#endif