[PATCH v2 1/3] gpio: xgene: add support to configure GPIO line as input, output or external IRQ pin
Quan Nguyen
qnguyen at apm.com
Thu Oct 29 22:41:03 PDT 2015
Forgive me for not turn on plain text mode my last email.
Hi Linus,
My name is Quan Nguyen, I'm working with Y Vo on this patch.
Allow me to explain as below:
In current implementation, gic irq resources were used in both sbgpio
and gpios-key nodes, and this causes confusion.
To avoid this, we introduce sbgpio driver as interrupt controller, it
now provides 6 external irq pins mapped from gpio line 8-13. The
gpio-keys node now uses sbgpio irq resources instead.
-- Quan
On Thu, Oct 29, 2015 at 8:28 PM, Linus Walleij <linus.walleij at linaro.org> wrote:
> On Mon, Oct 26, 2015 at 7:49 AM, Y Vo <yvo at apm.com> wrote:
>
>> Add support to configure GPIO line as input, output or external IRQ pin.
>>
>> Signed-off-by: Y Vo <yvo at apm.com>
>
> As I will say again, this description is too terse, add lots of information
> on how IRQs work on this controller please. I get confused.
How about:
+++++++++++++++++++++++++++++++++
Enable X-Gene standby GPIO driver as interrupt controller, it provides
6 external irq pins via gpio line 8-13.
+++++++++++++++++++++++++++++++++
>
> (...)
>
>> +#define XGENE_GPIO8_HWIRQ 0x48
>> +#define XGENE_GPIO8_IDX 8
> (...)
>> +#define XGENE_HWIRQ_TO_GPIO(hwirq) ((hwirq) + XGENE_GPIO8_IDX)
>> +#define XGENE_GPIO_TO_HWIRQ(gpio) ((gpio) - XGENE_GPIO8_IDX)
>> +#define GIC_IRQ_TO_GPIO_IRQ(hwirq) ((hwirq) - XGENE_GPIO8_HWIRQ)
>> +#define GPIO_IRQ_TO_GIC_IRQ(hwirq) ((hwirq) + XGENE_GPIO8_HWIRQ)
>
> I'm a bit uneasy about this, maybe I just don't get it.
>
> What is this indexing into "GIC IRQ" that is starting to happen
> here?
>
> The GIC (if that is drivers/irqchip/irq-gic.c) has a totally dynamic IRQ
> translation and the Linux IRQs it is using may change. I am worried
> that there is some reliance here on Linux IRQ having certain numbers
> because there is certainly no ABI like that.
>
> Is this 0x48 really an index into the *hardware* offset in the GIC?
>
> And if it is: why are we not getting this hardware information from the
> device tree like all other interrupt numbers and offsets?
>
> I'm worried about this.
The SPI40(0x48) through SPI45(0x4D) from GIC are mapped as external
IRQ0 - IRQ5 in this GPIO block, so it is hardware offset not mapped
irq number.
Below is detail:
+ GIC: SPI40 (hwirq=0x48) <=> SB-GPIO: (hwirq=0) (gpio line 8)
+ GIC: SPI41 (hwirq=0x49) <=> SB-GPIO: (hwirq=1) (gpio line 9)
...
+ GIC: SPI45 (hwirq=0x4D) <=> SB-GPIO: (hwirq=5) (gpio line 13)
These defines are to help translating between Gic hardware irq and
SBGPIO hardware irq number.
>
>> - u32 *irq;
>> + void __iomem *regs;
>> + struct irq_domain *gic_domain;
>> + struct irq_domain *irq_domain;
>
> And there is some secondary gic_domain here, which is confusing
> since the GIC does have an IRQ domain too.
>
> I think I want a clear explanation to how this GPIO controller interacts
> with the GIC, and I want it to be part of the patch, as comments in the
> code and in the commit message (which is way too small for a complex
> patch like this).
>
> Otherwise I have no chance to understand what is really going on here.
SBGPIO currently is not capable to mask/unmask/... irqs, so these will
rely on the parent (GIC) instead. To do so, we need keep a parent
domain reference here "struct irq_domain *gic_domain" so we can find
correspond parent irq in runtime.
>
>> +static int xgene_gpio_sb_irq_set_type(struct irq_data *d, unsigned int type)
>> +{
>> + int hwirq = d->hwirq;
>> + int gpio = XGENE_HWIRQ_TO_GPIO(hwirq);
>> + struct xgene_gpio_sb *priv = irq_data_get_irq_chip_data(d);
>> + int lvl_type;
>> + int ret;
>> +
>> + switch (type & IRQ_TYPE_SENSE_MASK) {
>> + case IRQ_TYPE_EDGE_RISING:
>> + case IRQ_TYPE_LEVEL_HIGH:
>> + lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
>> + break;
>> + case IRQ_TYPE_EDGE_FALLING:
>> + case IRQ_TYPE_LEVEL_LOW:
>> + lvl_type = GPIO_INT_LVL_LEVEL_LOW;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + ret = gpiochip_lock_as_irq(&priv->bgc.gc, gpio);
>> + if (ret) {
>> + dev_err(priv->bgc.gc.dev,
>> + "Unable to configure XGene GPIO standby pin %d as IRQ\n",
>> + gpio);
>> + return ret;
>> + }
>> +
>> + if ((gpio >= XGENE_GPIO8_IDX) &&
>> + (hwirq < XGENE_MAX_GPIO_DS_IRQ)) {
>> + xgene_gpio_set_bit(&priv->bgc, priv->regs + MPA_GPIO_SEL_LO,
>> + gpio * 2, 1);
>> + xgene_gpio_set_bit(&priv->bgc, priv->regs + MPA_GPIO_INT_LVL,
>> + hwirq, lvl_type);
>> + }
>> + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
>> + irq_set_handler_locked(d, handle_edge_irq);
>> + else
>> + irq_set_handler_locked(d, handle_level_irq);
>> +
>> + return 0;
>> +}
>
> If you are assigning hadle_edge_irq() your irqchip *must* have an
> .irq_ack() callback that acknowledges the IRQs as they come in.
>
> This makes me suspect that you haven't really tested edge
> interrupts, because if you did, the kernel would crash as it
> is unconditionally calling the .irq_ack() from handle_level_irq().
irq_ack() callback is no-op function in this patch.
+static struct irq_chip xgene_gpio_sb_irq_chip = {
+ .name = "sbgpio",
+ .irq_ack = xgene_gpio_sb_nop,
>
> Yours,
> Linus Walleij
More information about the linux-arm-kernel
mailing list