Current-Users archive

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

Adding an interrupt locator to the GPIO, I2C and SPI buses



                        Hi current-users@,

in the process of writing more drivers for the Nokia N900 (OMAP3) I
realize that quite a few devices and sensors interrupt on GPIO pins. I
finally understood recently that the GPIO pins are actually usable
directly as interrupt identifiers, as referenced in their respective
"intrbase" locators. An example to illustrate this:

omapgpio0 at obio1 addr 0x48310000 size 0x0400 intrbase 96 intr 29

Here, a bunch of pins belonging to [what really is] gpio0 interrupt
internally as 29, but in turn each pin is individually usable as an
interrupt identifier as 96 + the pin offset:
- pin 1 is mapped as interrupt 96
- pin 2 is at 97
- ...and so on for as many pins as found on gpio0 (here 32)

For the devices or sensors found on either of the GPIO, I2C or SPI buses
and interrupting on a GPIO pin, I think it would totally make sense to
be able to specify the proper pin directly within the kernel
configuration file. In my particular case, the configuration file would
then look like this:

n900cambtn0 at gpio2 offset 4 mask 0x3 intr 164 #165 too actually
n900acad0 at gpio0 offset 7 mask 0x1 intr 103
n900kbdslide0 at gpio2 offset 7 mask 0x1 intr 167
n900lckbtn0 at gpio3 offset 17 mask 0x1 intr 209
stmemsis0 at iic2 addr 0x1d intr 277
tsc2005ts0 at spi0 slave 0 intr 196
wilink0 at spi3 slave 0 intr 138

This makes sense on the GPIO bus too, because a given device may use
multiple pins (eg as input/output) while having a separate one for
interrupts.

I am attaching a patch that implements this extra locator for the GPIO,
I2C and SPI buses. I have tested it successfully on GPIO and I2C; I
would like to have positive feedback before I commit it.

The second patch illustrates how it lets me get rid of the locators I
had to hard-code for the first two N900 drivers that I have committed so
far.

HTH,
-- 
khorben
Index: sys/dev/gpio/files.gpio
===================================================================
RCS file: /cvsroot/src/sys/dev/gpio/files.gpio,v
retrieving revision 1.10
diff -p -u -r1.10 files.gpio
--- sys/dev/gpio/files.gpio     13 Nov 2011 12:33:00 -0000      1.10
+++ sys/dev/gpio/files.gpio     17 Apr 2013 23:41:59 -0000
@@ -1,6 +1,6 @@
 # $NetBSD: files.gpio,v 1.10 2011/11/13 12:33:00 mbalmer Exp $
 
-define gpio {[offset = -1], [mask = 0], [flag = 0]}
+define gpio {[offset = -1], [mask = 0], [flag = 0], [intr = -1]}
 
 device gpio: gpio
 attach gpio at gpiobus
Index: sys/dev/gpio/gpio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/gpio/gpio.c,v
retrieving revision 1.51
diff -p -u -r1.51 gpio.c
--- sys/dev/gpio/gpio.c 17 Oct 2012 21:35:39 -0000      1.51
+++ sys/dev/gpio/gpio.c 17 Apr 2013 23:41:59 -0000
@@ -249,6 +249,7 @@ gpio_search(device_t parent, cfdata_t cf
        ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET];
        ga.ga_mask = cf->cf_loc[GPIOCF_MASK];
        ga.ga_flags = cf->cf_loc[GPIOCF_FLAG];
+       ga.ga_intr = cf->cf_loc[GPIOCF_INTR];
        namlen = strlen(cf->cf_name) + 1;
        ga.ga_dvname = kmem_alloc(namlen, KM_NOSLEEP);
        if (ga.ga_dvname == NULL)
Index: sys/dev/gpio/gpiovar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/gpio/gpiovar.h,v
retrieving revision 1.15
diff -p -u -r1.15 gpiovar.h
--- sys/dev/gpio/gpiovar.h      13 Nov 2011 13:20:02 -0000      1.15
+++ sys/dev/gpio/gpiovar.h      17 Apr 2013 23:41:59 -0000
@@ -71,6 +71,7 @@ struct gpio_attach_args {
        uint32_t         ga_mask;
        char            *ga_dvname;
        uint32_t         ga_flags;
+       int              ga_intr;
 };
 
 /* GPIO pin map */
