Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153231467
D999.id2094.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D999.id2094.diff
View Options
Index: sys/dev/gpio/gpiobus.c
===================================================================
--- sys/dev/gpio/gpiobus.c
+++ sys/dev/gpio/gpiobus.c
@@ -38,6 +38,13 @@
#include "gpiobus_if.h"
+#define GPIOBUS_DEBUG
+#ifdef GPIOBUS_DEBUG
+#define dprintf printf
+#else
+#define dprintf(x, arg...)
+#endif
+
static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int);
static int gpiobus_probe(device_t);
static int gpiobus_attach(device_t);
@@ -99,6 +106,39 @@
printf("%d", range_start);
}
+int
+gpiobus_init_softc(device_t dev)
+{
+ struct gpiobus_softc *sc;
+
+ sc = GPIOBUS_SOFTC(dev);
+ sc->sc_busdev = dev;
+ sc->sc_dev = device_get_parent(dev);
+ sc->sc_intr_rman.rm_type = RMAN_ARRAY;
+ sc->sc_intr_rman.rm_descr = "GPIO Interrupts";
+ if (rman_init(&sc->sc_intr_rman) != 0 ||
+ rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0)
+ panic("%s: failed to set up rman.", __func__);
+
+ if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
+ return (ENXIO);
+
+ KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
+
+ /* Pins = GPIO_PIN_MAX() + 1 */
+ sc->sc_npins++;
+
+ sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (sc->sc_pins_mapped == NULL)
+ return (ENOMEM);
+
+ /* Initialize the bus lock. */
+ GPIOBUS_LOCK_INIT(sc);
+
+ return (0);
+}
+
static int
gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
{
@@ -163,30 +203,11 @@
static int
gpiobus_attach(device_t dev)
{
- struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
- int res;
-
- sc->sc_busdev = dev;
- sc->sc_dev = device_get_parent(dev);
- res = GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins);
- if (res)
- return (ENXIO);
-
- KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
-
- /*
- * Increase to get number of pins
- */
- sc->sc_npins++;
-
- sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF,
- M_NOWAIT | M_ZERO);
-
- if (!sc->sc_pins_mapped)
- return (ENOMEM);
+ int err;
- /* init bus lock */
- GPIOBUS_LOCK_INIT(sc);
+ err = gpiobus_init_softc(dev);
+ if (err != 0)
+ return (err);
/*
* Get parent's pins and mark them as unmapped
@@ -260,6 +281,7 @@
retval += bus_print_child_header(dev, child);
retval += printf(" at pin(s) ");
gpiobus_print_pins(devi);
+ resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
retval += bus_print_child_footer(dev, child);
return (retval);
@@ -297,7 +319,9 @@
device_delete_child(dev, child);
return (0);
}
+ resource_list_init(&devi->rl);
device_set_ivars(child, devi);
+
return (child);
}
@@ -307,14 +331,111 @@
struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
struct gpiobus_ivar *devi;
device_t child;
- int pins;
-
+ int irq, pins;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
devi = GPIOBUS_IVAR(child);
resource_int_value(dname, dunit, "pins", &pins);
if (gpiobus_parse_pins(sc, child, pins))
device_delete_child(bus, child);
+ if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
+ if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
+ device_printf(bus,
+ "warning: bus_set_resource() failed\n");
+ }
+}
+
+static int
+gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
+ u_long start, u_long count)
+{
+ struct gpiobus_ivar *devi;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+
+ devi = GPIOBUS_IVAR(child);
+ rl = &devi->rl;
+
+ dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n",
+ __func__, dev, child, type, rid, (void *)(intptr_t)start, count);
+
+ rle = resource_list_add(rl, type, rid, start, start + count - 1,
+ count);
+ if (rle == NULL)
+ return (ENXIO);
+
+ return (0);
+}
+
+static struct resource *
+gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct gpiobus_softc *sc;
+ struct resource *rv;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+ int isdefault;
+
+ if (type != SYS_RES_IRQ)
+ return (NULL);
+
+ isdefault = (start == 0UL && end == ~0UL && count == 1);
+ rle = NULL;
+
+ if (isdefault) {
+ rl = BUS_GET_RESOURCE_LIST(bus, child);
+ if (rl == NULL)
+ return (NULL);
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+ if (rle->res != NULL)
+ panic("%s: resource entry is busy", __func__);
+ start = rle->start;
+ count = rle->count;
+ end = rle->end;
+ }
+
+ sc = device_get_softc(bus);
+ rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags,
+ child);
+ if (rv == NULL)
+ return (NULL);
+ rman_set_rid(rv, *rid);
+
+ if ((flags & RF_ACTIVE) != 0 &&
+ bus_activate_resource(child, type, *rid, rv) != 0) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+
+ return (rv);
+}
+
+static int
+gpiobus_release_resource(device_t bus __unused, device_t child, int type,
+ int rid, struct resource *r)
+{
+ int error;
+
+ if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
+ error = bus_deactivate_resource(child, type, rid, r);
+ if (error)
+ return (error);
+ }
+
+ return (rman_release_resource(r));
+}
+
+static struct resource_list *
+gpiobus_get_resource_list(device_t bus __unused, device_t child)
+{
+ struct gpiobus_ivar *ivar;
+
+ ivar = GPIOBUS_IVAR(child);
+
+ return (&ivar->rl);
}
static void
@@ -453,6 +574,15 @@
DEVMETHOD(device_resume, gpiobus_resume),
/* Bus interface */
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_config_intr, bus_generic_config_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_set_resource, gpiobus_set_resource),
+ DEVMETHOD(bus_alloc_resource, gpiobus_alloc_resource),
+ DEVMETHOD(bus_release_resource, gpiobus_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list),
DEVMETHOD(bus_add_child, gpiobus_add_child),
DEVMETHOD(bus_print_child, gpiobus_print_child),
DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str),
Index: sys/dev/gpio/gpiobusvar.h
===================================================================
--- sys/dev/gpio/gpiobusvar.h
+++ sys/dev/gpio/gpiobusvar.h
@@ -34,6 +34,7 @@
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/rman.h>
#ifdef FDT
#include <dev/ofw/ofw_bus_subr.h>
@@ -41,7 +42,12 @@
#include "gpio_if.h"
+#ifdef FDT
+#define GPIOBUS_IVAR(d) (struct gpiobus_ivar *) \
+ &((struct ofw_gpiobus_devinfo *)device_get_ivars(d))->opd_dinfo
+#else
#define GPIOBUS_IVAR(d) (struct gpiobus_ivar *) device_get_ivars(d)
+#endif
#define GPIOBUS_SOFTC(d) (struct gpiobus_softc *) device_get_softc(d)
#define GPIOBUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define GPIOBUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
@@ -54,6 +60,7 @@
struct gpiobus_softc
{
struct mtx sc_mtx; /* bus mutex */
+ struct rman sc_intr_rman; /* isr resources */
device_t sc_busdev; /* bus device */
device_t sc_owner; /* bus owner */
device_t sc_dev; /* driver device */
@@ -63,6 +70,7 @@
struct gpiobus_ivar
{
+ struct resource_list rl; /* isr resource list */
uint32_t npins; /* pins total */
uint32_t *flags; /* pins flags */
uint32_t *pins; /* pins map */
@@ -84,6 +92,7 @@
device_t ofw_gpiobus_add_fdt_child(device_t, phandle_t);
#endif
void gpiobus_print_pins(struct gpiobus_ivar *);
+int gpiobus_init_softc(device_t);
extern driver_t gpiobus_driver;
Index: sys/dev/gpio/ofw_gpiobus.c
===================================================================
--- sys/dev/gpio/ofw_gpiobus.c
+++ sys/dev/gpio/ofw_gpiobus.c
@@ -239,6 +239,14 @@
return (NULL);
}
+ /* And now the interrupt resources. */
+ resource_list_init(&dinfo->opd_dinfo.rl);
+ if (ofw_bus_intr_to_rl(dev, node, &dinfo->opd_dinfo.rl) != 0) {
+ ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
+ free(dinfo, M_DEVBUF);
+ return (NULL);
+ }
+
return (dinfo);
}
@@ -246,6 +254,7 @@
ofw_gpiobus_destroy_devinfo(struct ofw_gpiobus_devinfo *dinfo)
{
+ resource_list_free(&dinfo->opd_dinfo.rl);
ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo);
free(dinfo, M_DEVBUF);
}
@@ -264,33 +273,13 @@
static int
ofw_gpiobus_attach(device_t dev)
{
- struct gpiobus_softc *sc;
+ int err;
phandle_t child;
- sc = GPIOBUS_SOFTC(dev);
- sc->sc_busdev = dev;
- sc->sc_dev = device_get_parent(dev);
-
- /* Read the pin max. value */
- if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
- return (ENXIO);
-
- KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
-
- /*
- * Increase to get number of pins.
- */
- sc->sc_npins++;
-
- sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF,
- M_NOWAIT | M_ZERO);
-
- if (!sc->sc_pins_mapped)
- return (ENOMEM);
-
- /* Init the bus lock. */
- GPIOBUS_LOCK_INIT(sc);
-
+ err = gpiobus_init_softc(dev);
+ if (err != 0)
+ return (err);
+
bus_generic_probe(dev);
bus_enumerate_hinted_children(dev);
@@ -346,6 +335,8 @@
retval += bus_print_child_header(dev, child);
retval += printf(" at pin(s) ");
gpiobus_print_pins(&devi->opd_dinfo);
+ resource_list_print_type(&devi->opd_dinfo.rl, "irq", SYS_RES_IRQ,
+ "%ld");
retval += bus_print_child_footer(dev, child);
return (retval);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 20, 11:14 PM (17 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31870783
Default Alt Text
D999.id2094.diff (9 KB)
Attached To
Mode
D999: Add basic support to GPIO interrupts on gpiobus and ofw_gpiobus
Attached
Detach File
Event Timeline
Log In to Comment