diff mbox series

pinctrl: mediatek: add eint new design for mt8196

Message ID 20241025031814.21442-1-ot_chhao.chang@mediatek.com (mailing list archive)
State New
Headers show
Series pinctrl: mediatek: add eint new design for mt8196 | expand

Commit Message

chang hao Oct. 25, 2024, 3:16 a.m. UTC
From: Chhao Chang <ot_chhao.chang@mediatek.com>

eint is divided from the original base address into base addresses
in five directions: east, south, west, north, and center.
Stores a limited number of eint numbers in each direction.

Signed-off-by: Chhao Chang <ot_chhao.chang@mediatek.com>
---
 drivers/pinctrl/mediatek/mtk-eint.c           | 831 +++++++++++++-----
 drivers/pinctrl/mediatek/mtk-eint.h           |  75 +-
 .../pinctrl/mediatek/pinctrl-mtk-common-v2.c  |  50 +-
 3 files changed, 723 insertions(+), 233 deletions(-)

Comments

Chen-Yu Tsai Oct. 25, 2024, 4:12 a.m. UTC | #1
On Fri, Oct 25, 2024 at 11:19 AM chang hao <ot_chhao.chang@mediatek.com> wrote:
>
> From: Chhao Chang <ot_chhao.chang@mediatek.com>

Please properly version your patch, and also add changelogs. You have
sent three already and I have no idea which one is which version or
what changed.

ChenYu

