12c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim/*
22c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim * Interrupt controller support for MAX8998
32c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim *
42c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim * Copyright (C) 2010 Samsung Electronics Co.Ltd
52c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim * Author: Joonyoung Shim <jy0922.shim@samsung.com>
62c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim *
72c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim * This program is free software; you can redistribute  it and/or modify it
82c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim * under  the terms of  the GNU General  Public License as published by the
92c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim * Free Software Foundation;  either version 2 of the  License, or (at your
102c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim * option) any later version.
112c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim *
122c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim */
132c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
142c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim#include <linux/device.h>
152c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim#include <linux/interrupt.h>
162c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim#include <linux/irq.h>
172c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim#include <linux/mfd/max8998-private.h>
182c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
192c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimstruct max8998_irq_data {
202c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int reg;
212c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int mask;
222c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim};
232c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
242c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimstatic struct max8998_irq_data max8998_irqs[] = {
252c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_DCINF] = {
262c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 1,
272c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_DCINF_MASK,
282c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
292c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_DCINR] = {
302c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 1,
312c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_DCINR_MASK,
322c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
332c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_JIGF] = {
342c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 1,
352c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_JIGF_MASK,
362c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
372c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_JIGR] = {
382c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 1,
392c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_JIGR_MASK,
402c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
412c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_PWRONF] = {
422c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 1,
432c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_PWRONF_MASK,
442c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
452c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_PWRONR] = {
462c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 1,
472c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_PWRONR_MASK,
482c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
492c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_WTSREVNT] = {
502c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 2,
512c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_WTSREVNT_MASK,
522c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
532c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_SMPLEVNT] = {
542c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 2,
552c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_SMPLEVNT_MASK,
562c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
572c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_ALARM1] = {
582c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 2,
592c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_ALARM1_MASK,
602c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
612c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_ALARM0] = {
622c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 2,
632c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_ALARM0_MASK,
642c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
652c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_ONKEY1S] = {
662c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 3,
672c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_ONKEY1S_MASK,
682c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
692c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_TOPOFFR] = {
702c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 3,
712c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_TOPOFFR_MASK,
722c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
732c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_DCINOVPR] = {
742c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 3,
752c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_DCINOVPR_MASK,
762c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
772c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_CHGRSTF] = {
782c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 3,
792c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_CHGRSTF_MASK,
802c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
812c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_DONER] = {
822c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 3,
832c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_DONER_MASK,
842c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
852c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_CHGFAULT] = {
862c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 3,
872c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_CHGFAULT_MASK,
882c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
892c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_LOBAT1] = {
902c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 4,
912c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_LOBAT1_MASK,
922c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
932c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	[MAX8998_IRQ_LOBAT2] = {
942c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.reg = 4,
952c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		.mask = MAX8998_IRQ_LOBAT2_MASK,
962c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	},
972c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim};
982c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
992c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimstatic inline struct max8998_irq_data *
1002c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimirq_to_max8998_irq(struct max8998_dev *max8998, int irq)
1012c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
1022c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	return &max8998_irqs[irq - max8998->irq_base];
1032c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
1042c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1052898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brownstatic void max8998_irq_lock(struct irq_data *data)
1062c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
1072898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
1082c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1092c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	mutex_lock(&max8998->irqlock);
1102c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
1112c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1122898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brownstatic void max8998_irq_sync_unlock(struct irq_data *data)
1132c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
1142898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
1152c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int i;
1162c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1172c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	for (i = 0; i < ARRAY_SIZE(max8998->irq_masks_cur); i++) {
1182c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		/*
1192c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		 * If there's been a change in the mask write it back
1202c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		 * to the hardware.
1212c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		 */
1222c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		if (max8998->irq_masks_cur[i] != max8998->irq_masks_cache[i]) {
1232c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			max8998->irq_masks_cache[i] = max8998->irq_masks_cur[i];
1242c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			max8998_write_reg(max8998->i2c, MAX8998_REG_IRQM1 + i,
1252c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim					max8998->irq_masks_cur[i]);
1262c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		}
1272c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
1282c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1292c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	mutex_unlock(&max8998->irqlock);
1302c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
1312c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1322898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brownstatic void max8998_irq_unmask(struct irq_data *data)
1332c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
1342898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
1352898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998,
1362898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown							       data->irq);
1372c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1382c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	max8998->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
1392c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
1402c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1412898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brownstatic void max8998_irq_mask(struct irq_data *data)
1422c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
1432898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	struct max8998_dev *max8998 = irq_data_get_irq_chip_data(data);
1442898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	struct max8998_irq_data *irq_data = irq_to_max8998_irq(max8998,
1452898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown							       data->irq);
1462c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1472c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	max8998->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
1482c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
1492c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1502c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimstatic struct irq_chip max8998_irq_chip = {
1512c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	.name = "max8998",
1522898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	.irq_bus_lock = max8998_irq_lock,
1532898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	.irq_bus_sync_unlock = max8998_irq_sync_unlock,
1542898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	.irq_mask = max8998_irq_mask,
1552898577e160c7d60d2b11cb3b1c3b55d0e1468dbMark Brown	.irq_unmask = max8998_irq_unmask,
1562c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim};
1572c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1582c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimstatic irqreturn_t max8998_irq_thread(int irq, void *data)
1592c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
1602c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	struct max8998_dev *max8998 = data;
1612c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	u8 irq_reg[MAX8998_NUM_IRQ_REGS];
1622c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int ret;
1632c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int i;
1642c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1652c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	ret = max8998_bulk_read(max8998->i2c, MAX8998_REG_IRQ1,
1662c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			MAX8998_NUM_IRQ_REGS, irq_reg);
1672c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	if (ret < 0) {
1682c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		dev_err(max8998->dev, "Failed to read interrupt register: %d\n",
1692c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim				ret);
1702c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		return IRQ_NONE;
1712c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
1722c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1732c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	/* Apply masking */
1742c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	for (i = 0; i < MAX8998_NUM_IRQ_REGS; i++)
1752c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		irq_reg[i] &= ~max8998->irq_masks_cur[i];
1762c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1772c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	/* Report */
1782c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	for (i = 0; i < MAX8998_IRQ_NR; i++) {
1792c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask)
1802c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			handle_nested_irq(max8998->irq_base + i);
1812c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
1822c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1832c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	return IRQ_HANDLED;
1842c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
1852c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
186cdd137c9c86c201ddb7f42ec978d2da45e7b7a17MyungJoo Hamint max8998_irq_resume(struct max8998_dev *max8998)
187cdd137c9c86c201ddb7f42ec978d2da45e7b7a17MyungJoo Ham{
188cdd137c9c86c201ddb7f42ec978d2da45e7b7a17MyungJoo Ham	if (max8998->irq && max8998->irq_base)
189cdd137c9c86c201ddb7f42ec978d2da45e7b7a17MyungJoo Ham		max8998_irq_thread(max8998->irq_base, max8998);
190cdd137c9c86c201ddb7f42ec978d2da45e7b7a17MyungJoo Ham	return 0;
191cdd137c9c86c201ddb7f42ec978d2da45e7b7a17MyungJoo Ham}
192cdd137c9c86c201ddb7f42ec978d2da45e7b7a17MyungJoo Ham
1932c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimint max8998_irq_init(struct max8998_dev *max8998)
1942c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
1952c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int i;
1962c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int cur_irq;
1972c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	int ret;
1982c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
1992c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	if (!max8998->irq) {
2002c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		dev_warn(max8998->dev,
2012c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			 "No interrupt specified, no interrupts\n");
2022c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		max8998->irq_base = 0;
2032c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		return 0;
2042c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
2052c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2062c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	if (!max8998->irq_base) {
2072c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		dev_err(max8998->dev,
2082c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			"No interrupt base specified, no interrupts\n");
2092c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		return 0;
2102c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
2112c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2122c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	mutex_init(&max8998->irqlock);
2132c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2142c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	/* Mask the individual interrupt sources */
2152c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	for (i = 0; i < MAX8998_NUM_IRQ_REGS; i++) {
2162c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		max8998->irq_masks_cur[i] = 0xff;
2172c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		max8998->irq_masks_cache[i] = 0xff;
2182c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		max8998_write_reg(max8998->i2c, MAX8998_REG_IRQM1 + i, 0xff);
2192c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
2202c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2212c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff);
2222c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff);
2232c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2242c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	/* register with genirq */
2252c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	for (i = 0; i < MAX8998_IRQ_NR; i++) {
2262c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		cur_irq = i + max8998->irq_base;
227d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner		irq_set_chip_data(cur_irq, max8998);
228d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner		irq_set_chip_and_handler(cur_irq, &max8998_irq_chip,
2292c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim					 handle_edge_irq);
230d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner		irq_set_nested_thread(cur_irq, 1);
2312c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim#ifdef CONFIG_ARM
2322c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		set_irq_flags(cur_irq, IRQF_VALID);
2332c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim#else
234d5bb122165981aed327845c32a9916d1b8ae0e4bThomas Gleixner		irq_set_noprobe(cur_irq);
2352c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim#endif
2362c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
2372c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2382c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread,
2392c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
2402c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim				   "max8998-irq", max8998);
2412c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	if (ret) {
2422c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		dev_err(max8998->dev, "Failed to request IRQ %d: %d\n",
2432c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			max8998->irq, ret);
2442c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		return ret;
2452c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	}
2462c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2472c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	if (!max8998->ono)
2482c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		return 0;
2492c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2502c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	ret = request_threaded_irq(max8998->ono, NULL, max8998_irq_thread,
2512c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim				   IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
2522c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim				   IRQF_ONESHOT, "max8998-ono", max8998);
2532c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	if (ret)
2542c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		dev_err(max8998->dev, "Failed to request IRQ %d: %d\n",
2552c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim			max8998->ono, ret);
2562c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2572c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	return 0;
2582c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
2592c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim
2602c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shimvoid max8998_irq_exit(struct max8998_dev *max8998)
2612c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim{
2621558b51eb7c813b3d90bdd68057403f7cac191faAxel Lin	if (max8998->ono)
2631558b51eb7c813b3d90bdd68057403f7cac191faAxel Lin		free_irq(max8998->ono, max8998);
2641558b51eb7c813b3d90bdd68057403f7cac191faAxel Lin
2652c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim	if (max8998->irq)
2662c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim		free_irq(max8998->irq, max8998);
2672c7e6f5797140b33ec2b967ff28941e1c7eff4b2Joonyoung Shim}
268