/** * regmap_add_irq_chip(): Use standard regmap IRQ controller handling * * map: The regmap for the device. * irq: The IRQ the device uses to signal interrupts * irq_flags: The IRQF_ flags to use for the primary interrupt. * chip: Configuration for the interrupt controller. * data: Runtime data structure for the controller, allocated on success * * Returns 0 on success or an errno on failure. * * In order for this to be efficient the chip really should use a * register cache. The chip driver is responsible for restoring the * register values used by the IRQ controller over suspend and resume. */ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, int irq_base, struct regmap_irq_chip *chip, struct regmap_irq_chip_data **data) { struct regmap_irq_chip_data *d; int cur_irq, i; int ret = -ENOMEM; irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0); if (irq_base < 0) { dev_warn(map->dev, "Failed to allocate IRQs: %d\n", irq_base); return irq_base; } d = kzalloc(sizeof(*d), GFP_KERNEL); if (!d) return -ENOMEM; d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs, GFP_KERNEL); if (!d->status_buf) goto err_alloc; d->status_reg_buf = kzalloc(map->format.val_bytes * chip->num_regs, GFP_KERNEL); if (!d->status_reg_buf) goto err_alloc; d->mask_buf = kzalloc(sizeof(unsigned int) * chip->num_regs, GFP_KERNEL); if (!d->mask_buf) goto err_alloc; d->mask_buf_def = kzalloc(sizeof(unsigned int) * chip->num_regs, GFP_KERNEL); if (!d->mask_buf_def) goto err_alloc; d->map = map; d->chip = chip; d->irq_base = irq_base; mutex_init(&d->lock); for (i = 0; i < chip->num_irqs; i++) d->mask_buf_def[chip->irqs[i].reg_offset] |= chip->irqs[i].mask; /* Mask all the interrupts by default */ for (i = 0; i < chip->num_regs; i++) { d->mask_buf[i] = d->mask_buf_def[i]; ret = regmap_write(map, chip->mask_base + i, d->mask_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", chip->mask_base + i, ret); goto err_alloc; } } /* Register them with genirq */ for (cur_irq = irq_base; cur_irq < chip->num_irqs + irq_base; cur_irq++) { irq_set_chip_data(cur_irq, d); irq_set_chip_and_handler(cur_irq, ®map_irq_chip, handle_edge_irq); irq_set_nested_thread(cur_irq, 1); /* ARM needs us to explicitly flag the IRQ as valid * and will set them noprobe when we do so. */ #ifdef CONFIG_ARM set_irq_flags(cur_irq, IRQF_VALID); #else irq_set_noprobe(cur_irq); #endif } ret = request_threaded_irq(irq, NULL, regmap_irq_thread, irq_flags, chip->name, d); if (ret != 0) { dev_err(map->dev, "Failed to request IRQ %d: %d\n", irq, ret); goto err_alloc; } return 0; err_alloc: kfree(d->mask_buf_def); kfree(d->mask_buf); kfree(d->status_reg_buf); kfree(d->status_buf); kfree(d); return ret; }
int arizona_irq_init(struct arizona *arizona) { int flags = IRQF_ONESHOT; int ret, i; struct regmap_irq_chip *aod, *irq; bool ctrlif_error = true; int irq_base; struct irq_data *irq_data; switch (arizona->type) { #ifdef CONFIG_MFD_WM5102 case WM5102: aod = &wm5102_aod; irq = &wm5102_irq; ctrlif_error = false; break; #endif #ifdef CONFIG_MFD_WM5110 case WM5110: aod = &wm5110_aod; irq = &wm5110_irq; ctrlif_error = false; break; #endif default: BUG_ON("Unknown Arizona class device" == NULL); return -EINVAL; } /* Disable all wake sources by default */ regmap_write(arizona->regmap, ARIZONA_WAKE_CONTROL, 0); /* Read the flags from the interrupt controller if not specified */ if (!arizona->pdata.irq_flags) { irq_data = irq_get_irq_data(arizona->irq); if (!irq_data) { dev_err(arizona->dev, "Invalid IRQ: %d\n", arizona->irq); return -EINVAL; } arizona->pdata.irq_flags = irqd_get_trigger_type(irq_data); switch (arizona->pdata.irq_flags) { case IRQF_TRIGGER_LOW: case IRQF_TRIGGER_HIGH: case IRQF_TRIGGER_RISING: case IRQF_TRIGGER_FALLING: break; case IRQ_TYPE_NONE: default: /* Device default */ arizona->pdata.irq_flags = IRQF_TRIGGER_LOW; break; } } if (arizona->pdata.irq_flags & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_RISING)) { ret = regmap_update_bits(arizona->regmap, ARIZONA_IRQ_CTRL_1, ARIZONA_IRQ_POL, 0); if (ret != 0) { dev_err(arizona->dev, "Couldn't set IRQ polarity: %d\n", ret); goto err; } } flags |= arizona->pdata.irq_flags; /* set up virtual IRQs */ irq_base = irq_alloc_descs(arizona->pdata.irq_base, 0, ARRAY_SIZE(arizona->virq), 0); if (irq_base < 0) { dev_warn(arizona->dev, "Failed to allocate IRQs: %d\n", irq_base); return irq_base; } arizona->virq[0] = irq_base; arizona->virq[1] = irq_base + 1; irq_base += 2; for (i = 0; i < ARRAY_SIZE(arizona->virq); i++) { irq_set_chip_and_handler(arizona->virq[i], &arizona_irq_chip, handle_edge_irq); irq_set_nested_thread(arizona->virq[i], 1); /* ARM needs us to explicitly flag the IRQ as valid * and will set them noprobe when we do so. */ #ifdef CONFIG_ARM set_irq_flags(arizona->virq[i], IRQF_VALID); #else irq_set_noprobe(arizona->virq[i]); #endif } ret = regmap_add_irq_chip(arizona->regmap, arizona->virq[0], IRQF_ONESHOT, irq_base, aod, &arizona->aod_irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret); goto err_domain; } ret = regmap_add_irq_chip(arizona->regmap, arizona->virq[1], IRQF_ONESHOT, irq_base + ARIZONA_NUM_IRQ, irq, &arizona->irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add IRQs: %d\n", ret); goto err_aod; } /* Make sure the boot done IRQ is unmasked for resumes */ i = arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE); ret = request_threaded_irq(i, NULL, arizona_boot_done, IRQF_ONESHOT, "Boot done", arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to request boot done %d: %d\n", arizona->irq, ret); goto err_boot_done; } /* Handle control interface errors in the core */ if (ctrlif_error) { i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR); ret = request_threaded_irq(i, NULL, arizona_ctrlif_err, IRQF_ONESHOT, "Control interface error", arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to request CTRLIF_ERR %d: %d\n", arizona->irq, ret); goto err_ctrlif; } } /* Used to emulate edge trigger and to work around broken pinmux */ if (arizona->pdata.irq_gpio) { if (gpio_to_irq(arizona->pdata.irq_gpio) != arizona->irq) { dev_warn(arizona->dev, "IRQ %d is not GPIO %d (%d)\n", arizona->irq, arizona->pdata.irq_gpio, gpio_to_irq(arizona->pdata.irq_gpio)); arizona->irq = gpio_to_irq(arizona->pdata.irq_gpio); } ret = gpio_request_one(arizona->pdata.irq_gpio, GPIOF_IN, "arizona IRQ"); if (ret != 0) { dev_err(arizona->dev, "Failed to request IRQ GPIO %d:: %d\n", arizona->pdata.irq_gpio, ret); arizona->pdata.irq_gpio = 0; } } ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread, flags, "arizona", arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to request primary IRQ %d: %d\n", arizona->irq, ret); goto err_main_irq; } return 0; err_main_irq: free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona); err_ctrlif: free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona); err_boot_done: regmap_del_irq_chip(arizona->virq[1], arizona->irq_chip); err_aod: regmap_del_irq_chip(arizona->virq[0], arizona->aod_irq_chip); err_domain: err: return ret; }
int max77804k_irq_init(struct max77804k_dev *max77804k) { int i; int cur_irq; int ret; u8 i2c_data; pr_info("func: %s, irq_gpio: %d, irq_base: %d\n", __func__, max77804k->irq_gpio, max77804k->irq_base); if (!max77804k->irq_gpio) { dev_warn(max77804k->dev, "No interrupt specified.\n"); max77804k->irq_base = 0; return 0; } if (!max77804k->irq_base) { dev_err(max77804k->dev, "No interrupt base specified.\n"); return 0; } mutex_init(&max77804k->irqlock); max77804k->irq = gpio_to_irq(max77804k->irq_gpio); ret = gpio_request(max77804k->irq_gpio, "if_pmic_irq"); if (ret) { dev_err(max77804k->dev, "%s: failed requesting gpio %d\n", __func__, max77804k->irq_gpio); return ret; } gpio_direction_input(max77804k->irq_gpio); gpio_free(max77804k->irq_gpio); /* Mask individual interrupt sources */ for (i = 0; i < MAX77804K_IRQ_GROUP_NR; i++) { struct i2c_client *i2c; /* MUIC IRQ 0:MASK 1:NOT MASK */ /* Other IRQ 1:MASK 0:NOT MASK */ if (i >= MAX77804K_MUIC_INT1 && i <= MAX77804K_MUIC_INT3) { max77804k->irq_masks_cur[i] = 0x00; max77804k->irq_masks_cache[i] = 0x00; } else { max77804k->irq_masks_cur[i] = 0xff; max77804k->irq_masks_cache[i] = 0xff; } i2c = get_i2c(max77804k, i); if (IS_ERR_OR_NULL(i2c)) continue; if (max77804k_mask_reg[i] == MAX77804K_REG_INVALID) continue; if (i >= MAX77804K_MUIC_INT1 && i <= MAX77804K_MUIC_INT3) max77804k_write_reg(i2c, max77804k_mask_reg[i], 0x00); else max77804k_write_reg(i2c, max77804k_mask_reg[i], 0xff); } /* Register with genirq */ for (i = 0; i < MAX77804K_IRQ_NR; i++) { cur_irq = i + max77804k->irq_base; irq_set_chip_data(cur_irq, max77804k); irq_set_chip_and_handler(cur_irq, &max77804k_irq_chip, handle_edge_irq); irq_set_nested_thread(cur_irq, 1); #ifdef CONFIG_ARM set_irq_flags(cur_irq, IRQF_VALID); #else irq_set_noprobe(cur_irq); #endif } /* Unmask max77804k interrupt */ ret = max77804k_read_reg(max77804k->i2c, MAX77804K_PMIC_REG_INTSRC_MASK, &i2c_data); if (ret) { dev_err(max77804k->dev, "%s: fail to read muic reg\n", __func__); return ret; } i2c_data &= ~(MAX77804K_IRQSRC_CHG); /* Unmask charger interrupt */ i2c_data &= ~(MAX77804K_IRQSRC_MUIC); /* Unmask muic interrupt */ max77804k_write_reg(max77804k->i2c, MAX77804K_PMIC_REG_INTSRC_MASK, i2c_data); ret = request_threaded_irq(max77804k->irq, NULL, max77804k_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "max77804k-irq", max77804k); if (ret) { dev_err(max77804k->dev, "Failed to request IRQ %d: %d\n", max77804k->irq, ret); return ret; } return 0; }
int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end, unsigned long features) { int status; int i; u8 mask[4]; static struct irq_chip twl6030_irq_chip; if (features & TWL6032_SUBCLASS) twl6030_interrupt_mapping = twl6032_interrupt_mapping_table; mask[1] = 0xFF; mask[2] = 0xFF; mask[3] = 0xFF; status = twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */ status |= twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */ status |= twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */ if (status < 0) { pr_err("twl6030: I2C err writing TWL_MODULE_PIH: %d\n", status); return status; } twl6030_irq_base = irq_base; twl6030_irq_end = irq_end; /* install an irq handler for each of the modules; * clone dummy irq_chip since PIH can't *do* anything */ twl6030_irq_chip = dummy_irq_chip; twl6030_irq_chip.name = "twl6030"; twl6030_irq_chip.irq_set_type = NULL; twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake; for (i = irq_base; i < irq_end; i++) { irq_set_chip_and_handler(i, &twl6030_irq_chip, handle_simple_irq); irq_set_chip_data(i, (void *)irq_num); irq_set_nested_thread(i, 1); activate_irq(i); } twl6030_irq_next = i; pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", irq_num, irq_base, twl6030_irq_next - 1); status = request_threaded_irq(irq_num, NULL, twl6030_irq_thread, IRQF_ONESHOT, "TWL6030-PIH", NULL); if (status < 0) { pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); goto fail_irq; } twl_irq = irq_num; register_pm_notifier(&twl6030_irq_pm_notifier_block); status = twl6030_vlow_init(twl6030_irq_base + TWL_VLOW_INTR_OFFSET); if (status < 0) goto fail_vlow; return status; fail_vlow: free_irq(irq_num, NULL); fail_irq: for (i = irq_base; i < irq_end; i++) irq_set_chip_and_handler(i, NULL, NULL); return status; }
int sec_irq_init(struct sec_pmic_dev *sec_pmic) { int i, reg_int1m, reg_irq_nr; int cur_irq; int ret = 0; int type = sec_pmic->device_type; if (!sec_pmic->irq) { dev_warn(sec_pmic->dev, "No interrupt specified, no interrupts\n"); sec_pmic->irq_base = 0; return 0; } if (!sec_pmic->irq_base) { dev_err(sec_pmic->dev, "No interrupt base specified, no interrupts\n"); return 0; } mutex_init(&sec_pmic->irqlock); switch (type) { case S5M8763X: reg_int1m = S5M8763_REG_IRQM1; reg_irq_nr = S5M8763_IRQ_NR; break; case S5M8767X: reg_int1m = S5M8767_REG_INT1M; reg_irq_nr = S5M8767_IRQ_NR; break; case S2MPS11X: reg_int1m = S2MPS11_REG_INT1M; reg_irq_nr = S2MPS11_IRQ_NR; break; default: dev_err(sec_pmic->dev, "Unknown device type %d\n", sec_pmic->device_type); return -EINVAL; } for (i = 0; i < NUM_IRQ_REGS - 1; i++) { sec_pmic->irq_masks_cur[i] = 0xff; sec_pmic->irq_masks_cache[i] = 0xff; sec_reg_write(sec_pmic, reg_int1m + i, 0xff); } for (i = 0; i < reg_irq_nr; i++) { cur_irq = i + sec_pmic->irq_base; ret = irq_set_chip_data(cur_irq, sec_pmic); if (ret) { dev_err(sec_pmic->dev, "Failed to irq_set_chip_data %d: %d\n", sec_pmic->irq, ret); return ret; } irq_set_chip_and_handler(cur_irq, &sec_pmic_irq_chip, handle_edge_irq); irq_set_nested_thread(cur_irq, 1); #ifdef CONFIG_ARM set_irq_flags(cur_irq, IRQF_VALID); #else irq_set_noprobe(cur_irq); #endif } ret = request_threaded_irq(sec_pmic->irq, NULL, sec_pmic_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "sec-pmic-irq", sec_pmic); if (ret) { dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n", sec_pmic->irq, ret); return ret; } if (!sec_pmic->ono) return 0; ret = request_threaded_irq(sec_pmic->ono, NULL, sec_pmic_irq_thread, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "sec-pmic-ono", sec_pmic); if (ret) { dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n", sec_pmic->ono, ret); return ret; } return 0; }
int arizona_irq_init(struct arizona *arizona) { int flags = IRQF_ONESHOT; int ret, i; struct regmap_irq_chip *aod, *irq; bool ctrlif_error = true; int irq_base; switch (arizona->type) { #ifdef CONFIG_MFD_WM5102 case WM5102: aod = &wm5102_aod; irq = &wm5102_irq; switch (arizona->rev) { case 0: ctrlif_error = false; break; default: break; } break; #endif #ifdef CONFIG_MFD_WM5110 case WM5110: aod = &wm5110_aod; irq = &wm5110_irq; switch (arizona->rev) { case 0: ctrlif_error = false; break; default: break; } break; #endif default: BUG_ON("Unknown Arizona class device" == NULL); return -EINVAL; } if (arizona->pdata.irq_active_high) { ret = regmap_update_bits(arizona->regmap, ARIZONA_IRQ_CTRL_1, ARIZONA_IRQ_POL, 0); if (ret != 0) { dev_err(arizona->dev, "Couldn't set IRQ polarity: %d\n", ret); goto err; } flags |= IRQF_TRIGGER_HIGH; } else { flags |= IRQF_TRIGGER_LOW; } /* set virtual IRQs */ if (arizona->pdata.irq_base > 0) { arizona->virq[0] = arizona->pdata.irq_base; arizona->virq[1] = arizona->pdata.irq_base + 1; } else { dev_err(arizona->dev, "No irq_base specified\n"); return -EINVAL; } ret = irq_alloc_descs(arizona->pdata.irq_base, 0, ARRAY_SIZE(arizona->virq), 0); if (ret < 0) { dev_err(arizona->dev, "Failed to allocate IRQs: %d\n", ret); return ret; } for (i = 0; i < ARRAY_SIZE(arizona->virq); i++) { irq_set_chip_data(arizona->virq[i], arizona); irq_set_chip_and_handler(arizona->virq[i], &arizona_irq_chip, handle_edge_irq); irq_set_nested_thread(arizona->virq[i], 1); /* ARM needs us to explicitly flag the IRQ as valid and * will set them noprobe when we do so. */ #ifdef CONFIG_ARM set_irq_flags(arizona->virq[i], IRQF_VALID); #else irq_set_noprobe(arizona->virq[i]); #endif } irq_base = arizona->pdata.irq_base + 2; ret = regmap_add_irq_chip(arizona->regmap, arizona->virq[0], IRQF_ONESHOT, irq_base, aod, &arizona->aod_irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret); goto err_domain; } irq_base = arizona->pdata.irq_base + 2 + ARIZONA_NUM_IRQ; ret = regmap_add_irq_chip(arizona->regmap, arizona->virq[1], IRQF_ONESHOT, irq_base, irq, &arizona->irq_chip); if (ret != 0) { dev_err(arizona->dev, "Failed to add IRQs: %d\n", ret); goto err_aod; } /* Make sure the boot done IRQ is unmasked for resumes */ i = arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE); ret = request_threaded_irq(i, NULL, arizona_boot_done, IRQF_ONESHOT, "Boot done", arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to request boot done %d: %d\n", arizona->irq, ret); goto err_boot_done; } /* Handle control interface errors in the core */ if (ctrlif_error) { i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR); ret = request_threaded_irq(i, NULL, arizona_ctrlif_err, IRQF_ONESHOT, "Control interface error", arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to request CTRLIF_ERR %d: %d\n", arizona->irq, ret); goto err_ctrlif; } } ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread, flags, "arizona", arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to request IRQ %d: %d\n", arizona->irq, ret); goto err_main_irq; } return 0; err_main_irq: free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona); err_ctrlif: free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona); err_boot_done: regmap_del_irq_chip(arizona->virq[1], arizona->irq_chip); err_aod: regmap_del_irq_chip(arizona->virq[0], arizona->aod_irq_chip); err_domain: err: return ret; }
int max77828_irq_init(struct max77828_dev *max77828) { int i; int cur_irq; int ret; if (!max77828->irq_gpio) { dev_warn(max77828->dev, "No interrupt specified.\n"); max77828->irq_base = 0; return 0; } if (!max77828->irq_base) { dev_err(max77828->dev, "No interrupt base specified.\n"); return 0; } mutex_init(&max77828->irqlock); max77828->irq = gpio_to_irq(max77828->irq_gpio); pr_info("%s:%s irq=%d, irq->gpio=%d\n", MFD_DEV_NAME, __func__, max77828->irq, max77828->irq_gpio); ret = gpio_request(max77828->irq_gpio, "if_pmic_irq"); if (ret) { dev_err(max77828->dev, "%s: failed requesting gpio %d\n", __func__, max77828->irq_gpio); return ret; } gpio_direction_input(max77828->irq_gpio); gpio_free(max77828->irq_gpio); /* Mask individual interrupt sources */ for (i = 0; i < MAX77828_IRQ_GROUP_NR; i++) { struct i2c_client *i2c; /* MUIC IRQ 0:MASK 1:NOT MASK */ /* Other IRQ 1:MASK 0:NOT MASK */ if (i >= MUIC_INT1 && i <= MUIC_INT3) { max77828->irq_masks_cur[i] = 0x00; max77828->irq_masks_cache[i] = 0x00; } else { max77828->irq_masks_cur[i] = 0xff; max77828->irq_masks_cache[i] = 0xff; } i2c = get_i2c(max77828, i); if (IS_ERR_OR_NULL(i2c)) continue; if (max77828_mask_reg[i] == MAX77828_REG_INVALID) continue; if (i >= MUIC_INT1 && i <= MUIC_INT3) max77828_write_reg(i2c, max77828_mask_reg[i], 0x00); else max77828_write_reg(i2c, max77828_mask_reg[i], 0xff); } /* Register with genirq */ for (i = 0; i < MAX77828_IRQ_NR; i++) { cur_irq = i + max77828->irq_base; irq_set_chip_data(cur_irq, max77828); irq_set_chip_and_handler(cur_irq, &max77828_irq_chip, handle_level_irq); irq_set_nested_thread(cur_irq, 1); #ifdef CONFIG_ARM set_irq_flags(cur_irq, IRQF_VALID); #else irq_set_noprobe(cur_irq); #endif } ret = request_threaded_irq(max77828->irq, NULL, max77828_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "max77828-irq", max77828); if (ret) { dev_err(max77828->dev, "Failed to request IRQ %d: %d\n", max77828->irq, ret); return ret; } return 0; }
int max77665_irq_init(struct max77665_dev *max77665) { int i; int cur_irq; int ret; u8 i2c_data; if (!max77665->irq) { dev_warn(max77665->dev, "No interrupt specified.\n"); max77665->irq_base = 0; return 0; } if (!max77665->irq_base) { dev_err(max77665->dev, "No interrupt base specified.\n"); return 0; } mutex_init(&max77665->irqlock); /* Mask individual interrupt sources */ for (i = 0; i < MAX77665_IRQ_GROUP_NR; i++) { struct i2c_client *i2c; if(i == MUIC_INT1) { max77665->irq_masks_cur[i] = 0x00; max77665->irq_masks_cache[i] = 0x00; } else { max77665->irq_masks_cur[i] = 0xff; max77665->irq_masks_cache[i] = 0xff; } i2c = get_i2c(max77665, i); if (IS_ERR_OR_NULL(i2c)) continue; if (max77665_mask_reg[i] == MAX77665_REG_INVALID) continue; if(i == MUIC_INT1) { max77665_write_reg(i2c, max77665_mask_reg[i], 0x00); } else { max77665_write_reg(i2c, max77665_mask_reg[i], 0xff); } } /* Register with genirq */ for (i = 0; i < MAX77665_IRQ_NR; i++) { cur_irq = i + max77665->irq_base; irq_set_chip_data(cur_irq, max77665); irq_set_chip_and_handler(cur_irq, &max77665_irq_chip, handle_edge_irq); irq_set_nested_thread(cur_irq, 1); #ifdef CONFIG_ARM set_irq_flags(cur_irq, IRQF_VALID); #else irq_set_noprobe(cur_irq); #endif } /* Unmask max77665 interrupt */ ret = max77665_read_reg(max77665->i2c, MAX77665_PMIC_REG_INTSRC_MASK, &i2c_data); if (ret) { dev_err(max77665->dev, "%s: fail to read muic reg\n", __func__); return ret; } i2c_data &= ~(MAX77665_IRQSRC_CHG); /* Unmask charger interrupt */ i2c_data &= ~(MAX77665_IRQSRC_MUIC); /* Unmask muic interrupt */ max77665_write_reg(max77665->i2c, MAX77665_PMIC_REG_INTSRC_MASK, i2c_data); ret = request_threaded_irq(max77665->irq, NULL, max77665_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "max77665-irq", max77665); if (ret) { dev_err(max77665->dev, "Failed to request IRQ %d: %d\n", max77665->irq, ret); return ret; } return 0; }