> eint is divided from the original base address into base addresses
> in five directions: east, south, west, north, and center.
> Stores a limited number of eint numbers in each direction.
>
> Signed-off-by: Chhao Chang <ot_chhao.chang@mediatek.com>
> ---
>  drivers/pinctrl/mediatek/mtk-eint.c           | 831 +++++++++++++-----
>  drivers/pinctrl/mediatek/mtk-eint.h           |  75 +-
>  .../pinctrl/mediatek/pinctrl-mtk-common-v2.c  |  50 +-
>  3 files changed, 723 insertions(+), 233 deletions(-)
>
> diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
> index 27f0a54e12bf..57f812299340 100644
> --- a/drivers/pinctrl/mediatek/mtk-eint.c
> +++ b/drivers/pinctrl/mediatek/mtk-eint.c
> @@ -17,16 +17,13 @@
>  #include <linux/irqdomain.h>
>  #include <linux/module.h>
>  #include <linux/of_irq.h>
> +#include <linux/of_address.h>
>  #include <linux/platform_device.h>
>
>  #include "mtk-eint.h"
>
> -#define MTK_EINT_EDGE_SENSITIVE           0
> -#define MTK_EINT_LEVEL_SENSITIVE          1
> -#define MTK_EINT_DBNC_SET_DBNC_BITS      4
> -#define MTK_EINT_DBNC_MAX                16
> -#define MTK_EINT_DBNC_RST_BIT            (0x1 << 1)
> -#define MTK_EINT_DBNC_SET_EN             (0x1 << 0)
> +static struct mtk_eint *global_eintc;
> +struct mtk_eint_pin pin;
>
>  static const struct mtk_eint_regs mtk_generic_eint_regs = {
>         .stat      = 0x000,
> @@ -47,6 +44,10 @@ static const struct mtk_eint_regs mtk_generic_eint_regs = {
>         .dbnc_ctrl = 0x500,
>         .dbnc_set  = 0x600,
>         .dbnc_clr  = 0x700,
> +       .event     = 0x800,
> +       .event_set = 0x840,
> +       .event_clr = 0x880,
> +       .raw_stat  = 0xa00,
>  };
>
>  const unsigned int debounce_time_mt2701[] = {
> @@ -64,60 +65,145 @@ const unsigned int debounce_time_mt6795[] = {
>  };
>  EXPORT_SYMBOL_GPL(debounce_time_mt6795);
>
> -static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
> +/*
> + * Return the iomem of specific register ofset and decode the coordinate
> + * (instance, index) from global eint number.
> + * If return NULL, then it must be either out-of-range or do-not-support.
> + */
> +static void __iomem *mtk_eint_get_ofset(struct mtk_eint *eint,
>                                          unsigned int eint_num,
> -                                        unsigned int offset)
> +                                        unsigned int ofset,
> +                                        unsigned int *instance,
> +                                        unsigned int *index)
>  {
> -       unsigned int eint_base = 0;
>         void __iomem *reg;
>
> -       if (eint_num >= eint->hw->ap_num)
> -               eint_base = eint->hw->ap_num;
> +       if (eint_num >= eint->total_pin_number ||
> +           !eint->pins[eint_num].enabled) {
> +               WARN_ON(1);
> +               return NULL;
> +       }
>
> -       reg = eint->base + offset + ((eint_num - eint_base) / 32) * 4;
> +       *instance = eint->pins[eint_num].instance;
> +       *index = eint->pins[eint_num].index;
> +       reg = eint->instances[*instance].base + ofset + (*index / MAX_BIT * REG_OFSET);
>
>         return reg;
>  }
>
> +/*
> + * Generate helper function to access property register of a dedicate pin.
> + */
> +#define DEFINE_EINT_GET_FUNCTION(_NAME, _OFSET) \
> +static unsigned int mtk_eint_get_##_NAME(struct mtk_eint *eint, \
> +                                  unsigned int eint_num) \
> +{ \
> +       unsigned int instance, index; \
> +       void __iomem *reg = mtk_eint_get_ofset(eint, eint_num, \
> +                                               _OFSET, \
> +                                               &instance, &index); \
> +       unsigned int bit = BIT(index & 0x1f);\
> +\
> +       if (!reg) { \
> +               dev_err(eint->dev, "%s invalid eint_num %d\n", \
> +                       __func__, eint_num); \
> +               return 0;\
> +       } \
> +\
> +       return !!(readl(reg) & bit); \
> +}
> +
> +DEFINE_EINT_GET_FUNCTION(stat, eint->comp->regs->stat);
> +DEFINE_EINT_GET_FUNCTION(mask, eint->comp->regs->mask);
> +DEFINE_EINT_GET_FUNCTION(sens, eint->comp->regs->sens);
> +DEFINE_EINT_GET_FUNCTION(pol, eint->comp->regs->pol);
> +DEFINE_EINT_GET_FUNCTION(dom_en, eint->comp->regs->dom_en);
> +DEFINE_EINT_GET_FUNCTION(event, eint->comp->regs->event);
> +DEFINE_EINT_GET_FUNCTION(raw_stat, eint->comp->regs->raw_stat);
> +
> +int dump_eint_pin_status(unsigned int eint_num)
> +{
> +       unsigned int stat, raw_stat, mask, sens, pol, dom_en, event;
> +
> +       if (eint_num < 0 || eint_num > global_eintc->total_pin_number)
> +               return ENODEV;
> +
> +       stat = mtk_eint_get_stat(global_eintc, eint_num);
> +       raw_stat = mtk_eint_get_raw_stat(global_eintc, eint_num);
> +       mask = mtk_eint_get_mask(global_eintc, eint_num);
> +       sens = mtk_eint_get_sens(global_eintc, eint_num);
> +       pol = mtk_eint_get_pol(global_eintc, eint_num);
> +       dom_en = mtk_eint_get_dom_en(global_eintc, eint_num);
> +       event = mtk_eint_get_event(global_eintc, eint_num);
> +       dev_info(global_eintc->dev, "%s eint_num:%u=stat:%u,raw:%u, \
> +                      mask:%u, sens:%u,pol:%u,dom_en:%u,event:%u\n",
> +                      __func__, eint_num, stat, raw_stat, mask, sens,
> +                      pol, dom_en, event);
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(dump_eint_pin_status);
> +
>  static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
>                                              unsigned int eint_num)
>  {
>         unsigned int sens;
> -       unsigned int bit = BIT(eint_num % 32);
> -       void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
> -                                               eint->regs->sens);
> +       unsigned int instance, index;
> +       void __iomem *reg = mtk_eint_get_ofset(eint, eint_num,
> +                                               eint->comp->regs->sens,
> +                                               &instance, &index);
> +       unsigned int bit = BIT(index & 0x1f);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %d\n",
> +                       __func__, eint_num);
> +               return 0;
> +       }
>
>         if (readl(reg) & bit)
>                 sens = MTK_EINT_LEVEL_SENSITIVE;
>         else
>                 sens = MTK_EINT_EDGE_SENSITIVE;
>
> -       if (eint_num < eint->hw->db_cnt && sens != MTK_EINT_EDGE_SENSITIVE)
> +       if (eint->pins[eint_num].debounce &&
> +           sens != MTK_EINT_EDGE_SENSITIVE)
>                 return 1;
>         else
>                 return 0;
>  }
>
> -static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
> +static int mtk_eint_flip_edge(struct mtk_eint *eint, int eint_num)
>  {
>         int start_level, curr_level;
> -       unsigned int reg_offset;
> -       u32 mask = BIT(hwirq & 0x1f);
> -       u32 port = (hwirq >> 5) & eint->hw->port_mask;
> -       void __iomem *reg = eint->base + (port << 2);
> +       unsigned int reg_ofset;
> +       unsigned int instance, index, mask, port;
> +       void __iomem *reg;
>
> -       curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, hwirq);
> +       reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
> +                                 &instance, &index);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %d\n",
> +                       __func__, eint_num);
> +               return 0;
> +       }
> +
> +       mask = BIT(index & 0x1f);
> +       port = index >> REG_GROUP;
> +       reg = eint->instances[instance].base + port * REG_OFSET;
> +
> +       curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, eint_num);
>
>         do {
>                 start_level = curr_level;
>                 if (start_level)
> -                       reg_offset = eint->regs->pol_clr;
> +                       reg_ofset = eint->comp->regs->pol_clr;
>                 else
> -                       reg_offset = eint->regs->pol_set;
> -               writel(mask, reg + reg_offset);
> +                       reg_ofset = eint->comp->regs->pol_set;
> +
> +               writel(mask, reg + reg_ofset);
>
>                 curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl,
> -                                                             hwirq);
> +                                                             eint_num);
>         } while (start_level != curr_level);
>
>         return start_level;
> @@ -126,11 +212,19 @@ static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
>  static void mtk_eint_mask(struct irq_data *d)
>  {
>         struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
> -       u32 mask = BIT(d->hwirq & 0x1f);
> -       void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
> -                                               eint->regs->mask_set);
> +       unsigned int instance, index;
> +       void __iomem *reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                               eint->comp->regs->mask_set,
> +                                               &instance, &index);
> +       u32 mask = BIT(index & 0x1f);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %lu\n",
> +                       __func__, d->hwirq);
> +               return;
> +       }
>
> -       eint->cur_mask[d->hwirq >> 5] &= ~mask;
> +       eint->instances[instance].cur_mask[index >> REG_GROUP] &= ~mask;
>
>         writel(mask, reg);
>  }
> @@ -138,43 +232,91 @@ static void mtk_eint_mask(struct irq_data *d)
>  static void mtk_eint_unmask(struct irq_data *d)
>  {
>         struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
> -       u32 mask = BIT(d->hwirq & 0x1f);
> -       void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
> -                                               eint->regs->mask_clr);
> +       unsigned int instance, index;
> +       void __iomem *reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                               eint->comp->regs->mask_clr,
> +                                               &instance, &index);
> +       u32 mask = BIT(index & 0x1f);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %lu\n",
> +                       __func__, d->hwirq);
> +               return;
> +       }
>
> -       eint->cur_mask[d->hwirq >> 5] |= mask;
> +       eint->instances[instance].cur_mask[index >> REG_GROUP] |= mask;
>
>         writel(mask, reg);
>
> -       if (eint->dual_edge[d->hwirq])
> +       if (eint->pins[d->hwirq].dual_edge)
>                 mtk_eint_flip_edge(eint, d->hwirq);
>  }
>
> -static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
> +static void mtk_eint_ack(struct irq_data *d)
> +{
> +       struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
> +       unsigned int instance, index;
> +       void __iomem *reg;
> +       unsigned int bit;
> +
> +       if (eint->comp->ops.ack)
> +               eint->comp->ops.ack(d);
> +       else {
> +               reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                         eint->comp->regs->ack,
> +                                         &instance, &index);
> +               bit = BIT(index & 0x1f);
> +               if (!reg) {
> +                       dev_err(eint->dev, "%s invalid eint_num %lu\n",
> +                               __func__, d->hwirq);
> +                       return;
> +               }
> +
> +               writel(bit, reg);
> +       }
> +}
> +
> +static void mtk_eint_soft_set(struct mtk_eint *eint,
>                                       unsigned int eint_num)
>  {
> -       unsigned int bit = BIT(eint_num % 32);
> -       void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
> -                                               eint->regs->mask);
> +       unsigned int instance, index;
> +       void __iomem *reg = mtk_eint_get_ofset(eint, eint_num,
> +                                               eint->comp->regs->soft_set,
> +                                               &instance, &index);
> +       unsigned int bit = BIT(index & 0x1f);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %d\n",
> +                       __func__, eint_num);
> +               return;
> +       }
>
> -       return !!(readl(reg) & bit);
> +       writel(bit, reg);
>  }
>
> -static void mtk_eint_ack(struct irq_data *d)
> +static void mtk_eint_soft_clr(struct mtk_eint *eint,
> +                                     unsigned int eint_num)
>  {
> -       struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
> -       u32 mask = BIT(d->hwirq & 0x1f);
> -       void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
> -                                               eint->regs->ack);
> +       unsigned int instance, index;
> +       void __iomem *reg = mtk_eint_get_ofset(eint, eint_num,
> +                                               eint->comp->regs->soft_clr,
> +                                               &instance, &index);
> +       unsigned int bit = BIT(index & 0x1f);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %d\n",
> +                       __func__, eint_num);
> +               return;
> +       }
>
> -       writel(mask, reg);
> +       writel(bit, reg);
>  }
>
>  static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
>  {
>         struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
> -       bool masked;
> -       u32 mask = BIT(d->hwirq & 0x1f);
> +       u32 mask;
> +       unsigned int instance, index;
>         void __iomem *reg;
>
>         if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
> @@ -186,36 +328,42 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
>         }
>
>         if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
> -               eint->dual_edge[d->hwirq] = 1;
> +               eint->pins[d->hwirq].dual_edge = 1;
>         else
> -               eint->dual_edge[d->hwirq] = 0;
> +               eint->pins[d->hwirq].dual_edge = 0;
>
> -       if (!mtk_eint_get_mask(eint, d->hwirq)) {
> -               mtk_eint_mask(d);
> -               masked = false;
> -       } else {
> -               masked = true;
> -       }
> +       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
> +               reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                         eint->comp->regs->pol_clr,
> +                                         &instance, &index);
> +       else
> +               reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                         eint->comp->regs->pol_set,
> +                                         &instance, &index);
>
> -       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
> -               reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
> -               writel(mask, reg);
> -       } else {
> -               reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_set);
> -               writel(mask, reg);
> -       }
> +       mask = BIT(index & 0x1f);
> +       writel(mask, reg);
> +
> +       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
> +               reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                         eint->comp->regs->sens_clr,
> +                                         &instance, &index);
> +       else
> +               reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                         eint->comp->regs->sens_set,
> +                                         &instance, &index);
>
> -       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
> -               reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_clr);
> -               writel(mask, reg);
> -       } else {
> -               reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_set);
> -               writel(mask, reg);
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %lu\n",
> +                       __func__, d->hwirq);
> +               return 0;
>         }
>
> -       mtk_eint_ack(d);
> -       if (!masked)
> -               mtk_eint_unmask(d);
> +       mask = BIT(index & 0x1f);
> +       writel(mask, reg);
> +
> +       if (eint->pins[d->hwirq].dual_edge)
> +               mtk_eint_flip_edge(eint, d->hwirq);
>
>         return 0;
>  }
> @@ -223,30 +371,28 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
>  static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
>  {
>         struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
> -       int shift = d->hwirq & 0x1f;
> -       int reg = d->hwirq >> 5;
> +       unsigned int instance, index, shift, port;
> +       void __iomem *reg = mtk_eint_get_ofset(eint, d->hwirq,
> +                                               MTK_EINT_NO_OFSET,
> +                                               &instance, &index);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %lu\n",
> +                       __func__, d->hwirq);
> +               return 0;
> +       }
> +
> +       shift = index & 0x1f;
> +       port = index >> REG_GROUP;
>
>         if (on)
> -               eint->wake_mask[reg] |= BIT(shift);
> +               eint->instances[instance].wake_mask[port] |= BIT(shift);
>         else
> -               eint->wake_mask[reg] &= ~BIT(shift);
> +               eint->instances[instance].wake_mask[port] &= ~BIT(shift);
>
>         return 0;
>  }
>
> -static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
> -                                    void __iomem *base, u32 *buf)
> -{
> -       int port;
> -       void __iomem *reg;
> -
> -       for (port = 0; port < eint->hw->ports; port++) {
> -               reg = base + (port << 2);
> -               writel_relaxed(~buf[port], reg + eint->regs->mask_set);
> -               writel_relaxed(buf[port], reg + eint->regs->mask_clr);
> -       }
> -}
> -
>  static int mtk_eint_irq_request_resources(struct irq_data *d)
>  {
>         struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
> @@ -290,7 +436,7 @@ static void mtk_eint_irq_release_resources(struct irq_data *d)
>  }
>
>  static struct irq_chip mtk_eint_irq_chip = {
> -       .name = "mt-eint",
> +       .name = "mtk-eint",
>         .irq_disable = mtk_eint_mask,
>         .irq_mask = mtk_eint_mask,
>         .irq_unmask = mtk_eint_unmask,
> @@ -301,35 +447,51 @@ static struct irq_chip mtk_eint_irq_chip = {
>         .irq_release_resources = mtk_eint_irq_release_resources,
>  };
>
> +/*
> + * Configure all EINT pins as domain 0, which only belongs to AP.
> + */
>  static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
>  {
> -       void __iomem *dom_en = eint->base + eint->regs->dom_en;
> -       void __iomem *mask_set = eint->base + eint->regs->mask_set;
> -       unsigned int i;
> -
> -       for (i = 0; i < eint->hw->ap_num; i += 32) {
> -               writel(0xffffffff, dom_en);
> -               writel(0xffffffff, mask_set);
> -               dom_en += 4;
> -               mask_set += 4;
> +       void __iomem *reg,*eevt_clr;
> +       unsigned int i, j;
> +
> +       for (i = 0; i < eint->instance_number; i++) {
> +               reg = eint->instances[i].base + eint->comp->regs->dom_en;
> +               eevt_clr = eint->instances[i].base + eint->comp->regs->event_clr;
> +               for (j = 0; j < eint->instances[i].number; j += MAX_BIT, reg += REG_OFSET, eevt_clr += REG_OFSET) {
> +                       writel(REG_VAL, reg);
> +                       writel(REG_VAL, eevt_clr);
> +               }
>         }
>
>         return 0;
>  }
>
>  static inline void
> -mtk_eint_debounce_process(struct mtk_eint *eint, int index)
> +mtk_eint_debounce_process(struct mtk_eint *eint, int eint_num)
>  {
> -       unsigned int rst, ctrl_offset;
> +       unsigned int rst, ctrl_ofset;
>         unsigned int bit, dbnc;
> +       unsigned int instance, index;
> +       void __iomem *reg;
> +
> +       reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
> +                                 &instance, &index);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %d\n",
> +                       __func__, eint_num);
> +               return;
> +       }
> +
> +       ctrl_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
> +       dbnc = readl(eint->instances[instance].base + ctrl_ofset);
> +       bit = MTK_EINT_DBNC_SET_EN << ((index % REG_OFSET) * DB_GROUP);
>
> -       ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_ctrl;
> -       dbnc = readl(eint->base + ctrl_offset);
> -       bit = MTK_EINT_DBNC_SET_EN << ((index % 4) * 8);
>         if ((bit & dbnc) > 0) {
> -               ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_set;
> -               rst = MTK_EINT_DBNC_RST_BIT << ((index % 4) * 8);
> -               writel(rst, eint->base + ctrl_offset);
> +               ctrl_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_set;
> +               rst = MTK_EINT_DBNC_RST_BIT << ((index % REG_OFSET) * DB_GROUP);
> +               writel(rst, eint->instances[instance].base + ctrl_ofset);
>         }
>  }
>
> @@ -337,65 +499,72 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
>  {
>         struct irq_chip *chip = irq_desc_get_chip(desc);
>         struct mtk_eint *eint = irq_desc_get_handler_data(desc);
> -       unsigned int status, eint_num;
> -       int offset, mask_offset, index;
> -       void __iomem *reg =  mtk_eint_get_offset(eint, 0, eint->regs->stat);
> -       int dual_edge, start_level, curr_level;
> +       unsigned int status, i, j;
> +       int shift, port, eint_num, virq;
> +       unsigned int dual_edge, start_level, curr_level;
> +       struct mtk_eint_instance eint_instance;
> +       void __iomem *addr;
>
>         chained_irq_enter(chip, desc);
> -       for (eint_num = 0; eint_num < eint->hw->ap_num; eint_num += 32,
> -            reg += 4) {
> -               status = readl(reg);
> -               while (status) {
> -                       offset = __ffs(status);
> -                       mask_offset = eint_num >> 5;
> -                       index = eint_num + offset;
> -                       status &= ~BIT(offset);
> -
> -                       /*
> -                        * If we get an interrupt on pin that was only required
> -                        * for wake (but no real interrupt requested), mask the
> -                        * interrupt (as would mtk_eint_resume do anyway later
> -                        * in the resume sequence).
> -                        */
> -                       if (eint->wake_mask[mask_offset] & BIT(offset) &&
> -                           !(eint->cur_mask[mask_offset] & BIT(offset))) {
> -                               writel_relaxed(BIT(offset), reg -
> -                                       eint->regs->stat +
> -                                       eint->regs->mask_set);
> -                       }
> -
> -                       dual_edge = eint->dual_edge[index];
> -                       if (dual_edge) {
> -                               /*
> -                                * Clear soft-irq in case we raised it last
> -                                * time.
> -                                */
> -                               writel(BIT(offset), reg - eint->regs->stat +
> -                                      eint->regs->soft_clr);
>
> -                               start_level =
> -                               eint->gpio_xlate->get_gpio_state(eint->pctl,
> -                                                                index);
> -                       }
> +       for (i = 0; i < eint->instance_number; i++) {
> +               eint_instance = eint->instances[i];
>
> -                       generic_handle_domain_irq(eint->domain, index);
> +               /* Iterate all pins by port */
> +               for (j = 0; j < eint_instance.number; j += MAX_BIT) {
> +                       port = j >> REG_GROUP;
> +                       status = readl(eint_instance.base + port * REG_OFSET +
> +                                      eint->comp->regs->stat);
> +                       while (status) {
> +                               shift = __ffs(status);
> +                               status &= ~BIT(shift);
>
> -                       if (dual_edge) {
> -                               curr_level = mtk_eint_flip_edge(eint, index);
> +                               eint_num = eint->instances[i].pin_list[shift + j];
> +                               virq = irq_find_mapping(eint->domain, eint_num);
>
>                                 /*
> -                                * If level changed, we might lost one edge
> -                                * interrupt, raised it through soft-irq.
> +                                * If we get an interrupt on pin that was only required
> +                                * for wake (but no real interrupt requested), mask the
> +                                * interrupt (as would mtk_eint_resume do anyway later
> +                                * in the resume sequence).
>                                  */
> -                               if (start_level != curr_level)
> -                                       writel(BIT(offset), reg -
> -                                              eint->regs->stat +
> -                                              eint->regs->soft_set);
> -                       }
> +                               if (eint->instances[i].wake_mask[port] & BIT(shift) &&
> +                                   !(eint->instances[i].cur_mask[port] & BIT(shift))) {
> +                                       addr = eint_instance.base + port * REG_OFSET +
> +                                               eint->comp->regs->mask_set;
> +                                       writel_relaxed(BIT(shift), addr);
> +                               }
> +
> +                               dual_edge = eint->pins[eint_num].dual_edge;
> +                               if (dual_edge) {
> +                                       /*
> +                                        * Clear soft-irq in case we raised it last
> +                                        * time.
> +                                        */
> +                                       mtk_eint_soft_clr(eint, eint_num);
> +
> +                                       start_level =
> +                                       eint->gpio_xlate->get_gpio_state(eint->pctl,
> +                                                                        eint_num);
> +                               }
> +
> +                               generic_handle_irq(virq);
> +
> +                               if (dual_edge) {
> +                                       curr_level = mtk_eint_flip_edge(eint, eint_num);
> +
> +                                       /*
> +                                        * If level changed, we might lost one edge
> +                                        * interrupt, raised it through soft-irq.
> +                                        */
> +                                       if (start_level != curr_level)
> +                                               mtk_eint_soft_set(eint, eint_num);
> +                               }
> +
> +                               if (eint->pins[eint_num].debounce)
> +                                       mtk_eint_debounce_process(eint, eint_num);
>
> -                       if (index < eint->hw->db_cnt)
> -                               mtk_eint_debounce_process(eint, index);
> +                       }
>                 }
>         }
>         chained_irq_exit(chip, desc);
> @@ -403,7 +572,20 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
>
>  int mtk_eint_do_suspend(struct mtk_eint *eint)
>  {
> -       mtk_eint_chip_write_mask(eint, eint->base, eint->wake_mask);
> +       unsigned int i, j, port;
> +
> +       for (i = 0; i < eint->instance_number; i++) {
> +               struct mtk_eint_instance inst = eint->instances[i];
> +
> +               for (j = 0; j < inst.number; j += MAX_BIT) {
> +                       port = j >> REG_GROUP;
> +                       writel_relaxed(~inst.wake_mask[port],
> +                                      inst.base + port*REG_OFSET + eint->comp->regs->mask_set);
> +                       writel_relaxed(inst.wake_mask[port],
> +                                      inst.base + port*REG_OFSET + eint->comp->regs->mask_clr);
> +               }
> +       }
> +       dsb(sy);
>
>         return 0;
>  }
> @@ -411,7 +593,20 @@ EXPORT_SYMBOL_GPL(mtk_eint_do_suspend);
>
>  int mtk_eint_do_resume(struct mtk_eint *eint)
>  {
> -       mtk_eint_chip_write_mask(eint, eint->base, eint->cur_mask);
> +       unsigned int i, j, port;
> +
> +       for (i = 0; i < eint->instance_number; i++) {
> +               struct mtk_eint_instance inst = eint->instances[i];
> +
> +               for (j = 0; j < inst.number; j += MAX_BIT) {
> +                       port = j >> REG_GROUP;
> +                       writel_relaxed(~inst.cur_mask[port],
> +                                      inst.base + port*REG_OFSET + eint->comp->regs->mask_set);
> +                       writel_relaxed(inst.cur_mask[port],
> +                                      inst.base + port*REG_OFSET + eint->comp->regs->mask_clr);
> +               }
> +       }
> +       dsb(sy);
>
>         return 0;
>  }
> @@ -420,27 +615,45 @@ EXPORT_SYMBOL_GPL(mtk_eint_do_resume);
>  int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
>                           unsigned int debounce)
>  {
> -       int virq, eint_offset;
> -       unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask,
> +       int virq, eint_ofset;
> +       unsigned int set_ofset, bit, clr_bit, clr_ofset, rst, i, unmask,
>                      dbnc;
> +       static const unsigned int debounce_time[] = { 156, 313, 625, 1250,
> +               20000, 40000, 80000, 160000, 320000, 640000 };
>         struct irq_data *d;
> +       unsigned int instance, index;
> +       void __iomem *reg;
>
> -       if (!eint->hw->db_time)
> -               return -EOPNOTSUPP;
> +       /*
> +        * Due to different number of bit field, we only decode
> +        * the coordinate here, instead of get the VA.
> +        */
> +       reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
> +                                 &instance, &index);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %lu\n",
> +                       __func__, eint_num);
> +               return 0;
> +       }
>
>         virq = irq_find_mapping(eint->domain, eint_num);
> -       eint_offset = (eint_num % 4) * 8;
> +       eint_ofset = (index % REG_OFSET) * DB_GROUP;
>         d = irq_get_irq_data(virq);
>
> -       set_offset = (eint_num / 4) * 4 + eint->regs->dbnc_set;
> -       clr_offset = (eint_num / 4) * 4 + eint->regs->dbnc_clr;
> +       reg = eint->instances[instance].base;
> +       set_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_set;
> +       clr_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_clr;
>
>         if (!mtk_eint_can_en_debounce(eint, eint_num))
>                 return -EINVAL;
>
> -       dbnc = eint->num_db_time;
> -       for (i = 0; i < eint->num_db_time; i++) {
> -               if (debounce <= eint->hw->db_time[i]) {
> +       /*
> +        * Check eint number to avoid access out-of-range
> +        */
> +       dbnc = ARRAY_SIZE(debounce_time) - 1;
> +       for (i = 0; i < ARRAY_SIZE(debounce_time); i++) {
> +               if (debounce <= debounce_time[i]) {
>                         dbnc = i;
>                         break;
>                 }
> @@ -449,23 +662,20 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
>         if (!mtk_eint_get_mask(eint, eint_num)) {
>                 mtk_eint_mask(d);
>                 unmask = 1;
> -       } else {
> +       } else
>                 unmask = 0;
> -       }
>
> -       clr_bit = 0xff << eint_offset;
> -       writel(clr_bit, eint->base + clr_offset);
> +       clr_bit = 0xff << eint_ofset;
> +       writel(clr_bit, reg + clr_ofset);
>
> -       bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS) | MTK_EINT_DBNC_SET_EN) <<
> -               eint_offset;
> -       rst = MTK_EINT_DBNC_RST_BIT << eint_offset;
> -       writel(rst | bit, eint->base + set_offset);
> +       bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS)
> +               | MTK_EINT_DBNC_SET_EN) << eint_ofset;
> +       rst = MTK_EINT_DBNC_RST_BIT << eint_ofset;
> +       writel(rst | bit, reg + set_ofset);
>
>         /*
> -        * Delay a while (more than 2T) to wait for hw debounce counter reset
> -        * work correctly.
> +        * Delay should be (8T @ 32k) from dbc rst to work correctly.
>          */
> -       udelay(1);
>         if (unmask == 1)
>                 mtk_eint_unmask(d);
>
> @@ -473,6 +683,53 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
>  }
>  EXPORT_SYMBOL_GPL(mtk_eint_set_debounce);
>
> +unsigned int mtk_eint_get_debounce_en(struct mtk_eint *eint,
> +                                     unsigned int eint_num)
> +{
> +       unsigned int instance, index, bit;
> +       void __iomem *reg;
> +
> +       reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
> +                                 &instance, &index);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %d\n",
> +                       __func__, eint_num);
> +               return 0;
> +       }
> +
> +       reg = eint->instances[instance].base +
> +               (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
> +
> +       bit = MTK_EINT_DBNC_SET_EN << ((index % REG_OFSET) * DB_GROUP);
> +
> +       return (readl(reg) & bit) ? 1 : 0;
> +}
> +
> +unsigned int mtk_eint_get_debounce_value(struct mtk_eint *eint,
> +                                          unsigned int eint_num)
> +{
> +       unsigned int instance, index, mask, ofset;
> +       void __iomem *reg;
> +
> +       reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
> +                                 &instance, &index);
> +
> +       if (!reg) {
> +               dev_err(eint->dev, "%s invalid eint_num %d\n",
> +                       __func__, eint_num);
> +               return 0;
> +       }
> +
> +       reg = eint->instances[instance].base +
> +               (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
> +
> +       ofset = MTK_EINT_DBNC_SET_DBNC_BITS + ((index % REG_OFSET) * DB_GROUP);
> +       mask = 0xf << ofset;
> +
> +       return ((readl(reg) & mask) >> ofset);
> +}
> +
>  int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
>  {
>         int irq;
> @@ -485,45 +742,209 @@ int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
>  }
>  EXPORT_SYMBOL_GPL(mtk_eint_find_irq);
>
> +static const struct mtk_eint_compatible default_compat = {
> +       .regs = &mtk_generic_eint_regs,
> +};
> +
> +static const struct of_device_id eint_compatible_ids[] = {
> +       { }
> +};
> +
>  int mtk_eint_do_init(struct mtk_eint *eint)
>  {
> -       int i;
> +       int i, virq;
> +       unsigned int size, inst = 0;
> +       eint->instance_number = 1;
> +       eint->total_pin_number = eint->hw->ap_num;
> +
> +       for (i = 0; i < eint->total_pin_number; i++) {
> +               eint->pins[i].enabled = true;
> +               eint->pins[i].instance = inst;
> +               eint->pins[i].index = i;
> +               eint->pins[i].debounce =  (i < eint->hw->db_cnt) ? 1 : 0;
> +
> +               eint->instances[inst].pin_list[i] = i;
> +               eint->instances[inst].number++;
> +       }
>
> -       /* If clients don't assign a specific regs, let's use generic one */
> -       if (!eint->regs)
> -               eint->regs = &mtk_generic_eint_regs;
> +       for (i = 0; i < eint->instance_number; i++) {
> +               size = (eint->instances[i].number / MAX_BIT + 1) * sizeof(unsigned int);
> +               eint->instances[i].wake_mask =
> +                       devm_kzalloc(eint->dev, size, GFP_KERNEL);
> +               eint->instances[i].cur_mask =
> +                       devm_kzalloc(eint->dev, size, GFP_KERNEL);
>
> -       eint->wake_mask = devm_kcalloc(eint->dev, eint->hw->ports,
> -                                      sizeof(*eint->wake_mask), GFP_KERNEL);
> -       if (!eint->wake_mask)
> +               if (!eint->instances[i].wake_mask ||
> +                   !eint->instances[i].cur_mask)
> +                       return -ENOMEM;
> +       }
> +
> +       eint->comp = &default_compat;
> +
> +       eint->domain = irq_domain_add_linear(eint->dev->of_node,
> +                                            eint->total_pin_number,
> +                                            &irq_domain_simple_ops, NULL);
> +       if (!eint->domain)
>                 return -ENOMEM;
>
> -       eint->cur_mask = devm_kcalloc(eint->dev, eint->hw->ports,
> -                                     sizeof(*eint->cur_mask), GFP_KERNEL);
> -       if (!eint->cur_mask)
> +       mtk_eint_hw_init(eint);
> +       for (i = 0; i < eint->total_pin_number; i++) {
> +               virq = irq_create_mapping(eint->domain, i);
> +
> +               irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
> +                                        handle_level_irq);
> +               irq_set_chip_data(virq, eint);
> +       }
> +
> +       irq_set_chained_handler_and_data(eint->irq, mtk_eint_irq_handler,
> +                                        eint);
> +
> +       global_eintc = eint;
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(mtk_eint_do_init);
> +
> +int mtk_eint_do_init_v2(struct mtk_eint *eint)
> +{
> +       int i, virq, matrix_number = 0;
> +       struct device_node *node;
> +       unsigned int ret, size, ofset;
> +       unsigned int id, inst, idx, support_deb;
> +
> +       const phandle *ph;
> +
> +       ph = of_get_property(eint->dev->of_node, "mediatek,eint", NULL);
> +       if (!ph) {
> +               dev_err(eint->dev, "Cannot find EINT phandle in PIO node.\n");
> +               return -ENODEV;
> +       }
> +
> +       node = of_find_node_by_phandle(be32_to_cpup(ph));
> +       if (!node) {
> +               dev_err(eint->dev, "Cannot find EINT node by phandle.\n");
> +               return -ENODEV;
> +       }
> +
> +       ret = of_property_read_u32(node, "mediatek,total-pin-number",
> +                                  &eint->total_pin_number);
> +       if (ret) {
> +               dev_err(eint->dev,
> +                      "%s cannot read total-pin-number from device node.\n",
> +                      __func__);
> +               return -EINVAL;
> +       }
> +
> +       dev_info(eint->dev, "%s eint total %u pins.\n", __func__,
> +               eint->total_pin_number);
> +
> +       ret = of_property_read_u32(node, "mediatek,instance-num",
> +                                  &eint->instance_number);
> +       if (ret)
> +               eint->instance_number = 1; // only 1 instance in legacy chip
> +
> +       size = eint->instance_number * sizeof(struct mtk_eint_instance);
> +       eint->instances = devm_kzalloc(eint->dev, size, GFP_KERNEL);
> +       if (!eint->instances)
>                 return -ENOMEM;
>
> -       eint->dual_edge = devm_kcalloc(eint->dev, eint->hw->ap_num,
> -                                      sizeof(int), GFP_KERNEL);
> -       if (!eint->dual_edge)
> +       size = eint->total_pin_number * sizeof(struct mtk_eint_pin);
> +       eint->pins = devm_kzalloc(eint->dev, size, GFP_KERNEL);
> +       if (!eint->pins)
>                 return -ENOMEM;
>
> +       for (i = 0; i < eint->instance_number; i++) {
> +               ret = of_property_read_string_index(node, "reg-name", i,
> +                                                   &(eint->instances[i].name));
> +               if (ret) {
> +                       dev_info(eint->dev,
> +                                "%s cannot read the name of instance %d.\n",
> +                                __func__, i);
> +               }
> +
> +               eint->instances[i].base = of_iomap(node, i);
> +               if (!eint->instances[i].base)
> +                       return -ENOMEM;
> +       }
> +
> +       matrix_number = of_property_count_u32_elems(node, "mediatek,pins") / ARRAY_0;
> +       if (matrix_number < 0) {
> +               matrix_number = eint->total_pin_number;
> +               dev_info(eint->dev, "%s eint in legacy mode, assign the matrix number to %u.\n",
> +                        __func__, matrix_number);
> +       } else
> +               dev_info(eint->dev, "%s eint in new mode, assign the matrix number to %u.\n",
> +                        __func__, matrix_number);
> +
> +       for (i = 0; i < matrix_number; i++) {
> +               ofset = i * REG_OFSET;
> +
> +               ret = of_property_read_u32_index(node, "mediatek,pins",
> +                                          ofset, &id);
> +               ret |= of_property_read_u32_index(node, "mediatek,pins",
> +                                          ofset+FIRST, &inst);
> +               ret |= of_property_read_u32_index(node, "mediatek,pins",
> +                                          ofset+SECOND, &idx);
> +               ret |= of_property_read_u32_index(node, "mediatek,pins",
> +                                          ofset+THIRD, &support_deb);
> +
> +               /* Legacy chip which no need to give coordinate list */
> +               if (ret) {
> +                       id = i;
> +                       inst = 0;
> +                       idx = i;
> +                       support_deb = (i < MAX_BIT) ? 1 : 0;
> +               }
> +
> +               eint->pins[id].enabled = true;
> +               eint->pins[id].instance = inst;
> +               eint->pins[id].index = idx;
> +               eint->pins[id].debounce = support_deb;
> +
> +               eint->instances[inst].pin_list[idx] = id;
> +               eint->instances[inst].number++;
> +
> +#if defined(MTK_EINT_DEBUG)
> +               pin = eint->pins[id];
> +               dev_info(eint->dev,
> +                        "EINT%u in (%u-%u), su_deb = %u",
> +                        id,
> +                        pin.instance,
> +                        eint->instances[inst].number,
> +                        pin.debounce,
> +#endif
> +       }
> +
> +       for (i = 0; i < eint->instance_number; i++) {
> +               size = (eint->instances[i].number / MAX_BIT + 1) * sizeof(unsigned int);
> +               eint->instances[i].wake_mask =
> +                       devm_kzalloc(eint->dev, size, GFP_KERNEL);
> +               eint->instances[i].cur_mask =
> +                       devm_kzalloc(eint->dev, size, GFP_KERNEL);
> +
> +               if (!eint->instances[i].wake_mask ||
> +                   !eint->instances[i].cur_mask)
> +                       return -ENOMEM;
> +       }
> +
> +       eint->comp = &default_compat;
> +
> +       eint->irq = irq_of_parse_and_map(node, 0);
> +       if (!eint->irq) {
> +               dev_err(eint->dev,
> +                       "%s IRQ parse fail.\n", __func__);
> +               return -EINVAL;
> +       }
> +
>         eint->domain = irq_domain_add_linear(eint->dev->of_node,
> -                                            eint->hw->ap_num,
> +                                            eint->total_pin_number,
>                                              &irq_domain_simple_ops, NULL);
>         if (!eint->domain)
>                 return -ENOMEM;
>
> -       if (eint->hw->db_time) {
> -               for (i = 0; i < MTK_EINT_DBNC_MAX; i++)
> -                       if (eint->hw->db_time[i] == 0)
> -                               break;
> -               eint->num_db_time = i;
> -       }
> -
>         mtk_eint_hw_init(eint);
> -       for (i = 0; i < eint->hw->ap_num; i++) {
> -               int virq = irq_create_mapping(eint->domain, i);
> +       for (i = 0; i < eint->total_pin_number; i++) {
> +               virq = irq_create_mapping(eint->domain, i);
>
>                 irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
>                                          handle_level_irq);
> @@ -533,9 +954,11 @@ int mtk_eint_do_init(struct mtk_eint *eint)
>         irq_set_chained_handler_and_data(eint->irq, mtk_eint_irq_handler,
>                                          eint);
>
> +       global_eintc = eint;
> +
>         return 0;
>  }
> -EXPORT_SYMBOL_GPL(mtk_eint_do_init);
> +EXPORT_SYMBOL_GPL(mtk_eint_do_init_v2);
>
>  MODULE_LICENSE("GPL v2");
>  MODULE_DESCRIPTION("MediaTek EINT Driver");
> diff --git a/drivers/pinctrl/mediatek/mtk-eint.h b/drivers/pinctrl/mediatek/mtk-eint.h
> index 6139b16cd225..aa17a6073029 100644
> --- a/drivers/pinctrl/mediatek/mtk-eint.h
> +++ b/drivers/pinctrl/mediatek/mtk-eint.h
> @@ -11,6 +11,25 @@
>
>  #include <linux/irqdomain.h>
>
> +#define MAX_PIN 999
> +#define MTK_EINT_EDGE_SENSITIVE           0
> +#define MTK_EINT_LEVEL_SENSITIVE          1
> +#define MTK_EINT_DBNC_SET_DBNC_BITS       4
> +#define MTK_EINT_DBNC_RST_BIT             (0x1 << 1)
> +#define MTK_EINT_DBNC_SET_EN              (0x1 << 0)
> +#define MTK_EINT_NO_OFSET                 0
> +#define MAX_BIT                           32
> +#define REG_OFSET                         4
> +#define REG_GROUP                         5
> +#define REG_VAL                           0xFFFFFFFF
> +#define DB_GROUP                          8
> +#define FIRST                             1
> +#define SECOND                            2
> +#define THIRD                             3
> +#define ARRAY_0                           4
> +
> +//#define MTK_EINT_DEBUG
> +
>  struct mtk_eint_regs {
>         unsigned int    stat;
>         unsigned int    ack;
> @@ -30,6 +49,36 @@ struct mtk_eint_regs {
>         unsigned int    dbnc_ctrl;
>         unsigned int    dbnc_set;
>         unsigned int    dbnc_clr;
> +       unsigned int    event;
> +       unsigned int    event_set;
> +       unsigned int    event_clr;
> +       unsigned int    raw_stat;
> +};
> +
> +struct mtk_eint_ops {
> +       void (*ack)(struct irq_data *d);
> +};
> +
> +struct mtk_eint_compatible {
> +       struct mtk_eint_ops ops;
> +       const struct mtk_eint_regs *regs;
> +};
> +
> +struct mtk_eint_instance {
> +       const char *name;
> +       void __iomem *base;
> +       unsigned int number;
> +       unsigned int pin_list[MAX_PIN];
> +       unsigned int *wake_mask;
> +       unsigned int *cur_mask;
> +};
> +
> +struct mtk_eint_pin {
> +       bool enabled;
> +       unsigned int instance;
> +       unsigned int index;
> +       bool debounce;
> +       bool dual_edge;
>  };
>
>  struct mtk_eint_hw {
> @@ -60,11 +109,14 @@ struct mtk_eint {
>         struct irq_domain *domain;
>         int irq;
>
> -       int *dual_edge;
> -       u32 *wake_mask;
> -       u32 *cur_mask;
> -
> -       /* Used to fit into various EINT device */
> +       /* An array to record the coordinate, index by global EINT ID */
> +       struct mtk_eint_pin *pins;
> +       /* An array to record the global EINT ID, index by coordinate*/
> +       struct mtk_eint_instance *instances;
> +       unsigned int total_pin_number;
> +       unsigned int instance_number;
> +       unsigned int dump_target_eint;
> +       const struct mtk_eint_compatible *comp;
>         const struct mtk_eint_hw *hw;
>         const struct mtk_eint_regs *regs;
>         u16 num_db_time;
> @@ -74,13 +126,15 @@ struct mtk_eint {
>         const struct mtk_eint_xt *gpio_xlate;
>  };
>
> -#if IS_ENABLED(CONFIG_EINT_MTK)
> +#if (IS_ENABLED(CONFIG_EINT_MTK) || IS_ENABLED(CONFIG_DEVICE_MODULES_EINT_MTK))
>  int mtk_eint_do_init(struct mtk_eint *eint);
> +int mtk_eint_do_init_v2(struct mtk_eint *eint);
>  int mtk_eint_do_suspend(struct mtk_eint *eint);
>  int mtk_eint_do_resume(struct mtk_eint *eint);
>  int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
>                           unsigned int debounce);
>  int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n);
> +int dump_eint_pin_status(unsigned int eint_num);
>
>  #else
>  static inline int mtk_eint_do_init(struct mtk_eint *eint)
> @@ -88,6 +142,11 @@ static inline int mtk_eint_do_init(struct mtk_eint *eint)
>         return -EOPNOTSUPP;
>  }
>
> +static inline int mtk_eint_do_init_v2(struct mtk_eint *eint)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
>  static inline int mtk_eint_do_suspend(struct mtk_eint *eint)
>  {
>         return -EOPNOTSUPP;
> @@ -108,5 +167,9 @@ static inline int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
>  {
>         return -EOPNOTSUPP;
>  }
> +static inline int dump_eint_pin_status(unsigned int eint_num)
> +{
> +       return -EOPNOTSUPP;
> +}
>  #endif
>  #endif /* __MTK_EINT_H */
> diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
> index 54301fbba524..3740e868c650 100644
> --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
> +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
> @@ -375,33 +375,37 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
>         if (!of_property_read_bool(np, "interrupt-controller"))
>                 return -ENODEV;
>
> -       hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
> -       if (!hw->eint)
> -               return -ENOMEM;
> -
> -       hw->eint->base = devm_platform_ioremap_resource_byname(pdev, "eint");
> -       if (IS_ERR(hw->eint->base)) {
> -               ret = PTR_ERR(hw->eint->base);
> -               goto err_free_eint;
> -       }
> +       if (hw->soc->eint_hw) {
> +               hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
> +               if (!hw->eint)
> +                       return -ENOMEM;
> +
> +               hw->eint->base = devm_platform_ioremap_resource_byname(pdev, "eint");
> +               if (IS_ERR(hw->eint->base)) {
> +                       ret = PTR_ERR(hw->eint->base);
> +                       goto err_free_eint;
> +               }
>
> -       hw->eint->irq = irq_of_parse_and_map(np, 0);
> -       if (!hw->eint->irq) {
> -               ret = -EINVAL;
> -               goto err_free_eint;
> -       }
> +               hw->eint->irq = irq_of_parse_and_map(np, 0);
> +               if (!hw->eint->irq) {
> +                       ret = -EINVAL;
> +                       goto err_free_eint;
> +               }
>
> -       if (!hw->soc->eint_hw) {
> -               ret = -ENODEV;
> -               goto err_free_eint;
> -       }
> +               hw->eint->dev = &pdev->dev;
> +               hw->eint->hw = hw->soc->eint_hw;
> +               hw->eint->pctl = hw;
> +               hw->eint->gpio_xlate = &mtk_eint_xt;
> +
> +                return mtk_eint_do_init(hw->eint);
>
> -       hw->eint->dev = &pdev->dev;
> -       hw->eint->hw = hw->soc->eint_hw;
> -       hw->eint->pctl = hw;
> -       hw->eint->gpio_xlate = &mtk_eint_xt;
> +        } else {
> +                hw->eint->dev = &pdev->dev;
> +                hw->eint->pctl = hw;
> +                hw->eint->gpio_xlate = &mtk_eint_xt;
>
> -       return mtk_eint_do_init(hw->eint);
> +                return mtk_eint_do_init_v2(hw->eint);
> +       }
>
>  err_free_eint:
>         devm_kfree(hw->dev, hw->eint);
> --
> 2.34.1
>
>
kernel test robot Oct. 26, 2024, 6:27 p.m. UTC | #2
Hi chang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on linusw-pinctrl/for-next linus/master v6.12-rc4 next-20241025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/chang-hao/pinctrl-mediatek-add-eint-new-design-for-mt8196/20241025-111952
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
patch link:    https://lore.kernel.org/r/20241025031814.21442-1-ot_chhao.chang%40mediatek.com
patch subject: [PATCH] pinctrl: mediatek: add eint new design for mt8196
config: arm-randconfig-r122-20241026 (https://download.01.org/0day-ci/archive/20241027/202410270252.vGIAE54G-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 14.1.0
reproduce: (https://download.01.org/0day-ci/archive/20241027/202410270252.vGIAE54G-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410270252.vGIAE54G-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/pinctrl/mediatek/mtk-eint.c:686:14: sparse: sparse: symbol 'mtk_eint_get_debounce_en' was not declared. Should it be static?
>> drivers/pinctrl/mediatek/mtk-eint.c:709:14: sparse: sparse: symbol 'mtk_eint_get_debounce_value' was not declared. Should it be static?
>> drivers/pinctrl/mediatek/mtk-eint.c:823:53: sparse: sparse: incorrect type in argument 1 (different base types) @@     expected restricted __be32 const [usertype] *p @@     got unsigned int const [usertype] *[assigned] ph @@
   drivers/pinctrl/mediatek/mtk-eint.c:823:53: sparse:     expected restricted __be32 const [usertype] *p
   drivers/pinctrl/mediatek/mtk-eint.c:823:53: sparse:     got unsigned int const [usertype] *[assigned] ph

vim +/mtk_eint_get_debounce_en +686 drivers/pinctrl/mediatek/mtk-eint.c

   685	
 > 686	unsigned int mtk_eint_get_debounce_en(struct mtk_eint *eint,
   687					      unsigned int eint_num)
   688	{
   689		unsigned int instance, index, bit;
   690		void __iomem *reg;
   691	
   692		reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
   693					  &instance, &index);
   694	
   695		if (!reg) {
   696			dev_err(eint->dev, "%s invalid eint_num %d\n",
   697				__func__, eint_num);
   698			return 0;
   699		}
   700	
   701		reg = eint->instances[instance].base +
   702			(index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
   703	
   704		bit = MTK_EINT_DBNC_SET_EN << ((index % REG_OFSET) * DB_GROUP);
   705	
   706		return (readl(reg) & bit) ? 1 : 0;
   707	}
   708	
 > 709	unsigned int mtk_eint_get_debounce_value(struct mtk_eint *eint,
   710						   unsigned int eint_num)
   711	{
   712		unsigned int instance, index, mask, ofset;
   713		void __iomem *reg;
   714	
   715		reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
   716					  &instance, &index);
   717	
   718		if (!reg) {
   719			dev_err(eint->dev, "%s invalid eint_num %d\n",
   720				__func__, eint_num);
   721			return 0;
   722		}
   723	
   724		reg = eint->instances[instance].base +
   725			(index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
   726	
   727		ofset = MTK_EINT_DBNC_SET_DBNC_BITS + ((index % REG_OFSET) * DB_GROUP);
   728		mask = 0xf << ofset;
   729	
   730		return ((readl(reg) & mask) >> ofset);
   731	}
   732	
   733	int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
   734	{
   735		int irq;
   736	
   737		irq = irq_find_mapping(eint->domain, eint_n);
   738		if (!irq)
   739			return -EINVAL;
   740	
   741		return irq;
   742	}
   743	EXPORT_SYMBOL_GPL(mtk_eint_find_irq);
   744	
   745	static const struct mtk_eint_compatible default_compat = {
   746		.regs = &mtk_generic_eint_regs,
   747	};
   748	
   749	static const struct of_device_id eint_compatible_ids[] = {
   750		{ }
   751	};
   752	
   753	int mtk_eint_do_init(struct mtk_eint *eint)
   754	{
   755		int i, virq;
   756		unsigned int size, inst = 0;
   757		eint->instance_number = 1;
   758		eint->total_pin_number = eint->hw->ap_num;
   759	
   760		for (i = 0; i < eint->total_pin_number; i++) {
   761			eint->pins[i].enabled = true;
   762			eint->pins[i].instance = inst;
   763			eint->pins[i].index = i;
   764			eint->pins[i].debounce =  (i < eint->hw->db_cnt) ? 1 : 0;
   765	
   766			eint->instances[inst].pin_list[i] = i;
   767			eint->instances[inst].number++;
   768		}
   769	
   770		for (i = 0; i < eint->instance_number; i++) {
   771			size = (eint->instances[i].number / MAX_BIT + 1) * sizeof(unsigned int);
   772			eint->instances[i].wake_mask =
   773				devm_kzalloc(eint->dev, size, GFP_KERNEL);
   774			eint->instances[i].cur_mask =
   775				devm_kzalloc(eint->dev, size, GFP_KERNEL);
   776	
   777			if (!eint->instances[i].wake_mask ||
   778			    !eint->instances[i].cur_mask)
   779				return -ENOMEM;
   780		}
   781	
   782		eint->comp = &default_compat;
   783	
   784		eint->domain = irq_domain_add_linear(eint->dev->of_node,
   785						     eint->total_pin_number,
   786						     &irq_domain_simple_ops, NULL);
   787		if (!eint->domain)
   788			return -ENOMEM;
   789	
   790		mtk_eint_hw_init(eint);
   791		for (i = 0; i < eint->total_pin_number; i++) {
   792			virq = irq_create_mapping(eint->domain, i);
   793	
   794			irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
   795						 handle_level_irq);
   796			irq_set_chip_data(virq, eint);
   797		}
   798	
   799		irq_set_chained_handler_and_data(eint->irq, mtk_eint_irq_handler,
   800						 eint);
   801	
   802		global_eintc = eint;
   803	
   804		return 0;
   805	}
   806	EXPORT_SYMBOL_GPL(mtk_eint_do_init);
   807	
   808	int mtk_eint_do_init_v2(struct mtk_eint *eint)
   809	{
   810		int i, virq, matrix_number = 0;
   811		struct device_node *node;
   812		unsigned int ret, size, ofset;
   813		unsigned int id, inst, idx, support_deb;
   814	
   815		const phandle *ph;
   816	
   817		ph = of_get_property(eint->dev->of_node, "mediatek,eint", NULL);
   818		if (!ph) {
   819			dev_err(eint->dev, "Cannot find EINT phandle in PIO node.\n");
   820			return -ENODEV;
   821		}
   822	
 > 823		node = of_find_node_by_phandle(be32_to_cpup(ph));
   824		if (!node) {
   825			dev_err(eint->dev, "Cannot find EINT node by phandle.\n");
   826			return -ENODEV;
   827		}
   828	
   829		ret = of_property_read_u32(node, "mediatek,total-pin-number",
   830					   &eint->total_pin_number);
   831		if (ret) {
   832			dev_err(eint->dev,
   833			       "%s cannot read total-pin-number from device node.\n",
   834			       __func__);
   835			return -EINVAL;
   836		}
   837	
   838		dev_info(eint->dev, "%s eint total %u pins.\n", __func__,
   839			eint->total_pin_number);
   840	
   841		ret = of_property_read_u32(node, "mediatek,instance-num",
   842					   &eint->instance_number);
   843		if (ret)
   844			eint->instance_number = 1; // only 1 instance in legacy chip
   845	
   846		size = eint->instance_number * sizeof(struct mtk_eint_instance);
   847		eint->instances = devm_kzalloc(eint->dev, size, GFP_KERNEL);
   848		if (!eint->instances)
   849			return -ENOMEM;
   850	
   851		size = eint->total_pin_number * sizeof(struct mtk_eint_pin);
   852		eint->pins = devm_kzalloc(eint->dev, size, GFP_KERNEL);
   853		if (!eint->pins)
   854			return -ENOMEM;
   855	
   856		for (i = 0; i < eint->instance_number; i++) {
   857			ret = of_property_read_string_index(node, "reg-name", i,
   858							    &(eint->instances[i].name));
   859			if (ret) {
   860				dev_info(eint->dev,
   861					 "%s cannot read the name of instance %d.\n",
   862					 __func__, i);
   863			}
   864	
   865			eint->instances[i].base = of_iomap(node, i);
   866			if (!eint->instances[i].base)
   867				return -ENOMEM;
   868		}
   869	
   870		matrix_number = of_property_count_u32_elems(node, "mediatek,pins") / ARRAY_0;
   871		if (matrix_number < 0) {
   872			matrix_number = eint->total_pin_number;
   873			dev_info(eint->dev, "%s eint in legacy mode, assign the matrix number to %u.\n",
   874				 __func__, matrix_number);
   875		} else
   876			dev_info(eint->dev, "%s eint in new mode, assign the matrix number to %u.\n",
   877				 __func__, matrix_number);
   878	
   879		for (i = 0; i < matrix_number; i++) {
   880			ofset = i * REG_OFSET;
   881	
   882			ret = of_property_read_u32_index(node, "mediatek,pins",
   883						   ofset, &id);
   884			ret |= of_property_read_u32_index(node, "mediatek,pins",
   885						   ofset+FIRST, &inst);
   886			ret |= of_property_read_u32_index(node, "mediatek,pins",
   887						   ofset+SECOND, &idx);
   888			ret |= of_property_read_u32_index(node, "mediatek,pins",
   889						   ofset+THIRD, &support_deb);
   890	
   891			/* Legacy chip which no need to give coordinate list */
   892			if (ret) {
   893				id = i;
   894				inst = 0;
   895				idx = i;
   896				support_deb = (i < MAX_BIT) ? 1 : 0;
   897			}
   898	
   899			eint->pins[id].enabled = true;
   900			eint->pins[id].instance = inst;
   901			eint->pins[id].index = idx;
   902			eint->pins[id].debounce = support_deb;
   903	
   904			eint->instances[inst].pin_list[idx] = id;
   905			eint->instances[inst].number++;
   906
kernel test robot Oct. 27, 2024, 3:35 a.m. UTC | #3
Hi chang,

kernel test robot noticed the following build errors:

[auto build test ERROR on linusw-pinctrl/devel]
[also build test ERROR on linusw-pinctrl/for-next linus/master v6.12-rc4 next-20241025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/chang-hao/pinctrl-mediatek-add-eint-new-design-for-mt8196/20241025-111952
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
patch link:    https://lore.kernel.org/r/20241025031814.21442-1-ot_chhao.chang%40mediatek.com
patch subject: [PATCH] pinctrl: mediatek: add eint new design for mt8196
config: csky-randconfig-r071-20241027 (https://download.01.org/0day-ci/archive/20241027/202410271123.3hyFF6pg-lkp@intel.com/config)
compiler: csky-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241027/202410271123.3hyFF6pg-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410271123.3hyFF6pg-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/pinctrl/mediatek/mtk-eint.c: In function 'mtk_eint_do_suspend':
>> drivers/pinctrl/mediatek/mtk-eint.c:588:9: error: implicit declaration of function 'dsb' [-Wimplicit-function-declaration]
     588 |         dsb(sy);
         |         ^~~
>> drivers/pinctrl/mediatek/mtk-eint.c:588:13: error: 'sy' undeclared (first use in this function); did you mean 's8'?
     588 |         dsb(sy);
         |             ^~
         |             s8
   drivers/pinctrl/mediatek/mtk-eint.c:588:13: note: each undeclared identifier is reported only once for each function it appears in
   drivers/pinctrl/mediatek/mtk-eint.c: In function 'mtk_eint_do_resume':
   drivers/pinctrl/mediatek/mtk-eint.c:609:13: error: 'sy' undeclared (first use in this function); did you mean 's8'?
     609 |         dsb(sy);
         |             ^~
         |             s8
   drivers/pinctrl/mediatek/mtk-eint.c: At top level:
   drivers/pinctrl/mediatek/mtk-eint.c:686:14: warning: no previous prototype for 'mtk_eint_get_debounce_en' [-Wmissing-prototypes]
     686 | unsigned int mtk_eint_get_debounce_en(struct mtk_eint *eint,
         |              ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/mediatek/mtk-eint.c:709:14: warning: no previous prototype for 'mtk_eint_get_debounce_value' [-Wmissing-prototypes]
     709 | unsigned int mtk_eint_get_debounce_value(struct mtk_eint *eint,
         |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/mediatek/mtk-eint.c:749:34: warning: 'eint_compatible_ids' defined but not used [-Wunused-const-variable=]
     749 | static const struct of_device_id eint_compatible_ids[] = {
         |                                  ^~~~~~~~~~~~~~~~~~~

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for GET_FREE_REGION
   Depends on [n]: SPARSEMEM [=n]
   Selected by [m]:
   - RESOURCE_KUNIT_TEST [=m] && RUNTIME_TESTING_MENU [=y] && KUNIT [=m]


vim +/dsb +588 drivers/pinctrl/mediatek/mtk-eint.c

   572	
   573	int mtk_eint_do_suspend(struct mtk_eint *eint)
   574	{
   575		unsigned int i, j, port;
   576	
   577		for (i = 0; i < eint->instance_number; i++) {
   578			struct mtk_eint_instance inst = eint->instances[i];
   579	
   580			for (j = 0; j < inst.number; j += MAX_BIT) {
   581				port = j >> REG_GROUP;
   582				writel_relaxed(~inst.wake_mask[port],
   583					       inst.base + port*REG_OFSET + eint->comp->regs->mask_set);
   584				writel_relaxed(inst.wake_mask[port],
   585					       inst.base + port*REG_OFSET + eint->comp->regs->mask_clr);
   586			}
   587		}
 > 588		dsb(sy);
   589	
   590		return 0;
   591	}
   592	EXPORT_SYMBOL_GPL(mtk_eint_do_suspend);
   593
kernel test robot Oct. 27, 2024, 6:20 p.m. UTC | #4
Hi chang,

kernel test robot noticed the following build errors:

[auto build test ERROR on linusw-pinctrl/devel]
[also build test ERROR on linusw-pinctrl/for-next linus/master v6.12-rc4 next-20241025]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/chang-hao/pinctrl-mediatek-add-eint-new-design-for-mt8196/20241025-111952
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
patch link:    https://lore.kernel.org/r/20241025031814.21442-1-ot_chhao.chang%40mediatek.com
patch subject: [PATCH] pinctrl: mediatek: add eint new design for mt8196
config: s390-randconfig-r131-20241027 (https://download.01.org/0day-ci/archive/20241028/202410280230.KAMZK7aZ-lkp@intel.com/config)
compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
reproduce: (https://download.01.org/0day-ci/archive/20241028/202410280230.KAMZK7aZ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410280230.KAMZK7aZ-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from drivers/pinctrl/mediatek/mtk-eint.c:14:
   In file included from include/linux/gpio/driver.h:8:
   In file included from include/linux/irqchip/chained_irq.h:10:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:14:
   In file included from arch/s390/include/asm/io.h:93:
   include/asm-generic/io.h:548:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:561:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/big_endian.h:37:59: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) __swab16((__force __u16)(__le16)(x))
                                                             ^
   include/uapi/linux/swab.h:102:54: note: expanded from macro '__swab16'
   #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
                                                        ^
   In file included from drivers/pinctrl/mediatek/mtk-eint.c:14:
   In file included from include/linux/gpio/driver.h:8:
   In file included from include/linux/irqchip/chained_irq.h:10:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:14:
   In file included from arch/s390/include/asm/io.h:93:
   include/asm-generic/io.h:574:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/big_endian.h:35:59: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x))
                                                             ^
   include/uapi/linux/swab.h:115:54: note: expanded from macro '__swab32'
   #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x))
                                                        ^
   In file included from drivers/pinctrl/mediatek/mtk-eint.c:14:
   In file included from include/linux/gpio/driver.h:8:
   In file included from include/linux/irqchip/chained_irq.h:10:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:14:
   In file included from arch/s390/include/asm/io.h:93:
   include/asm-generic/io.h:585:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:595:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:605:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:693:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           readsb(PCI_IOBASE + addr, buffer, count);
                  ~~~~~~~~~~ ^
   include/asm-generic/io.h:701:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           readsw(PCI_IOBASE + addr, buffer, count);
                  ~~~~~~~~~~ ^
   include/asm-generic/io.h:709:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           readsl(PCI_IOBASE + addr, buffer, count);
                  ~~~~~~~~~~ ^
   include/asm-generic/io.h:718:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           writesb(PCI_IOBASE + addr, buffer, count);
                   ~~~~~~~~~~ ^
   include/asm-generic/io.h:727:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           writesw(PCI_IOBASE + addr, buffer, count);
                   ~~~~~~~~~~ ^
   include/asm-generic/io.h:736:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           writesl(PCI_IOBASE + addr, buffer, count);
                   ~~~~~~~~~~ ^
>> drivers/pinctrl/mediatek/mtk-eint.c:588:2: error: call to undeclared function 'dsb'; ISO C99 and later do not support implicit function declarations [-Werror,-Wimplicit-function-declaration]
           dsb(sy);
           ^
   drivers/pinctrl/mediatek/mtk-eint.c:588:6: error: use of undeclared identifier 'sy'
           dsb(sy);
               ^
   drivers/pinctrl/mediatek/mtk-eint.c:609:2: error: call to undeclared function 'dsb'; ISO C99 and later do not support implicit function declarations [-Werror,-Wimplicit-function-declaration]
           dsb(sy);
           ^
   drivers/pinctrl/mediatek/mtk-eint.c:609:6: error: use of undeclared identifier 'sy'
           dsb(sy);
               ^
   drivers/pinctrl/mediatek/mtk-eint.c:686:14: warning: no previous prototype for function 'mtk_eint_get_debounce_en' [-Wmissing-prototypes]
   unsigned int mtk_eint_get_debounce_en(struct mtk_eint *eint,
                ^
   drivers/pinctrl/mediatek/mtk-eint.c:686:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   unsigned int mtk_eint_get_debounce_en(struct mtk_eint *eint,
   ^
   static 
   drivers/pinctrl/mediatek/mtk-eint.c:709:14: warning: no previous prototype for function 'mtk_eint_get_debounce_value' [-Wmissing-prototypes]
   unsigned int mtk_eint_get_debounce_value(struct mtk_eint *eint,
                ^
   drivers/pinctrl/mediatek/mtk-eint.c:709:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   unsigned int mtk_eint_get_debounce_value(struct mtk_eint *eint,
   ^
   static 
   14 warnings and 4 errors generated.


vim +/dsb +588 drivers/pinctrl/mediatek/mtk-eint.c

   572	
   573	int mtk_eint_do_suspend(struct mtk_eint *eint)
   574	{
   575		unsigned int i, j, port;
   576	
   577		for (i = 0; i < eint->instance_number; i++) {
   578			struct mtk_eint_instance inst = eint->instances[i];
   579	
   580			for (j = 0; j < inst.number; j += MAX_BIT) {
   581				port = j >> REG_GROUP;
   582				writel_relaxed(~inst.wake_mask[port],
   583					       inst.base + port*REG_OFSET + eint->comp->regs->mask_set);
   584				writel_relaxed(inst.wake_mask[port],
   585					       inst.base + port*REG_OFSET + eint->comp->regs->mask_clr);
   586			}
   587		}
 > 588		dsb(sy);
   589	
   590		return 0;
   591	}
   592	EXPORT_SYMBOL_GPL(mtk_eint_do_suspend);
   593
diff mbox series

Patch

diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c
index 27f0a54e12bf..57f812299340 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.c
+++ b/drivers/pinctrl/mediatek/mtk-eint.c
@@ -17,16 +17,13 @@ 
 #include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of_irq.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 
 #include "mtk-eint.h"
 
-#define MTK_EINT_EDGE_SENSITIVE           0
-#define MTK_EINT_LEVEL_SENSITIVE          1
-#define MTK_EINT_DBNC_SET_DBNC_BITS	  4
-#define MTK_EINT_DBNC_MAX		  16
-#define MTK_EINT_DBNC_RST_BIT		  (0x1 << 1)
-#define MTK_EINT_DBNC_SET_EN		  (0x1 << 0)
+static struct mtk_eint *global_eintc;
+struct mtk_eint_pin pin;
 
 static const struct mtk_eint_regs mtk_generic_eint_regs = {
 	.stat      = 0x000,
@@ -47,6 +44,10 @@  static const struct mtk_eint_regs mtk_generic_eint_regs = {
 	.dbnc_ctrl = 0x500,
 	.dbnc_set  = 0x600,
 	.dbnc_clr  = 0x700,
+	.event     = 0x800,
+	.event_set = 0x840,
+	.event_clr = 0x880,
+	.raw_stat  = 0xa00,
 };
 
 const unsigned int debounce_time_mt2701[] = {
@@ -64,60 +65,145 @@  const unsigned int debounce_time_mt6795[] = {
 };
 EXPORT_SYMBOL_GPL(debounce_time_mt6795);
 
-static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
+/*
+ * Return the iomem of specific register ofset and decode the coordinate
+ * (instance, index) from global eint number.
+ * If return NULL, then it must be either out-of-range or do-not-support.
+ */
+static void __iomem *mtk_eint_get_ofset(struct mtk_eint *eint,
 					 unsigned int eint_num,
-					 unsigned int offset)
+					 unsigned int ofset,
+					 unsigned int *instance,
+					 unsigned int *index)
 {
-	unsigned int eint_base = 0;
 	void __iomem *reg;
 
-	if (eint_num >= eint->hw->ap_num)
-		eint_base = eint->hw->ap_num;
+	if (eint_num >= eint->total_pin_number ||
+	    !eint->pins[eint_num].enabled) {
+		WARN_ON(1);
+		return NULL;
+	}
 
-	reg = eint->base + offset + ((eint_num - eint_base) / 32) * 4;
+	*instance = eint->pins[eint_num].instance;
+	*index = eint->pins[eint_num].index;
+	reg = eint->instances[*instance].base + ofset + (*index / MAX_BIT * REG_OFSET);
 
 	return reg;
 }
 
+/*
+ * Generate helper function to access property register of a dedicate pin.
+ */
+#define DEFINE_EINT_GET_FUNCTION(_NAME, _OFSET) \
+static unsigned int mtk_eint_get_##_NAME(struct mtk_eint *eint, \
+				   unsigned int eint_num) \
+{ \
+	unsigned int instance, index; \
+	void __iomem *reg = mtk_eint_get_ofset(eint, eint_num, \
+						_OFSET, \
+						&instance, &index); \
+	unsigned int bit = BIT(index & 0x1f);\
+\
+	if (!reg) { \
+		dev_err(eint->dev, "%s invalid eint_num %d\n", \
+			__func__, eint_num); \
+		return 0;\
+	} \
+\
+	return !!(readl(reg) & bit); \
+}
+
+DEFINE_EINT_GET_FUNCTION(stat, eint->comp->regs->stat);
+DEFINE_EINT_GET_FUNCTION(mask, eint->comp->regs->mask);
+DEFINE_EINT_GET_FUNCTION(sens, eint->comp->regs->sens);
+DEFINE_EINT_GET_FUNCTION(pol, eint->comp->regs->pol);
+DEFINE_EINT_GET_FUNCTION(dom_en, eint->comp->regs->dom_en);
+DEFINE_EINT_GET_FUNCTION(event, eint->comp->regs->event);
+DEFINE_EINT_GET_FUNCTION(raw_stat, eint->comp->regs->raw_stat);
+
+int dump_eint_pin_status(unsigned int eint_num)
+{
+       unsigned int stat, raw_stat, mask, sens, pol, dom_en, event;
+
+       if (eint_num < 0 || eint_num > global_eintc->total_pin_number)
+               return ENODEV;
+
+       stat = mtk_eint_get_stat(global_eintc, eint_num);
+       raw_stat = mtk_eint_get_raw_stat(global_eintc, eint_num);
+       mask = mtk_eint_get_mask(global_eintc, eint_num);
+       sens = mtk_eint_get_sens(global_eintc, eint_num);
+       pol = mtk_eint_get_pol(global_eintc, eint_num);
+       dom_en = mtk_eint_get_dom_en(global_eintc, eint_num);
+       event = mtk_eint_get_event(global_eintc, eint_num);
+       dev_info(global_eintc->dev, "%s eint_num:%u=stat:%u,raw:%u, \
+		       mask:%u, sens:%u,pol:%u,dom_en:%u,event:%u\n",
+		       __func__, eint_num, stat, raw_stat, mask, sens,
+		       pol, dom_en, event);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dump_eint_pin_status);
+
 static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
 					     unsigned int eint_num)
 {
 	unsigned int sens;
-	unsigned int bit = BIT(eint_num % 32);
-	void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
-						eint->regs->sens);
+	unsigned int instance, index;
+	void __iomem *reg = mtk_eint_get_ofset(eint, eint_num,
+						eint->comp->regs->sens,
+						&instance, &index);
+	unsigned int bit = BIT(index & 0x1f);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %d\n",
+			__func__, eint_num);
+		return 0;
+	}
 
 	if (readl(reg) & bit)
 		sens = MTK_EINT_LEVEL_SENSITIVE;
 	else
 		sens = MTK_EINT_EDGE_SENSITIVE;
 
-	if (eint_num < eint->hw->db_cnt && sens != MTK_EINT_EDGE_SENSITIVE)
+	if (eint->pins[eint_num].debounce &&
+	    sens != MTK_EINT_EDGE_SENSITIVE)
 		return 1;
 	else
 		return 0;
 }
 
-static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
+static int mtk_eint_flip_edge(struct mtk_eint *eint, int eint_num)
 {
 	int start_level, curr_level;
-	unsigned int reg_offset;
-	u32 mask = BIT(hwirq & 0x1f);
-	u32 port = (hwirq >> 5) & eint->hw->port_mask;
-	void __iomem *reg = eint->base + (port << 2);
+	unsigned int reg_ofset;
+	unsigned int instance, index, mask, port;
+	void __iomem *reg;
 
-	curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, hwirq);
+	reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
+				  &instance, &index);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %d\n",
+			__func__, eint_num);
+		return 0;
+	}
+
+	mask = BIT(index & 0x1f);
+	port = index >> REG_GROUP;
+	reg = eint->instances[instance].base + port * REG_OFSET;
+
+	curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, eint_num);
 
 	do {
 		start_level = curr_level;
 		if (start_level)
-			reg_offset = eint->regs->pol_clr;
+			reg_ofset = eint->comp->regs->pol_clr;
 		else
-			reg_offset = eint->regs->pol_set;
-		writel(mask, reg + reg_offset);
+			reg_ofset = eint->comp->regs->pol_set;
+
+		writel(mask, reg + reg_ofset);
 
 		curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl,
-							      hwirq);
+							      eint_num);
 	} while (start_level != curr_level);
 
 	return start_level;
@@ -126,11 +212,19 @@  static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
 static void mtk_eint_mask(struct irq_data *d)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	u32 mask = BIT(d->hwirq & 0x1f);
-	void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
-						eint->regs->mask_set);
+	unsigned int instance, index;
+	void __iomem *reg = mtk_eint_get_ofset(eint, d->hwirq,
+						eint->comp->regs->mask_set,
+						&instance, &index);
+	u32 mask = BIT(index & 0x1f);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %lu\n",
+			__func__, d->hwirq);
+		return;
+	}
 
-	eint->cur_mask[d->hwirq >> 5] &= ~mask;
+	eint->instances[instance].cur_mask[index >> REG_GROUP] &= ~mask;
 
 	writel(mask, reg);
 }
