tech-embed archive

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

Re: GPIO subsystem and interrupts -- no way to do rising & falling edge on same pin?




> On May 15, 2018, at 7:17 AM, Jason Thorpe <thorpej%me.com@localhost> wrote:
> 
> I’ve done this — I’m going to be posting some more on this as soon as I’ve tested it (and had Brad Spencer verify that the PPS driver he submitted still works correctly with the new way).

Ok, well, testing is still pending, but I figured I’m stuck on a plane and have some time so might as well post about what the new interface looks like.

The following have been added to gpio_chipset_tag_t:

        void *  (*gp_intr_establish)(void *, int, int, int,
                                     int (*)(void *), void *);
        void    (*gp_intr_disestablish)(void *, void *);
        bool    (*gp_intr_str)(void *, int, int, char *, size_t);

A back-end would initialize them with pointers to functions such as these:

static void *
bcmgpio_gpio_intr_establish(void *vsc, int pin, int ipl, int irqmode,
                            int (*func)(void *), void *arg);

static void
bcmgpio_gpio_intr_disestablish(void *vsc, void *ih);

static bool
bcmgpio_gpio_intrstr(void *vsc, int pin, int irqmode, char *buf, size_t buflen);

The gpio_pin structure no longer has pin_callback or pin_callback_arg fields.  The following fields have been added (filled in by the back-end).

	int			pin_intrcaps;	/* interrupt capabilities */

gpio_pin_ctl_intr() has been removed, as has gpio_intr() and gpio_pin_irqen().  Instead, we have:

void *	gpio_intr_establish(void *, struct gpio_pinmap *, int, int, int,
			    int (*)(void *), void *);
void	gpio_intr_disestablish(void *, void *);
bool	gpio_intr_str(void *, struct gpio_pinmap *, int, int,
		      char *, size_t);

Interrupts will be dispatched by the back-end GPIO controller driver, as they are with FDT-registered interrupts.  This allows the GPIO code to support level-triggered interrupts, among other things.

A new gpio_pin_intrcaps() has been added, which is like gpio_pin_caps(), but it returns the interrupt capabilities instead.

gpio_pin_get_conf() and gpio_pin_set_conf() have been added; gpio_pin_set_conf() is like gpio_pin_ctl(), but it checks the requested mode against the capabilities of the pin.  gpio_pin_get_conf() returns the currently set mode.

There is also a new gpio_pin_irqmode_issupported(), which, in addition to checking against pin capabilities, checks for non-sensical interrupt mode combinations.

The old GPIO pin mode flags GPIO_PIN_EVENTS, GPIO_PIN_LEVEL, and GPIO_PIN_FALLING have been removed and are now available for recycling.

There are new, separate GPIO interrupt flags:

/* GPIO interrupt flags */
#define GPIO_INTR_POS_EDGE      0x00000001      /* interrupt on rising edge */
#define GPIO_INTR_NEG_EDGE      0x00000002      /* interrupt on falling edge */
#define GPIO_INTR_DOUBLE_EDGE   0x00000004      /* interrupt on both edges */
#define GPIO_INTR_HIGH_LEVEL    0x00000008      /* interrupt on high level */
#define GPIO_INTR_LOW_LEVEL     0x00000010      /* interrupt on low level */
#define GPIO_INTR_MPSAFE        0x80000000      /* MP-safe handling */

These are expressive enough to describe the capabilities of modern GPIO controllers, and the modes (EDGE and LEVEL bits) are generally treated as mutually exclusive, although if you request a POS_EDGE and a NEG_EDGE interrupt together, the code will internally map that to DOUBLE_EDGE before checking for that capability on the pin.

This doesn’t change any of the API for userland at all; none of the interrupt bits were useful to userland before, and nothing in the tree used them at all.

Here’s a link to the GPIO infrastructure diffs, with the bcm2835 back-end changes to support both FDT and GPIO interrupt interfaces.

	https://www.dropbox.com/s/zlmi8ang9gje6ld/gpio-diffs-20180515.txt

Tip o’ the hat to Brad Spencer for his initial work on supporting GPIO interrupts on Raspberry Pi.  Once the infrastructure changes are in, I intend to integrate his “gpioiorq” sample driver, “gpiopps” NTP PPS driver, and “gpiorng” radioactive-decay random number generator driver (all modified to work with the new GPIO interrupt infrastructure).

At some future juncture, it would be awfully nice if the FDT and the GPIO interrupt interfaces were fully harmonized.  But for now, this is a big improvement and will support stuff like Brad’s nifty hardware hacks (you guys should really read his web pages - good stuff!) as well as my silly little clock project.

Feedback appreciated.

Thx.

-- thorpej
   (Gosh, it’s fun to be properly hacking on NetBSD again…)




Home | Main Index | Thread Index | Old Index