diff options
Diffstat (limited to 'driver')
-rw-r--r-- | driver/accel_kxcj9.c | 249 | ||||
-rw-r--r-- | driver/accel_kxcj9.h | 132 | ||||
-rw-r--r-- | driver/build.mk | 3 |
3 files changed, 384 insertions, 0 deletions
diff --git a/driver/accel_kxcj9.c b/driver/accel_kxcj9.c new file mode 100644 index 0000000000..83967eb873 --- /dev/null +++ b/driver/accel_kxcj9.c @@ -0,0 +1,249 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* KXCJ9 gsensor module for Chrome EC */ + +#include "accelerometer.h" +#include "common.h" +#include "console.h" +#include "driver/accel_kxcj9.h" +#include "gpio.h" +#include "i2c.h" +#include "util.h" + +/* Range of the accelerometers: 2G, 4G, or 8G. */ +static int sensor_range[ACCEL_COUNT] = {KXCJ9_GSEL_2G, KXCJ9_GSEL_2G}; + +/* Resolution: KXCJ9_RES_12BIT or KXCJ9_RES_12BIT. */ +static int sensor_resolution[ACCEL_COUNT] = {KXCJ9_RES_12BIT, KXCJ9_RES_12BIT}; + +/* Output data rate: KXCJ9_OSA_* ranges from 0.781Hz to 1600Hz. */ +static int sensor_datarate[ACCEL_COUNT] = {KXCJ9_OSA_12_50HZ, + KXCJ9_OSA_12_50HZ}; + +#ifdef CONFIG_CMD_ACCELS +/** + * Read register from accelerometer. + */ +static int raw_read8(const int addr, const int reg, int *data_ptr) +{ + return i2c_read8(I2C_PORT_ACCEL, addr, reg, data_ptr); +} +#endif /* CONFIG_CMD_ACCELS */ + +/** + * Write register from accelerometer. + */ +static int raw_write8(const int addr, const int reg, int data) +{ + return i2c_write8(I2C_PORT_ACCEL, addr, reg, data); +} + + +int accel_write_range(const enum accel_id id, const int range) +{ + int ret; + + /* Check for valid id. */ + if (id < 0 || id >= ACCEL_COUNT) + return EC_ERROR_INVAL; + + /* + * Verify that the input range is valid. Note that we currently + * don't support the 8G with 14-bit resolution mode. + */ + if (range != KXCJ9_GSEL_2G && range != KXCJ9_GSEL_4G && + range != KXCJ9_GSEL_8G) + return EC_ERROR_INVAL; + + ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, + KXCJ9_CTRL1_PC1 | sensor_resolution[id] | range); + + /* If successfully written, then save the range. */ + if (ret == EC_SUCCESS) + sensor_range[id] = range; + + return ret; +} + +int accel_write_resolution(const enum accel_id id, const int res) +{ + int ret; + + /* Check for valid id. */ + if (id < 0 || id >= ACCEL_COUNT) + return EC_ERROR_INVAL; + + /* Check that resolution input is valid. */ + if (res != KXCJ9_RES_12BIT && res != KXCJ9_RES_8BIT) + return EC_ERROR_INVAL; + + ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, + KXCJ9_CTRL1_PC1 | res | sensor_range[id]); + + /* If successfully written, then save the range. */ + if (ret == EC_SUCCESS) + sensor_resolution[id] = res; + + return ret; +} + +int accel_write_datarate(const enum accel_id id, const int rate) +{ + int ret; + + /* Check for valid id. */ + if (id < 0 || id >= ACCEL_COUNT) + return EC_ERROR_INVAL; + + /* Check that rate input is valid. */ + if (rate < KXCJ9_OSA_12_50HZ || rate > KXCJ9_OSA_6_250HZ) + return EC_ERROR_INVAL; + + /* Set output data rate. */ + ret = raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, rate); + + /* If successfully written, then save the range. */ + if (ret == EC_SUCCESS) + sensor_datarate[id] = rate; + + return ret; +} + +int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc) +{ + uint8_t acc[6]; + uint8_t reg = KXCJ9_XOUT_L; + int ret, multiplier; + + /* Check for valid id. */ + if (id < 0 || id >= ACCEL_COUNT) + return EC_ERROR_INVAL; + + /* Read 6 bytes starting at KXCJ9_XOUT_L. */ + ret = i2c_xfer(I2C_PORT_ACCEL, accel_addr[id], ®, 1, acc, 6, + I2C_XFER_SINGLE); + + if (ret != EC_SUCCESS) + return ret; + + /* Determine multiplier based on stored range. */ + switch (sensor_range[id]) { + case KXCJ9_GSEL_2G: + multiplier = 1; + break; + case KXCJ9_GSEL_4G: + multiplier = 2; + break; + case KXCJ9_GSEL_8G: + multiplier = 4; + break; + default: + return EC_ERROR_UNKNOWN; + } + + /* + * Convert acceleration to a signed 12-bit number. Note, based on + * the order of the registers: + * + * acc[0] = KXCJ9_XOUT_L + * acc[1] = KXCJ9_XOUT_H + * acc[2] = KXCJ9_YOUT_L + * acc[3] = KXCJ9_YOUT_H + * acc[4] = KXCJ9_ZOUT_L + * acc[5] = KXCJ9_ZOUT_H + */ + *x_acc = multiplier * (((int8_t)acc[1]) << 4) | (acc[0] >> 4); + *y_acc = multiplier * (((int8_t)acc[3]) << 4) | (acc[2] >> 4); + *z_acc = multiplier * (((int8_t)acc[5]) << 4) | (acc[4] >> 4); + + return EC_SUCCESS; +} + +int accel_init(enum accel_id id) +{ + int ret = EC_SUCCESS; + + /* Check for valid id. */ + if (id < 0 || id >= ACCEL_COUNT) + return EC_ERROR_INVAL; + + /* Enable accelerometer, 12-bit resolution mode, +/- 2G range.*/ + ret |= raw_write8(accel_addr[id], KXCJ9_CTRL1, + KXCJ9_CTRL1_PC1 | sensor_resolution[id] | + sensor_range[id]); + + /* Set output data rate. */ + ret |= raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, + sensor_datarate[id]); + + return ret; +} + + + +/*****************************************************************************/ +/* Console commands */ + +#ifdef CONFIG_CMD_ACCELS +static int command_read_accelerometer(int argc, char **argv) +{ + char *e; + int addr, reg, data; + + if (argc != 3) + return EC_ERROR_PARAM_COUNT; + + /* First argument is address. */ + addr = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + + /* Second argument is register offset. */ + reg = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + raw_read8(addr, reg, &data); + + ccprintf("0x%02x\n", data); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(accelread, command_read_accelerometer, + "addr reg", + "Read from accelerometer at slave address addr", NULL); + +static int command_write_accelerometer(int argc, char **argv) +{ + char *e; + int addr, reg, data; + + if (argc != 4) + return EC_ERROR_PARAM_COUNT; + + /* First argument is address. */ + addr = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + + /* Second argument is register offset. */ + reg = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + /* Third argument is data. */ + data = strtoi(argv[3], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + + raw_write8(addr, reg, data); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(accelwrite, command_write_accelerometer, + "addr reg data", + "Write to accelerometer at slave address addr", NULL); +#endif /* CONFIG_CMD_ACCELS */ diff --git a/driver/accel_kxcj9.h b/driver/accel_kxcj9.h new file mode 100644 index 0000000000..9451421be5 --- /dev/null +++ b/driver/accel_kxcj9.h @@ -0,0 +1,132 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* KXCJ9 gsensor module for Chrome EC */ + +#ifndef __CROS_EC_ACCEL_KXCJ9_H +#define __CROS_EC_ACCEL_KXCJ9_H + +/* + * 7-bit address is 000111Xb. Where 'X' is determined + * by the voltage on the ADDR pin. + */ +#define KXCJ9_ADDR0 0x1c +#define KXCJ9_ADDR1 0x1e + +/* Chip-specific registers */ +#define KXCJ9_XOUT_L 0x06 +#define KXCJ9_XOUT_H 0x07 +#define KXCJ9_YOUT_L 0x08 +#define KXCJ9_YOUT_H 0x09 +#define KXCJ9_ZOUT_L 0x0a +#define KXCJ9_ZOUT_H 0x0b +#define KXCJ9_DCST_RESP 0x0c +#define KXCJ9_WHOAMI 0x0f +#define KXCJ9_INT_SRC1 0x16 +#define KXCJ9_INT_SRC2 0x17 +#define KXCJ9_STATUS 0x18 +#define KXCJ9_INT_REL 0x1a +#define KXCJ9_CTRL1 0x1b +#define KXCJ9_CTRL2 0x1d +#define KXCJ9_INT_CTRL1 0x1e +#define KXCJ9_INT_CTRL2 0x1f +#define KXCJ9_DATA_CTRL 0x21 +#define KXCJ9_WAKEUP_TIMER 0x29 +#define KXCJ9_SELF_TEST 0x3a +#define KXCJ9_WAKEUP_THRESHOLD 0x6a + +#define KXCJ9_INT_SRC1_WUFS (1 << 1) +#define KXCJ9_INT_SRC1_DRDY (1 << 4) + +#define KXCJ9_INT_SRC2_ZPWU (1 << 0) +#define KXCJ9_INT_SRC2_ZNWU (1 << 1) +#define KXCJ9_INT_SRC2_YPWU (1 << 2) +#define KXCJ9_INT_SRC2_YNWU (1 << 3) +#define KXCJ9_INT_SRC2_XPWU (1 << 4) +#define KXCJ9_INT_SRC2_XNWU (1 << 5) + +#define KXCJ9_STATUS_INT (1 << 4) + +#define KXCJ9_CTRL1_WUFE (1 << 1) +#define KXCJ9_CTRL1_DRDYE (1 << 5) +#define KXCJ9_CTRL1_PC1 (1 << 7) + +#define KXCJ9_GSEL_2G (0 << 3) +#define KXCJ9_GSEL_4G (1 << 3) +#define KXCJ9_GSEL_8G (2 << 3) +#define KXCJ9_GSEL_8G_14BIT (3 << 3) + +#define KXCJ9_RES_8BIT (0 << 6) +#define KXCJ9_RES_12BIT (1 << 6) + +#define KXCJ9_CTRL2_OWUF (7 << 0) +#define KXCJ9_CTRL2_DCST (1 << 4) +#define KXCJ9_CTRL2_SRST (1 << 7) + +#define KXCJ9_OWUF_0_781HZ 0 +#define KXCJ9_OWUF_1_563HZ 1 +#define KXCJ9_OWUF_3_125HZ 2 +#define KXCJ9_OWUF_6_250HZ 3 +#define KXCJ9_OWUF_12_50HZ 4 +#define KXCJ9_OWUF_25_00HZ 5 +#define KXCJ9_OWUF_50_00HZ 6 +#define KXCJ9_OWUF_100_0HZ 7 + +#define KXCJ9_INT_CTRL1_IEL (1 << 3) +#define KXCJ9_INT_CTRL1_IEA (1 << 4) +#define KXCJ9_INT_CTRL1_IEN (1 << 5) + +#define KXCJ9_INT_CTRL2_ZPWUE (1 << 0) +#define KXCJ9_INT_CTRL2_ZNWUE (1 << 1) +#define KXCJ9_INT_CTRL2_YPWUE (1 << 2) +#define KXCJ9_INT_CTRL2_YNWUE (1 << 3) +#define KXCJ9_INT_CTRL2_XPWUE (1 << 4) +#define KXCJ9_INT_CTRL2_XNWUE (1 << 5) + +#define KXCJ9_OSA_0_781HZ 8 +#define KXCJ9_OSA_1_563HZ 9 +#define KXCJ9_OSA_3_125HZ 0xa +#define KXCJ9_OSA_6_250HZ 0xb +#define KXCJ9_OSA_12_50HZ 0 +#define KXCJ9_OSA_25_00HZ 1 +#define KXCJ9_OSA_50_00HZ 2 +#define KXCJ9_OSA_100_0HZ 3 +#define KXCJ9_OSA_200_0HZ 4 +#define KXCJ9_OSA_400_0HZ 5 +#define KXCJ9_OSA_800_0HZ 6 +#define KXCJ9_OSA_1600_HZ 7 + + +/** + * Write the accelerometer range. + * + * @param id Target accelerometer + * @param range Range (KXCJ9_GSEL_*). + * + * @return EC_SUCCESS if successful, non-zero if error. + */ +int accel_write_range(const enum accel_id id, const int range); + +/** + * Write the accelerometer resolution. + * + * @param id Target accelerometer + * @param range Resolution (KXCJ9_RES_*). + * + * @return EC_SUCCESS if successful, non-zero if error. + */ +int accel_write_resolution(const enum accel_id id, const int res); + +/** + * Write the accelerometer data rate. + * + * @param id Target accelerometer + * @param range Data rate (KXCJ9_OSA_*). + * + * @return EC_SUCCESS if successful, non-zero if error. + */ +int accel_write_datarate(const enum accel_id id, const int rate); + +#endif /* __CROS_EC_ACCEL_KXCJ9_H */ diff --git a/driver/build.mk b/driver/build.mk index f981b6942c..f9c31b143b 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -6,6 +6,9 @@ # Drivers for off-chip devices # +# Accelerometers +driver-$(CONFIG_ACCEL_KXCJ9)+=accel_kxcj9.o + # ALS drivers driver-$(CONFIG_ALS_ISL29035)+=als_isl29035.o |