@@ -138,43 +232,91 @@  static void mtk_eint_mask(struct irq_data *d)
 static void mtk_eint_unmask(struct irq_data *d)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	u32 mask = BIT(d->hwirq & 0x1f);
-	void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
-						eint->regs->mask_clr);
+	unsigned int instance, index;
+	void __iomem *reg = mtk_eint_get_ofset(eint, d->hwirq,
+						eint->comp->regs->mask_clr,
+						&instance, &index);
+	u32 mask = BIT(index & 0x1f);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %lu\n",
+			__func__, d->hwirq);
+		return;
+	}
 
-	eint->cur_mask[d->hwirq >> 5] |= mask;
+	eint->instances[instance].cur_mask[index >> REG_GROUP] |= mask;
 
 	writel(mask, reg);
 
-	if (eint->dual_edge[d->hwirq])
+	if (eint->pins[d->hwirq].dual_edge)
 		mtk_eint_flip_edge(eint, d->hwirq);
 }
 
-static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
+static void mtk_eint_ack(struct irq_data *d)
+{
+	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
+	unsigned int instance, index;
+	void __iomem *reg;
+	unsigned int bit;
+
+	if (eint->comp->ops.ack)
+		eint->comp->ops.ack(d);
+	else {
+		reg = mtk_eint_get_ofset(eint, d->hwirq,
+					  eint->comp->regs->ack,
+					  &instance, &index);
+		bit = BIT(index & 0x1f);
+		if (!reg) {
+			dev_err(eint->dev, "%s invalid eint_num %lu\n",
+				__func__, d->hwirq);
+			return;
+		}
+
+		writel(bit, reg);
+	}
+}
+
+static void mtk_eint_soft_set(struct mtk_eint *eint,
 				      unsigned int eint_num)
 {
-	unsigned int bit = BIT(eint_num % 32);
-	void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
-						eint->regs->mask);
+	unsigned int instance, index;
+	void __iomem *reg = mtk_eint_get_ofset(eint, eint_num,
+						eint->comp->regs->soft_set,
+						&instance, &index);
+	unsigned int bit = BIT(index & 0x1f);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %d\n",
+			__func__, eint_num);
+		return;
+	}
 
