summaryrefslogtreecommitdiff
path: root/sys/dev/gpio
diff options
context:
space:
mode:
authorMarc Balmer <mbalmer@cvs.openbsd.org>2008-11-24 12:12:13 +0000
committerMarc Balmer <mbalmer@cvs.openbsd.org>2008-11-24 12:12:13 +0000
commitb4ed2f28ea065bc5bcbe1d53040fb5279aeb61c8 (patch)
treec4160f4c716b126e6f70a6d856147c5952f04367 /sys/dev/gpio
parent4b1d709239a91447e0420f89c7a1bd2ba3916ded (diff)
- Add two new ioctls to gpio(4), GPIOATTACH and GPIODETACH, to allow to attach
and detach devices on a gpiobus at runtime. The offset and mask locators in kernel config files can still be used for static configuration, so this does not break existing custome kernel configs. - Have gpioow(4) unmap the pins it used from the gpiobus during detach Changes to gpioctl(8) will be a separate committ. ok uwe
Diffstat (limited to 'sys/dev/gpio')
-rw-r--r--sys/dev/gpio/files.gpio9
-rw-r--r--sys/dev/gpio/gpio.c51
-rw-r--r--sys/dev/gpio/gpioiic.c6
-rw-r--r--sys/dev/gpio/gpioow.c8
-rw-r--r--sys/dev/gpio/gpiovar.h8
5 files changed, 73 insertions, 9 deletions
diff --git a/sys/dev/gpio/files.gpio b/sys/dev/gpio/files.gpio
index 79fd80d3a03..796dbc02e43 100644
--- a/sys/dev/gpio/files.gpio
+++ b/sys/dev/gpio/files.gpio
@@ -1,11 +1,16 @@
-# $OpenBSD: files.gpio,v 1.6 2006/03/04 16:27:03 grange Exp $
+# $OpenBSD: files.gpio,v 1.7 2008/11/24 12:12:12 mbalmer Exp $
-define gpio {offset, mask}
+define gpio {[offset = -1], [mask = 0]}
device gpio: gpio
attach gpio at gpiobus
file dev/gpio/gpio.c gpio needs-flag
+# GPIO simulator
+device gpiosim: gpiobus
+attach gpiosim at root
+file dev/gpio/gpiosim.c gpiosim needs-flag
+
# I2C bus bit-banging
device gpioiic: i2cbus, i2c_bitbang
attach gpioiic at gpio
diff --git a/sys/dev/gpio/gpio.c b/sys/dev/gpio/gpio.c
index 88326b0a313..9a910140ba6 100644
--- a/sys/dev/gpio/gpio.c
+++ b/sys/dev/gpio/gpio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gpio.c,v 1.7 2006/03/26 18:48:17 grange Exp $ */
+/* $OpenBSD: gpio.c,v 1.8 2008/11/24 12:12:12 mbalmer Exp $ */
/*
* Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
@@ -28,6 +28,8 @@
#include <sys/ioctl.h>
#include <sys/gpio.h>
#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
#include <dev/gpio/gpiovar.h>
@@ -39,9 +41,11 @@ struct gpio_softc {
int sc_npins; /* total number of pins */
int sc_opened;
+ LIST_HEAD(, gpio_dev) sc_list;
};
int gpio_match(struct device *, void *, void *);
+int gpio_submatch(struct device *, void *, void *);
void gpio_attach(struct device *, struct device *, void *);
int gpio_detach(struct device *, int);
int gpio_search(struct device *, void *, void *);
@@ -64,10 +68,16 @@ gpio_match(struct device *parent, void *match, void *aux)
struct cfdata *cf = match;
struct gpiobus_attach_args *gba = aux;
- if (strcmp(gba->gba_name, cf->cf_driver->cd_name) != 0)
- return (0);
+ return (strcmp(gba->gba_name, cf->cf_driver->cd_name) == 0);
+}
+
+int
+gpio_submatch(struct device *parent, void *match, void *aux)
+{
+ struct cfdata *cf = match;
+ struct gpio_attach_args *ga = aux;
- return (1);
+ return (strcmp(ga->ga_dvname, cf->cf_driver->cd_name) == 0);
}
void
@@ -263,6 +273,10 @@ gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
struct gpio_info *info;
struct gpio_pin_op *op;
struct gpio_pin_ctl *ctl;
+ struct gpio_attach *attach;
+ struct gpio_attach_args ga;
+ struct gpio_dev *gdev;
+ struct device *dv;
int pin, value, flags;
sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
@@ -352,6 +366,35 @@ gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
sc->sc_pins[pin].pin_flags = flags;
}
break;
+ case GPIOATTACH:
+ attach = (struct gpio_attach *)data;
+ bzero(&ga, sizeof(ga));
+ ga.ga_gpio = sc;
+ ga.ga_dvname = attach->ga_dvname;
+ ga.ga_offset = attach->ga_offset;
+ ga.ga_mask = attach->ga_mask;
+ dv = config_found_sm((struct device *)sc, &ga, gpiobus_print,
+ gpio_submatch);
+ if (dv != NULL) {
+ gdev = malloc(sizeof(struct gpio_dev), M_DEVBUF,
+ M_WAITOK);
+ gdev->sc_dev = dv;
+ LIST_INSERT_HEAD(&sc->sc_list, gdev, sc_next);
+ }
+ break;
+ case GPIODETACH:
+ attach = (struct gpio_attach *)data;
+ LIST_FOREACH(gdev, &sc->sc_list, sc_next) {
+ if (strcmp(gdev->sc_dev->dv_xname, attach->ga_dvname)
+ == 0) {
+ if (config_detach(gdev->sc_dev, 0) == 0) {
+ LIST_REMOVE(gdev, sc_next);
+ free(gdev, M_DEVBUF);
+ }
+ break;
+ }
+ }
+ break;
default:
return (ENOTTY);
}
diff --git a/sys/dev/gpio/gpioiic.c b/sys/dev/gpio/gpioiic.c
index 559717f8f7c..ea86c322b7d 100644
--- a/sys/dev/gpio/gpioiic.c
+++ b/sys/dev/gpio/gpioiic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gpioiic.c,v 1.7 2007/06/05 08:37:20 jsg Exp $ */
+/* $OpenBSD: gpioiic.c,v 1.8 2008/11/24 12:12:12 mbalmer Exp $ */
/*
* Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
@@ -90,6 +90,10 @@ int
gpioiic_match(struct device *parent, void *match, void *aux)
{
struct cfdata *cf = match;
+ struct gpio_attach_args *ga = aux;
+
+ if (ga->ga_offset == -1)
+ return 0;
return (strcmp(cf->cf_driver->cd_name, "gpioiic") == 0);
}
diff --git a/sys/dev/gpio/gpioow.c b/sys/dev/gpio/gpioow.c
index 23adb2fc6f8..51536de91c5 100644
--- a/sys/dev/gpio/gpioow.c
+++ b/sys/dev/gpio/gpioow.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gpioow.c,v 1.2 2006/06/23 06:27:11 miod Exp $ */
+/* $OpenBSD: gpioow.c,v 1.3 2008/11/24 12:12:12 mbalmer Exp $ */
/*
* Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
@@ -82,6 +82,10 @@ int
gpioow_match(struct device *parent, void *match, void *aux)
{
struct cfdata *cf = match;
+ struct gpio_attach_args *ga = aux;
+
+ if (ga->ga_offset == -1)
+ return 0;
return (strcmp(cf->cf_driver->cd_name, "gpioow") == 0);
}
@@ -157,6 +161,8 @@ gpioow_detach(struct device *self, int flags)
struct gpioow_softc *sc = (struct gpioow_softc *)self;
int rv = 0;
+ gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
+
if (sc->sc_ow_dev != NULL)
rv = config_detach(sc->sc_ow_dev, flags);
diff --git a/sys/dev/gpio/gpiovar.h b/sys/dev/gpio/gpiovar.h
index e8568fe4464..b507370ebe2 100644
--- a/sys/dev/gpio/gpiovar.h
+++ b/sys/dev/gpio/gpiovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $ */
+/* $OpenBSD: gpiovar.h,v 1.4 2008/11/24 12:12:12 mbalmer Exp $ */
/*
* Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
@@ -60,6 +60,7 @@ struct gpio_attach_args {
void * ga_gpio;
int ga_offset;
u_int32_t ga_mask;
+ char *ga_dvname;
};
/* GPIO pin map */
@@ -68,6 +69,11 @@ struct gpio_pinmap {
int pm_size; /* map size */
};
+struct gpio_dev {
+ struct device *sc_dev; /* the gpio device */
+ LIST_ENTRY(gpio_dev) sc_next;
+};
+
int gpio_pin_map(void *, int, u_int32_t, struct gpio_pinmap *);
void gpio_pin_unmap(void *, struct gpio_pinmap *);
int gpio_pin_read(void *, struct gpio_pinmap *, int);