Patchwork [2/2] mfd: max77693: handle IRQs using regmap

login
register
mail settings
Submitter Robert Baldyga
Date April 28, 2014, 2:08 p.m.
Message ID <1398694103-29320-3-git-send-email-r.baldyga@samsung.com>
Download mbox | patch
Permalink /patch/343439/
State New
Headers show

Comments

Robert Baldyga - April 28, 2014, 2:08 p.m.
This patch modifies mfd driver to use regmap for handling interrupts.
It allows to simplify irq handling process. This modifications needed
to make small changes in function drivers, which use interrupts.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/extcon/extcon-max77693.c     |   3 +-
 drivers/mfd/Kconfig                  |   1 +
 drivers/mfd/Makefile                 |   2 +-
 drivers/mfd/max77693-irq.c           | 337 -----------------------------------
 drivers/mfd/max77693.c               | 158 ++++++++++++++--
 include/linux/mfd/max77693-private.h |  47 ++++-
 6 files changed, 196 insertions(+), 352 deletions(-)
 delete mode 100644 drivers/mfd/max77693-irq.c
Krzysztof Kozlowski - April 28, 2014, 3:01 p.m.
On pon, 2014-04-28 at 16:08 +0200, Robert Baldyga wrote:
> This patch modifies mfd driver to use regmap for handling interrupts.
> It allows to simplify irq handling process. This modifications needed
> to make small changes in function drivers, which use interrupts.
> 
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
>  drivers/extcon/extcon-max77693.c     |   3 +-
>  drivers/mfd/Kconfig                  |   1 +
>  drivers/mfd/Makefile                 |   2 +-
>  drivers/mfd/max77693-irq.c           | 337 -----------------------------------
>  drivers/mfd/max77693.c               | 158 ++++++++++++++--
>  include/linux/mfd/max77693-private.h |  47 ++++-
>  6 files changed, 196 insertions(+), 352 deletions(-)
>  delete mode 100644 drivers/mfd/max77693-irq.c

(...)

> diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
> index 6336251..8b2633d 100644
> --- a/drivers/mfd/max77693.c
> +++ b/drivers/mfd/max77693.c
> @@ -55,12 +55,95 @@ static const struct regmap_config max77693_regmap_config = {
>  	.max_register = MAX77693_PMIC_REG_END,
>  };
>  
> +static const struct regmap_irq max77693_led_irqs[] = {
> +	{ .mask = LED_IRQ_FLED2_OPEN, },
> +	{ .mask = LED_IRQ_FLED2_SHORT, },
> +	{ .mask = LED_IRQ_FLED1_OPEN, },
> +	{ .mask = LED_IRQ_FLED1_SHORT, },
> +	{ .mask = LED_IRQ_MAX_FLASH, },
> +};
> +
> +static const struct regmap_irq_chip max77693_led_irq_chip = {
> +	.name                   = "max77693-led",
> +	.status_base            = MAX77693_LED_REG_FLASH_INT,
> +	.mask_base              = MAX77693_LED_REG_FLASH_INT_MASK,
> +	.mask_invert            = false,
> +	.num_regs               = 1,
> +	.irqs                   = max77693_led_irqs,
> +	.num_irqs               = ARRAY_SIZE(max77693_led_irqs),
> +};
> +
> +static const struct regmap_irq max77693_topsys_irqs[] = {
> +	{ .mask = TOPSYS_IRQ_T120C_INT, },
> +	{ .mask = TOPSYS_IRQ_T140C_INT, },
> +	{ .mask = TOPSYS_IRQ_LOWSYS_INT, },
> +};
> +
> +static const struct regmap_irq_chip max77693_topsys_irq_chip = {
> +	.name                   = "max77693-topsys",
> +	.status_base            = MAX77693_PMIC_REG_TOPSYS_INT,
> +	.mask_base              = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
> +	.mask_invert            = false,
> +	.num_regs               = 1,
> +	.irqs                   = max77693_topsys_irqs,
> +	.num_irqs               = ARRAY_SIZE(max77693_topsys_irqs),
> +};
> +
> +static const struct regmap_irq max77693_charger_irqs[] = {
> +	{ .mask = CHG_IRQ_BYP_I, },
> +	{ .mask = CHG_IRQ_THM_I, },
> +	{ .mask = CHG_IRQ_BAT_I, },
> +	{ .mask = CHG_IRQ_CHG_I, },
> +	{ .mask = CHG_IRQ_CHGIN_I, },
> +};
> +
> +static const struct regmap_irq_chip max77693_charger_irq_chip = {
> +	.name                   = "max77693-charger",
> +	.status_base            = MAX77693_CHG_REG_CHG_INT,
> +	.mask_base              = MAX77693_CHG_REG_CHG_INT_MASK,
> +	.mask_invert            = false,
> +	.num_regs               = 1,
> +	.irqs                   = max77693_charger_irqs,
> +	.num_irqs               = ARRAY_SIZE(max77693_charger_irqs),
> +};
> +
>  static const struct regmap_config max77693_regmap_muic_config = {
>  	.reg_bits = 8,
>  	.val_bits = 8,
>  	.max_register = MAX77693_MUIC_REG_END,
>  };
>  
> +static const struct regmap_irq max77693_muic_irqs[] = {
> +	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC, },
> +	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_LOW, },
> +	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_ERR, },
> +	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC1K, },
> +
> +	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGTYP, },
> +	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGDETREUN, },
> +	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DCDTMR, },
> +	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DXOVP, },
> +	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VBVOLT, },
> +	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VIDRM, },
> +
> +	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_EOC, },
> +	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CGMBC, },
> +	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_OVP, },
> +	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_MBCCHG_ERR, },
> +	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CHG_ENABLED, },
> +	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_BAT_DET, },
> +};
> +
> +static const struct regmap_irq_chip max77693_muic_irq_chip = {
> +	.name                   = "max77693-muic",
> +	.status_base            = MAX77693_MUIC_REG_INT1,
> +	.mask_base              = MAX77693_MUIC_REG_INTMASK1,
> +	.mask_invert            = true,
> +	.num_regs               = 3,
> +	.irqs                   = max77693_muic_irqs,
> +	.num_irqs               = ARRAY_SIZE(max77693_muic_irqs),
> +};
> +
>  static int max77693_i2c_probe(struct i2c_client *i2c,
>  			      const struct i2c_device_id *id)
>  {
> @@ -124,9 +207,45 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
>  		goto err_regmap_muic;
>  	}
>  
> -	ret = max77693_irq_init(max77693);
> -	if (ret < 0)
> -		goto err_irq;
> +	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
> +				IRQF_ONESHOT | IRQF_SHARED |
> +				IRQF_TRIGGER_FALLING, 0,
> +				&max77693_led_irq_chip,
> +				&max77693->irq_data_led);
> +	if (ret) {
> +		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
> +		goto err_regmap_muic;
> +	}
> +
> +	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
> +				IRQF_ONESHOT | IRQF_SHARED |
> +				IRQF_TRIGGER_FALLING, 0,
> +				&max77693_topsys_irq_chip,
> +				&max77693->irq_data_topsys);
> +	if (ret) {
> +		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
> +		goto err_irq_topsys;
> +	}
> +
> +	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
> +				IRQF_ONESHOT | IRQF_SHARED |
> +				IRQF_TRIGGER_FALLING, 0,
> +				&max77693_charger_irq_chip,
> +				&max77693->irq_data_charger);
> +	if (ret) {
> +		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
> +		goto err_irq_charger;
> +	}
> +
> +	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
> +				IRQF_ONESHOT | IRQF_SHARED |
> +				IRQF_TRIGGER_FALLING, 0,
> +				&max77693_muic_irq_chip,
> +				&max77693->irq_data_muic);
> +	if (ret) {
> +		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
> +		goto err_irq_muic;
> +	}
>  
>  	pm_runtime_set_active(max77693->dev);
>  
> @@ -138,8 +257,14 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
>  	return ret;
>  
>  err_mfd:
> -	max77693_irq_exit(max77693);
> -err_irq:
> +	mfd_remove_devices(max77693->dev);

Hmmm... The mfd_add_devices() calls mfd_remove_devices() on failure so
why calling it also here?

> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
> +err_irq_muic:
> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
> +err_irq_charger:
> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
> +err_irq_topsys:
> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
>  err_regmap_muic:
>  	i2c_unregister_device(max77693->haptic);
>  err_i2c_haptic:
> @@ -152,7 +277,12 @@ static int max77693_i2c_remove(struct i2c_client *i2c)
>  	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
>  
>  	mfd_remove_devices(max77693->dev);
> -	max77693_irq_exit(max77693);
> +
> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
> +	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
> +
>  	i2c_unregister_device(max77693->muic);
>  	i2c_unregister_device(max77693->haptic);
>  
> @@ -170,8 +300,11 @@ static int max77693_suspend(struct device *dev)
>  	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
>  	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
>  
> -	if (device_may_wakeup(dev))
> -		irq_set_irq_wake(max77693->irq, 1);
> +	if (device_may_wakeup(dev)) {
> +		enable_irq_wake(max77693->irq);
> +		disable_irq(max77693->irq);
> +	}

The disable_irq() should be called regardless of wakeup source. Actually
I could reproduce error even when the driver was not a wakeup source.

> +
>  	return 0;
>  }
>  
> @@ -180,9 +313,12 @@ static int max77693_resume(struct device *dev)
>  	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
>  	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
>  
> -	if (device_may_wakeup(dev))
> -		irq_set_irq_wake(max77693->irq, 0);
> -	return max77693_irq_resume(max77693);
> +	if (device_may_wakeup(dev)) {
> +		disable_irq_wake(max77693->irq);
> +		enable_irq(max77693->irq);

Same here.

Best regards,
Krzysztof

Patch

diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index efa105f..b0cbb95 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -1154,7 +1154,8 @@  static int max77693_muic_probe(struct platform_device *pdev)
 		struct max77693_muic_irq *muic_irq = &muic_irqs[i];
 		unsigned int virq = 0;
 
-		virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq);
+		virq = regmap_irq_get_virq(max77693->irq_data_muic,
+					muic_irq->irq);
 		if (!virq) {
 			ret = -EINVAL;
 			goto err_irq;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 67141e8..9e479d0 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -372,6 +372,7 @@  config MFD_MAX77693
 	depends on I2C=y
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	help
 	  Say yes here to add support for Maxim Semiconductor MAX77693.
 	  This is a companion Power Management IC with Flash, Haptic, Charger,
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 6d0f65e..b0c55e4 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -114,7 +114,7 @@  obj-$(CONFIG_MFD_DA9063)	+= da9063.o
 
 obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
 obj-$(CONFIG_MFD_MAX77686)	+= max77686.o max77686-irq.o
-obj-$(CONFIG_MFD_MAX77693)	+= max77693.o max77693-irq.o
+obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
 obj-$(CONFIG_MFD_MAX8907)	+= max8907.o
 max8925-objs			:= max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c
deleted file mode 100644
index 1a89ec2..0000000
--- a/drivers/mfd/max77693-irq.c
+++ /dev/null
@@ -1,337 +0,0 @@ 
-/*
- * max77693-irq.c - Interrupt controller support for MAX77693
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * SangYoung Son <hello.son@samsung.com>
- *
- * This program is not provided / owned by Maxim Integrated Products.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * This driver is based on max8997-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/irqdomain.h>
-#include <linux/mfd/max77693.h>
-#include <linux/mfd/max77693-private.h>
-#include <linux/regmap.h>
-
-static const unsigned int max77693_mask_reg[] = {
-	[LED_INT] = MAX77693_LED_REG_FLASH_INT_MASK,
-	[TOPSYS_INT] = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
-	[CHG_INT] = MAX77693_CHG_REG_CHG_INT_MASK,
-	[MUIC_INT1] = MAX77693_MUIC_REG_INTMASK1,
-	[MUIC_INT2] = MAX77693_MUIC_REG_INTMASK2,
-	[MUIC_INT3] = MAX77693_MUIC_REG_INTMASK3,
-};
-
-static struct regmap *max77693_get_regmap(struct max77693_dev *max77693,
-				enum max77693_irq_source src)
-{
-	switch (src) {
-	case LED_INT ... CHG_INT:
-		return max77693->regmap;
-	case MUIC_INT1 ... MUIC_INT3:
-		return max77693->regmap_muic;
-	default:
-		return ERR_PTR(-EINVAL);
-	}
-}
-
-struct max77693_irq_data {
-	int mask;
-	enum max77693_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask)		\
-	[(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max77693_irq_data max77693_irqs[] = {
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_OPEN,	LED_INT, 1 << 0),
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_SHORT,	LED_INT, 1 << 1),
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_OPEN,	LED_INT, 1 << 2),
-	DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_SHORT,	LED_INT, 1 << 3),
-	DECLARE_IRQ(MAX77693_LED_IRQ_MAX_FLASH,		LED_INT, 1 << 4),
-
-	DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T120C_INT,	TOPSYS_INT, 1 << 0),
-	DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T140C_INT,	TOPSYS_INT, 1 << 1),
-	DECLARE_IRQ(MAX77693_TOPSYS_IRQ_LOWSYS_INT,	TOPSYS_INT, 1 << 3),
-
-	DECLARE_IRQ(MAX77693_CHG_IRQ_BYP_I,		CHG_INT, 1 << 0),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_THM_I,		CHG_INT, 1 << 2),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_BAT_I,		CHG_INT, 1 << 3),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_CHG_I,		CHG_INT, 1 << 4),
-	DECLARE_IRQ(MAX77693_CHG_IRQ_CHGIN_I,		CHG_INT, 1 << 6),
-
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC,		MUIC_INT1, 1 << 0),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_LOW,	MUIC_INT1, 1 << 1),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_ERR,	MUIC_INT1, 1 << 2),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC1K,	MUIC_INT1, 1 << 3),
-
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGTYP,	MUIC_INT2, 1 << 0),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGDETREUN,	MUIC_INT2, 1 << 1),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DCDTMR,	MUIC_INT2, 1 << 2),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DXOVP,	MUIC_INT2, 1 << 3),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VBVOLT,	MUIC_INT2, 1 << 4),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VIDRM,	MUIC_INT2, 1 << 5),
-
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_EOC,		MUIC_INT3, 1 << 0),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CGMBC,	MUIC_INT3, 1 << 1),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_OVP,		MUIC_INT3, 1 << 2),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR,	MUIC_INT3, 1 << 3),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CHG_ENABLED,	MUIC_INT3, 1 << 4),
-	DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_BAT_DET,	MUIC_INT3, 1 << 5),
-};
-
-static void max77693_irq_lock(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-
-	mutex_lock(&max77693->irqlock);
-}
-
-static void max77693_irq_sync_unlock(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-	int i;
-
-	for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
-		u8 mask_reg = max77693_mask_reg[i];
-		struct regmap *map = max77693_get_regmap(max77693, i);
-
-		if (mask_reg == MAX77693_REG_INVALID ||
-				IS_ERR_OR_NULL(map))
-			continue;
-		max77693->irq_masks_cache[i] = max77693->irq_masks_cur[i];
-
-		regmap_write(map, max77693_mask_reg[i],
-				max77693->irq_masks_cur[i]);
-	}
-
-	mutex_unlock(&max77693->irqlock);
-}
-
-static const inline struct max77693_irq_data *
-irq_to_max77693_irq(struct max77693_dev *max77693, int irq)
-{
-	struct irq_data *data = irq_get_irq_data(irq);
-	return &max77693_irqs[data->hwirq];
-}
-
-static void max77693_irq_mask(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-	const struct max77693_irq_data *irq_data =
-				irq_to_max77693_irq(max77693, data->irq);
-
-	if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
-		return;
-
-	if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
-		max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-	else
-		max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
-}
-
-static void max77693_irq_unmask(struct irq_data *data)
-{
-	struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-	const struct max77693_irq_data *irq_data =
-	    irq_to_max77693_irq(max77693, data->irq);
-
-	if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
-		return;
-
-	if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
-		max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
-	else
-		max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-}
-
-static struct irq_chip max77693_irq_chip = {
-	.name			= "max77693",
-	.irq_bus_lock		= max77693_irq_lock,
-	.irq_bus_sync_unlock	= max77693_irq_sync_unlock,
-	.irq_mask		= max77693_irq_mask,
-	.irq_unmask		= max77693_irq_unmask,
-};
-
-#define MAX77693_IRQSRC_CHG		(1 << 0)
-#define MAX77693_IRQSRC_TOP		(1 << 1)
-#define MAX77693_IRQSRC_FLASH		(1 << 2)
-#define MAX77693_IRQSRC_MUIC		(1 << 3)
-static irqreturn_t max77693_irq_thread(int irq, void *data)
-{
-	struct max77693_dev *max77693 = data;
-	unsigned int irq_reg[MAX77693_IRQ_GROUP_NR] = {};
-	unsigned int irq_src;
-	int ret;
-	int i, cur_irq;
-
-	ret = regmap_read(max77693->regmap, MAX77693_PMIC_REG_INTSRC,
-				&irq_src);
-	if (ret < 0) {
-		dev_err(max77693->dev, "Failed to read interrupt source: %d\n",
-				ret);
-		return IRQ_NONE;
-	}
-
-	if (irq_src & MAX77693_IRQSRC_CHG)
-		/* CHG_INT */
-		ret = regmap_read(max77693->regmap, MAX77693_CHG_REG_CHG_INT,
-				&irq_reg[CHG_INT]);
-
-	if (irq_src & MAX77693_IRQSRC_TOP)
-		/* TOPSYS_INT */
-		ret = regmap_read(max77693->regmap,
-			MAX77693_PMIC_REG_TOPSYS_INT, &irq_reg[TOPSYS_INT]);
-
-	if (irq_src & MAX77693_IRQSRC_FLASH)
-		/* LED_INT */
-		ret = regmap_read(max77693->regmap,
-			MAX77693_LED_REG_FLASH_INT, &irq_reg[LED_INT]);
-
-	if (irq_src & MAX77693_IRQSRC_MUIC)
-		/* MUIC INT1 ~ INT3 */
-		regmap_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1,
-			&irq_reg[MUIC_INT1], MAX77693_NUM_IRQ_MUIC_REGS);
-
-	/* Apply masking */
-	for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
-		if (i >= MUIC_INT1 && i <= MUIC_INT3)
-			irq_reg[i] &= max77693->irq_masks_cur[i];
-		else
-			irq_reg[i] &= ~max77693->irq_masks_cur[i];
-	}
-
-	/* Report */
-	for (i = 0; i < MAX77693_IRQ_NR; i++) {
-		if (irq_reg[max77693_irqs[i].group] & max77693_irqs[i].mask) {
-			cur_irq = irq_find_mapping(max77693->irq_domain, i);
-			if (cur_irq)
-				handle_nested_irq(cur_irq);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-int max77693_irq_resume(struct max77693_dev *max77693)
-{
-	if (max77693->irq)
-		max77693_irq_thread(0, max77693);
-
-	return 0;
-}
-
-static int max77693_irq_domain_map(struct irq_domain *d, unsigned int irq,
-				irq_hw_number_t hw)
-{
-	struct max77693_dev *max77693 = d->host_data;
-
-	irq_set_chip_data(irq, max77693);
-	irq_set_chip_and_handler(irq, &max77693_irq_chip, handle_edge_irq);
-	irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-	set_irq_flags(irq, IRQF_VALID);
-#else
-	irq_set_noprobe(irq);
-#endif
-	return 0;
-}
-
-static struct irq_domain_ops max77693_irq_domain_ops = {
-	.map = max77693_irq_domain_map,
-};
-
-int max77693_irq_init(struct max77693_dev *max77693)
-{
-	struct irq_domain *domain;
-	int i;
-	int ret = 0;
-	unsigned int intsrc_mask;
-
-	mutex_init(&max77693->irqlock);
-
-	/* Mask individual interrupt sources */
-	for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
-		struct regmap *map;
-		/* MUIC IRQ  0:MASK 1:NOT MASK */
-		/* Other IRQ 1:MASK 0:NOT MASK */
-		if (i >= MUIC_INT1 && i <= MUIC_INT3) {
-			max77693->irq_masks_cur[i] = 0x00;
-			max77693->irq_masks_cache[i] = 0x00;
-		} else {
-			max77693->irq_masks_cur[i] = 0xff;
-			max77693->irq_masks_cache[i] = 0xff;
-		}
-		map = max77693_get_regmap(max77693, i);
-
-		if (IS_ERR_OR_NULL(map))
-			continue;
-		if (max77693_mask_reg[i] == MAX77693_REG_INVALID)
-			continue;
-		if (i >= MUIC_INT1 && i <= MUIC_INT3)
-			regmap_write(map, max77693_mask_reg[i], 0x00);
-		else
-			regmap_write(map, max77693_mask_reg[i], 0xff);
-	}
-
-	domain = irq_domain_add_linear(NULL, MAX77693_IRQ_NR,
-					&max77693_irq_domain_ops, max77693);
-	if (!domain) {
-		dev_err(max77693->dev, "could not create irq domain\n");
-		ret = -ENODEV;
-		goto err_irq;
-	}
-	max77693->irq_domain = domain;
-
-	/* Unmask max77693 interrupt */
-	ret = regmap_read(max77693->regmap,
-			MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask);
-	if (ret < 0) {
-		dev_err(max77693->dev, "fail to read PMIC register\n");
-		goto err_irq;
-	}
-
-	intsrc_mask &= ~(MAX77693_IRQSRC_CHG);
-	intsrc_mask &= ~(MAX77693_IRQSRC_FLASH);
-	intsrc_mask &= ~(MAX77693_IRQSRC_MUIC);
-	ret = regmap_write(max77693->regmap,
-			MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask);
-	if (ret < 0) {
-		dev_err(max77693->dev, "fail to write PMIC register\n");
-		goto err_irq;
-	}
-
-	ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread,
-				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-				   "max77693-irq", max77693);
-	if (ret)
-		dev_err(max77693->dev, "Failed to request IRQ %d: %d\n",
-			max77693->irq, ret);
-
-err_irq:
-	return ret;
-}
-
-void max77693_irq_exit(struct max77693_dev *max77693)
-{
-	if (max77693->irq)
-		free_irq(max77693->irq, max77693);
-}
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 6336251..8b2633d 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -55,12 +55,95 @@  static const struct regmap_config max77693_regmap_config = {
 	.max_register = MAX77693_PMIC_REG_END,
 };
 
