linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: gregory.clement@free-electrons.com (Gregory CLEMENT)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
Date: Tue, 28 Mar 2017 12:36:49 +0200	[thread overview]
Message-ID: <87vaqtadry.fsf@free-electrons.com> (raw)
In-Reply-To: CACRpkdYv6WDWM60dRMaYfEt50M8N-yLYk2TRguNi78aQtt6X9A@mail.gmail.com

Hi Linus,
 
 On lun., mars 27 2017, Linus Walleij <linus.walleij@linaro.org> wrote:

> On Tue, Mar 21, 2017 at 7:28 PM, Gregory CLEMENT
> <gregory.clement@free-electrons.com> wrote:
>
>> The Armada 37xx SoCs can handle interrupt through GPIO. However it can
>> only manage the edge ones.
>>
>> The way the interrupt are managed are classical so we can use the generic
>> interrupt chip model.
>>
>> The only unusual "feature" is that many interrupts are connected to the
>> parent interrupt controller. But we do not take advantage of this and use
>> the chained irq with all of them.
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>
> You need something in your Kconfig
> doing select GPIOLIB_IRQCHIP unless there is
> something I miss here.

I forgot to add it, I will do it in the v4.

>
>> +#define IRQ_EN         0x0
>> +#define IRQ_POL                0x08
>> +#define IRQ_STATUS     0x10
>
> This just cries out to me that there is a register 0x0c
> and I bet it handles edges vs levels so you could also implement
> level IRQs. Am I right?

