finally fix pesky irq issues
[openwrt/svn-archive/archive.git] / openwrt / target / linux / aruba-2.6 / patches / 002-irq.patch
index d789a2104b6a89b393b9821f52dd29f739fb8ed3..308c39903d5a425f8794c992528beda5e5a9b061 100644 (file)
@@ -92,7 +92,7 @@ diff -Nur linux-2.6.15/arch/mips/aruba/idtIRQ.S linux-2.6.15-openwrt/arch/mips/a
 diff -Nur linux-2.6.15/arch/mips/aruba/irq.c linux-2.6.15-openwrt/arch/mips/aruba/irq.c
 --- linux-2.6.15/arch/mips/aruba/irq.c 1970-01-01 01:00:00.000000000 +0100
 +++ linux-2.6.15-openwrt/arch/mips/aruba/irq.c 2006-01-10 00:32:32.000000000 +0100
-@@ -0,0 +1,393 @@
+@@ -0,0 +1,424 @@
 +/**************************************************************************
 + *
 + *  BRIEF MODULE DESCRIPTION
@@ -242,9 +242,14 @@ diff -Nur linux-2.6.15/arch/mips/aruba/irq.c linux-2.6.15-openwrt/arch/mips/arub
 +
 +static void aruba_enable_irq(unsigned int irq_nr)
 +{
++      unsigned long flags;
 +      int ip = irq_nr - GROUP0_IRQ_BASE;
 +      unsigned int group, intr_bit;
 +      volatile unsigned int *addr;
++
++
++      local_irq_save(flags);
++      
 +      if (ip < 0) {
 +              enable_local_irq(irq_nr);
 +      } else {
@@ -281,57 +286,70 @@ diff -Nur linux-2.6.15/arch/mips/aruba/irq.c linux-2.6.15-openwrt/arch/mips/arub
 +                              break;
 +              }
 +      }
++
++      local_irq_restore(flags);
++
 +}
 +
 +static void aruba_disable_irq(unsigned int irq_nr)
 +{
++      unsigned long flags;
 +      int ip = irq_nr - GROUP0_IRQ_BASE;
 +      unsigned int group, intr_bit, mask;
 +      volatile unsigned int *addr;
 +
-+      // calculate group
-+      switch (mips_machtype) {
-+              case MACH_ARUBA_AP70:
-+                      group = ip >> 5;
-+                      break;
-+              case MACH_ARUBA_AP65:
-+              case MACH_ARUBA_AP60:
-+              default:
-+                      group = 0;
-+                      break;
-+      }
++      local_irq_save(flags);
 +
-+      // calc interrupt bit within group
-+      ip -= group << 5;
-+      intr_bit = 1 << ip;
++      if (ip < 0) {
++              disable_local_irq(irq_nr);
++      } else {
++              // calculate group
++              switch (mips_machtype) {
++                      case MACH_ARUBA_AP70:
++                              group = ip >> 5;
++                              break;
++                      case MACH_ARUBA_AP65:
++                      case MACH_ARUBA_AP60:
++                      default:
++                              group = 0;
++                              break;
++              }
 +
-+      switch (mips_machtype) {
-+              case MACH_ARUBA_AP70:
-+                      addr = intr_group_muscat[group].base_addr;
-+                      // mask intr within group
-+                      mask = READ_MASK_MUSCAT(addr);
-+                      mask |= intr_bit;
-+                      WRITE_MASK_MUSCAT(addr, mask);
++              // calc interrupt bit within group
++              ip -= group << 5;
++              intr_bit = 1 << ip;
++
++              switch (mips_machtype) {
++                      case MACH_ARUBA_AP70:
++                              addr = intr_group_muscat[group].base_addr;
++                              // mask intr within group
++                              mask = READ_MASK_MUSCAT(addr);
++                              mask |= intr_bit;
++                              WRITE_MASK_MUSCAT(addr, mask);
 +      
-+                      /*
-+                         if there are no more interrupts enabled in this
-+                         group, disable corresponding IP
-+                       */
-+                      if (mask == intr_group_muscat[group].mask)
-+                              disable_local_irq(group_to_ip(group));
-+                      break;
-+              case MACH_ARUBA_AP65:
-+              case MACH_ARUBA_AP60:
-+              default:
-+                      addr = intr_group_merlot[group].base_addr;
-+                      // mask intr within group
-+                      mask = READ_MASK_MERLOT(addr);
-+                      mask &= ~intr_bit;
-+                      WRITE_MASK_MERLOT(addr, mask);
-+                      if (!mask)
-+                              disable_local_irq(group_to_ip(group));
-+                      break;
++                              /*
++                                 if there are no more interrupts enabled in this
++                                 group, disable corresponding IP
++                               */
++                              if (mask == intr_group_muscat[group].mask)
++                                      disable_local_irq(group_to_ip(group));
++                              break;
++                      case MACH_ARUBA_AP65:
++                      case MACH_ARUBA_AP60:
++                      default:
++                              addr = intr_group_merlot[group].base_addr;
++                              // mask intr within group
++                              mask = READ_MASK_MERLOT(addr);
++                              mask &= ~intr_bit;
++                              WRITE_MASK_MERLOT(addr, mask);
++                              if (!mask)
++                                      disable_local_irq(group_to_ip(group));
++                              break;
++              }
 +      }
