Line data Source code
1 : /* $OpenBSD: lis331dl.c,v 1.1 2009/08/12 14:51:20 cnst Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2009 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : #include <sys/param.h>
20 : #include <sys/systm.h>
21 : #include <sys/device.h>
22 : #include <sys/sensors.h>
23 :
24 : #include <dev/i2c/i2cvar.h>
25 :
26 : /*
27 : * STMicroelectronics LIS331DL
28 : * MEMS motion sensor
29 : * http://www.stm.com/stonline/products/literature/ds/13951.pdf
30 : * April 2008
31 : */
32 :
33 : /* 3-axis accelerometer */
34 : #define LISA_NUM_AXIS 3
35 : static const struct {
36 : const char *name;
37 : const uint8_t reg;
38 : } lisa_axis[LISA_NUM_AXIS] = {
39 : { "OUT_X", 0x29 },
40 : { "OUT_Y", 0x2b },
41 : { "OUT_Z", 0x2d }
42 : };
43 :
44 : struct lisa_softc {
45 : struct device sc_dev;
46 : i2c_tag_t sc_tag;
47 : i2c_addr_t sc_addr;
48 :
49 : struct ksensor sc_sensors[LISA_NUM_AXIS];
50 : struct ksensordev sc_sensordev;
51 : };
52 :
53 :
54 : int lisa_match(struct device *, void *, void *);
55 : void lisa_attach(struct device *, struct device *, void *);
56 : void lisa_refresh(void *);
57 :
58 : uint8_t lisa_readreg(struct lisa_softc *, uint8_t);
59 : void lisa_writereg(struct lisa_softc *, uint8_t, uint8_t);
60 :
61 :
62 : struct cfattach lisa_ca = {
63 : sizeof(struct lisa_softc), lisa_match, lisa_attach
64 : };
65 :
66 : struct cfdriver lisa_cd = {
67 : NULL, "lisa", DV_DULL
68 : };
69 :
70 :
71 : int
72 0 : lisa_match(struct device *parent, void *match, void *aux)
73 : {
74 0 : struct i2c_attach_args *ia = aux;
75 :
76 0 : if (strcmp(ia->ia_name, "lis331dl") == 0)
77 0 : return 1;
78 0 : return 0;
79 0 : }
80 :
81 : void
82 0 : lisa_attach(struct device *parent, struct device *self, void *aux)
83 : {
84 0 : struct lisa_softc *sc = (struct lisa_softc *)self;
85 0 : struct i2c_attach_args *ia = aux;
86 : int i;
87 :
88 0 : sc->sc_tag = ia->ia_tag;
89 0 : sc->sc_addr = ia->ia_addr;
90 :
91 0 : printf(": %s", ia->ia_name);
92 :
93 0 : strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
94 : sizeof(sc->sc_sensordev.xname));
95 :
96 0 : for (i = 0; i < LISA_NUM_AXIS; i++) {
97 0 : strlcpy(sc->sc_sensors[i].desc, lisa_axis[i].name,
98 : sizeof(sc->sc_sensors[i].desc));
99 0 : sc->sc_sensors[i].type = SENSOR_INTEGER;
100 0 : sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
101 : }
102 :
103 0 : if (sensor_task_register(sc, lisa_refresh, 1) == NULL) {
104 0 : printf(", unable to register update task\n");
105 0 : return;
106 : }
107 :
108 0 : sensordev_install(&sc->sc_sensordev);
109 0 : printf("\n");
110 0 : }
111 :
112 : void
113 0 : lisa_refresh(void *arg)
114 : {
115 0 : struct lisa_softc *sc = arg;
116 0 : struct ksensor *s = sc->sc_sensors;
117 : int i;
118 :
119 0 : iic_acquire_bus(sc->sc_tag, 0);
120 0 : for (i = 0; i < LISA_NUM_AXIS; i++)
121 0 : s[i].value = (int8_t)lisa_readreg(sc, lisa_axis[i].reg);
122 0 : iic_release_bus(sc->sc_tag, 0);
123 0 : }
124 :
125 : uint8_t
126 0 : lisa_readreg(struct lisa_softc *sc, uint8_t reg)
127 : {
128 0 : uint8_t data;
129 :
130 0 : iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
131 0 : sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0);
132 :
133 0 : return data;
134 0 : }
135 :
136 : void
137 0 : lisa_writereg(struct lisa_softc *sc, uint8_t reg, uint8_t data)
138 : {
139 0 : iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
140 0 : sc->sc_addr, ®, sizeof reg, &data, sizeof data, 0);
141 0 : }
|