Annotation of sys/arch/macppc/dev/asms.c, Revision 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