Index: sys/dev/i2c/files.i2c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/files.i2c,v
retrieving revision 1.47
diff -p -u -r1.47 files.i2c
--- sys/dev/i2c/files.i2c       31 Dec 2012 19:47:27 -0000      1.47
+++ sys/dev/i2c/files.i2c       17 Apr 2013 23:41:59 -0000
@@ -4,7 +4,7 @@ obsolete defflag        opt_i2cbus.h            I2C_SCAN
 define i2cbus { }
 define i2cexec
 
-device iic { [addr = -1], [size = -1] }
+device iic { [addr = -1], [size = -1], [intr = -1] }
 attach iic at i2cbus
 file   dev/i2c/i2c.c                           iic
 file   dev/i2c/i2c_exec.c                      iic | i2cbus | i2cexec
Index: sys/dev/i2c/i2c.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/i2c.c,v
retrieving revision 1.39
diff -p -u -r1.39 i2c.c
--- sys/dev/i2c/i2c.c   3 Feb 2013 16:28:51 -0000       1.39
+++ sys/dev/i2c/i2c.c   17 Apr 2013 23:41:59 -0000
@@ -112,6 +112,7 @@ iic_search(device_t parent, cfdata_t cf,
        ia.ia_tag = sc->sc_tag;
        ia.ia_addr = cf->cf_loc[IICCF_ADDR];
        ia.ia_size = cf->cf_loc[IICCF_SIZE];
+       ia.ia_intr = cf->cf_loc[IICCF_INTR];
        ia.ia_type = sc->sc_type;
 
        ia.ia_name = NULL;
@@ -192,6 +193,7 @@ iic_attach(device_t parent, device_t sel
                prop_dictionary_t dev;
                prop_data_t cdata;
                uint32_t addr, size;
+               int intr;
                uint64_t cookie;
                const char *name;
                struct i2c_attach_args ia;
@@ -214,6 +216,8 @@ iic_attach(device_t parent, device_t sel
                                loc[1] = size;
                        else
                                loc[1] = -1;
+                       if (!prop_dictionary_get_uint32(dev, "intr", &intr))
+                               intr = -1;
 
                        memset(&ia, 0, sizeof ia);
                        ia.ia_addr = addr;
@@ -222,6 +226,7 @@ iic_attach(device_t parent, device_t sel
                        ia.ia_name = name;
                        ia.ia_cookie = cookie;
                        ia.ia_size = size;
+                       ia.ia_intr = intr;
 
                        buf = NULL;
                        cdata = prop_dictionary_get(dev, "compatible");
Index: sys/dev/i2c/i2cvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/i2cvar.h,v
retrieving revision 1.8
diff -p -u -r1.8 i2cvar.h
--- sys/dev/i2c/i2cvar.h        28 Feb 2010 15:33:21 -0000      1.8
+++ sys/dev/i2c/i2cvar.h        17 Apr 2013 23:41:59 -0000
@@ -117,6 +117,7 @@ struct i2c_attach_args {
        i2c_tag_t       ia_tag;         /* our controller */
        i2c_addr_t      ia_addr;        /* address of device */
        int             ia_size;        /* size (for EEPROMs) */
+       int             ia_intr;        /* interrupt */
        int             ia_type;        /* bus type */
        /* only set if using direct config */
        const char *    ia_name;        /* name of the device */
Index: sys/dev/spi/files.spi
===================================================================
RCS file: /cvsroot/src/sys/dev/spi/files.spi,v
retrieving revision 1.2
diff -p -u -r1.2 files.spi
--- sys/dev/spi/files.spi       7 Oct 2006 07:21:13 -0000       1.2
+++ sys/dev/spi/files.spi       17 Apr 2013 23:41:59 -0000
@@ -2,7 +2,7 @@
 
 define spibus { }
 
-device spi { slave }
+device spi { slave, [intr = -1] }
 attach spi at spibus
 file   dev/spi/spi.c                   spi | spibus
 
Index: sys/dev/spi/spi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/spi/spi.c,v
retrieving revision 1.8
diff -p -u -r1.8 spi.c
--- sys/dev/spi/spi.c   15 Feb 2013 17:44:40 -0000      1.8
+++ sys/dev/spi/spi.c   17 Apr 2013 23:41:59 -0000
@@ -119,6 +119,7 @@ spi_search(device_t parent, cfdata_t cf,
        }
 
        sa.sa_handle = &sc->sc_slaves[addr];
+       sa.sa_intr = cf->cf_loc[SPICF_INTR];
 
        if (config_match(parent, cf, &sa) > 0)
                config_attach(parent, cf, &sa, spi_print);
Index: sys/dev/spi/spivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/spi/spivar.h,v
retrieving revision 1.4
diff -p -u -r1.4 spivar.h
--- sys/dev/spi/spivar.h        8 Jun 2011 23:05:48 -0000       1.4
+++ sys/dev/spi/spivar.h        17 Apr 2013 23:41:59 -0000
@@ -82,6 +82,7 @@ struct spibus_attach_args {
 
 struct spi_attach_args {
        struct spi_handle       *sa_handle;
+       int                     sa_intr;
 };
 
 /*
Index: sys/arch/evbarm/n900/n900_acad.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/n900/n900_acad.c,v
retrieving revision 1.3
diff -p -u -r1.3 n900_acad.c
--- sys/arch/evbarm/n900/n900_acad.c    17 Apr 2013 01:10:28 -0000      1.3
+++ sys/arch/evbarm/n900/n900_acad.c    17 Apr 2013 23:43:10 -0000
@@ -45,11 +45,6 @@ __KERNEL_RCSID(0, "$NetBSD: n900_acad.c,
 #include <arm/omap/omap2_gpio.h>
 
 
-/* The base interrupt for the corresponding GPIO device where this driver
- * attaches. This is an ugly workaround the current limitations of gpio(4),
- * which does not seem to allow a better way to locate the interrupt yet. */
-#define N900ACAD_GPIO_BASE     96
-
 #define N900ACAD_PIN_INPUT     0
 #define N900ACAD_NPINS 1
 
@@ -127,8 +122,8 @@ n900acad_attach(device_t parent, device_
        gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, N900ACAD_PIN_INPUT,
                        GPIO_PIN_INPUT);
 
-       sc->sc_intr = intr_establish(N900ACAD_GPIO_BASE + ga->ga_offset,
-                       IST_EDGE_BOTH, IPL_VM, n900acad_intr, sc);
+       sc->sc_intr = intr_establish(ga->ga_intr, IST_EDGE_BOTH, IPL_VM,
+                       n900acad_intr, sc);
        if (sc->sc_intr == NULL) {
                aprint_error(": could not establish interrupt\n");
                gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
Index: sys/arch/evbarm/n900/n900_lckbtn.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/n900/n900_lckbtn.c,v
retrieving revision 1.1
diff -p -u -r1.1 n900_lckbtn.c
--- sys/arch/evbarm/n900/n900_lckbtn.c  17 Apr 2013 01:06:14 -0000      1.1
+++ sys/arch/evbarm/n900/n900_lckbtn.c  17 Apr 2013 23:43:10 -0000
@@ -45,11 +45,6 @@ __KERNEL_RCSID(0, "$NetBSD: n900_lckbtn.
 #include <arm/omap/omap2_gpio.h>
 
 
-/* The base interrupt for the corresponding GPIO device where this driver
- * attaches. This is an ugly workaround the current limitations of gpio(4),
- * which does not seem to allow a better way to locate the interrupt yet. */
-#define N900LCKBTN_GPIO_BASE   192
-
 #define N900LCKBTN_PIN_INPUT   0
 #define N900LCKBTN_NPINS       1
 
@@ -128,8 +123,8 @@ n900lckbtn_attach(device_t parent, devic
        gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, N900LCKBTN_PIN_INPUT,
                        GPIO_PIN_INPUT);
 
-       sc->sc_intr = intr_establish(N900LCKBTN_GPIO_BASE + ga->ga_offset,
-                       IST_EDGE_BOTH, IPL_VM, n900lckbtn_intr, sc);
+       sc->sc_intr = intr_establish(ga->ga_intr, IST_EDGE_BOTH, IPL_VM,
+                       n900lckbtn_intr, sc);
        if (sc->sc_intr == NULL) {
                aprint_error(": could not establish interrupt\n");
                gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);


Home | Main Index | Thread Index | Old Index