diff options
author | Constantine A. Murenin <cnst@cvs.openbsd.org> | 2009-08-12 14:51:21 +0000 |
---|---|---|
committer | Constantine A. Murenin <cnst@cvs.openbsd.org> | 2009-08-12 14:51:21 +0000 |
commit | 2fecdb755746b90f914eb6293ba03f3d1c6bd93b (patch) | |
tree | 3de39dbbdf6e846111f77aec07adad287c025123 /sys/dev | |
parent | 41f7beea342b39552a07eda8d3b742194d8e7d63 (diff) |
New lisa(4) driver for ST LIS331DL accelerometer in HP 2133 Mini-Note PC; ok deraadt
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/i2c/files.i2c | 7 | ||||
-rw-r--r-- | sys/dev/i2c/i2c_scan.c | 10 | ||||
-rw-r--r-- | sys/dev/i2c/lis331dl.c | 141 |
3 files changed, 156 insertions, 2 deletions
diff --git a/sys/dev/i2c/files.i2c b/sys/dev/i2c/files.i2c index 79143eaebe1..2c9d3ef8c51 100644 --- a/sys/dev/i2c/files.i2c +++ b/sys/dev/i2c/files.i2c @@ -1,4 +1,4 @@ -# $OpenBSD: files.i2c,v 1.46 2008/04/21 04:48:25 deraadt Exp $ +# $OpenBSD: files.i2c,v 1.47 2009/08/12 14:51:20 cnst Exp $ # $NetBSD: files.i2c,v 1.3 2003/10/20 16:24:10 briggs Exp $ define i2c {[addr = -1], [size = -1]} @@ -161,3 +161,8 @@ file dev/i2c/sdtemp.c sdtemp device adtfsm attach adtfsm at i2c file dev/i2c/adt7462.c adtfsm + +# STMicroelectronics LIS331DL MEMS motion sensor +device lisa +attach lisa at i2c +file dev/i2c/lis331dl.c diff --git a/sys/dev/i2c/i2c_scan.c b/sys/dev/i2c/i2c_scan.c index b06e86b9648..5235b2a5671 100644 --- a/sys/dev/i2c/i2c_scan.c +++ b/sys/dev/i2c/i2c_scan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i2c_scan.c,v 1.133 2009/07/10 19:58:41 cnst Exp $ */ +/* $OpenBSD: i2c_scan.c,v 1.134 2009/08/12 14:51:20 cnst Exp $ */ /* * Copyright (c) 2005 Theo de Raadt <deraadt@openbsd.org> @@ -883,6 +883,14 @@ iic_probe_sensor(struct device *self, u_int8_t addr) (iicprobew(0x07) & 0xffe0) == 0x0800 && iicprobew(0x00) == 0x001f) { name = "cat34ts02"; /* or cat6095 */ + } else if ((addr & 0x7e) == 0x1c && iicprobe(0x0f) == 0x3b && + (iicprobe(0x21) & 0x60) == 0x00 && + iicprobe(0x0f) == iicprobe(0x8f) && /* registers address is 7 bits */ + iicprobe(0x20) == iicprobe(0xa0) && + iicprobe(0x21) == iicprobe(0xa1) && + iicprobe(0x22) == iicprobe(0xa2) && + iicprobe(0x07) == 0x00) { /* 0x00 to 0x0e are reserved */ + name = "lis331dl"; } else if (name == NULL && (addr & 0x78) == 0x48) { /* addr 0b1001xxx */ name = lm75probe(); diff --git a/sys/dev/i2c/lis331dl.c b/sys/dev/i2c/lis331dl.c new file mode 100644 index 00000000000..76cef4b2df0 --- /dev/null +++ b/sys/dev/i2c/lis331dl.c @@ -0,0 +1,141 @@ +/* $OpenBSD: lis331dl.c,v 1.1 2009/08/12 14:51:20 cnst Exp $ */ + +/* + * Copyright (c) 2009 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> + * + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/sensors.h> + +#include <dev/i2c/i2cvar.h> + +/* + * STMicroelectronics LIS331DL + * MEMS motion sensor + * http://www.stm.com/stonline/products/literature/ds/13951.pdf + * April 2008 + */ + +/* 3-axis accelerometer */ +#define LISA_NUM_AXIS 3 +static const struct { + const char *name; + const uint8_t reg; +} lisa_axis[LISA_NUM_AXIS] = { + { "OUT_X", 0x29 }, + { "OUT_Y", 0x2b }, + { "OUT_Z", 0x2d } +}; + +struct lisa_softc { + struct device sc_dev; + i2c_tag_t sc_tag; + i2c_addr_t sc_addr; + + struct ksensor sc_sensors[LISA_NUM_AXIS]; + struct ksensordev sc_sensordev; +}; + + +int lisa_match(struct device *, void *, void *); +void lisa_attach(struct device *, struct device *, void *); +void lisa_refresh(void *); + +uint8_t lisa_readreg(struct lisa_softc *, uint8_t); +void lisa_writereg(struct lisa_softc *, uint8_t, uint8_t); + + +struct cfattach lisa_ca = { + sizeof(struct lisa_softc), lisa_match, lisa_attach +}; + +struct cfdriver lisa_cd = { + NULL, "lisa", DV_DULL +}; + + +int +lisa_match(struct device *parent, void *match, void *aux) +{ + struct i2c_attach_args *ia = aux; + + if (strcmp(ia->ia_name, "lis331dl") == 0) + return 1; + return 0; +} + +void +lisa_attach(struct device *parent, struct device *self, void *aux) +{ + struct lisa_softc *sc = (struct lisa_softc *)self; + struct i2c_attach_args *ia = aux; + int i; + + sc->sc_tag = ia->ia_tag; + sc->sc_addr = ia->ia_addr; + + printf(": %s", ia->ia_name); + + strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, + sizeof(sc->sc_sensordev.xname)); + + for (i = 0; i < LISA_NUM_AXIS; i++) { + strlcpy(sc->sc_sensors[i].desc, lisa_axis[i].name, + sizeof(sc->sc_sensors[i].desc)); + sc->sc_sensors[i].type = SENSOR_INTEGER; + sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); + } + + if (sensor_task_register(sc, lisa_refresh, 1) == NULL) { + printf(", unable to register update task\n"); + return; + } + + sensordev_install(&sc->sc_sensordev); + printf("\n"); +} + +void +lisa_refresh(void *arg) +{ + struct lisa_softc *sc = arg; + struct ksensor *s = sc->sc_sensors; + int i; + + iic_acquire_bus(sc->sc_tag, 0); + for (i = 0; i < LISA_NUM_AXIS; i++) + s[i].value = (int8_t)lisa_readreg(sc, lisa_axis[i].reg); + iic_release_bus(sc->sc_tag, 0); +} + +uint8_t +lisa_readreg(struct lisa_softc *sc, uint8_t reg) +{ + uint8_t data; + + iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, + sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); + + return data; +} + +void +lisa_writereg(struct lisa_softc *sc, uint8_t reg, uint8_t data) +{ + iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0); +} |