[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAAfSe-sVfZ8YNnxK4e1CphnxXOgEZaEfWZFV_CrSZA0nmBrZjA@mail.gmail.com>
Date: Mon, 22 Jan 2024 18:00:52 +0800
From: Chunyan Zhang <zhang.lyra@...il.com>
To: Wenhua Lin <Wenhua.Lin@...soc.com>
Cc: Linus Walleij <linus.walleij@...aro.org>, Andy Shevchenko <andy@...nel.org>,
Bartosz Golaszewski <brgl@...ev.pl>, Orson Zhai <orsonzhai@...il.com>,
Baolin Wang <baolin.wang@...ux.alibaba.com>, linux-gpio@...r.kernel.org,
linux-kernel@...r.kernel.org, wenhua lin <wenhua.lin1994@...il.com>,
Xiongpeng Wu <xiongpeng.wu@...soc.com>
Subject: Re: [PATCH V4 1/2] gpio: eic-sprd: Clear interrupt after set the
interrupt type
On Tue, 9 Jan 2024 at 15:39, Wenhua Lin <Wenhua.Lin@...soc.com> wrote:
>
> The raw interrupt status of eic maybe set before the interrupt is enabled,
> since the eic interrupt has a latch function, which would trigger the
> interrupt event once enabled it from user side. To solve this problem,
> interrupts generated before setting the interrupt trigger type are ignored.
>
> Fixes: 25518e024e3a ("gpio: Add Spreadtrum EIC driver support")
> Signed-off-by: Wenhua Lin <Wenhua.Lin@...soc.com>
Acked-by: Chunyan Zhang <zhang.lyra@...il.com>
> ---
> drivers/gpio/gpio-eic-sprd.c | 32 ++++++++++++++++++++++++++++----
> 1 file changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
> index be7f2fa5aa7b..806b88d8dfb7 100644
> --- a/drivers/gpio/gpio-eic-sprd.c
> +++ b/drivers/gpio/gpio-eic-sprd.c
> @@ -330,20 +330,27 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
> switch (flow_type) {
> case IRQ_TYPE_LEVEL_HIGH:
> sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1);
> break;
> case IRQ_TYPE_LEVEL_LOW:
> sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
> + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1);
> break;
> case IRQ_TYPE_EDGE_RISING:
> case IRQ_TYPE_EDGE_FALLING:
> case IRQ_TYPE_EDGE_BOTH:
> state = sprd_eic_get(chip, offset);
> - if (state)
> + if (state) {
> sprd_eic_update(chip, offset,
> SPRD_EIC_DBNC_IEV, 0);
> - else
> + sprd_eic_update(chip, offset,
> + SPRD_EIC_DBNC_IC, 1);
> + } else {
> sprd_eic_update(chip, offset,
> SPRD_EIC_DBNC_IEV, 1);
> + sprd_eic_update(chip, offset,
> + SPRD_EIC_DBNC_IC, 1);
> + }
> break;
> default:
> return -ENOTSUPP;
> @@ -355,20 +362,27 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
> switch (flow_type) {
> case IRQ_TYPE_LEVEL_HIGH:
> sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0);
> + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1);
> break;
> case IRQ_TYPE_LEVEL_LOW:
> sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1);
> break;
> case IRQ_TYPE_EDGE_RISING:
> case IRQ_TYPE_EDGE_FALLING:
> case IRQ_TYPE_EDGE_BOTH:
> state = sprd_eic_get(chip, offset);
> - if (state)
> + if (state) {
> sprd_eic_update(chip, offset,
> SPRD_EIC_LATCH_INTPOL, 0);
> - else
> + sprd_eic_update(chip, offset,
> + SPRD_EIC_LATCH_INTCLR, 1);
> + } else {
> sprd_eic_update(chip, offset,
> SPRD_EIC_LATCH_INTPOL, 1);
> + sprd_eic_update(chip, offset,
> + SPRD_EIC_LATCH_INTCLR, 1);
> + }
> break;
> default:
> return -ENOTSUPP;
> @@ -382,29 +396,34 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_edge_irq);
> break;
> case IRQ_TYPE_EDGE_FALLING:
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
> + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_edge_irq);
> break;
> case IRQ_TYPE_EDGE_BOTH:
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_edge_irq);
> break;
> case IRQ_TYPE_LEVEL_HIGH:
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_level_irq);
> break;
> case IRQ_TYPE_LEVEL_LOW:
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
> sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
> + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_level_irq);
> break;
> default:
> @@ -417,29 +436,34 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_edge_irq);
> break;
> case IRQ_TYPE_EDGE_FALLING:
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
> + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_edge_irq);
> break;
> case IRQ_TYPE_EDGE_BOTH:
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_edge_irq);
> break;
> case IRQ_TYPE_LEVEL_HIGH:
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
> + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_level_irq);
> break;
> case IRQ_TYPE_LEVEL_LOW:
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
> sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
> + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
> irq_set_handler_locked(data, handle_level_irq);
> break;
> default:
> --
> 2.17.1
>
Powered by blists - more mailing lists