Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Jun 2019 14:59:53 +0300
From:      Andriy Gapon <avg@FreeBSD.org>
To:        Ian Lepore <ian@freebsd.org>, FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: gpio interrupt on x86
Message-ID:  <0544d3b9-7f6a-5626-3ab3-90c262a3f21d@FreeBSD.org>
In-Reply-To: <cca176e63c8ea40f9f49602f7b5ad977b9ae8e6d.camel@freebsd.org>
References:  <2c99a77c-a423-c2ea-1b2c-b2eefbae13c1@FreeBSD.org> <cca176e63c8ea40f9f49602f7b5ad977b9ae8e6d.camel@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On 30/05/2019 18:35, Ian Lepore wrote:
> On Mon, 2019-05-27 at 18:17 +0300, Andriy Gapon wrote:
>> I would like to run some code when an input pin changes its state.
>> A GPIO controller that handles that pin is capable of generating an interrupt.
>> I can configure the type of a signal change that would trigger the interrupt.
>> The GPIO controller would generate the interrupt on that change.
>> I would be able to query the controller for a specific pin (if interrupts for
>> multiple pins are enabled).
>> All is good.
>>
>> Now, the question is how to _properly_ hook my code to the gpiobus hanging off
>> the controller.
>> I see that embedded (or not so embedded) platforms typically define a "slave"
>> interrupt controller.  I guess that it defines a new interrupt number (and
>> interrupt source, etc) for each interrupt capable pin.  And then hooking to that
>> pin is a matter of just installing an interrupt handler for a specific interrupt
>> and enabling it.
>>
>> But I am not sure if the same approach would work on x86.
>> Is there any other alternative approach?
>> Perhaps even a more light-weight one?
>> Any code examples?
>>
>> Thank you.
> 
> The way this works on modern embedded systems is via INTRNG, a
> framework that allows any number of interrupt controllers of differing
> types and capabilities to coexist.  A gpio hardware driver registers
> itself as an interrupt controller, then the interrupts it provides
> (each gpio pin) are accessible as resources just like interrupts on the
> primary controller, and so drivers just use interrupts that originate
> from a gpio pin the same as they would any other interrupt.
> 
> Of course, one required piece of magic to make all this work is
> metadata:  something needs to make the connection between the gpio
> controller and pin, and the driver that wants to use changes on that
> pin as an interrupt indication.  In the embedded world it's FDT data
> that describes those connections, so that when a driver asks for
> interrupt resource index N it reads the FDT data to find a cross-
> reference to which gpio device and pin to use for that.  The
> connections between the gpiopin interrupt source and the resources
> allocated by other drivers are made in nexus.  This is because
> typically there isn't a parent-child relationship between the device
> that manages the gpio pins and the devices that want to use those pins
> as a source of interrupts; nexus is the common ancestor of both.
> 
> The x86 world doesn't use INTRNG (but it must have something similar,
> since all modern x86 hardware has multiple interrupt controllers).  So
> I'm not sure how a gpio driver for x86 might be an interrupt source,
> but there should be a way for that to happen.  The harder part, I
> think, will be coming up with the metadata to allow another driver
> which is not a [grand]child of the gpio controller to use those
> interrupts.

Thank you for the detailed explanation, Ian.
It's a good to understand how things are before talking / ranting about how I
would want them to be :)

Ideally, I would like to see more support from gpio bus for pin events.
I think that it would be nice to have interfaces to enable events on a pin and
types of events to report. To register a callback for a pin event, etc.  Just
like we have interface to configure a pin to be an output or an input. To set or
query its level.  That is, I want to say that gpio controller drivers do not
have to be interrupt controllers (directly).  They must, of course, provide
access to interrupt related hardware configuration.  But I would prefer it to be
on a lower level.  Then, there could be a "gpio pic" that would provide
interrupt controller functionality on top of gpio controller pin event
capabilities.  In theory, a single gpio-pic driver could handle common
functionality of all interrupt capable gpio controllers.
Also, it could be that having an interrupt controller would not always be
necessary and a simple callback function for a pin event would be sufficient and
easier to work with.
But maybe there is not much practical difference between what I want and what we
already have.

It's certainly not impossible to add another interrupt controller type on x86.
But I fear that it may have its rough edges.  E.g., until recently x86 interrupt
controllers had to be aware of each other.  It was not really plug-and-play.
Not sure about the latest state of the matters.
But if we will need some global changes for each interrupt controller and there
will be many x86 gpio controllers with interrupt controller interface, then it
may get cumbersome.
Certainly, gpio as an interrupt controller would be novel on x86.

There is another angle that you mentioned.
Nowadays, x86 single-board computers are not a rare thing.  I can have a perfect
knowledge of what hardware components are present on the board and how they are
connected.  But there is no good way for me to pass that knowledge to the OS if
the firmware does not do it.  And quite often it does not.
As I understand, on x86 we still use ACPI to describe the hardware (and to
interact with it, to some degree).  And, as far as I have been able to find out,
there is no standard ACPI way to describe, e.g., a GPIO controller.  Or LEDs
connected to it.  Even if there is such a way, then many vendors simply won't do
hard ACPI things for a variety of reasons (competence, return on investment,
etc).  They seem to mostly just re-use some reference ACPI code.  It's possible
to customize DSDT, but writing correct ASL is far from trivial.  Comparing to
something like FDT (that does a single job and does it very well), DSDT is much
more complex.  It's both declarative and imperative and it does so many
different things and has so many complex interactions.

So, what do we have without FDT and without full device description in ACPI?
Only hints.  But hints are too simplistic to express proper device relationships.
For example, if I have two GPIO controllers and it's up to a chance which one
would be gpio0 on this boot, then how can I refer to the right controller in the
hints...

In the end I feel that I would need sort of a "meta-driver" for a concrete SBC
platform that would use explicit "add child" calls to build parts of the device
tree that are not described in ACPI.
And that's messy as well.

Done for now :)
-- 
Andriy Gapon



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?0544d3b9-7f6a-5626-3ab3-90c262a3f21d>