tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: gpio interrupts



bouyer%antioche.eu.org@localhost (Manuel Bouyer) writes:

>The attached patch adds two functions to gpio.c:
>gpio_pin_wait() is called by a thread that wants to wait on an interrupt.
>A thread can wait only on a single pin.

>gpio_intr() is called from backends when an interrupt-enabled gpio is
>triggered. Multiple pins events can be signaled in a single call.


My current (non-functional) code would provide a method
to register an event handler with the backend for interrupts
that occur on a specified set of pins.

E.g. in gpiobutton, registering an interrupt callback with the backend.

        sc->sc_use_events = false;
        if ((caps & GPIO_PIN_EVENTS) != 0) {
                sc->sc_data.gc_cookie = sc;
                sc->sc_data.gc_offset = ga->ga_offset;
                sc->sc_data.gc_mask = ga->ga_mask;
                error = gpio_event_register(sc->sc_gpio, &sc->sc_map,
                                            &sc->sc_data,
                                            gpiobutton_eventhandler);
                if (error == 0)
                        sc->sc_use_events = true;
        }

static void
gpiobutton_eventhandler(gpio_callback_data_t *data)
{
        struct gpiobutton_softc * const sc = data->gc_cookie;

        gpiobutton_poll(sc);
}

gpio_event_register() calls the new backend function:

#define gpiobus_pin_event(gc, cbdata, cbfunc) \
    ((gc)->gp_pin_event((gc)->gp_cookie, (cbdata), (cbfunc)))


If you want to wait for a pin you can simply use a condition variable
and make the eventhandler trigger it.


>The backend provides an additionnal callback: gp_pin_irqen(), called by
>gpio(4) to mask/unmask an interrupt on a specific pin.
>the backend masks pending interrupts before calling gpio_intr(),
>and gpio_pin_wait() has to explicitely unmask the interrupt before waiting.

The gp_pin_ctl() callback is used to set characteristics of a pin.
My idea was to also configure interrupts with it:

The flags GPIO_PIN_LEVEL and GPIO_PIN_FALLING were supposed to configure
the interrupt type (edge/level) and polarity (falling/rising,low/high).

When you set GPIO_PIN_EVENTS you enable the interrupt. This correlates
to the same flag in caps where it says that the pin does support interrupts.


>I don't need to have userland wait on interrupts; this could be added but
>I don't know yet what the best way to do it would be (an ioctl or a
>kevent?).

I don't know either. For userland you need a file descriptor that you
can simply read() from. Waiting means to read from a blocking descriptor
or to use poll()/select()/kevent(), but the open /dev/gpioX file is not
sufficient.

One idea was to create an ioctl() that returns a freshly created
file descriptor to be used to read events from a pin. This could
also be used as an I/O channel for other GPIO drivers. But it
still feels like a hack.

Reading events, instead of just waiting for interrupt, also solves
another problem. The event can be precisely timestamped in the
kernel.

-- 
-- 
                                Michael van Elst
Internet: mlelstv%serpens.de@localhost
                                "A potential Snark may lurk in every tree."


Home | Main Index | Thread Index | Old Index