Re: [PATCH v4 2/4] gpio: visconti: Add Toshiba Visconti GPIO support
From: Nobuhiro Iwamatsu
Date: Wed Dec 16 2020 - 04:14:20 EST
Hi,
Thanks for your review.
On Sat, Dec 12, 2020 at 12:20:47AM +0100, Linus Walleij wrote:
> On Fri, Dec 11, 2020 at 1:43 AM Nobuhiro Iwamatsu
> <nobuhiro1.iwamatsu@xxxxxxxxxxxxx> wrote:
>
> This iteration is looking really good, but we are not quite there yet,
> because now that the driver looks so much better I can see that it
> is a hierarchical interrupt controller.
As you pointed out, this GPIO interrupt is directly linked to the GIC
interrupt.
As a function of the GPIO driver, there is a function (IRQ_DOMAIN_HIERARCHY)
that can handle these as one-to-one, so it is pointed out that it is better
to use this. Is this correct?
>
> > Add the GPIO driver for Toshiba Visconti ARM SoCs.
> >
> > Signed-off-by: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@xxxxxxxxxxxxx>
> > Reviewed-by: Punit Agrawal <punit1.agrawal@xxxxxxxxxxxxx>
> (...)
>
> > +config GPIO_VISCONTI
> > + tristate "Toshiba Visconti GPIO support"
> > + depends on ARCH_VISCONTI || COMPILE_TEST
> > + depends on OF_GPIO
> > + select GPIOLIB_IRQCHIP
> > + select GPIO_GENERIC
> > + help
> > + Say yes here to support GPIO on Tohisba Visconti.
>
> Add
> select IRQ_DOMAIN_HIERARCHY
OK, I will add this.
>
> > +struct visconti_gpio {
> > + void __iomem *base;
> > + int *irq;
>
> Don't keep these irqs around.
>
OK, I will remove this
.
> > + ret = platform_irq_count(pdev);
> > + if (ret < 0)
> > + return ret;
> > +
> > + num_irq = ret;
> > +
> > + priv->irq = devm_kcalloc(dev, num_irq, sizeof(priv->irq), GFP_KERNEL);
> > + if (!priv->irq)
> > + return -ENOMEM;
> > +
> > + for (i = 0; i < num_irq; i++) {
> > + priv->irq[i] = platform_get_irq(pdev, i);
> > + if (priv->irq[i] < 0) {
> > + dev_err(dev, "invalid IRQ[%d]\n", i);
> > + return priv->irq[i];
> > + }
> > + }
>
> Instead of doing this, look in for example
> drivers/gpio/gpio-ixp4xx.c
>
> You need:
>
> > + girq = &priv->gpio_chip.irq;
> > + girq->chip = irq_chip;
>
> girq->fwnode = fwnode;
> girq->parent_domain = parent;
> girq->child_to_parent_hwirq = visconti_gpio_child_to_parent_hwirq;
>
I understood that the irq_domain specified by girq->parent_domain will be the
GIC. Is this correct?
> The mapping function will be something like this:
>
> static int visconti_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
> unsigned int child,
> unsigned int child_type,
> unsigned int *parent,
> unsigned int *parent_type)
> {
> /* Interrupts 0..15 mapped to interrupts 24..39 on the GIC */
> if (child < 16) {
> /* All these interrupts are level high in the CPU */
> *parent_type = IRQ_TYPE_LEVEL_HIGH;
> *parent = child + 24;
> return 0;
> }
> return -EINVAL;
> }
>
I see, I will add this function.
> > + priv->gpio_chip.irq.init_valid_mask = visconti_init_irq_valid_mask;
>
> This will be set up by gpiolib when using hierarchical irqs.
>
OK.
> > + /* This will let us handle the parent IRQ in the driver */
> > + girq->parent_handler = NULL;
> > + girq->num_parents = 0;
> > + girq->parents = NULL;
>
> You don't need this.
>
> > + girq->default_type = IRQ_TYPE_NONE;
> > + girq->handler = handle_level_irq;
>
> But this stays.
>
OK, I will update to these.
> > + for (i = 0; i < num_irq; i++) {
> > + desc = irq_to_desc(priv->irq[i]);
> > + desc->status_use_accessors |= IRQ_NOAUTOEN;
> > + if (devm_request_irq(dev, priv->irq[i],
> > + visconti_gpio_irq_handler, 0, name, priv)) {
> > + dev_err(dev, "failed to request IRQ[%d]\n", i);
> > + return -ENOENT;
> > + }
> > + }
>
> This should not be needed either when using hiearchical IRQs,
> also the irqchip maintainers will beat us up for poking around in the
> descs like this.
I understand that the processing equivalent to request_irq() is processed
by the irqchip frame work (or GIC driver). Is this correct?
>
> The rest looks solid!
>
Thank you.
I will apply your point into the driver.
Best regards,
Nobuhiro