#define BYT_VAL_REG            0x008
 #define BYT_DFT_REG            0x00c
 #define BYT_INT_STAT_REG       0x800
+#define BYT_DIRECT_IRQ_REG     0x980
 #define BYT_DEBOUNCE_REG       0x9d0
 
 /* BYT_CONF0_REG register bits */
        chip->irq_eoi(data);
 }
 
+static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 conf0)
+{
+       int direct_irq, ioapic_direct_irq_base;
+       u8 *match, direct_irq_mux[16];
+       u32 trig;
+
+       memcpy_fromio(direct_irq_mux, vg->communities->pad_regs + BYT_DIRECT_IRQ_REG,
+                     sizeof(direct_irq_mux));
+       match = memchr(direct_irq_mux, pin, sizeof(direct_irq_mux));
+       if (!match) {
+               dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set but no IRQ assigned, clearing\n", pin);
+               return false;
+       }
+
+       direct_irq = match - direct_irq_mux;
+       /* Base IO-APIC pin numbers come from atom-e3800-family-datasheet.pdf */
+       ioapic_direct_irq_base = (vg->communities->npins == BYT_NGPIO_SCORE) ? 51 : 67;
+       dev_dbg(vg->dev, "Pin %i: uses direct IRQ %d (IO-APIC %d)\n", pin,
+               direct_irq, direct_irq + ioapic_direct_irq_base);
+
+       /*
+        * Testing has shown that the way direct IRQs work is that the combination of the
+        * direct-irq-en flag and the direct IRQ mux connect the output of the GPIO's IRQ
+        * trigger block, which normally sets the status flag in the IRQ status reg at
+        * 0x800, to one of the IO-APIC pins according to the mux registers.
+        *
+        * This means that:
+        * 1. The TRIG_MASK bits must be set to configure the GPIO's IRQ trigger block
+        * 2. The TRIG_LVL bit *must* be set, so that the GPIO's input value is directly
+        *    passed (1:1 or inverted) to the IO-APIC pin, if TRIG_LVL is not set,
+        *    selecting edge mode operation then on the first edge the IO-APIC pin goes
+        *    high, but since no write-to-clear write will be done to the IRQ status reg
+        *    at 0x800, the detected edge condition will never get cleared.
+        */
+       trig = conf0 & BYT_TRIG_MASK;
+       if (trig != (BYT_TRIG_POS | BYT_TRIG_LVL) &&
+           trig != (BYT_TRIG_NEG | BYT_TRIG_LVL)) {
+               dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set without trigger (conf0: %xh), clearing\n",
+                        pin, conf0);
+               return false;
+       }
+
+       return true;
+}
+
 static void byt_init_irq_valid_mask(struct gpio_chip *chip,
                                    unsigned long *valid_mask,
                                    unsigned int ngpios)
 
                value = readl(reg);
                if (value & BYT_DIRECT_IRQ_EN) {
-                       clear_bit(i, valid_mask);
-                       dev_dbg(vg->dev, "excluding GPIO %d from IRQ domain\n", i);
+                       if (byt_direct_irq_sanity_check(vg, i, value)) {
+                               clear_bit(i, valid_mask);
+                       } else {
+                               value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS |
+                                          BYT_TRIG_NEG | BYT_TRIG_LVL);
+                               writel(value, reg);
+                       }
                } else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
                        byt_gpio_clear_triggering(vg, i);
                        dev_dbg(vg->dev, "disabling GPIO %d\n", i);