+static const struct regmap_irq max77693_led_irqs[] = {
+	{ .mask = LED_IRQ_FLED2_OPEN, },
+	{ .mask = LED_IRQ_FLED2_SHORT, },
+	{ .mask = LED_IRQ_FLED1_OPEN, },
+	{ .mask = LED_IRQ_FLED1_SHORT, },
+	{ .mask = LED_IRQ_MAX_FLASH, },
+};
+
+static const struct regmap_irq_chip max77693_led_irq_chip = {
+	.name                   = "max77693-led",
+	.status_base            = MAX77693_LED_REG_FLASH_INT,
+	.mask_base              = MAX77693_LED_REG_FLASH_INT_MASK,
+	.mask_invert            = false,
+	.num_regs               = 1,
+	.irqs                   = max77693_led_irqs,
+	.num_irqs               = ARRAY_SIZE(max77693_led_irqs),
+};
+
+static const struct regmap_irq max77693_topsys_irqs[] = {
+	{ .mask = TOPSYS_IRQ_T120C_INT, },
+	{ .mask = TOPSYS_IRQ_T140C_INT, },
+	{ .mask = TOPSYS_IRQ_LOWSYS_INT, },
+};
+
+static const struct regmap_irq_chip max77693_topsys_irq_chip = {
+	.name                   = "max77693-topsys",
+	.status_base            = MAX77693_PMIC_REG_TOPSYS_INT,
+	.mask_base              = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
+	.mask_invert            = false,
+	.num_regs               = 1,
+	.irqs                   = max77693_topsys_irqs,
+	.num_irqs               = ARRAY_SIZE(max77693_topsys_irqs),
+};
+
+static const struct regmap_irq max77693_charger_irqs[] = {
+	{ .mask = CHG_IRQ_BYP_I, },
+	{ .mask = CHG_IRQ_THM_I, },
+	{ .mask = CHG_IRQ_BAT_I, },
+	{ .mask = CHG_IRQ_CHG_I, },
+	{ .mask = CHG_IRQ_CHGIN_I, },
+};
+
+static const struct regmap_irq_chip max77693_charger_irq_chip = {
+	.name                   = "max77693-charger",
+	.status_base            = MAX77693_CHG_REG_CHG_INT,
+	.mask_base              = MAX77693_CHG_REG_CHG_INT_MASK,
+	.mask_invert            = false,
+	.num_regs               = 1,
+	.irqs                   = max77693_charger_irqs,
+	.num_irqs               = ARRAY_SIZE(max77693_charger_irqs),
+};
+
 static const struct regmap_config max77693_regmap_muic_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
 	.max_register = MAX77693_MUIC_REG_END,
 };
 