-	return !!(readl(reg) & bit);
+	writel(bit, reg);
 }
 
-static void mtk_eint_ack(struct irq_data *d)
+static void mtk_eint_soft_clr(struct mtk_eint *eint,
+				      unsigned int eint_num)
 {
-	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	u32 mask = BIT(d->hwirq & 0x1f);
-	void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
-						eint->regs->ack);
+	unsigned int instance, index;
+	void __iomem *reg = mtk_eint_get_ofset(eint, eint_num,
+						eint->comp->regs->soft_clr,
+						&instance, &index);
+	unsigned int bit = BIT(index & 0x1f);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %d\n",
+			__func__, eint_num);
+		return;
+	}
 
-	writel(mask, reg);
+	writel(bit, reg);
 }
 
 static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	bool masked;
-	u32 mask = BIT(d->hwirq & 0x1f);
+	u32 mask;
+	unsigned int instance, index;
 	void __iomem *reg;
 
 	if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
@@ -186,36 +328,42 @@  static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
 	}
 
 	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-		eint->dual_edge[d->hwirq] = 1;
+		eint->pins[d->hwirq].dual_edge = 1;
 	else
-		eint->dual_edge[d->hwirq] = 0;
+		eint->pins[d->hwirq].dual_edge = 0;
 
-	if (!mtk_eint_get_mask(eint, d->hwirq)) {
-		mtk_eint_mask(d);
-		masked = false;
-	} else {
-		masked = true;
-	}
+	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
+		reg = mtk_eint_get_ofset(eint, d->hwirq,
+					  eint->comp->regs->pol_clr,
+					  &instance, &index);
+	else
+		reg = mtk_eint_get_ofset(eint, d->hwirq,
+					  eint->comp->regs->pol_set,
+					  &instance, &index);
 
