Import general purpose I/O framework from OpenBSD.
This commit is contained in:
parent
70c1989a17
commit
bec79ef231
|
@ -0,0 +1,7 @@
|
|||
# $NetBSD: files.gpio,v 1.1 2005/09/27 02:34:02 jmcneill Exp $
|
||||
|
||||
define gpio {pin, mask}
|
||||
|
||||
device gpio: gpio
|
||||
attach gpio at gpiobus
|
||||
file dev/gpio/gpio.c gpio needs-flag
|
|
@ -0,0 +1,284 @@
|
|||
/* $NetBSD: gpio.c,v 1.1 2005/09/27 02:34:02 jmcneill Exp $ */
|
||||
/* $OpenBSD: gpio.c,v 1.4 2004/11/23 21:18:37 grange Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* General Purpose Input/Output framework.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/gpio.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <dev/gpio/gpiovar.h>
|
||||
|
||||
struct gpio_softc {
|
||||
struct device sc_dev;
|
||||
|
||||
gpio_chipset_tag_t sc_gc; /* our GPIO controller */
|
||||
gpio_pin_t *sc_pins; /* pins array */
|
||||
int sc_npins; /* total number of pins */
|
||||
|
||||
int sc_opened;
|
||||
int sc_dying;
|
||||
};
|
||||
|
||||
int gpio_match(struct device *, struct cfdata *, void *);
|
||||
void gpio_attach(struct device *, struct device *, void *);
|
||||
int gpio_detach(struct device *, int);
|
||||
int gpio_activate(struct device *, enum devact);
|
||||
int gpio_search(struct device *, struct cfdata *, const int *, void *);
|
||||
int gpio_print(void *, const char *);
|
||||
|
||||
CFATTACH_DECL(gpio, sizeof(struct gpio_softc),
|
||||
gpio_match, gpio_attach, gpio_detach, gpio_activate);
|
||||
|
||||
dev_type_open(gpioopen);
|
||||
dev_type_close(gpioclose);
|
||||
dev_type_ioctl(gpioioctl);
|
||||
|
||||
const struct cdevsw gpio_cdevsw = {
|
||||
gpioopen, gpioclose, noread, nowrite, gpioioctl,
|
||||
nostop, notty, nopoll, nommap, nokqfilter,
|
||||
};
|
||||
|
||||
extern struct cfdriver gpio_cd;
|
||||
|
||||
int
|
||||
gpio_match(struct device *parent, struct cfdata *cf, void *aux)
|
||||
{
|
||||
struct gpiobus_attach_args *gba = aux;
|
||||
|
||||
if (strcmp(gba->gba_name, cf->cf_name) != 0)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
gpio_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct gpio_softc *sc = (struct gpio_softc *)self;
|
||||
struct gpiobus_attach_args *gba = aux;
|
||||
|
||||
sc->sc_gc = gba->gba_gc;
|
||||
sc->sc_pins = gba->gba_pins;
|
||||
sc->sc_npins = gba->gba_npins;
|
||||
|
||||
printf(": %d pins\n", sc->sc_npins);
|
||||
|
||||
/*
|
||||
* Attach all devices that can be connected to the GPIO pins
|
||||
* described in the kernel configuration file.
|
||||
*/
|
||||
config_search_ia(gpio_search, self, "gpio", NULL);
|
||||
}
|
||||
|
||||
int
|
||||
gpio_detach(struct device *self, int flags)
|
||||
{
|
||||
#if 0
|
||||
int maj, mn;
|
||||
|
||||
/* Locate the major number */
|
||||
for (maj = 0; maj < nchrdev; maj++)
|
||||
if (cdevsw[maj].d_open == gpioopen)
|
||||
break;
|
||||
|
||||
/* Nuke the vnodes for any open instances (calls close) */
|
||||
mn = self->dv_unit;
|
||||
vdevgone(maj, mn, mn, VCHR);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
gpio_activate(struct device *self, enum devact act)
|
||||
{
|
||||
struct gpio_softc *sc = (struct gpio_softc *)self;
|
||||
|
||||
switch (act) {
|
||||
case DVACT_ACTIVATE:
|
||||
return (EOPNOTSUPP);
|
||||
case DVACT_DEACTIVATE:
|
||||
sc->sc_dying = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
gpio_search(struct device *parent, struct cfdata *cf,
|
||||
const int *ldesc, void *aux)
|
||||
{
|
||||
struct gpio_attach_args ga;
|
||||
|
||||
ga.ga_pin = cf->cf_loc[0];
|
||||
ga.ga_mask = cf->cf_loc[1];
|
||||
|
||||
if (config_match(parent, cf, &ga) > 0)
|
||||
config_attach(parent, cf, &ga, gpio_print);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
gpio_print(void *aux, const char *pnp)
|
||||
{
|
||||
struct gpio_attach_args *ga = aux;
|
||||
int i;
|
||||
|
||||
printf(" pins");
|
||||
for (i = 0; i < 32; i++)
|
||||
if (ga->ga_mask & (1 << i))
|
||||
printf(" %d", ga->ga_pin + i);
|
||||
|
||||
return (UNCONF);
|
||||
}
|
||||
|
||||
int
|
||||
gpiobus_print(void *aux, const char *pnp)
|
||||
{
|
||||
struct gpiobus_attach_args *gba = aux;
|
||||
|
||||
if (pnp != NULL)
|
||||
printf("%s at %s", gba->gba_name, pnp);
|
||||
|
||||
return (UNCONF);
|
||||
}
|
||||
|
||||
int
|
||||
gpioopen(dev_t dev, int flag, int mode, struct proc *p)
|
||||
{
|
||||
struct gpio_softc *sc;
|
||||
|
||||
sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (sc->sc_opened)
|
||||
return (EBUSY);
|
||||
sc->sc_opened = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
gpioclose(dev_t dev, int flag, int mode, struct proc *p)
|
||||
{
|
||||
struct gpio_softc *sc;
|
||||
|
||||
sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
|
||||
sc->sc_opened = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
|
||||
{
|
||||
struct gpio_softc *sc;
|
||||
gpio_chipset_tag_t gc;
|
||||
struct gpio_info *info;
|
||||
struct gpio_pin_op *op;
|
||||
struct gpio_pin_ctl *ctl;
|
||||
int pin, value, flags;
|
||||
|
||||
sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
|
||||
gc = sc->sc_gc;
|
||||
|
||||
switch (cmd) {
|
||||
case GPIOINFO:
|
||||
info = (struct gpio_info *)data;
|
||||
|
||||
info->gpio_npins = sc->sc_npins;
|
||||
break;
|
||||
case GPIOPINREAD:
|
||||
op = (struct gpio_pin_op *)data;
|
||||
|
||||
pin = op->gp_pin;
|
||||
if (pin < 0 || pin >= sc->sc_npins)
|
||||
return (EINVAL);
|
||||
|
||||
/* return read value */
|
||||
op->gp_value = gpiobus_pin_read(gc, pin);
|
||||
break;
|
||||
case GPIOPINWRITE:
|
||||
op = (struct gpio_pin_op *)data;
|
||||
|
||||
pin = op->gp_pin;
|
||||
if (pin < 0 || pin >= sc->sc_npins)
|
||||
return (EINVAL);
|
||||
|
||||
value = op->gp_value;
|
||||
if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
|
||||
return (EINVAL);
|
||||
|
||||
gpiobus_pin_write(gc, pin, value);
|
||||
/* return old value */
|
||||
op->gp_value = sc->sc_pins[pin].pin_state;
|
||||
/* update current value */
|
||||
sc->sc_pins[pin].pin_state = value;
|
||||
break;
|
||||
case GPIOPINTOGGLE:
|
||||
op = (struct gpio_pin_op *)data;
|
||||
|
||||
pin = op->gp_pin;
|
||||
if (pin < 0 || pin >= sc->sc_npins)
|
||||
return (EINVAL);
|
||||
|
||||
value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
|
||||
GPIO_PIN_HIGH : GPIO_PIN_LOW);
|
||||
gpiobus_pin_write(gc, pin, value);
|
||||
/* return old value */
|
||||
op->gp_value = sc->sc_pins[pin].pin_state;
|
||||
/* update current value */
|
||||
sc->sc_pins[pin].pin_state = value;
|
||||
break;
|
||||
case GPIOPINCTL:
|
||||
ctl = (struct gpio_pin_ctl *)data;
|
||||
|
||||
pin = ctl->gp_pin;
|
||||
if (pin < 0 || pin >= sc->sc_npins)
|
||||
return (EINVAL);
|
||||
|
||||
flags = ctl->gp_flags;
|
||||
/* check that the controller supports all requested flags */
|
||||
if ((flags & sc->sc_pins[pin].pin_caps) != flags)
|
||||
return (ENODEV);
|
||||
|
||||
ctl->gp_caps = sc->sc_pins[pin].pin_caps;
|
||||
/* return old value */
|
||||
ctl->gp_flags = sc->sc_pins[pin].pin_flags;
|
||||
if (flags > 0) {
|
||||
gpiobus_pin_ctl(gc, pin, flags);
|
||||
/* update current value */
|
||||
sc->sc_pins[pin].pin_flags = flags;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/* $NetBSD: gpiovar.h,v 1.1 2005/09/27 02:34:02 jmcneill Exp $ */
|
||||
/* $OpenBSD: gpiovar.h,v 1.1 2004/06/03 18:08:00 grange Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_GPIO_GPIOVAR_H_
|
||||
#define _DEV_GPIO_GPIOVAR_H_
|
||||
|
||||
/* GPIO controller description */
|
||||
typedef struct gpio_chipset_tag {
|
||||
void *gp_cookie;
|
||||
|
||||
int (*gp_pin_read)(void *, int);
|
||||
void (*gp_pin_write)(void *, int, int);
|
||||
void (*gp_pin_ctl)(void *, int, int);
|
||||
} *gpio_chipset_tag_t;
|
||||
|
||||
/* GPIO pin description */
|
||||
typedef struct gpio_pin {
|
||||
int pin_num; /* number */
|
||||
int pin_caps; /* capabilities */
|
||||
int pin_flags; /* current configuration */
|
||||
int pin_state; /* current state */
|
||||
} gpio_pin_t;
|
||||
|
||||
/* Attach GPIO framework to the controller */
|
||||
struct gpiobus_attach_args {
|
||||
const char *gba_name; /* bus name */
|
||||
gpio_chipset_tag_t gba_gc; /* underlying controller */
|
||||
gpio_pin_t *gba_pins; /* pins array */
|
||||
int gba_npins; /* total number of pins */
|
||||
};
|
||||
|
||||
int gpiobus_print(void *, const char *);
|
||||
|
||||
/* GPIO framework private methods */
|
||||
#define gpiobus_pin_read(gc, pin) \
|
||||
((gc)->gp_pin_read((gc)->gp_cookie, (pin)))
|
||||
#define gpiobus_pin_write(gc, pin, value) \
|
||||
((gc)->gp_pin_write((gc)->gp_cookie, (pin), (value)))
|
||||
#define gpiobus_pin_ctl(gc, pin, flags) \
|
||||
((gc)->gp_pin_ctl((gc)->gp_cookie, (pin), (flags)))
|
||||
|
||||
|
||||
/* Attach devices connected to the GPIO pins */
|
||||
struct gpio_attach_args {
|
||||
int ga_pin;
|
||||
u_int32_t ga_mask;
|
||||
};
|
||||
|
||||
#endif /* !_DEV_GPIO_GPIOVAR_H_ */
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.75 2005/09/19 03:15:22 simonb Exp $
|
||||
# $NetBSD: Makefile,v 1.76 2005/09/27 02:35:09 jmcneill Exp $
|
||||
|
||||
INCSDIR= /usr/include/sys
|
||||
|
||||
|
@ -11,7 +11,7 @@ INCS= acct.h agpio.h ansi.h ataio.h audioio.h \
|
|||
endian.h envsys.h errno.h event.h exec.h exec_aout.h \
|
||||
exec_coff.h exec_ecoff.h exec_elf.h exec_script.h extattr.h extent.h \
|
||||
fcntl.h fd_set.h fdio.h featuretest.h file.h filedesc.h filio.h \
|
||||
float_ieee754.h fstypes.h gmon.h hash.h \
|
||||
float_ieee754.h fstypes.h gmon.h gpio.h hash.h \
|
||||
ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h ipc.h \
|
||||
joystick.h \
|
||||
kcore.h kgdb.h ksem.h ksyms.h ktrace.h \
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* $NetBSD: gpio.h,v 1.1 2005/09/27 02:35:09 jmcneill Exp $ */
|
||||
/* $OpenBSD: gpio.h,v 1.1 2004/06/03 18:08:00 grange Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_GPIO_H_
|
||||
#define _SYS_GPIO_H_
|
||||
|
||||
/* GPIO pin states */
|
||||
#define GPIO_PIN_LOW 0x00 /* low level (logical 0) */
|
||||
#define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */
|
||||
|
||||
/* GPIO pin configuration flags */
|
||||
#define GPIO_PIN_INPUT 0x0001 /* input direction */
|
||||
#define GPIO_PIN_OUTPUT 0x0002 /* output direction */
|
||||
#define GPIO_PIN_INOUT 0x0004 /* bi-directional */
|
||||
#define GPIO_PIN_OPENDRAIN 0x0008 /* open-drain output */
|
||||
#define GPIO_PIN_PUSHPULL 0x0010 /* push-pull output */
|
||||
#define GPIO_PIN_TRISTATE 0x0020 /* output disabled */
|
||||
#define GPIO_PIN_PULLUP 0x0040 /* internal pull-up enabled */
|
||||
|
||||
/* GPIO controller description */
|
||||
struct gpio_info {
|
||||
int gpio_npins; /* total number of pins available */
|
||||
};
|
||||
|
||||
/* GPIO pin operation (read/write/toggle) */
|
||||
struct gpio_pin_op {
|
||||
int gp_pin; /* pin number */
|
||||
int gp_value; /* value */
|
||||
};
|
||||
|
||||
/* GPIO pin control */
|
||||
struct gpio_pin_ctl {
|
||||
int gp_pin; /* pin number */
|
||||
int gp_caps; /* pin capabilities (read-only) */
|
||||
int gp_flags; /* pin configuration flags */
|
||||
};
|
||||
|
||||
#define GPIOINFO _IOR('G', 0, struct gpio_info)
|
||||
#define GPIOPINREAD _IOWR('G', 1, struct gpio_pin_op)
|
||||
#define GPIOPINWRITE _IOWR('G', 2, struct gpio_pin_op)
|
||||
#define GPIOPINTOGGLE _IOWR('G', 3, struct gpio_pin_op)
|
||||
#define GPIOPINCTL _IOWR('G', 4, struct gpio_pin_ctl)
|
||||
|
||||
#endif /* !_SYS_GPIO_H_ */
|
Loading…
Reference in New Issue