From: grant.likely@secretlab.ca (Grant Likely)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] gpio/mxs: support irqs triggered by both edges
Date: Mon, 12 Mar 2012 10:35:03 -0600 [thread overview]
Message-ID: <20120312163503.AEBC73E07B0@localhost> (raw)
In-Reply-To: <1329745925-7868-1-git-send-email-enrico.scholz@sigma-chemnitz.de>
On Mon, 20 Feb 2012 14:52:05 +0100, Enrico Scholz <enrico.scholz@sigma-chemnitz.de> wrote:
> iMX28 silicon does not support irqs triggered by both gpio edges. Patch
> emulates this behavior by configuring such irqs as level triggered and
> by switching polarity in the interrupt handler.
>
> Signed-off-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de>
That looks dodgy and hacky. This will definitely miss interrupts if they
come in too fast. I don't like this approach. What do you need it for?
g.
> ---
> drivers/gpio/gpio-mxs.c | 31 +++++++++++++++++++++++++++++--
> 1 files changed, 29 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
> index 385c58e..ab973be 100644
> --- a/drivers/gpio/gpio-mxs.c
> +++ b/drivers/gpio/gpio-mxs.c
> @@ -57,6 +57,7 @@ struct mxs_gpio_port {
> int id;
> int irq;
> int virtual_irq_start;
> + unsigned long both_edge;
> struct bgpio_chip bgc;
> };
>
> @@ -68,9 +69,12 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
> u32 pin_mask = 1 << (gpio & 31);
> struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> struct mxs_gpio_port *port = gc->private;
> + int lvl;
> void __iomem *pin_addr;
> int edge;
>
> + clear_bit(gpio & 31, &port->both_edge);
> +
> switch (type) {
> case IRQ_TYPE_EDGE_RISING:
> edge = GPIO_INT_RISE_EDGE;
> @@ -84,6 +88,14 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
> case IRQ_TYPE_LEVEL_HIGH:
> edge = GPIO_INT_HIGH_LEV;
> break;
> + case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
> + /* mx28 does not support triggering irq by both edges; emulate
> + * behavior by configuring irq as level triggered and update
> + * irq polarity in the irq handler */
> + set_bit(gpio & 31, &port->both_edge);
> + lvl = readl(port->base + PINCTRL_DIN(port->id));
> + edge = (lvl & pin_mask) ? GPIO_INT_LOW_LEV : GPIO_INT_HIGH_LEV;
> + break;
> default:
> return -EINVAL;
> }
> @@ -114,11 +126,26 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
> u32 irq_stat;
> struct mxs_gpio_port *port = irq_get_handler_data(irq);
> u32 gpio_irq_no_base = port->virtual_irq_start;
> + void __iomem *base = port->base;
> + u32 pol_msk;
>
> desc->irq_data.chip->irq_ack(&desc->irq_data);
>
> - irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) &
> - readl(port->base + PINCTRL_IRQEN(port->id));
> + irq_stat = readl(base + PINCTRL_IRQSTAT(port->id)) &
> + readl(base + PINCTRL_IRQEN(port->id));
> +
> + /* handle irqs triggered by both edges */
> + pol_msk = irq_stat & port->both_edge;
> + if (pol_msk) {
> + void __iomem *reg = base + PINCTRL_IRQPOL(port->id);
> + u32 port_lvl = readl(base + PINCTRL_DIN(port->id));
> +
> + /* \todo write into the TOGGLE register (without reading port
> + * level register); this requires a special unmask operation
> + * which updates the IRQPOL register */
> + writel(pol_msk & port_lvl, reg + MXS_CLR);
> + writel(pol_msk & ~port_lvl, reg + MXS_SET);
> + }
>
> while (irq_stat != 0) {
> int irqoffset = fls(irq_stat) - 1;
> --
> 1.7.7.6
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Grant Likely, B.Sc, P.Eng.
Secret Lab Technologies,Ltd.
next prev parent reply other threads:[~2012-03-12 16:35 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-20 13:52 [PATCH] gpio/mxs: support irqs triggered by both edges Enrico Scholz
2012-03-12 16:35 ` Grant Likely [this message]
2012-03-12 17:02 ` Enrico Scholz
2012-03-12 17:17 ` Grant Likely
2012-03-12 17:38 ` Enrico Scholz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120312163503.AEBC73E07B0@localhost \
--to=grant.likely@secretlab.ca \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.