Annotation of sys/arch/macppc/dev/asms.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: asms.c,v 1.6 2007/06/24 05:34:35 dlg Exp $ */
2: /*
3: * Copyright (c) 2005 Xavier Santolaria <xsa@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: /*
19: * A driver for the Apple Sudden Motion Sensor based on notes from
20: * http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification
21: */
22:
23: #include <sys/param.h>
24: #include <sys/systm.h>
25: #include <sys/device.h>
26: #include <sys/sensors.h>
27:
28: #include <dev/i2c/i2cvar.h>
29:
30: /* ASMS Registers */
31: #define ASMS_REG_COMMAND 0x00
32: #define ASMS_REG_STATUS 0x01
33: #define ASMS_REG_RCONTROL1 0x02
34: #define ASMS_REG_RCONTROL2 0x03
35: #define ASMS_REG_RCONTROL3 0x04
36: #define ASMS_REG_RDATA1 0x05
37: #define ASMS_REG_RDATA2 0x06
38: #define ASMS_REG_DATA_X 0x20
39: #define ASMS_REG_DATA_Y 0x21
40: #define ASMS_REG_DATA_Z 0x22
41: #define ASMS_REG_SENS_LOW 0x26 /* init with 0x15 */
42: #define ASMS_REG_SENS_HIGH 0x27 /* init with 0x60 */
43: #define ASMS_REG_CONTROL_X 0x28 /* init with 0x08 */
44: #define ASMS_REG_CONTROL_Y 0x29 /* init with 0x0f */
45: #define ASMS_REG_CONTROL_Z 0x2a /* init with 0x4f */
46: #define ASMS_REG_UNKNOWN1 0x2b /* init with 0x14 */
47: #define ASMS_REG_VENDOR 0x2e
48: #define ASMS_CMD_READ_VER 0x01
49: #define ASMS_CMD_READ_MEM 0x02
50: #define ASMS_CMD_RESET 0x07
51: #define ASMS_CMD_START 0x08
52:
53: /* Sensors */
54: #define ASMS_DATA_X 0
55: #define ASMS_DATA_Y 1
56: #define ASMS_DATA_Z 2
57: #define ASMS_NUM_SENSORS 3
58:
59: struct asms_softc {
60: struct device sc_dev;
61: i2c_tag_t sc_tag;
62: i2c_addr_t sc_addr;
63:
64: struct ksensor sc_sensor[ASMS_NUM_SENSORS];
65: struct ksensordev sc_sensordev;
66: };
67:
68: int asms_match(struct device *, void *, void *);
69: void asms_attach(struct device *, struct device *, void *);
70: void asms_refresh(void *);
71:
72: struct cfattach asms_ca = {
73: sizeof(struct asms_softc), asms_match, asms_attach
74: };
75:
76: struct cfdriver asms_cd = {
77: NULL, "asms", DV_DULL
78: };
79:
80: int
81: asms_match(struct device *parent, void *match, void *aux)
82: {
83: struct i2c_attach_args *ia = aux;
84:
85: if (strcmp(ia->ia_name, "AAPL,accelerometer_1") == 0)
86: return (1);
87: return (0);
88: }
89:
90: void
91: asms_attach(struct device *parent, struct device *self, void *aux)
92: {
93: struct asms_softc *sc = (struct asms_softc *)self;
94: struct i2c_attach_args *ia = aux;
95: u_int8_t cmd, data;
96: int i, vflag = 0;
97:
98: sc->sc_tag = ia->ia_tag;
99: sc->sc_addr = ia ->ia_addr;
100:
101: iic_acquire_bus(sc->sc_tag, 0);
102:
103: cmd = ASMS_REG_COMMAND; data = ASMS_CMD_START;
104: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
105: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
106: iic_release_bus(sc->sc_tag, 0);
107: printf(": cannot write command register\n");
108: return;
109: }
110: delay(10000);
111:
112: cmd = ASMS_REG_RCONTROL1; data = 0x02;
113: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
114: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
115: iic_release_bus(sc->sc_tag, 0);
116: printf(": cannot write read control register\n");
117: return;
118: }
119:
120: cmd = ASMS_REG_RCONTROL2; data = 0x85;
121: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
122: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
123: iic_release_bus(sc->sc_tag, 0);
124: printf(": cannot write read control register\n");
125: return;
126: }
127:
128: cmd = ASMS_REG_RCONTROL3; data = 0x01;
129: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
130: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
131: iic_release_bus(sc->sc_tag, 0);
132: printf(": cannot write read control register\n");
133: return;
134: }
135:
136: cmd = ASMS_REG_COMMAND; data = ASMS_CMD_READ_MEM;
137: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
138: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
139: iic_release_bus(sc->sc_tag, 0);
140: printf(": cannot write command register\n");
141: return;
142: }
143: delay(10000);
144:
145: cmd = ASMS_REG_RDATA1;
146: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
147: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
148: iic_release_bus(sc->sc_tag, 0);
149: printf(": cannot read data register\n");
150: return;
151: }
152: printf(", rev %x", data);
153:
154: cmd = ASMS_REG_RDATA2;
155: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
156: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
157: iic_release_bus(sc->sc_tag, 0);
158: printf(": cannot read data register\n");
159: return;
160: }
161: printf(".%x", data);
162:
163: cmd = ASMS_REG_COMMAND; data = ASMS_CMD_READ_VER;
164: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
165: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
166: iic_release_bus(sc->sc_tag, 0);
167: printf(": cannot write command register\n");
168: return;
169: }
170: delay(10000);
171:
172: cmd = ASMS_REG_RDATA1;
173: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
174: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
175: iic_release_bus(sc->sc_tag, 0);
176: printf(": cannot read data register\n");
177: return;
178: }
179: printf(", version %x", data);
180:
181: cmd = ASMS_REG_RDATA2;
182: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
183: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
184: iic_release_bus(sc->sc_tag, 0);
185: printf(": cannot read data register\n");
186: return;
187: }
188: printf(".%x", data);
189:
190: cmd = ASMS_REG_VENDOR;
191: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
192: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
193: iic_release_bus(sc->sc_tag, 0);
194: printf(": cannot read vendor register\n");
195: return;
196: }
197: if (data & 0x10)
198: vflag = 1;
199:
200: cmd = ASMS_REG_SENS_LOW; data = 0x15;
201: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
202: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
203: iic_release_bus(sc->sc_tag, 0);
204: printf(": cannot write sensibility low register\n");
205: return;
206: }
207:
208: cmd = ASMS_REG_SENS_HIGH; data = 0x60;
209: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
210: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
211: iic_release_bus(sc->sc_tag, 0);
212: printf(": cannot write sensibility high register\n");
213: return;
214: }
215:
216: cmd = ASMS_REG_CONTROL_X; data = 0x08;
217: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
218: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
219: iic_release_bus(sc->sc_tag, 0);
220: printf(": cannot write control X register\n");
221: return;
222: }
223:
224: cmd = ASMS_REG_CONTROL_Y; data= 0x0f;
225: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
226: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
227: iic_release_bus(sc->sc_tag, 0);
228: printf(": cannot write control Y register\n");
229: return;
230: }
231:
232: cmd = ASMS_REG_CONTROL_Z; data = 0x4f;
233: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
234: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
235: iic_release_bus(sc->sc_tag, 0);
236: printf(": cannot write control Z register\n");
237: return;
238: }
239:
240: cmd = ASMS_REG_UNKNOWN1; data = 0x14;
241: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
242: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
243: iic_release_bus(sc->sc_tag, 0);
244: printf(": cannot write unknown 1 register\n");
245: return;
246: }
247:
248: iic_release_bus(sc->sc_tag, 0);
249:
250: /* Initialize sensor data. */
251: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
252: sizeof(sc->sc_sensordev.xname));
253:
254: sc->sc_sensor[ASMS_DATA_X].type = SENSOR_INTEGER;
255: strlcpy(sc->sc_sensor[ASMS_DATA_X].desc, "X_ACCEL",
256: sizeof(sc->sc_sensor[ASMS_DATA_X].desc));
257:
258: sc->sc_sensor[ASMS_DATA_Y].type = SENSOR_INTEGER;
259: strlcpy(sc->sc_sensor[ASMS_DATA_Y].desc, "Y_ACCEL",
260: sizeof(sc->sc_sensor[ASMS_DATA_Y].desc));
261:
262: sc->sc_sensor[ASMS_DATA_Z].type = SENSOR_INTEGER;
263: strlcpy(sc->sc_sensor[ASMS_DATA_Z].desc, "Z_ACCEL",
264: sizeof(sc->sc_sensor[ASMS_DATA_Z].desc));
265:
266: if (sensor_task_register(sc, asms_refresh, 5) == NULL) {
267: printf(": unable to register update task\n");
268: return;
269: }
270:
271: for (i = 0; i < ASMS_NUM_SENSORS; i++)
272: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
273: sensordev_install(&sc->sc_sensordev);
274:
275: printf("\n");
276: }
277:
278: void
279: asms_refresh(void *arg)
280: {
281: struct asms_softc *sc = arg;
282: u_int8_t cmd;
283: int8_t sdata;
284:
285: iic_acquire_bus(sc->sc_tag, 0);
286:
287: cmd = ASMS_REG_DATA_X;
288: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
289: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
290: sc->sc_sensor[ASMS_DATA_X].value = sdata;
291:
292: cmd = ASMS_REG_DATA_Y;
293: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
294: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
295: sc->sc_sensor[ASMS_DATA_Y].value = sdata;
296:
297: cmd = ASMS_REG_DATA_Z;
298: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
299: sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
300: sc->sc_sensor[ASMS_DATA_Z].value = sdata;
301:
302: iic_release_bus(sc->sc_tag, 0);
303: }
CVSweb