-	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
-		reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
-		writel(mask, reg);
-	} else {
-		reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_set);
-		writel(mask, reg);
-	}
+	mask = BIT(index & 0x1f);
+	writel(mask, reg);
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		reg = mtk_eint_get_ofset(eint, d->hwirq,
+					  eint->comp->regs->sens_clr,
+					  &instance, &index);
+	else
+		reg = mtk_eint_get_ofset(eint, d->hwirq,
+					  eint->comp->regs->sens_set,
+					  &instance, &index);
 
-	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-		reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_clr);
-		writel(mask, reg);
-	} else {
-		reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_set);
-		writel(mask, reg);
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %lu\n",
+			__func__, d->hwirq);
+		return 0;
 	}
 
-	mtk_eint_ack(d);
-	if (!masked)
-		mtk_eint_unmask(d);
+	mask = BIT(index & 0x1f);
+	writel(mask, reg);
+
+	if (eint->pins[d->hwirq].dual_edge)
+		mtk_eint_flip_edge(eint, d->hwirq);
 
 	return 0;
 }
@@ -223,30 +371,28 @@  static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
 static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
-	int shift = d->hwirq & 0x1f;
-	int reg = d->hwirq >> 5;
+	unsigned int instance, index, shift, port;
+	void __iomem *reg = mtk_eint_get_ofset(eint, d->hwirq,
+						MTK_EINT_NO_OFSET,
+						&instance, &index);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %lu\n",
+			__func__, d->hwirq);
+		return 0;
+	}
+
+	shift = index & 0x1f;
+	port = index >> REG_GROUP;
 
 	if (on)
