summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/macppc/conf/GENERIC3
-rw-r--r--sys/arch/macppc/conf/files.macppc7
-rw-r--r--sys/arch/macppc/dev/asms.c302
3 files changed, 310 insertions, 2 deletions
diff --git a/sys/arch/macppc/conf/GENERIC b/sys/arch/macppc/conf/GENERIC
index d5896e05ab3..1280a59ab27 100644
--- a/sys/arch/macppc/conf/GENERIC
+++ b/sys/arch/macppc/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.120 2006/01/01 20:52:23 deraadt Exp $g
+# $OpenBSD: GENERIC,v 1.121 2006/01/03 17:23:19 xsa Exp $g
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
@@ -266,6 +266,7 @@ gpio* at pcagpio?
maxds* at iic?
fcu* at iic?
adt* at iic?
+#asms* at iic?
# CardBus bus support
cardbus* at cardslot?
diff --git a/sys/arch/macppc/conf/files.macppc b/sys/arch/macppc/conf/files.macppc
index b8a2ce0eba0..b6008874578 100644
--- a/sys/arch/macppc/conf/files.macppc
+++ b/sys/arch/macppc/conf/files.macppc
@@ -1,4 +1,4 @@
-# $OpenBSD: files.macppc,v 1.44 2006/01/01 20:52:23 deraadt Exp $
+# $OpenBSD: files.macppc,v 1.45 2006/01/03 17:23:19 xsa Exp $
#
# macppc-specific configuration info
@@ -288,3 +288,8 @@ file dev/pci/if_hme_pci.c hme_pci
device tpms: hid, wsmousedev
attach tpms at uhidbus
file arch/macppc/dev/tpms.c tpms
+
+# Apple Sudden Motion Sensor
+device asms
+attach asms at i2c
+file arch/macppc/dev/asms.c asms
diff --git a/sys/arch/macppc/dev/asms.c b/sys/arch/macppc/dev/asms.c
new file mode 100644
index 00000000000..0c37f6b268f
--- /dev/null
+++ b/sys/arch/macppc/dev/asms.c
@@ -0,0 +1,302 @@
+/* $OpenBSD: asms.c,v 1.1 2006/01/03 17:23:19 xsa Exp $ */
+/*
+ * Copyright (c) 2005 Xavier Santolaria <xsa@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.
+ */
+
+/*
+ * A driver for the Apple Sudden Motion Sensor based on notes from
+ * http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/sensors.h>
+
+#include <dev/i2c/i2cvar.h>
+
+/* ASMS Registers */
+#define ASMS_REG_COMMAND 0x00
+#define ASMS_REG_STATUS 0x01
+#define ASMS_REG_RCONTROL1 0x02
+#define ASMS_REG_RCONTROL2 0x03
+#define ASMS_REG_RCONTROL3 0x04
+#define ASMS_REG_RDATA1 0x05
+#define ASMS_REG_RDATA2 0x06
+#define ASMS_REG_DATA_X 0x20
+#define ASMS_REG_DATA_Y 0x21
+#define ASMS_REG_DATA_Z 0x22
+#define ASMS_REG_SENS_LOW 0x26 /* init with 0x15 */
+#define ASMS_REG_SENS_HIGH 0x27 /* init with 0x60 */
+#define ASMS_REG_CONTROL_X 0x28 /* init with 0x08 */
+#define ASMS_REG_CONTROL_Y 0x29 /* init with 0x0f */
+#define ASMS_REG_CONTROL_Z 0x2a /* init with 0x4f */
+#define ASMS_REG_UNKNOWN1 0x2b /* init with 0x14 */
+#define ASMS_REG_VENDOR 0x2e
+#define ASMS_CMD_READ_VER 0x01
+#define ASMS_CMD_READ_MEM 0x02
+#define ASMS_CMD_RESET 0x07
+#define ASMS_CMD_START 0x08
+
+/* Sensors */
+#define ASMS_DATA_X 0
+#define ASMS_DATA_Y 1
+#define ASMS_DATA_Z 2
+#define ASMS_NUM_SENSORS 3
+
+struct asms_softc {
+ struct device sc_dev;
+ i2c_tag_t sc_tag;
+ i2c_addr_t sc_addr;
+
+ struct sensor sc_sensor[ASMS_NUM_SENSORS];
+};
+
+int asms_match(struct device *, void *, void *);
+void asms_attach(struct device *, struct device *, void *);
+void asms_refresh(void *);
+
+struct cfattach asms_ca = {
+ sizeof(struct asms_softc), asms_match, asms_attach
+};
+
+struct cfdriver asms_cd = {
+ NULL, "asms", DV_DULL
+};
+
+int
+asms_match(struct device *parent, void *match, void *aux)
+{
+ struct i2c_attach_args *ia = aux;
+
+ if (strcmp(ia->ia_name, "AAPL,accelerometer_1") == 0)
+ return (1);
+ return (0);
+}
+
+void
+asms_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct asms_softc *sc = (struct asms_softc *)self;
+ struct i2c_attach_args *ia = aux;
+ u_int8_t cmd, data;
+ int i, vflag = 0;
+
+ sc->sc_tag = ia->ia_tag;
+ sc->sc_addr = ia ->ia_addr;
+
+ iic_acquire_bus(sc->sc_tag, 0);
+
+ cmd = ASMS_REG_COMMAND; data = ASMS_CMD_START;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write command register\n");
+ return;
+ }
+ delay(10000);
+
+ cmd = ASMS_REG_RCONTROL1; data = 0x02;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write read control register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_RCONTROL2; data = 0x85;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write read control register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_RCONTROL3; data = 0x01;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write read control register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_COMMAND; data = ASMS_CMD_READ_MEM;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write command register\n");
+ return;
+ }
+ delay(10000);
+
+ cmd = ASMS_REG_RDATA1;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot read data register\n");
+ return;
+ }
+ printf(", rev %x", data);
+
+ cmd = ASMS_REG_RDATA2;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot read data register\n");
+ return;
+ }
+ printf(".%x", data);
+
+ cmd = ASMS_REG_COMMAND; data = ASMS_CMD_READ_VER;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write command register\n");
+ return;
+ }
+ delay(1000);
+
+ cmd = ASMS_REG_RDATA1;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot read data register\n");
+ return;
+ }
+ printf(", version %x", data);
+
+ cmd = ASMS_REG_RDATA2;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot read data register\n");
+ return;
+ }
+ printf(".%x", data);
+
+ cmd = ASMS_REG_VENDOR;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot read vendor register\n");
+ return;
+ }
+ if (data & 0x10)
+ vflag = 1;
+
+ cmd = ASMS_REG_SENS_LOW; data = 0x15;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write sensibility low register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_SENS_HIGH; data = 0x60;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write sensibility high register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_CONTROL_X; data = 0x08;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write control X register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_CONTROL_Y; data= 0x0f;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write control Y register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_CONTROL_Z; data = 0x4f;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write control Z register\n");
+ return;
+ }
+
+ cmd = ASMS_REG_UNKNOWN1; data = 0x14;
+ if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
+ iic_release_bus(sc->sc_tag, 0);
+ printf(": cannot write unknown 1 register\n");
+ return;
+ }
+
+ iic_release_bus(sc->sc_tag, 0);
+
+ /* Initialize sensor data. */
+ for (i = 0; i < ASMS_NUM_SENSORS; i++)
+ strlcpy(sc->sc_sensor[i].device, sc->sc_dev.dv_xname,
+ sizeof(sc->sc_sensor[i].device));
+
+ sc->sc_sensor[ASMS_DATA_X].type = SENSOR_INTEGER;
+ strlcpy(sc->sc_sensor[ASMS_DATA_X].desc, "X_ACCEL",
+ sizeof(sc->sc_sensor[ASMS_DATA_X].desc));
+
+ sc->sc_sensor[ASMS_DATA_Y].type = SENSOR_INTEGER;
+ strlcpy(sc->sc_sensor[ASMS_DATA_Y].desc, "Y_ACCEL",
+ sizeof(sc->sc_sensor[ASMS_DATA_Y].desc));
+
+ sc->sc_sensor[ASMS_DATA_Z].type = SENSOR_INTEGER;
+ strlcpy(sc->sc_sensor[ASMS_DATA_Z].desc, "Z_ACCEL",
+ sizeof(sc->sc_sensor[ASMS_DATA_Z].desc));
+
+ if (sensor_task_register(sc, asms_refresh, 5)) {
+ printf(": unable to register update task\n");
+ return;
+ }
+
+ for (i = 0; i < ASMS_NUM_SENSORS; i++)
+ SENSOR_ADD(&sc->sc_sensor[i]);
+
+ printf("\n");
+}
+
+void
+asms_refresh(void *arg)
+{
+ struct asms_softc *sc = arg;
+ u_int8_t cmd;
+ int8_t sdata;
+
+ iic_acquire_bus(sc->sc_tag, 0);
+
+ cmd = ASMS_REG_DATA_X;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
+ sc->sc_sensor[ASMS_DATA_X].value = sdata;
+
+ cmd = ASMS_REG_DATA_Y;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
+ sc->sc_sensor[ASMS_DATA_Y].value = sdata;
+
+ cmd = ASMS_REG_DATA_Z;
+ if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+ sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
+ sc->sc_sensor[ASMS_DATA_Z].value = sdata;
+
+ iic_release_bus(sc->sc_tag, 0);
+}