+static const struct regmap_irq max77693_muic_irqs[] = {
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC, },
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_LOW, },
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_ERR, },
+	{ .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC1K, },
+
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGTYP, },
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGDETREUN, },
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DCDTMR, },
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_DXOVP, },
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VBVOLT, },
+	{ .reg_offset = 1, .mask = MUIC_IRQ_INT2_VIDRM, },
+
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_EOC, },
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CGMBC, },
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_OVP, },
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_MBCCHG_ERR, },
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_CHG_ENABLED, },
+	{ .reg_offset = 2, .mask = MUIC_IRQ_INT3_BAT_DET, },
+};
+
+static const struct regmap_irq_chip max77693_muic_irq_chip = {
+	.name                   = "max77693-muic",
+	.status_base            = MAX77693_MUIC_REG_INT1,
+	.mask_base              = MAX77693_MUIC_REG_INTMASK1,
+	.mask_invert            = true,
+	.num_regs               = 3,
+	.irqs                   = max77693_muic_irqs,
+	.num_irqs               = ARRAY_SIZE(max77693_muic_irqs),
+};
+
 static int max77693_i2c_probe(struct i2c_client *i2c,
 			      const struct i2c_device_id *id)
 {
@@ -124,9 +207,45 @@  static int max77693_i2c_probe(struct i2c_client *i2c,
 		goto err_regmap_muic;
 	}
 
-	ret = max77693_irq_init(max77693);
-	if (ret < 0)
-		goto err_irq;
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_led_irq_chip,
+				&max77693->irq_data_led);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_regmap_muic;
+	}
+
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_topsys_irq_chip,
+				&max77693->irq_data_topsys);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_irq_topsys;
+	}
+
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_charger_irq_chip,
+				&max77693->irq_data_charger);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_irq_charger;
+	}
+
+	ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max77693_muic_irq_chip,
+				&max77693->irq_data_muic);
+	if (ret) {
+		dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+		goto err_irq_muic;
+	}
 
 	pm_runtime_set_active(max77693->dev);
 
