2009-12-07 12:33:13

by Kenneth Johansson

[permalink] [raw]
Subject: gpio gpio_to_irq

I have a few questions regarding the gpio related to interrupts.

The hardware is a generic gpio block that is located on pci. The pins
themselves can be configured to in/out and generate interrupts.

All in all it looks to be very similar to the langwell gpio.
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/gpio/langwell_gpio.c;h=4baf3d7d0f8e6e4f1f7887625b7f73a62dba1a83;hb=22763c5cf3690a681551162c15d34d935308c8d7


Many gpio drivers use the set_irq_chained_handler() instead of calling
request_irq to get the main gpio interrupt. But doing so on a shared pci
interrupt do not look like a good idea.

Under what circumstance is set_irq_chained_handler allowed ?

The next thing is that the drivers then registers a "fake" interrupt
chip to make it possible for the gpio client to call request_irq with
the irq number returned from gpio_to_irq().

While using this interface is neat it do require that the gpio driver
somehow can just take over a few irq numbers from the system.

How is this supposed to be done?? the langwell driver reads a number
located at BAR1 and simply use that as the first irq number, hu?

others start to allocate from the top and so on. what is the correct way
to do this on a x86 with a gpio device on the pci bus ??



2009-12-08 22:22:33

by David Brownell

[permalink] [raw]
Subject: Re: gpio gpio_to_irq

On Monday 07 December 2009, Kenneth Johansson wrote:

> Many gpio drivers use the set_irq_chained_handler() instead of calling
> request_irq to get the main gpio interrupt.

Right ... mostly those are microcontrollers, where the top level
IRQ controller is hooked up to a few dozen on-chip peripherals,
and several of them are GPIO controllers. Most (or all!) external
IRQs come through GPIOs, with the more powerful ones offering some
control over trigger modes (which levels/edges) on the input side.


> But doing so on a shared pci
> interrupt do not look like a good idea.
>
> Under what circumstance is set_irq_chained_handler allowed ?

That's an IRQ question not a GPIO question. I think the answer
to that question has likely been evolving over time... and that
you may be right about doing this over PCI.


> The next thing is that the drivers then registers a "fake" interrupt
> chip to make it possible for the gpio client to call request_irq with
> the irq number returned from gpio_to_irq().

Not that I've ever seen. It's a real irq_chip. The only odd
case is when the IRQs are enabled/disabled/acked over a slow
bus like I2C ... that's stuff the IRQ framework hasn't much
liked, it wants to call those methods with a hard spinlock.

For the more typical case of an on-chip IRQ peripheral, just
think of it as another layer to the IRQ dispatch tree. There
can easily be two or more layers. If one of the IRQ controllers
has additional duties, instead of only handling IRQ dispatch,
that's routine; it fits into power management and wakeup too.


> While using this interface is neat it do require that the gpio driver
> somehow can just take over a few irq numbers from the system.
>
> How is this supposed to be done??

Last I looked, IRQ numbering was a global system-wide policy.

So plug'n'play of IRQ controllers was ... awkward, along with
dynamic assignment of IRQ numbers. True for all PCI-based IRQ
controllers. Southbridge IRQs are often wrapped up in ACPI,
so those issues don't surface in most PCs.

Again, not a GPIO question, but an IRQ question. (Or maybe an
x86 arch question.)


> the langwell driver reads a number
> located at BAR1 and simply use that as the first irq number, hu?
>
> others start to allocate from the top and so on. what is the correct way
> to do this on a x86 with a gpio device on the pci bus ??

Embedded platforms have typically done things like pre-allocate
a bunch of extra IRQ numbers, and then arrange to have each new
IRQ controller land in a board-assigned slot. It can waste RAM,
but is mostly painless.

That's fine so long as you have a sane level of control over
system bootup, where board-specific logic can for example know
which external chips (and thus irq_chip controllers) exist.
(And maybe even arrange via Kconfig to alloc extra IRQ numbers
only as needed.)

When you don't have such a notion of "board" -- maybe punting
everything to ACPI or some other "hide the hardware from the
OS" abstraction -- I'm not clear on a good solution.

With ACPI, the notion of whether a given GPIO is used for its
IRQ capabilities is hidden in ACPI bytecode and not exposed to
Linux. A lot of the ACPI event reports are from GPIO IRQs;
input buttons and so on. And a lot of that bytecode goes and
queries the GPIOs; I'd have to go re-read things, but a "GPE"
is intimately associated with a southbridge GPIO signal. If
you disassemble the bytecode and read some handlers, you'll
see exactly what I mean.

So the x86 world has thus far punted on a lot of the (good!)
questions you're asking, since the main use of GPIOs on a PC
is wrapped up in ACPI southbridge support, and is seen only
indirectly by Linux or any operating system.

- Dave

2009-12-09 04:43:24

by Kenneth Johansson

[permalink] [raw]
Subject: Re: gpio gpio_to_irq

On Tue, 2009-12-08 at 14:22 -0800, David Brownell wrote:
> On Monday 07 December 2009, Kenneth Johansson wrote:
> > But doing so on a shared pci
> > interrupt do not look like a good idea.
> >
> > Under what circumstance is set_irq_chained_handler allowed ?
>
> That's an IRQ question not a GPIO question. I think the answer
> to that question has likely been evolving over time... and that
> you may be right about doing this over PCI.

yes the irq thing is the only part of the gpio abstraction I have issue
with so this is basically all about that part. It all originates from
the gpio_to_irq function and what that one is supposed to return.

> > The next thing is that the drivers then registers a "fake" interrupt
> > chip to make it possible for the gpio client to call request_irq with
> > the irq number returned from gpio_to_irq().
>
> Not that I've ever seen. It's a real irq_chip.

I had it in quotes as I have a mental block on thinking of it as an
interrupt controller but you are right it can be view as a simple
controller.

> > While using this interface is neat it do require that the gpio driver
> > somehow can just take over a few irq numbers from the system.
> >
> > How is this supposed to be done??
>
> Last I looked, IRQ numbering was a global system-wide policy.
>
> So plug'n'play of IRQ controllers was ... awkward, along with
> dynamic assignment of IRQ numbers. True for all PCI-based IRQ
> controllers. Southbridge IRQs are often wrapped up in ACPI,
> so those issues don't surface in most PCs.
>
> Again, not a GPIO question, but an IRQ question. (Or maybe an
> x86 arch question.)

Yes I has hoped that the "overlord of low level hacking on
x86" (Gleixner) would bite but no such luck.

>
> > the langwell driver reads a number
> > located at BAR1 and simply use that as the first irq number, hu?
> >
> > others start to allocate from the top and so on. what is the correct way
> > to do this on a x86 with a gpio device on the pci bus ??
>
> Embedded platforms have typically done things like pre-allocate
> a bunch of extra IRQ numbers, and then arrange to have each new
> IRQ controller land in a board-assigned slot. It can waste RAM,
> but is mostly painless.
>
> That's fine so long as you have a sane level of control over
> system bootup, where board-specific logic can for example know
> which external chips (and thus irq_chip controllers) exist.
> (And maybe even arrange via Kconfig to alloc extra IRQ numbers
> only as needed.)
>
> When you don't have such a notion of "board" -- maybe punting
> everything to ACPI or some other "hide the hardware from the
> OS" abstraction -- I'm not clear on a good solution.

I wish the genirq had an allocation strategy for the irq numbers Then
that could basically be used by any gpio driver on any arch. basically
irq_get_free() would solve it.

Well I have to investigate more how msi interrupts is done as they also
need to allocate a new irq number whenever a pci device turns it on.

I just hoped I had missed something that would make this problem go
away.