++
++      local_irq_restore(flags);
++
 +}
 +
 +static unsigned int startup_irq(unsigned int irq_nr)
@@ -355,50 +373,60 @@ diff -Nur linux-2.6.15/arch/mips/aruba/irq.c linux-2.6.15-openwrt/arch/mips/arub
 +static void end_irq(unsigned int irq_nr)
 +{
 +
++      unsigned long flags;
 +      int ip = irq_nr - GROUP0_IRQ_BASE;
 +      unsigned int intr_bit, group;
 +      volatile unsigned int *addr;
 +
++
++      local_irq_save(flags);
 +      if (irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)) {
-+              printk("warning: end_irq %d did not enable (%x)\n",
++              printk("warning: end_irq %d did not enable (%x) (ignoring)\n",
 +                     irq_nr, irq_desc[irq_nr].status);
 +      }
 +
-+      switch (mips_machtype) {
-+              case MACH_ARUBA_AP70:
-+                      if (irq_nr == GROUP4_IRQ_BASE + 9)       idt_gpio->gpioistat &= 0xfffffdff;
-+                      else if (irq_nr == GROUP4_IRQ_BASE + 10) idt_gpio->gpioistat &= 0xfffffbff;
-+                      else if (irq_nr == GROUP4_IRQ_BASE + 11) idt_gpio->gpioistat &= 0xfffff7ff;
-+                      else if (irq_nr == GROUP4_IRQ_BASE + 12) idt_gpio->gpioistat &= 0xffffefff;
-+      
-+                      group = ip >> 5;
++      if (ip<0) {
++              enable_local_irq(irq_nr);
++      } else {
++
++              switch (mips_machtype) {
++                      case MACH_ARUBA_AP70:
++                              if (irq_nr == GROUP4_IRQ_BASE + 9)       idt_gpio->gpioistat &= 0xfffffdff;
++                              else if (irq_nr == GROUP4_IRQ_BASE + 10) idt_gpio->gpioistat &= 0xfffffbff;
++                              else if (irq_nr == GROUP4_IRQ_BASE + 11) idt_gpio->gpioistat &= 0xfffff7ff;
++                              else if (irq_nr == GROUP4_IRQ_BASE + 12) idt_gpio->gpioistat &= 0xffffefff;
++              
++                              group = ip >> 5;
++                      
++                              // calc interrupt bit within group
++                              ip -= (group << 5);
++                              intr_bit = 1 << ip;
++              
++                              // first enable the IP mapped to this IRQ
++                              enable_local_irq(group_to_ip(group));
++              
++                              addr = intr_group_muscat[group].base_addr;
++                              // unmask intr within group
++                              WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
++                              break;
++
++                      case MACH_ARUBA_AP65:
++                              case MACH_ARUBA_AP60:
++                              group = 0;
 +      
-+                      // calc interrupt bit within group
-+                      ip -= (group << 5);
-+                      intr_bit = 1 << ip;
++                              // calc interrupt bit within group
++                              intr_bit = 1 << ip;
 +      
-+                      // first enable the IP mapped to this IRQ
-+                      enable_local_irq(group_to_ip(group));
++                              // first enable the IP mapped to this IRQ
++                              enable_local_irq(group_to_ip(group));
 +      
-+                      addr = intr_group_muscat[group].base_addr;
-+                      // unmask intr within group
-+                      WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
-+                      break;
-+              case MACH_ARUBA_AP65:
-+              case MACH_ARUBA_AP60:
-+                      group = 0;
-+
-+                      // calc interrupt bit within group
-+                      intr_bit = 1 << ip;
-+
-+                      // first enable the IP mapped to this IRQ
-+                      enable_local_irq(group_to_ip(group));
-+
-+                      addr = intr_group_merlot[group].base_addr;
-+                      // unmask intr within group
-+                      WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
-+                      break;
++                              addr = intr_group_merlot[group].base_addr;
++                              // unmask intr within group
++                              WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
++                              break;
++              }
 +      }
++      local_irq_restore(flags);
 +}
 +
 +static struct hw_interrupt_type aruba_irq_type = {
@@ -418,6 +446,9 @@ diff -Nur linux-2.6.15/arch/mips/aruba/irq.c linux-2.6.15-openwrt/arch/mips/arub
 +      memset(irq_desc, 0, sizeof(irq_desc));
 +      set_except_vector(0, idtIRQ);
 +
++
++      set_c0_status(0xFF00);
++
 +      for (i = 0; i < RC32434_NR_IRQS; i++) {
 +              irq_desc[i].status = IRQ_DISABLED;
 +              irq_desc[i].action = NULL;