[PATCH] pinctrl: mediatek: add eint new design for mt8196
Chen-Yu Tsai
wenst at chromium.org
Thu Oct 24 21:12:02 PDT 2024
On Fri, Oct 25, 2024 at 11:19 AM chang hao <ot_chhao.chang at mediatek.com> wrote:
>
> From: Chhao Chang <ot_chhao.chang at 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 at 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
>
>
More information about the Linux-mediatek
mailing list