-		eint->wake_mask[reg] |= BIT(shift);
+		eint->instances[instance].wake_mask[port] |= BIT(shift);
 	else
-		eint->wake_mask[reg] &= ~BIT(shift);
+		eint->instances[instance].wake_mask[port] &= ~BIT(shift);
 
 	return 0;
 }
 
-static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
-				     void __iomem *base, u32 *buf)
-{
-	int port;
-	void __iomem *reg;
-
-	for (port = 0; port < eint->hw->ports; port++) {
-		reg = base + (port << 2);
-		writel_relaxed(~buf[port], reg + eint->regs->mask_set);
-		writel_relaxed(buf[port], reg + eint->regs->mask_clr);
-	}
-}
-
 static int mtk_eint_irq_request_resources(struct irq_data *d)
 {
 	struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
@@ -290,7 +436,7 @@  static void mtk_eint_irq_release_resources(struct irq_data *d)
 }
 
 static struct irq_chip mtk_eint_irq_chip = {
-	.name = "mt-eint",
+	.name = "mtk-eint",
 	.irq_disable = mtk_eint_mask,
 	.irq_mask = mtk_eint_mask,
 	.irq_unmask = mtk_eint_unmask,
@@ -301,35 +447,51 @@  static struct irq_chip mtk_eint_irq_chip = {
 	.irq_release_resources = mtk_eint_irq_release_resources,
 };
 
+/*
+ * Configure all EINT pins as domain 0, which only belongs to AP.
+ */
 static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
 {
-	void __iomem *dom_en = eint->base + eint->regs->dom_en;
-	void __iomem *mask_set = eint->base + eint->regs->mask_set;
-	unsigned int i;
-
-	for (i = 0; i < eint->hw->ap_num; i += 32) {
-		writel(0xffffffff, dom_en);
-		writel(0xffffffff, mask_set);
-		dom_en += 4;
-		mask_set += 4;
+	void __iomem *reg,*eevt_clr;
+	unsigned int i, j;
+
+	for (i = 0; i < eint->instance_number; i++) {
+		reg = eint->instances[i].base + eint->comp->regs->dom_en;
+		eevt_clr = eint->instances[i].base + eint->comp->regs->event_clr;
+		for (j = 0; j < eint->instances[i].number; j += MAX_BIT, reg += REG_OFSET, eevt_clr += REG_OFSET) {
+			writel(REG_VAL, reg);
+			writel(REG_VAL, eevt_clr);
+		}
 	}
 
 	return 0;
 }
 
 static inline void
-mtk_eint_debounce_process(struct mtk_eint *eint, int index)
+mtk_eint_debounce_process(struct mtk_eint *eint, int eint_num)
 {
-	unsigned int rst, ctrl_offset;
+	unsigned int rst, ctrl_ofset;
 	unsigned int bit, dbnc;
+	unsigned int instance, index;
+	void __iomem *reg;
+
+	reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
+				  &instance, &index);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %d\n",
+			__func__, eint_num);
+		return;
+	}
+
+	ctrl_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
+	dbnc = readl(eint->instances[instance].base + ctrl_ofset);
+	bit = MTK_EINT_DBNC_SET_EN << ((index % REG_OFSET) * DB_GROUP);
 