@@ -138,8 +257,14 @@  static int max77693_i2c_probe(struct i2c_client *i2c,
 	return ret;
 
 err_mfd:
-	max77693_irq_exit(max77693);
-err_irq:
+	mfd_remove_devices(max77693->dev);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
+err_irq_muic:
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+err_irq_charger:
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
+err_irq_topsys:
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
 err_regmap_muic:
 	i2c_unregister_device(max77693->haptic);
 err_i2c_haptic:
@@ -152,7 +277,12 @@  static int max77693_i2c_remove(struct i2c_client *i2c)
 	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
 
 	mfd_remove_devices(max77693->dev);
-	max77693_irq_exit(max77693);
+
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
+	regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
+
 	i2c_unregister_device(max77693->muic);
 	i2c_unregister_device(max77693->haptic);
 
@@ -170,8 +300,11 @@  static int max77693_suspend(struct device *dev)
 	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
 	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
 
-	if (device_may_wakeup(dev))
-		irq_set_irq_wake(max77693->irq, 1);
+	if (device_may_wakeup(dev)) {
+		enable_irq_wake(max77693->irq);
+		disable_irq(max77693->irq);
+	}
+
 	return 0;
 }
 
@@ -180,9 +313,12 @@  static int max77693_resume(struct device *dev)
 	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
 	struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
 
