static irqreturn_t pm8058_isr_thread(int irq_requested, void *data) { struct pm8058_chip *chip = data; int i, j, k; u8 root, block, config, bits; u8 blocks[MAX_PM_MASTERS]; int masters = 0, irq, handled = 0, spurious = 0; u16 irqs_to_handle[MAX_PM_IRQ]; mutex_lock(&chip->pm_lock); /* Read root for masters */ if (pm8058_read_root(chip, &root)) goto bail_out; masters = root >> 1; if (!(masters & chip->masters_allowed) || (masters & ~chip->masters_allowed)) { spurious = 1000000; } /* Read allowed masters for blocks. */ for (i = 0; i < chip->pm_max_masters; i++) { if (masters & (1 << i)) { if (pm8058_read_master(chip, i, &blocks[i])) goto bail_out; if (!blocks[i]) { if (pm8058_can_print()) pr_err("%s: Spurious master: %d " "(blocks=0)", __func__, i); spurious += 10000; } } else blocks[i] = 0; } /* Select block, read status and call isr */ for (i = 0; i < chip->pm_max_masters; i++) { if (!blocks[i]) continue; for (j = 0; j < 8; j++) { if (!(blocks[i] & (1 << j))) continue; block = i * 8 + j; /* block # */ if (pm8058_read_block(chip, &block, &bits)) goto bail_out; if (!bits) { if (pm8058_can_print()) pr_err("%s: Spurious block: " "[master, block]=[%d, %d] " "(bits=0)\n", __func__, i, j); spurious += 100; continue; } /* Check IRQ bits */ for (k = 0; k < 8; k++) { if (!(bits & (1 << k))) continue; /* Check spurious interrupts */ if (((1 << i) & chip->masters_allowed) && (blocks[i] & chip->blocks_allowed[i]) && (bits & chip->irqs_allowed[block])) { /* Found one */ irq = block * 8 + k; irqs_to_handle[handled] = irq + chip->pdata.irq_base; handled++; } else { /* Clear and mask wrong one */ config = PM8058_IRQF_W_C_M | (k << PM8058_IRQF_BITS_SHIFT); pm8058_config_irq(chip, &block, &config); if (pm8058_can_print()) pr_err("%s: Spurious IRQ: " "[master, block, bit]=" "[%d, %d (%d), %d]\n", __func__, i, j, block, k); spurious++; } } } } bail_out: mutex_unlock(&chip->pm_lock); for (i = 0; i < handled; i++) handle_nested_irq(irqs_to_handle[i]); for (i = 0; i < handled; i++) { irqs_to_handle[i] -= chip->pdata.irq_base; block = irqs_to_handle[i] / 8 ; config = PM8058_IRQF_WRITE | chip->config[irqs_to_handle[i]] | PM8058_IRQF_CLR; pm8058_config_irq(chip, &block, &config); } if (spurious) { if (!pm8058_can_print()) return IRQ_HANDLED; pr_err("%s: spurious = %d (handled = %d)\n", __func__, spurious, handled); pr_err(" root = 0x%x (masters_allowed<<1 = 0x%x)\n", root, chip->masters_allowed << 1); for (i = 0; i < chip->pm_max_masters; i++) { if (masters & (1 << i)) pr_err(" blocks[%d]=0x%x, " "allowed[%d]=0x%x\n", i, blocks[i], i, chip->blocks_allowed[i]); } } return IRQ_HANDLED; }
static irqreturn_t pm8058_isr_thread(int irq_requested, void *data) { struct pm8058_chip *chip = data; int i, j, k; u8 root, block, config, bits; u8 blocks[MAX_PM_MASTERS]; int masters = 0, irq, handled = 0, spurious = 0; u16 irqs_to_handle[MAX_PM_IRQ]; unsigned long irqsave; spin_lock_irqsave(&chip->pm_lock, irqsave); if (pm8058_read_root(chip, &root)) goto bail_out; masters = root >> 1; if (!(masters & chip->masters_allowed) || (masters & ~chip->masters_allowed)) { spurious = 1000000; } for (i = 0; i < chip->pm_max_masters; i++) { if (masters & (1 << i)) { if (pm8058_read_master(chip, i, &blocks[i])) goto bail_out; if (!blocks[i]) { if (pm8058_can_print()) pr_err("%s: Spurious master: %d " "(blocks=0)", __func__, i); spurious += 10000; } } else blocks[i] = 0; } for (i = 0; i < chip->pm_max_masters; i++) { if (!blocks[i]) continue; for (j = 0; j < 8; j++) { if (!(blocks[i] & (1 << j))) continue; block = i * 8 + j; if (pm8058_read_block(chip, &block, &bits)) goto bail_out; if (!bits) { if (pm8058_can_print()) pr_err("%s: Spurious block: " "[master, block]=[%d, %d] " "(bits=0)\n", __func__, i, j); spurious += 100; continue; } for (k = 0; k < 8; k++) { if (!(bits & (1 << k))) continue; if (((1 << i) & chip->masters_allowed) && (blocks[i] & chip->blocks_allowed[i]) && (bits & chip->irqs_allowed[block])) { irq = block * 8 + k; irqs_to_handle[handled] = irq + chip->pdata.irq_base; handled++; } else { config = PM8058_IRQF_W_C_M | (k < PM8058_IRQF_BITS_SHIFT); pm8058_config_irq(chip, &block, &config); if (pm8058_can_print()) pr_err("%s: Spurious IRQ: " "[master, block, bit]=" "[%d, %d (%d), %d]\n", __func__, i, j, block, k); spurious++; } } } } bail_out: spin_unlock_irqrestore(&chip->pm_lock, irqsave); for (i = 0; i < handled; i++) generic_handle_irq(irqs_to_handle[i]); if (spurious) { if (!pm8058_can_print()) return IRQ_HANDLED; pr_err("%s: spurious = %d (handled = %d)\n", __func__, spurious, handled); pr_err(" root = 0x%x (masters_allowed<<1 = 0x%x)\n", root, chip->masters_allowed << 1); for (i = 0; i < chip->pm_max_masters; i++) { if (masters & (1 << i)) pr_err(" blocks[%d]=0x%x, " "allowed[%d]=0x%x\n", i, blocks[i], i, chip->blocks_allowed[i]); } } return IRQ_HANDLED; }