-	ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_ctrl;
-	dbnc = readl(eint->base + ctrl_offset);
-	bit = MTK_EINT_DBNC_SET_EN << ((index % 4) * 8);
 	if ((bit & dbnc) > 0) {
-		ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_set;
-		rst = MTK_EINT_DBNC_RST_BIT << ((index % 4) * 8);
-		writel(rst, eint->base + ctrl_offset);
+		ctrl_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_set;
+		rst = MTK_EINT_DBNC_RST_BIT << ((index % REG_OFSET) * DB_GROUP);
+		writel(rst, eint->instances[instance].base + ctrl_ofset);
 	}
 }
 
@@ -337,65 +499,72 @@  static void mtk_eint_irq_handler(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct mtk_eint *eint = irq_desc_get_handler_data(desc);
-	unsigned int status, eint_num;
-	int offset, mask_offset, index;
-	void __iomem *reg =  mtk_eint_get_offset(eint, 0, eint->regs->stat);
-	int dual_edge, start_level, curr_level;
+	unsigned int status, i, j;
+	int shift, port, eint_num, virq;
+	unsigned int dual_edge, start_level, curr_level;
+	struct mtk_eint_instance eint_instance;
+	void __iomem *addr;
 
 	chained_irq_enter(chip, desc);
-	for (eint_num = 0; eint_num < eint->hw->ap_num; eint_num += 32,
-	     reg += 4) {
-		status = readl(reg);
-		while (status) {
-			offset = __ffs(status);
-			mask_offset = eint_num >> 5;
-			index = eint_num + offset;
-			status &= ~BIT(offset);
-
-			/*
-			 * If we get an interrupt on pin that was only required
-			 * for wake (but no real interrupt requested), mask the
-			 * interrupt (as would mtk_eint_resume do anyway later
-			 * in the resume sequence).
-			 */
-			if (eint->wake_mask[mask_offset] & BIT(offset) &&
-			    !(eint->cur_mask[mask_offset] & BIT(offset))) {
-				writel_relaxed(BIT(offset), reg -
-					eint->regs->stat +
-					eint->regs->mask_set);
-			}
-
-			dual_edge = eint->dual_edge[index];
-			if (dual_edge) {
-				/*
-				 * Clear soft-irq in case we raised it last
-				 * time.
-				 */
-				writel(BIT(offset), reg - eint->regs->stat +
-				       eint->regs->soft_clr);
 
-				start_level =
-				eint->gpio_xlate->get_gpio_state(eint->pctl,
-								 index);
-			}
+	for (i = 0; i < eint->instance_number; i++) {
+		eint_instance = eint->instances[i];
 
-			generic_handle_domain_irq(eint->domain, index);
+		/* Iterate all pins by port */
+		for (j = 0; j < eint_instance.number; j += MAX_BIT) {
+			port = j >> REG_GROUP;
+			status = readl(eint_instance.base + port * REG_OFSET +
+				       eint->comp->regs->stat);
+			while (status) {
+				shift = __ffs(status);
+				status &= ~BIT(shift);
 
-			if (dual_edge) {
-				curr_level = mtk_eint_flip_edge(eint, index);
+				eint_num = eint->instances[i].pin_list[shift + j];
+				virq = irq_find_mapping(eint->domain, eint_num);
 
 				/*
-				 * If level changed, we might lost one edge
-				 * interrupt, raised it through soft-irq.
+				 * If we get an interrupt on pin that was only required
+				 * for wake (but no real interrupt requested), mask the
+				 * interrupt (as would mtk_eint_resume do anyway later
+				 * in the resume sequence).
 				 */
-				if (start_level != curr_level)
-					writel(BIT(offset), reg -
-					       eint->regs->stat +
-					       eint->regs->soft_set);
-			}
+				if (eint->instances[i].wake_mask[port] & BIT(shift) &&
+				    !(eint->instances[i].cur_mask[port] & BIT(shift))) {
+					addr = eint_instance.base + port * REG_OFSET +
+						eint->comp->regs->mask_set;
+					writel_relaxed(BIT(shift), addr);
+				}
+
+				dual_edge = eint->pins[eint_num].dual_edge;
+				if (dual_edge) {
+					/*
+					 * Clear soft-irq in case we raised it last
+					 * time.
+					 */
+					mtk_eint_soft_clr(eint, eint_num);
+
+					start_level =
+					eint->gpio_xlate->get_gpio_state(eint->pctl,
+									 eint_num);
+				}
+
+				generic_handle_irq(virq);
+
+				if (dual_edge) {
+					curr_level = mtk_eint_flip_edge(eint, eint_num);
+
+					/*
+					 * If level changed, we might lost one edge
+					 * interrupt, raised it through soft-irq.
+					 */
+					if (start_level != curr_level)
+						mtk_eint_soft_set(eint, eint_num);
+				}
+
+				if (eint->pins[eint_num].debounce)
+					mtk_eint_debounce_process(eint, eint_num);
 
-			if (index < eint->hw->db_cnt)
-				mtk_eint_debounce_process(eint, index);
+			}
 		}
 	}
 	chained_irq_exit(chip, desc);
@@ -403,7 +572,20 @@  static void mtk_eint_irq_handler(struct irq_desc *desc)
 
 int mtk_eint_do_suspend(struct mtk_eint *eint)
 {
-	mtk_eint_chip_write_mask(eint, eint->base, eint->wake_mask);
+	unsigned int i, j, port;
+
+	for (i = 0; i < eint->instance_number; i++) {
+		struct mtk_eint_instance inst = eint->instances[i];
+
+		for (j = 0; j < inst.number; j += MAX_BIT) {
+			port = j >> REG_GROUP;
+			writel_relaxed(~inst.wake_mask[port],
+				       inst.base + port*REG_OFSET + eint->comp->regs->mask_set);
+			writel_relaxed(inst.wake_mask[port],
+				       inst.base + port*REG_OFSET + eint->comp->regs->mask_clr);
+		}
+	}
+	dsb(sy);
 
 	return 0;
 }
@@ -411,7 +593,20 @@  EXPORT_SYMBOL_GPL(mtk_eint_do_suspend);
 
 int mtk_eint_do_resume(struct mtk_eint *eint)
 {
-	mtk_eint_chip_write_mask(eint, eint->base, eint->cur_mask);
+	unsigned int i, j, port;
+
+	for (i = 0; i < eint->instance_number; i++) {
+		struct mtk_eint_instance inst = eint->instances[i];
+
+		for (j = 0; j < inst.number; j += MAX_BIT) {
+			port = j >> REG_GROUP;
+			writel_relaxed(~inst.cur_mask[port],
+				       inst.base + port*REG_OFSET + eint->comp->regs->mask_set);
+			writel_relaxed(inst.cur_mask[port],
+				       inst.base + port*REG_OFSET + eint->comp->regs->mask_clr);
+		}
+	}
+	dsb(sy);
 
 	return 0;
 }
@@ -420,27 +615,45 @@  EXPORT_SYMBOL_GPL(mtk_eint_do_resume);
 int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
 			  unsigned int debounce)
 {
-	int virq, eint_offset;
-	unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask,
+	int virq, eint_ofset;
+	unsigned int set_ofset, bit, clr_bit, clr_ofset, rst, i, unmask,
 		     dbnc;
+	static const unsigned int debounce_time[] = { 156, 313, 625, 1250,
+		20000, 40000, 80000, 160000, 320000, 640000 };
 	struct irq_data *d;
+	unsigned int instance, index;
+	void __iomem *reg;
 
-	if (!eint->hw->db_time)
-		return -EOPNOTSUPP;
+	/*
+	 * Due to different number of bit field, we only decode
+	 * the coordinate here, instead of get the VA.
+	 */
+	reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
+				  &instance, &index);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %lu\n",
+			__func__, eint_num);
+		return 0;
+	}
 
 	virq = irq_find_mapping(eint->domain, eint_num);
-	eint_offset = (eint_num % 4) * 8;
+	eint_ofset = (index % REG_OFSET) * DB_GROUP;
 	d = irq_get_irq_data(virq);
 
-	set_offset = (eint_num / 4) * 4 + eint->regs->dbnc_set;
-	clr_offset = (eint_num / 4) * 4 + eint->regs->dbnc_clr;
+	reg = eint->instances[instance].base;
+	set_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_set;
+	clr_ofset = (index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_clr;
 
 	if (!mtk_eint_can_en_debounce(eint, eint_num))
 		return -EINVAL;
 
-	dbnc = eint->num_db_time;
-	for (i = 0; i < eint->num_db_time; i++) {
-		if (debounce <= eint->hw->db_time[i]) {
+	/*
+	 * Check eint number to avoid access out-of-range
+	 */
+	dbnc = ARRAY_SIZE(debounce_time) - 1;
+	for (i = 0; i < ARRAY_SIZE(debounce_time); i++) {
+		if (debounce <= debounce_time[i]) {
 			dbnc = i;
 			break;
 		}
@@ -449,23 +662,20 @@  int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
 	if (!mtk_eint_get_mask(eint, eint_num)) {
 		mtk_eint_mask(d);
 		unmask = 1;
-	} else {
+	} else
 		unmask = 0;
-	}
 
-	clr_bit = 0xff << eint_offset;
-	writel(clr_bit, eint->base + clr_offset);
+	clr_bit = 0xff << eint_ofset;
+	writel(clr_bit, reg + clr_ofset);
 
-	bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS) | MTK_EINT_DBNC_SET_EN) <<
-		eint_offset;
-	rst = MTK_EINT_DBNC_RST_BIT << eint_offset;
-	writel(rst | bit, eint->base + set_offset);
+	bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS)
+		| MTK_EINT_DBNC_SET_EN) << eint_ofset;
+	rst = MTK_EINT_DBNC_RST_BIT << eint_ofset;
+	writel(rst | bit, reg + set_ofset);
 
 	/*
-	 * Delay a while (more than 2T) to wait for hw debounce counter reset
-	 * work correctly.
+	 * Delay should be (8T @ 32k) from dbc rst to work correctly.
 	 */
-	udelay(1);
 	if (unmask == 1)
 		mtk_eint_unmask(d);
 
@@ -473,6 +683,53 @@  int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
 }
 EXPORT_SYMBOL_GPL(mtk_eint_set_debounce);
 
+unsigned int mtk_eint_get_debounce_en(struct mtk_eint *eint,
+				      unsigned int eint_num)
+{
+	unsigned int instance, index, bit;
+	void __iomem *reg;
+
+	reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
+				  &instance, &index);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %d\n",
+			__func__, eint_num);
+		return 0;
+	}
+
+	reg = eint->instances[instance].base +
+		(index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
+
+	bit = MTK_EINT_DBNC_SET_EN << ((index % REG_OFSET) * DB_GROUP);
+
+	return (readl(reg) & bit) ? 1 : 0;
+}
+
+unsigned int mtk_eint_get_debounce_value(struct mtk_eint *eint,
+					   unsigned int eint_num)
+{
+	unsigned int instance, index, mask, ofset;
+	void __iomem *reg;
+
+	reg = mtk_eint_get_ofset(eint, eint_num, MTK_EINT_NO_OFSET,
+				  &instance, &index);
+
+	if (!reg) {
+		dev_err(eint->dev, "%s invalid eint_num %d\n",
+			__func__, eint_num);
+		return 0;
+	}
+
+	reg = eint->instances[instance].base +
+		(index / REG_OFSET) * REG_OFSET + eint->comp->regs->dbnc_ctrl;
+
+	ofset = MTK_EINT_DBNC_SET_DBNC_BITS + ((index % REG_OFSET) * DB_GROUP);
+	mask = 0xf << ofset;
+
+	return ((readl(reg) & mask) >> ofset);
+}
+
 int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
 {
 	int irq;
@@ -485,45 +742,209 @@  int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
 }
 EXPORT_SYMBOL_GPL(mtk_eint_find_irq);
 