-	if (device_may_wakeup(dev))
-		irq_set_irq_wake(max77693->irq, 0);
-	return max77693_irq_resume(max77693);
+	if (device_may_wakeup(dev)) {
+		disable_irq_wake(max77693->irq);
+		enable_irq(max77693->irq);
+	}
+
+	return 0;
 }
 
 static const struct dev_pm_ops max77693_pm = {
diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h
index 80ec31d..7257f3b 100644
--- a/include/linux/mfd/max77693-private.h
+++ b/include/linux/mfd/max77693-private.h
@@ -262,6 +262,42 @@  enum max77693_irq_source {
 	MAX77693_IRQ_GROUP_NR,
 };
 
+#define LED_IRQ_FLED2_OPEN		(0x1 << 0)
+#define LED_IRQ_FLED2_SHORT		(0x1 << 1)
+#define LED_IRQ_FLED1_OPEN		(0x1 << 2)
+#define LED_IRQ_FLED1_SHORT		(0x1 << 3)
+#define LED_IRQ_MAX_FLASH		(0x1 << 4)
+
+#define TOPSYS_IRQ_T120C_INT		(0x1 << 0)
+#define TOPSYS_IRQ_T140C_INT		(0x1 << 1)
+#define TOPSYS_IRQ_LOWSYS_INT		(0x1 << 3)
+
+#define CHG_IRQ_BYP_I			(0x1 << 0)
+#define CHG_IRQ_THM_I			(0x1 << 2)
+#define CHG_IRQ_BAT_I			(0x1 << 3)
+#define CHG_IRQ_CHG_I			(0x1 << 4)
+#define CHG_IRQ_CHGIN_I			(0x1 << 6)
+
+#define MUIC_IRQ_INT1_ADC		(0x1 << 0)
+#define MUIC_IRQ_INT1_ADC_LOW		(0x1 << 1)
+#define MUIC_IRQ_INT1_ADC_ERR		(0x1 << 2)
+#define MUIC_IRQ_INT1_ADC1K		(0x1 << 3)
+
+#define MUIC_IRQ_INT2_CHGTYP		(0x1 << 0)
+#define MUIC_IRQ_INT2_CHGDETREUN	(0x1 << 1)
+#define MUIC_IRQ_INT2_DCDTMR		(0x1 << 2)
+#define MUIC_IRQ_INT2_DXOVP		(0x1 << 3)
+#define MUIC_IRQ_INT2_VBVOLT		(0x1 << 4)
+#define MUIC_IRQ_INT2_VIDRM		(0x1 << 5)
+
+#define MUIC_IRQ_INT3_EOC		(0x1 << 0)
+#define MUIC_IRQ_INT3_CGMBC		(0x1 << 1)
+#define MUIC_IRQ_INT3_OVP		(0x1 << 2)
+#define MUIC_IRQ_INT3_MBCCHG_ERR	(0x1 << 3)
+#define MUIC_IRQ_INT3_CHG_ENABLED	(0x1 << 4)
+#define MUIC_IRQ_INT3_BAT_DET		(0x1 << 5)
+
+
 enum max77693_irq {
 	/* PMIC - FLASH */
 	MAX77693_LED_IRQ_FLED2_OPEN,
@@ -282,6 +318,10 @@  enum max77693_irq {
 	MAX77693_CHG_IRQ_CHG_I,
 	MAX77693_CHG_IRQ_CHGIN_I,
 
+	MAX77693_IRQ_NR,
+};
+
+enum max77693_irq_muic {
 	/* MUIC INT1 */
 	MAX77693_MUIC_IRQ_INT1_ADC,
 	MAX77693_MUIC_IRQ_INT1_ADC_LOW,
@@ -304,7 +344,7 @@  enum max77693_irq {
 	MAX77693_MUIC_IRQ_INT3_CHG_ENABLED,
 	MAX77693_MUIC_IRQ_INT3_BAT_DET,
 
-	MAX77693_IRQ_NR,
+	MAX77693_MUIC_IRQ_NR,
 };
 
 struct max77693_dev {
@@ -319,7 +359,10 @@  struct max77693_dev {
 	struct regmap *regmap_muic;
 	struct regmap *regmap_haptic;
 
-	struct irq_domain *irq_domain;
+	struct regmap_irq_chip_data *irq_data_led;
+	struct regmap_irq_chip_data *irq_data_topsys;
+	struct regmap_irq_chip_data *irq_data_charger;
+	struct regmap_irq_chip_data *irq_data_muic;
 
 	int irq;
 	int irq_gpio;