Example #1
0
/**
 * 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, &regmap_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;
}
Example #2
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;
	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;
}
Example #4
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;
}
Example #5
0
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;
}
Example #6
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;
}
Example #8
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;
}