Unfortunately, no :(

As far as I know there is now way to handle level.
The 0xc register is the IRQ_POL for the GPIO above 32.

>
>> -       aramda_37xx_update_reg(&reg, offset);
>> +       armada_37xx_update_reg(&reg, offset);
> (...)
>> -       aramda_37xx_update_reg(&reg, offset);
>> +       armada_37xx_update_reg(&reg, offset);
>
> These spelling fixes, do not do them in this patch, fix the first
> patch adding them
> instead. It's super-confusing. Applies everywhere.

It was a typo (too much 'a' in the same word) that I properly fixed in
the v3. (But I still need to fix the title of the patch in the v4)


>> +static void armada_37xx_irq_handler(struct irq_desc *desc)
>> +{
>> +       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
>> +       struct irq_chip *chip = irq_desc_get_chip(desc);
>> +       struct armada_37xx_pinctrl *info = gpiochip_get_data(gc);
>> +       struct irq_domain *d = gc->irqdomain;
>> +       int i;
>> +
>> +       chained_irq_enter(chip, desc);
>> +       for (i = 0; i <= d->revmap_size / GPIO_PER_REG; i++) {
>> +               u32 status;
>> +               unsigned long flags;
>> +
>> +               spin_lock_irqsave(&info->irq_lock, flags);
>> +               status = readl_relaxed(info->base + IRQ_STATUS + 4 * i);
>> +               /* Manage only the interrupt that was enabled */
>> +               status &= readl_relaxed(info->base + IRQ_EN + 4 * i);
>> +               spin_unlock_irqrestore(&info->irq_lock, flags);
>> +               while (status) {
>> +                       u32 hwirq = ffs(status) - 1;
>> +                       u32 virq = irq_linear_revmap(d, hwirq +
>> +                                                    i * GPIO_PER_REG);
>
> Use irq_find_mapping() instead please.

As we are in the interrupt handler I chose to use this function because
according to its documentation: "This is a fast path alternative to
irq_find_mapping() that can be called directly by irq controller code to
save a handful of instructions".

The only restriction is "It is always safe to call, but won't find irqs
mapped using the radix tree.". So I think that for this driver it is
okay.


>
>> +                       generic_handle_irq(virq);
>> +                       status &= ~(1 << hwirq);
>
> Why not status &= ~BIT(hwirq);

OK

>
>> +               }
>> +       }
>> +       chained_irq_exit(chip, desc);
>
> Apart from that nice, it re-reads status on every iteration which is
> good.
>
>> +static int armada_37xx_irqchip_register(struct platform_device *pdev,
>> +                                       struct armada_37xx_pinctrl *info)
>> +{
>> +       struct device_node *np = info->dev->of_node;
>> +       int nrirqs = info->data->nr_pins;
>> +       struct gpio_chip *gc = &info->gpio_chip;
>> +       struct irq_chip *irqchip = &info->irq_chip;
>> +       struct resource res;
>> +       int ret, i, nr_irq_parent;
>> +
>> +       for_each_child_of_node(info->dev->of_node, np) {
>> +               if (of_find_property(np, "gpio-controller", NULL)) {
>> +                       ret = 0;
>> +                       break;
>> +               }
>> +       };
>
> Now there is this thing again looping over the nodes.

As explained in the other patch we will only have one GPIO subnode.

>
>> +       if (ret)
>> +               return ret;
>
> ret may be used uninitialized here, if you loop over all nodes
> and do not find any "gpio-controller".
>
> The static code checks will just scream about this.
>
> (Please fix in the other patch as well if present there.)

OK

>
>> +       nr_irq_parent = of_irq_count(np);
>> +       spin_lock_init(&info->irq_lock);
>> +
>> +       if (!nr_irq_parent) {
>> +               dev_err(&pdev->dev, "Invalid or no IRQ\n");
>> +               return 0;
>> +       }
>
> What if it is > 1? That doesn't seem to work but will pass this
> check silently.

If we have nr_irq_parent > 1, it will work and it is actually expected.

>
>> +       ret = gpiochip_irqchip_add(gc, irqchip, 0,
>> +                                  handle_level_irq, IRQ_TYPE_NONE);
>
> If you also set up the handler in .set_type() you can assign
> handle_bad_irq() here and let .set_type set the right handler
> as e.g. drivers/gpio/gpio-pl061.c.

Well the hardware can only manage the edge trigger, so there is no
benefit to modify it each time we want to change the kind of edge we
want (raising or falling). But your comment make me realized that I used
the wrong one, I will move to handle_edge_irq in the v4.

>
>> +       for (i = 0; i < nrirqs; i++) {
>> +               struct irq_data *d = irq_get_irq_data(gc->irq_base + i);
>> +
>> +               d->mask = 1 << (i % GPIO_PER_REG);
>> +       }
>
> What is this? It looks like a big hack. At least put in a fat
> comment about what is going on and why.

I can reuse a part of the commit log here: "The only unusual "feature"
is that many interrupts are connected to the parent interrupt
controller. But we do not take advantage of this and use the chained irq
with all of them."

>
>> +       for (i = 0; i < nr_irq_parent; i++) {
>> +               int irq = irq_of_parse_and_map(np, i);
>
> I think gpiochip_irqchip_add() will do this for you already,
> as it calls irq_create_mapping() for all offsets which will call
> irq_of_parse_and_map() am I right?

After reading the code, it doesn't seem it is the case. At least there
is no irq_of_parse_and_map() call from gpiochip_irqchip_add(). And waht
we need here is to associate each IRQ to the same GPIO handler.

I can still try without this line to confirm it.

Gregory


-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

  reply	other threads:[~2017-03-28 10:36 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-21 18:28 [PATCH v2 0/7] Hi, Gregory CLEMENT
2017-03-21 18:28 ` [PATCH v2 1/7] pinctrl: dt-bindings: Add documentation for Armada 37xx pin controllers Gregory CLEMENT
2017-03-27  9:18   ` Linus Walleij
2017-03-28  9:35     ` Gregory CLEMENT
2017-03-21 18:28 ` [PATCH v2 2/7] arm64: marvell: enable the Armada 37xx pinctrl driver Gregory CLEMENT
2017-03-21 18:28 ` [PATCH v2 3/7] pinctrl: armada-37xx: Add pin controller support for Armada 37xx Gregory CLEMENT
2017-03-27  9:26   ` Linus Walleij
2017-03-28 10:43     ` Gregory CLEMENT
2017-03-21 18:28 ` [PATCH v2 4/7] pinctrl: armada-37xx: Add gpio support Gregory CLEMENT
2017-03-27  8:57   ` Linus Walleij
2017-03-27  9:46     ` Gregory CLEMENT
2017-03-21 18:28 ` [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support Gregory CLEMENT
2017-03-27  9:15   ` Linus Walleij
2017-03-28 10:36     ` Gregory CLEMENT [this message]
2017-03-28 13:04       ` Linus Walleij
2017-03-28 14:19         ` Gregory CLEMENT
2017-03-29  2:18           ` Linus Walleij
2017-03-30 16:57             ` Gregory CLEMENT
2017-03-21 18:28 ` [PATCH v2 6/7] ARM64: dts: marvell: Add pinctrl nodes for Armada 3700 Gregory CLEMENT
2017-03-21 18:28 ` [PATCH v2 7/7] ARM64: dts: marvell: armada37xx: add pinctrl definition Gregory CLEMENT
2017-03-21 20:50 ` [PATCH v2 0/7] Add support for pinctrl/gpio on Armada 37xx Was Re: [PATCH v2 0/7] Hi, Gregory CLEMENT
2017-03-22 11:40   ` Gregory CLEMENT

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=87vaqtadry.fsf@free-electrons.com \
    --to=gregory.clement@free-electrons.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).