+static const struct mtk_eint_compatible default_compat = {
+	.regs = &mtk_generic_eint_regs,
+};
+
+static const struct of_device_id eint_compatible_ids[] = {
+	{ }
+};
+
 int mtk_eint_do_init(struct mtk_eint *eint)
 {
-	int i;
+	int i, virq;
+	unsigned int size, inst = 0;
+	eint->instance_number = 1;
+	eint->total_pin_number = eint->hw->ap_num;
+
+	for (i = 0; i < eint->total_pin_number; i++) {
+		eint->pins[i].enabled = true;
+		eint->pins[i].instance = inst;
+		eint->pins[i].index = i;
+		eint->pins[i].debounce =  (i < eint->hw->db_cnt) ? 1 : 0;
+
+		eint->instances[inst].pin_list[i] = i;
+		eint->instances[inst].number++;
+	}
 
-	/* If clients don't assign a specific regs, let's use generic one */
-	if (!eint->regs)
-		eint->regs = &mtk_generic_eint_regs;
+	for (i = 0; i < eint->instance_number; i++) {
+		size = (eint->instances[i].number / MAX_BIT + 1) * sizeof(unsigned int);
+		eint->instances[i].wake_mask =
+			devm_kzalloc(eint->dev, size, GFP_KERNEL);
+		eint->instances[i].cur_mask =
+			devm_kzalloc(eint->dev, size, GFP_KERNEL);
 
-	eint->wake_mask = devm_kcalloc(eint->dev, eint->hw->ports,
-				       sizeof(*eint->wake_mask), GFP_KERNEL);
-	if (!eint->wake_mask)
+		if (!eint->instances[i].wake_mask ||
+		    !eint->instances[i].cur_mask)
+			return -ENOMEM;
+	}
+
+	eint->comp = &default_compat;
+
+	eint->domain = irq_domain_add_linear(eint->dev->of_node,
+					     eint->total_pin_number,
+					     &irq_domain_simple_ops, NULL);
+	if (!eint->domain)
 		return -ENOMEM;
 
-	eint->cur_mask = devm_kcalloc(eint->dev, eint->hw->ports,
-				      sizeof(*eint->cur_mask), GFP_KERNEL);
-	if (!eint->cur_mask)
+	mtk_eint_hw_init(eint);
+	for (i = 0; i < eint->total_pin_number; i++) {
+		virq = irq_create_mapping(eint->domain, i);
+
+		irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
+					 handle_level_irq);
+		irq_set_chip_data(virq, eint);
+	}
+
+	irq_set_chained_handler_and_data(eint->irq, mtk_eint_irq_handler,
+					 eint);
+
+	global_eintc = eint;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mtk_eint_do_init);
+
+int mtk_eint_do_init_v2(struct mtk_eint *eint)
+{
+	int i, virq, matrix_number = 0;
+	struct device_node *node;
+	unsigned int ret, size, ofset;
+	unsigned int id, inst, idx, support_deb;
+
+	const phandle *ph;
+
+	ph = of_get_property(eint->dev->of_node, "mediatek,eint", NULL);
+	if (!ph) {
+		dev_err(eint->dev, "Cannot find EINT phandle in PIO node.\n");
+		return -ENODEV;
+	}
+
+	node = of_find_node_by_phandle(be32_to_cpup(ph));
+	if (!node) {
+		dev_err(eint->dev, "Cannot find EINT node by phandle.\n");
+		return -ENODEV;
+	}
+
+	ret = of_property_read_u32(node, "mediatek,total-pin-number",
+				   &eint->total_pin_number);
+	if (ret) {
+		dev_err(eint->dev,
+		       "%s cannot read total-pin-number from device node.\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	dev_info(eint->dev, "%s eint total %u pins.\n", __func__,
+		eint->total_pin_number);
+
+	ret = of_property_read_u32(node, "mediatek,instance-num",
+				   &eint->instance_number);
+	if (ret)
+		eint->instance_number = 1; // only 1 instance in legacy chip
+
+	size = eint->instance_number * sizeof(struct mtk_eint_instance);
+	eint->instances = devm_kzalloc(eint->dev, size, GFP_KERNEL);
+	if (!eint->instances)
 		return -ENOMEM;
 
-	eint->dual_edge = devm_kcalloc(eint->dev, eint->hw->ap_num,
-				       sizeof(int), GFP_KERNEL);
-	if (!eint->dual_edge)
+	size = eint->total_pin_number * sizeof(struct mtk_eint_pin);
+	eint->pins = devm_kzalloc(eint->dev, size, GFP_KERNEL);
+	if (!eint->pins)
 		return -ENOMEM;
 
+	for (i = 0; i < eint->instance_number; i++) {
+		ret = of_property_read_string_index(node, "reg-name", i,
+						    &(eint->instances[i].name));
+		if (ret) {
+			dev_info(eint->dev,
+				 "%s cannot read the name of instance %d.\n",
+				 __func__, i);
+		}
+
+		eint->instances[i].base = of_iomap(node, i);
+		if (!eint->instances[i].base)
+			return -ENOMEM;
+	}
+
+	matrix_number = of_property_count_u32_elems(node, "mediatek,pins") / ARRAY_0;
+	if (matrix_number < 0) {
+		matrix_number = eint->total_pin_number;
+		dev_info(eint->dev, "%s eint in legacy mode, assign the matrix number to %u.\n",
+			 __func__, matrix_number);
+	} else
+		dev_info(eint->dev, "%s eint in new mode, assign the matrix number to %u.\n",
+			 __func__, matrix_number);
+
+	for (i = 0; i < matrix_number; i++) {
+		ofset = i * REG_OFSET;
+
+		ret = of_property_read_u32_index(node, "mediatek,pins",
+					   ofset, &id);
+		ret |= of_property_read_u32_index(node, "mediatek,pins",
+					   ofset+FIRST, &inst);
+		ret |= of_property_read_u32_index(node, "mediatek,pins",
+					   ofset+SECOND, &idx);
+		ret |= of_property_read_u32_index(node, "mediatek,pins",
+					   ofset+THIRD, &support_deb);
+
+		/* Legacy chip which no need to give coordinate list */
+		if (ret) {
+			id = i;
+			inst = 0;
+			idx = i;
+			support_deb = (i < MAX_BIT) ? 1 : 0;
+		}
+
+		eint->pins[id].enabled = true;
+		eint->pins[id].instance = inst;
+		eint->pins[id].index = idx;
+		eint->pins[id].debounce = support_deb;
+
+		eint->instances[inst].pin_list[idx] = id;
+		eint->instances[inst].number++;
+
+#if defined(MTK_EINT_DEBUG)
+		pin = eint->pins[id];
+		dev_info(eint->dev,
+			 "EINT%u in (%u-%u), su_deb = %u",
+			 id,
+			 pin.instance,
+			 eint->instances[inst].number,
+			 pin.debounce,
+#endif
+	}
+
+	for (i = 0; i < eint->instance_number; i++) {
+		size = (eint->instances[i].number / MAX_BIT + 1) * sizeof(unsigned int);
+		eint->instances[i].wake_mask =
+			devm_kzalloc(eint->dev, size, GFP_KERNEL);
+		eint->instances[i].cur_mask =
+			devm_kzalloc(eint->dev, size, GFP_KERNEL);
+
+		if (!eint->instances[i].wake_mask ||
+		    !eint->instances[i].cur_mask)
+			return -ENOMEM;
+	}
+
+	eint->comp = &default_compat;
+
+	eint->irq = irq_of_parse_and_map(node, 0);
+	if (!eint->irq) {
+		dev_err(eint->dev,
+			"%s IRQ parse fail.\n", __func__);
+		return -EINVAL;
+	}
+
 	eint->domain = irq_domain_add_linear(eint->dev->of_node,
-					     eint->hw->ap_num,
+					     eint->total_pin_number,
 					     &irq_domain_simple_ops, NULL);
 	if (!eint->domain)
 		return -ENOMEM;
 
-	if (eint->hw->db_time) {
-		for (i = 0; i < MTK_EINT_DBNC_MAX; i++)
-			if (eint->hw->db_time[i] == 0)
-				break;
-		eint->num_db_time = i;
-	}
-
 	mtk_eint_hw_init(eint);
-	for (i = 0; i < eint->hw->ap_num; i++) {
-		int virq = irq_create_mapping(eint->domain, i);
+	for (i = 0; i < eint->total_pin_number; i++) {
+		virq = irq_create_mapping(eint->domain, i);
 
 		irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
 					 handle_level_irq);
@@ -533,9 +954,11 @@  int mtk_eint_do_init(struct mtk_eint *eint)
 	irq_set_chained_handler_and_data(eint->irq, mtk_eint_irq_handler,
 					 eint);
 
+	global_eintc = eint;
+
 	return 0;
 }
-EXPORT_SYMBOL_GPL(mtk_eint_do_init);
+EXPORT_SYMBOL_GPL(mtk_eint_do_init_v2);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("MediaTek EINT Driver");
diff --git a/drivers/pinctrl/mediatek/mtk-eint.h b/drivers/pinctrl/mediatek/mtk-eint.h
index 6139b16cd225..aa17a6073029 100644
--- a/drivers/pinctrl/mediatek/mtk-eint.h
+++ b/drivers/pinctrl/mediatek/mtk-eint.h
@@ -11,6 +11,25 @@ 
 
 #include <linux/irqdomain.h>
 
+#define MAX_PIN 999
+#define MTK_EINT_EDGE_SENSITIVE           0
+#define MTK_EINT_LEVEL_SENSITIVE          1
+#define MTK_EINT_DBNC_SET_DBNC_BITS       4
+#define MTK_EINT_DBNC_RST_BIT             (0x1 << 1)
+#define MTK_EINT_DBNC_SET_EN              (0x1 << 0)
+#define MTK_EINT_NO_OFSET                 0
+#define MAX_BIT                           32
+#define REG_OFSET                         4
+#define REG_GROUP                         5
+#define REG_VAL                           0xFFFFFFFF
+#define DB_GROUP                          8
+#define FIRST                             1
+#define SECOND                            2
+#define THIRD                             3
+#define ARRAY_0                           4
+
+//#define MTK_EINT_DEBUG
+
 struct mtk_eint_regs {
 	unsigned int	stat;
 	unsigned int	ack;
@@ -30,6 +49,36 @@  struct mtk_eint_regs {
 	unsigned int	dbnc_ctrl;
 	unsigned int	dbnc_set;
 	unsigned int	dbnc_clr;
+	unsigned int	event;
+	unsigned int	event_set;
+	unsigned int	event_clr;
+	unsigned int	raw_stat;
+};
+
+struct mtk_eint_ops {
+	void (*ack)(struct irq_data *d);
+};
+
+struct mtk_eint_compatible {
+	struct mtk_eint_ops ops;
+	const struct mtk_eint_regs *regs;
+};
+
+struct mtk_eint_instance {
+	const char *name;
+	void __iomem *base;
+	unsigned int number;
+	unsigned int pin_list[MAX_PIN];
+	unsigned int *wake_mask;
+	unsigned int *cur_mask;
+};
+
+struct mtk_eint_pin {
+	bool enabled;
+	unsigned int instance;
+	unsigned int index;
+	bool debounce;
+	bool dual_edge;
 };
 
 struct mtk_eint_hw {
@@ -60,11 +109,14 @@  struct mtk_eint {
 	struct irq_domain *domain;
 	int irq;
 
-	int *dual_edge;
-	u32 *wake_mask;
-	u32 *cur_mask;
-
-	/* Used to fit into various EINT device */
+	/* An array to record the coordinate, index by global EINT ID */
+	struct mtk_eint_pin *pins;
+	/* An array to record the global EINT ID, index by coordinate*/
+	struct mtk_eint_instance *instances;
+	unsigned int total_pin_number;
+	unsigned int instance_number;
+	unsigned int dump_target_eint;
+	const struct mtk_eint_compatible *comp;
 	const struct mtk_eint_hw *hw;
 	const struct mtk_eint_regs *regs;
 	u16 num_db_time;
@@ -74,13 +126,15 @@  struct mtk_eint {
 	const struct mtk_eint_xt *gpio_xlate;
 };
 
-#if IS_ENABLED(CONFIG_EINT_MTK)
+#if (IS_ENABLED(CONFIG_EINT_MTK) || IS_ENABLED(CONFIG_DEVICE_MODULES_EINT_MTK))
 int mtk_eint_do_init(struct mtk_eint *eint);
+int mtk_eint_do_init_v2(struct mtk_eint *eint);
 int mtk_eint_do_suspend(struct mtk_eint *eint);
 int mtk_eint_do_resume(struct mtk_eint *eint);
 int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
 			  unsigned int debounce);
 int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n);
+int dump_eint_pin_status(unsigned int eint_num);
 
 #else
 static inline int mtk_eint_do_init(struct mtk_eint *eint)
@@ -88,6 +142,11 @@  static inline int mtk_eint_do_init(struct mtk_eint *eint)
 	return -EOPNOTSUPP;
 }
 
+static inline int mtk_eint_do_init_v2(struct mtk_eint *eint)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int mtk_eint_do_suspend(struct mtk_eint *eint)
 {
 	return -EOPNOTSUPP;
@@ -108,5 +167,9 @@  static inline int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
 {
 	return -EOPNOTSUPP;
 }
+static inline int dump_eint_pin_status(unsigned int eint_num)
+{
+	return -EOPNOTSUPP;
+}
 #endif
 #endif /* __MTK_EINT_H */
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index 54301fbba524..3740e868c650 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -375,33 +375,37 @@  int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
 	if (!of_property_read_bool(np, "interrupt-controller"))
 		return -ENODEV;
 
-	hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
-	if (!hw->eint)
-		return -ENOMEM;
-
-	hw->eint->base = devm_platform_ioremap_resource_byname(pdev, "eint");
-	if (IS_ERR(hw->eint->base)) {
-		ret = PTR_ERR(hw->eint->base);
-		goto err_free_eint;
-	}
+	if (hw->soc->eint_hw) {
+		hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
+		if (!hw->eint)
+			return -ENOMEM;
+
+		hw->eint->base = devm_platform_ioremap_resource_byname(pdev, "eint");
+		if (IS_ERR(hw->eint->base)) {
+			ret = PTR_ERR(hw->eint->base);
+			goto err_free_eint;
+		}
 
-	hw->eint->irq = irq_of_parse_and_map(np, 0);
-	if (!hw->eint->irq) {
-		ret = -EINVAL;
-		goto err_free_eint;
-	}
+		hw->eint->irq = irq_of_parse_and_map(np, 0);
+		if (!hw->eint->irq) {
+			ret = -EINVAL;
+			goto err_free_eint;
+		}
 
-	if (!hw->soc->eint_hw) {
-		ret = -ENODEV;
-		goto err_free_eint;
-	}
+		hw->eint->dev = &pdev->dev;
+		hw->eint->hw = hw->soc->eint_hw;
+		hw->eint->pctl = hw;
+		hw->eint->gpio_xlate = &mtk_eint_xt;
+
+                return mtk_eint_do_init(hw->eint);
 
-	hw->eint->dev = &pdev->dev;
-	hw->eint->hw = hw->soc->eint_hw;
-	hw->eint->pctl = hw;
-	hw->eint->gpio_xlate = &mtk_eint_xt;
+        } else {
+                hw->eint->dev = &pdev->dev;
+                hw->eint->pctl = hw;
+                hw->eint->gpio_xlate = &mtk_eint_xt;
 
-	return mtk_eint_do_init(hw->eint);
+                return mtk_eint_do_init_v2(hw->eint);
+	}
 
 err_free_eint:
 	devm_kfree(hw->dev, hw->eint);