summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cyan/board.c10
-rw-r--r--board/kunimitsu/board.c10
-rw-r--r--board/samus/board.c7
-rw-r--r--board/strago/board.c10
-rw-r--r--common/build.mk1
-rw-r--r--driver/accel_kionix.c509
-rw-r--r--driver/accel_kionix.h66
-rw-r--r--driver/accel_kx022.h122
-rw-r--r--driver/accel_kxcj9.c546
-rw-r--r--driver/accel_kxcj9.h15
-rw-r--r--driver/build.mk3
-rw-r--r--include/config.h1
-rw-r--r--include/ec_commands.h1
13 files changed, 729 insertions, 572 deletions
diff --git a/board/cyan/board.c b/board/cyan/board.c
index 595b2d08e4..aaa6ebcb89 100644
--- a/board/cyan/board.c
+++ b/board/cyan/board.c
@@ -7,6 +7,7 @@
#include "charger.h"
#include "charge_state.h"
+#include "driver/accel_kionix.h"
#include "driver/accel_kxcj9.h"
#include "driver/temp_sensor/tmp432.h"
#include "extpower.h"
@@ -99,7 +100,10 @@ BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT);
/* kxcj9 mutex and local/private data*/
static struct mutex g_kxcj9_mutex[2];
-struct kxcj9_data g_kxcj9_data[2];
+struct kionix_accel_data g_kxcj9_data[2] = {
+ {.variant = KXCJ9},
+ {.variant = KXCJ9},
+};
/* Four Motion sensors */
/* Matrix to rotate accelrator into standard reference frame */
@@ -121,7 +125,7 @@ struct motion_sensor_t motion_sensors[] = {
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
.location = MOTIONSENSE_LOC_BASE,
- .drv = &kxcj9_drv,
+ .drv = &kionix_accel_drv,
.mutex = &g_kxcj9_mutex[0],
.drv_data = &g_kxcj9_data[0],
.addr = KXCJ9_ADDR1,
@@ -155,7 +159,7 @@ struct motion_sensor_t motion_sensors[] = {
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
.location = MOTIONSENSE_LOC_LID,
- .drv = &kxcj9_drv,
+ .drv = &kionix_accel_drv,
.mutex = &g_kxcj9_mutex[1],
.drv_data = &g_kxcj9_data[1],
.addr = KXCJ9_ADDR0,
diff --git a/board/kunimitsu/board.c b/board/kunimitsu/board.c
index 5634ca3b58..a65c65a0b8 100644
--- a/board/kunimitsu/board.c
+++ b/board/kunimitsu/board.c
@@ -11,6 +11,7 @@
#include "charge_state.h"
#include "charger.h"
#include "console.h"
+#include "driver/accel_kionix.h"
#include "driver/accel_kxcj9.h"
#include "driver/als_opt3001.h"
#include "driver/temp_sensor/tmp432.h"
@@ -166,7 +167,10 @@ void board_reset_pd_mcu(void)
/* Four Motion sensors */
/* kxcj9 mutex and local/private data*/
static struct mutex g_kxcj9_mutex[2];
-struct kxcj9_data g_kxcj9_data[2];
+struct kionix_accel_data g_kxcj9_data[2] = {
+ {.variant = KXCJ9},
+ {.variant = KXCJ9},
+};
/* Matrix to rotate accelrator into standard reference frame */
const matrix_3x3_t base_standard_ref = {
@@ -187,7 +191,7 @@ struct motion_sensor_t motion_sensors[] = {
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
.location = MOTIONSENSE_LOC_BASE,
- .drv = &kxcj9_drv,
+ .drv = &kionix_accel_drv,
.mutex = &g_kxcj9_mutex[0],
.drv_data = &g_kxcj9_data[0],
.addr = KXCJ9_ADDR1,
@@ -221,7 +225,7 @@ struct motion_sensor_t motion_sensors[] = {
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
.location = MOTIONSENSE_LOC_LID,
- .drv = &kxcj9_drv,
+ .drv = &kionix_accel_drv,
.mutex = &g_kxcj9_mutex[1],
.drv_data = &g_kxcj9_data[1],
.addr = KXCJ9_ADDR0,
diff --git a/board/samus/board.c b/board/samus/board.c
index 5e53a7ba05..f20855e6e6 100644
--- a/board/samus/board.c
+++ b/board/samus/board.c
@@ -14,6 +14,7 @@
#include "charge_state.h"
#include "common.h"
#include "console.h"
+#include "driver/accel_kionix.h"
#include "driver/accel_kxcj9.h"
#include "driver/accelgyro_lsm6ds0.h"
#include "driver/als_isl29035.h"
@@ -273,7 +274,9 @@ static struct mutex g_base_mutex;
static struct mutex g_lid_mutex;
/* kxcj9 local/private data */
-struct kxcj9_data g_kxcj9_data;
+struct kionix_accel_data g_kxcj9_data = {
+ .variant = KXCJ9,
+};
/* lsm6ds0 local sensor data (per-sensor) */
struct lsm6ds0_data g_saved_data[2];
@@ -337,7 +340,7 @@ struct motion_sensor_t motion_sensors[] = {
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
.location = MOTIONSENSE_LOC_LID,
- .drv = &kxcj9_drv,
+ .drv = &kionix_accel_drv,
.mutex = &g_lid_mutex,
.drv_data = &g_kxcj9_data,
.addr = KXCJ9_ADDR0,
diff --git a/board/strago/board.c b/board/strago/board.c
index aec0a362f3..b43cac059f 100644
--- a/board/strago/board.c
+++ b/board/strago/board.c
@@ -12,6 +12,7 @@
#include "charge_manager.h"
#include "charge_state.h"
#include "console.h"
+#include "driver/accel_kionix.h"
#include "driver/accel_kxcj9.h"
#include "driver/als_isl29035.h"
#include "driver/temp_sensor/tmp432.h"
@@ -192,7 +193,10 @@ void board_reset_pd_mcu(void)
/* Four Motion sensors */
/* kxcj9 mutex and local/private data*/
static struct mutex g_kxcj9_mutex[2];
-struct kxcj9_data g_kxcj9_data[2];
+struct kionix_accel_data g_kxcj9_data[2] = {
+ {.variant = KXCJ9},
+ {.variant = KXCJ9},
+};
/* Matrix to rotate accelrator into standard reference frame */
const matrix_3x3_t base_standard_ref = {
@@ -213,7 +217,7 @@ struct motion_sensor_t motion_sensors[] = {
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
.location = MOTIONSENSE_LOC_BASE,
- .drv = &kxcj9_drv,
+ .drv = &kionix_accel_drv,
.mutex = &g_kxcj9_mutex[0],
.drv_data = &g_kxcj9_data[0],
.addr = KXCJ9_ADDR1,
@@ -247,7 +251,7 @@ struct motion_sensor_t motion_sensors[] = {
.chip = MOTIONSENSE_CHIP_KXCJ9,
.type = MOTIONSENSE_TYPE_ACCEL,
.location = MOTIONSENSE_LOC_LID,
- .drv = &kxcj9_drv,
+ .drv = &kionix_accel_drv,
.mutex = &g_kxcj9_mutex[1],
.drv_data = &g_kxcj9_data[1],
.addr = KXCJ9_ADDR0,
diff --git a/common/build.mk b/common/build.mk
index 312797ce87..6c534cbbd6 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -12,6 +12,7 @@ common-y+=version.o printf.o queue.o queue_policies.o
common-$(CONFIG_ACCELGYRO_BMI160)+=math_util.o
common-$(CONFIG_ACCELGYRO_LSM6DS0)+=math_util.o
common-$(CONFIG_ACCEL_KXCJ9)+=math_util.o
+common-$(CONFIG_ACCEL_KX022)+=math_util.o
common-$(CONFIG_ADC)+=adc.o
common-$(CONFIG_ALS)+=als.o
common-$(CONFIG_AP_HANG_DETECT)+=ap_hang_detect.o
diff --git a/driver/accel_kionix.c b/driver/accel_kionix.c
new file mode 100644
index 0000000000..8d86a5bbce
--- /dev/null
+++ b/driver/accel_kionix.c
@@ -0,0 +1,509 @@
+/* Copyright 2015 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.
+ */
+
+/*
+ * Kionix Accelerometer driver for Chrome EC
+ *
+ * Supported: KX022, KXCJ9
+ */
+
+#include "accelgyro.h"
+#include "common.h"
+#include "console.h"
+#include "driver/accel_kionix.h"
+#include "driver/accel_kx022.h"
+#include "driver/accel_kxcj9.h"
+#include "i2c.h"
+#include "math_util.h"
+#include "task.h"
+#include "util.h"
+
+#define CPUTS(outstr) cputs(CC_ACCEL, outstr)
+#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args)
+
+/* Number of times to attempt to enable sensor before giving up. */
+#define SENSOR_ENABLE_ATTEMPTS 3
+
+/* Index for which table to use. */
+#if !defined(CONFIG_ACCEL_KXCJ9) || !defined(CONFIG_ACCEL_KX022)
+#define T 0
+#else
+#define T (data->variant)
+#endif /* !defined(CONFIG_ACCEL_KXCJ9) || !defined(CONFIG_ACCEL_KX022) */
+
+/* List of range values in +/-G's and their associated register values. */
+static const struct accel_param_pair ranges[][3] = {
+#ifdef CONFIG_ACCEL_KX022
+ { {2, KX022_GSEL_2G},
+ {4, KX022_GSEL_4G},
+ {8, KX022_GSEL_8G} },
+#endif /* defined(CONFIG_ACCEL_KX022) */
+#ifdef CONFIG_ACCEL_KXCJ9
+ { {2, KXCJ9_GSEL_2G},
+ {4, KXCJ9_GSEL_4G},
+ {8, KXCJ9_GSEL_8G_14BIT} },
+#endif /* defined(CONFIG_ACCEL_KXCJ9) */
+};
+
+/* List of resolution values in bits and their associated register values. */
+static const struct accel_param_pair resolutions[][2] = {
+#ifdef CONFIG_ACCEL_KX022
+ { {8, KX022_RES_8BIT},
+ {16, KX022_RES_16BIT} },
+#endif /* defined(CONFIG_ACCEL_KX022) */
+#ifdef CONFIG_ACCEL_KXCJ9
+ { {8, KXCJ9_RES_8BIT},
+ {12, KXCJ9_RES_12BIT} },
+#endif /* defined(CONFIG_ACCEL_KXCJ9) */
+};
+
+/* List of ODR values in mHz and their associated register values. */
+static const struct accel_param_pair datarates[][13] = {
+#ifdef CONFIG_ACCEL_KX022
+ /* One duplicate because table sizes must match. */
+ { {781, KX022_OSA_0_781HZ},
+ {781, KX022_OSA_0_781HZ},
+ {1563, KX022_OSA_1_563HZ},
+ {3125, KX022_OSA_3_125HZ},
+ {6250, KX022_OSA_6_250HZ},
+ {12500, KX022_OSA_12_50HZ},
+ {25000, KX022_OSA_25_00HZ},
+ {50000, KX022_OSA_50_00HZ},
+ {100000, KX022_OSA_100_0HZ},
+ {200000, KX022_OSA_200_0HZ},
+ {400000, KX022_OSA_400_0HZ},
+ {800000, KX022_OSA_800_0HZ},
+ {1600000, KX022_OSA_1600HZ} },
+#endif /* defined(CONFIG_ACCEL_KX022) */
+#ifdef CONFIG_ACCEL_KXCJ9
+ { {0, KXCJ9_OSA_0_000HZ},
+ {781, KXCJ9_OSA_0_781HZ},
+ {1563, KXCJ9_OSA_1_563HZ},
+ {3125, KXCJ9_OSA_3_125HZ},
+ {6250, KXCJ9_OSA_6_250HZ},
+ {12500, KXCJ9_OSA_12_50HZ},
+ {25000, KXCJ9_OSA_25_00HZ},
+ {50000, KXCJ9_OSA_50_00HZ},
+ {100000, KXCJ9_OSA_100_0HZ},
+ {200000, KXCJ9_OSA_200_0HZ},
+ {400000, KXCJ9_OSA_400_0HZ},
+ {800000, KXCJ9_OSA_800_0HZ},
+ {1600000, KXCJ9_OSA_1600_HZ} },
+#endif /* defined(CONFIG_ACCEL_KXCJ9) */
+};
+
+/**
+ * Find index into a accel_param_pair that matches the given engineering value
+ * passed in. The round_up flag is used to specify whether to round up or down.
+ * Note, this function always returns a valid index. If the request is
+ * outside the range of values, it returns the closest valid index.
+ */
+static int find_param_index(const int eng_val, const int round_up,
+ const struct accel_param_pair *pairs,
+ const int size)
+{
+ int i;
+
+ /* Linear search for index to match. */
+ for (i = 0; i < size - 1; i++) {
+ if (eng_val <= pairs[i].val)
+ return i;
+
+ if (eng_val < pairs[i+1].val) {
+ if (round_up)
+ return i + 1;
+ else
+ return i;
+ }
+ }
+
+ return i;
+}
+
+/**
+ * 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);
+}
+
+/**
+ * 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);
+}
+
+/**
+ * Disable sensor by taking it out of operating mode. When disabled, the
+ * acceleration data does not change.
+ *
+ * Note: This is intended to be called in a pair with enable_sensor().
+ *
+ * @s Pointer to motion sensor data
+ * @reg_val Pointer to location to store control register after disabling
+ *
+ * @return EC_SUCCESS if successful, EC_ERROR_* otherwise
+ */
+static int disable_sensor(const struct motion_sensor_t *s, int *reg_val)
+{
+ int i, ret, reg, pc1_field;
+ struct kionix_accel_data *data = s->drv_data;
+
+ reg = KIONIX_CTRL1_REG(data->variant);
+ pc1_field = KIONIX_PC1_FIELD(data->variant);
+
+ /*
+ * Read the current state of the control register
+ * so that we can restore it later.
+ */
+ for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) {
+ ret = raw_read8(s->addr, reg, reg_val);
+ if (ret != EC_SUCCESS)
+ continue;
+
+ *reg_val &= ~pc1_field;
+
+ ret = raw_write8(s->addr, reg, *reg_val);
+ if (ret == EC_SUCCESS)
+ return EC_SUCCESS;
+ }
+ return ret;
+}
+
+/**
+ * Enable sensor by placing it in operating mode.
+ *
+ * Note: This is intended to be called in a pair with disable_sensor().
+ *
+ * @s Pointer to motion sensor data
+ * @reg_val Value of the control register to write to sensor
+ *
+ * @return EC_SUCCESS if successful, EC_ERROR_* otherwise
+ */
+static int enable_sensor(const struct motion_sensor_t *s, int reg_val)
+{
+ int i, ret, reg, pc1_field;
+ struct kionix_accel_data *data = s->drv_data;
+
+ reg = KIONIX_CTRL1_REG(data->variant);
+ pc1_field = KIONIX_PC1_FIELD(data->variant);
+
+ for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) {
+ ret = raw_read8(s->addr, reg, &reg_val);
+ if (ret != EC_SUCCESS)
+ continue;
+
+ /* Enable accelerometer based on reg_val value. */
+ ret = raw_write8(s->addr, reg,
+ reg_val | pc1_field);
+
+ /* On first success, we are done. */
+ if (ret == EC_SUCCESS)
+ return EC_SUCCESS;
+ }
+ return ret;
+}
+
+static int set_range(const struct motion_sensor_t *s, int range, int rnd)
+{
+ int ret, reg_val, reg_val_new, index, range_field, reg, range_val;
+ struct kionix_accel_data *data = s->drv_data;
+
+ /* Find index for interface pair matching the specified range. */
+ index = find_param_index(range, rnd, ranges[T], ARRAY_SIZE(ranges[T]));
+ range_field = KIONIX_RANGE_FIELD(data->variant);
+ reg = KIONIX_CTRL1_REG(data->variant);
+ range_val = ranges[T][index].reg;
+
+ /* Disable the sensor to allow for changing of critical parameters. */
+ mutex_lock(s->mutex);
+ ret = disable_sensor(s, &reg_val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+
+ /* Determine new value of control reg and attempt to write it. */
+ reg_val_new = (reg_val & ~range_field) | range_val;
+ ret = raw_write8(s->addr, reg, reg_val_new);
+
+ /* If successfully written, then save the range. */
+ if (ret == EC_SUCCESS) {
+ data->sensor_range = index;
+ reg_val = reg_val_new;
+ }
+
+ /* Re-enable the sensor. */
+ if (enable_sensor(s, reg_val) != EC_SUCCESS)
+ ret = EC_ERROR_UNKNOWN;
+
+ mutex_unlock(s->mutex);
+ return ret;
+}
+
+static int get_range(const struct motion_sensor_t *s)
+{
+ struct kionix_accel_data *data = s->drv_data;
+ return ranges[T][data->sensor_range].val;
+}
+
+static int set_resolution(const struct motion_sensor_t *s, int res, int rnd)
+{
+ int ret, reg_val, reg_val_new, index, reg, res_field, res_val;
+ struct kionix_accel_data *data = s->drv_data;
+
+ /* Find index for interface pair matching the specified resolution. */
+ index = find_param_index(res, rnd, resolutions[T],
+ ARRAY_SIZE(resolutions[T]));
+ res_val = resolutions[T][index].reg;
+ res_field = KIONIX_RES_FIELD(data->variant);
+ reg = KIONIX_CTRL1_REG(data->variant);
+
+ /* Disable the sensor to allow for changing of critical parameters. */
+ mutex_lock(s->mutex);
+ ret = disable_sensor(s, &reg_val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+
+ /* Determine new value of the control reg and attempt to write it. */
+ reg_val_new = (reg_val & ~res_field) | res_val;
+ ret = raw_write8(s->addr, reg, reg_val_new);
+
+ /* If successfully written, then save the range. */
+ if (ret == EC_SUCCESS) {
+ data->sensor_resolution = index;
+ reg_val = reg_val_new;
+ }
+
+ /* Re-enable the sensor. */
+ if (enable_sensor(s, reg_val) != EC_SUCCESS)
+ ret = EC_ERROR_UNKNOWN;
+
+ mutex_unlock(s->mutex);
+ return ret;
+}
+
+static int get_resolution(const struct motion_sensor_t *s)
+{
+ struct kionix_accel_data *data = s->drv_data;
+ return resolutions[T][data->sensor_resolution].val;
+}
+
+static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd)
+{
+ int ret, reg_val, index, odr_val, odr_val_new, reg, odr_field,
+ odr_reg_val;
+ struct kionix_accel_data *data = s->drv_data;
+
+ /* Find index for interface pair matching the specified rate. */
+ index = find_param_index(rate, rnd, datarates[T],
+ ARRAY_SIZE(datarates[T]));
+ odr_val = datarates[T][index].reg;
+ reg = KIONIX_ODR_REG(data->variant);
+ odr_field = KIONIX_ODR_FIELD(data->variant);
+
+ /* Disable the sensor to allow for changing of critical parameters. */
+ mutex_lock(s->mutex);
+ ret = disable_sensor(s, &reg_val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+
+ /* Determine the new value of control reg and attempt to write it. */
+ ret = raw_read8(s->addr, reg, &odr_reg_val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+ odr_val_new = (odr_reg_val & ~odr_field) | odr_val;
+ /* Set output data rate. */
+ ret = raw_write8(s->addr, reg, odr_val_new);
+
+ /* If successfully written, then save the new data rate. */
+ if (ret == EC_SUCCESS)
+ data->sensor_datarate = index;
+
+ /* Re-enable the sensor. */
+ if (enable_sensor(s, reg_val) != EC_SUCCESS)
+ ret = EC_ERROR_UNKNOWN;
+
+ mutex_unlock(s->mutex);
+ return ret;
+}
+
+static int get_data_rate(const struct motion_sensor_t *s)
+{
+ struct kionix_accel_data *data = s->drv_data;
+ return datarates[T][data->sensor_datarate].val;
+}
+
+static int set_offset(const struct motion_sensor_t *s, const int16_t *offset,
+ int16_t temp)
+{
+ /* temperature is ignored */
+ struct kionix_accel_data *data = s->drv_data;
+ data->offset[X] = offset[X];
+ data->offset[Y] = offset[Y];
+ data->offset[Z] = offset[Z];
+ return EC_SUCCESS;
+}
+
+static int get_offset(const struct motion_sensor_t *s, int16_t *offset,
+ int16_t *temp)
+{
+ struct kionix_accel_data *data = s->drv_data;
+ offset[X] = data->offset[X];
+ offset[Y] = data->offset[Y];
+ offset[Z] = data->offset[Z];
+ *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP;
+ return EC_SUCCESS;
+}
+
+static int read(const struct motion_sensor_t *s, vector_3_t v)
+{
+ uint8_t acc[6];
+ uint8_t reg;
+ int ret, i, range, resolution;
+ struct kionix_accel_data *data = s->drv_data;
+
+ /* Read 6 bytes starting at XOUT_L. */
+ reg = KIONIX_XOUT_L(data->variant);
+ mutex_lock(s->mutex);
+ i2c_lock(I2C_PORT_ACCEL, 1);
+ ret = i2c_xfer(I2C_PORT_ACCEL, s->addr, &reg, 1, acc, 6,
+ I2C_XFER_SINGLE);
+ i2c_lock(I2C_PORT_ACCEL, 0);
+ mutex_unlock(s->mutex);
+
+ if (ret != EC_SUCCESS)
+ return ret;
+
+ /*
+ * Convert acceleration to a signed 16-bit number. Note, based on
+ * the order of the registers:
+ *
+ * acc[0] = XOUT_L
+ * acc[1] = XOUT_H
+ * acc[2] = YOUT_L
+ * acc[3] = YOUT_H
+ * acc[4] = ZOUT_L
+ * acc[5] = ZOUT_H
+ *
+ * Add calibration offset before returning the data.
+ */
+ resolution = get_resolution(s);
+ for (i = X; i <= Z; i++) {
+ if (KXCJ9 == data->variant) {
+ v[i] = (((int8_t)acc[i * 2 + 1]) << 4) |
+ (acc[i * 2] >> 4);
+ v[i] <<= 16 - resolution;
+ } else if (KX022 == data->variant) {
+ if (resolution == 8)
+ acc[i * 2] = 0;
+ v[i] = (((int8_t)acc[i * 2 + 1]) << 8) | acc[i * 2];
+ }
+ }
+ rotate(v, *s->rot_standard_ref, v);
+
+ /* apply offset in the device coordinates */
+ range = get_range(s);
+ for (i = X; i <= Z; i++)
+ v[i] += (data->offset[i] << 5) / range;
+
+ return EC_SUCCESS;
+}
+
+static int init(const struct motion_sensor_t *s)
+{
+ int ret, val, reg, reset_field;
+ uint8_t timeout;
+ struct kionix_accel_data *data = s->drv_data;
+
+ reg = KIONIX_CTRL2_REG(data->variant);
+ reset_field = KIONIX_RESET_FIELD(data->variant);
+
+ /* Issue a software reset. */
+ mutex_lock(s->mutex);
+
+ /* Place the sensor in standby mode to make changes. */
+ ret = disable_sensor(s, &val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+ ret = raw_read8(s->addr, reg, &val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+ val |= reset_field;
+ ret = raw_write8(s->addr, reg, val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+
+ /* The SRST will be cleared when reset is complete. */
+ timeout = 0;
+ do {
+ msleep(1);
+
+ ret = raw_read8(s->addr, reg, &val);
+ if (ret != EC_SUCCESS) {
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+
+ /* Reset complete. */
+ if ((ret == EC_SUCCESS) && !(val & reset_field))
+ break;
+
+ /* Check for timeout. */
+ if (timeout++ > 5) {
+ ret = EC_ERROR_TIMEOUT;
+ mutex_unlock(s->mutex);
+ return ret;
+ }
+ } while (1);
+ mutex_unlock(s->mutex);
+
+ /* Initialize with the desired parameters. */
+ ret = set_range(s, s->default_range, 1);
+ if (ret != EC_SUCCESS)
+ return ret;
+
+ if (KXCJ9 == data->variant)
+ ret = set_resolution(s, 12, 1);
+ else if (KX022 == data->variant)
+ ret = set_resolution(s, 16, 1);
+ if (ret != EC_SUCCESS)
+ return ret;
+
+ CPRINTF("[%T %s: Done Init type:0x%X range:%d]\n",
+ s->name, s->type, get_range(s));
+
+ mutex_unlock(s->mutex);
+ return ret;
+}
+
+const struct accelgyro_drv kionix_accel_drv = {
+ .init = init,
+ .read = read,
+ .set_range = set_range,
+ .get_range = get_range,
+ .set_resolution = set_resolution,
+ .get_resolution = get_resolution,
+ .set_data_rate = set_data_rate,
+ .get_data_rate = get_data_rate,
+ .set_offset = set_offset,
+ .get_offset = get_offset,
+ .perform_calib = NULL,
+};
diff --git a/driver/accel_kionix.h b/driver/accel_kionix.h
new file mode 100644
index 0000000000..e326dd3cb3
--- /dev/null
+++ b/driver/accel_kionix.h
@@ -0,0 +1,66 @@
+/* Copyright 2015 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.
+ */
+
+/* Kionix Accelerometer driver for Chrome EC */
+
+#ifndef __CROS_EC_ACCEL_KIONIX_H
+#define __CROS_EC_ACCEL_KIONIX_H
+
+#include "common.h"
+#include "driver/accel_kx022.h"
+#include "driver/accel_kxcj9.h"
+
+enum kionix_accel {
+ KX022,
+ KXCJ9,
+ SUPPORTED_KIONIX_ACCELS,
+};
+
+/*
+ * Struct for pairing an engineering value with the register value for a
+ * parameter.
+ */
+struct accel_param_pair {
+ int val; /* Value in engineering units. */
+ int reg; /* Corresponding register value. */
+};
+
+struct kionix_accel_data {
+ /* Variant of Kionix Accelerometer. */
+ uint8_t variant;
+ /* Note, the following are indicies into their respective tables. */
+ /* Current range of accelerometer. */
+ int sensor_range;
+ /* Current output data rate of accelerometer. */
+ int sensor_datarate;
+ /* Current resolution of accelerometer. */
+ int sensor_resolution;
+ /* Device address. */
+ int accel_addr;
+ int16_t offset[3];
+};
+
+extern const struct accelgyro_drv kionix_accel_drv;
+
+#define KIONIX_CTRL1_REG(v) (KX022_CNTL1 + \
+ (v) * (KXCJ9_CTRL1 - KX022_CNTL1))
+#define KIONIX_CTRL2_REG(v) (KX022_CNTL2 + \
+ (v) * (KXCJ9_CTRL2 - KX022_CNTL2))
+#define KIONIX_ODR_REG(v) (KX022_ODCNTL + \
+ (v) * (KXCJ9_DATA_CTRL - KX022_ODCNTL))
+#define KIONIX_ODR_FIELD(v) (KX022_OSA_FIELD + \
+ (v) * (KXCJ9_OSA_FIELD - KX022_OSA_FIELD))
+#define KIONIX_PC1_FIELD(v) (KX022_CNTL1_PC1 + \
+ (v) * (KXCJ9_CTRL1_PC1 - KX022_CNTL1_PC1))
+#define KIONIX_RANGE_FIELD(v) (KX022_GSEL_FIELD + \
+ (v) * (KXCJ9_GSEL_ALL - KX022_GSEL_FIELD))
+#define KIONIX_RES_FIELD(v) (KX022_RES_16BIT + \
+ (v) * (KXCJ9_RES_12BIT - KX022_RES_16BIT))
+#define KIONIX_RESET_FIELD(v) (KX022_CNTL2_SRST + \
+ (v) * (KXCJ9_CTRL2_SRST - KX022_CNTL2_SRST))
+#define KIONIX_XOUT_L(v) (KX022_XOUT_L + \
+ (v) * (KXCJ9_XOUT_L - KX022_XOUT_L))
+
+#endif /* __CROS_EC_ACCEL_KIONIX_H */
diff --git a/driver/accel_kx022.h b/driver/accel_kx022.h
new file mode 100644
index 0000000000..3ed95a30a8
--- /dev/null
+++ b/driver/accel_kx022.h
@@ -0,0 +1,122 @@
+/* Copyright 2015 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.
+ */
+
+/* KX022 gsensor module for Chrome EC */
+
+#ifndef __CROS_EC_ACCEL_KX022_H
+#define __CROS_EC_ACCEL_KX022_H
+
+/*
+ * 7-bit address is 001111Xb. Where 'X' is determined
+ * by the voltage on the ADDR pin.
+ */
+#define KX022_ADDR0 0x3c
+#define KX022_ADDR1 0x3e
+
+/* Chip-specific registers */
+#define KX022_XHP_L 0x00
+#define KX022_XHP_H 0x01
+#define KX022_YHP_L 0x02
+#define KX022_YHP_H 0x03
+#define KX022_ZHP_L 0x04
+#define KX022_ZHP_H 0x05
+#define KX022_XOUT_L 0x06
+#define KX022_XOUT_H 0x07
+#define KX022_YOUT_L 0x08
+#define KX022_YOUT_H 0x09
+#define KX022_ZOUT_L 0x0a
+#define KX022_ZOUT_H 0x0b
+#define KX022_COTR 0x0c
+#define KX022_WHOAMI 0x0f
+#define KX022_TSCP 0x10
+#define KX022_TSPP 0x11
+#define KX022_INS1 0x12
+#define KX022_INS2 0x13
+#define KX022_INS3 0x14
+#define KX022_STATUS_REG 0x15
+#define KX022_INT_REL 0x17
+#define KX022_CNTL1 0x18
+#define KX022_CNTL2 0x19
+#define KX022_CNTL3 0x1a
+#define KX022_ODCNTL 0x1b
+#define KX022_INC1 0x1c
+#define KX022_INC2 0x1d
+#define KX022_INC3 0x1e
+#define KX022_INC4 0x1f
+#define KX022_INC5 0x20
+#define KX022_INC6 0x21
+#define KX022_TILT_TIMER 0x22
+#define KX022_WUFC 0x23
+#define KX022_TDTRC 0x24
+#define KX022_TDTC 0x25
+#define KX022_TTH 0x26
+#define KX022_TTL 0x27
+#define KX022_FTD 0x28
+#define KX022_STD 0x29
+#define KX022_TLT 0x2a
+#define KX022_TWS 0x2b
+#define KX022_ATH 0x30
+#define KX022_TILT_ANGLE_LL 0x32
+#define KX022_TILT_ANGLE_HL 0x33
+#define KX022_HYST_SET 0x34
+#define KX022_LP_CNTL 0x35
+#define KX022_BUF_CNTL1 0x3a
+#define KX022_BUF_CNTL2 0x3b
+#define KX022_BUF_STATUS_1 0x3c
+#define KX022_BUF_STATUS_2 0x3d
+#define KX022_BUF_CLEAR 0x3e
+#define KX022_BUF_READ 0x3f
+#define KX022_SELF_TEST 0x60
+
+
+#define KX022_CNTL1_PC1 (1 << 7)
+#define KX022_CNTL1_WUFE (1 << 1)
+
+#define KX022_CNTL2_SRST (1 << 7)
+
+#define KX022_CNTL3_OWUF_FIELD 7
+
+#define KX022_INC1_IEA (1 << 4)
+#define KX022_INC1_IEN (1 << 5)
+
+#define KX022_GSEL_2G (0 << 3)
+#define KX022_GSEL_4G (1 << 3)
+#define KX022_GSEL_8G (2 << 3)
+#define KX022_GSEL_FIELD (3 << 3)
+
+#define KX022_RES_8BIT (0 << 6)
+#define KX022_RES_16BIT (1 << 6)
+
+#define KX022_OSA_0_781HZ 8
+#define KX022_OSA_1_563HZ 9
+#define KX022_OSA_3_125HZ 0xa
+#define KX022_OSA_6_250HZ 0xb
+#define KX022_OSA_12_50HZ 0
+#define KX022_OSA_25_00HZ 1
+#define KX022_OSA_50_00HZ 2
+#define KX022_OSA_100_0HZ 3
+#define KX022_OSA_200_0HZ 4
+#define KX022_OSA_400_0HZ 5
+#define KX022_OSA_800_0HZ 6
+#define KX022_OSA_1600HZ 7
+#define KX022_OSA_FIELD 0xf
+
+#define KX022_OWUF_0_781HZ 0
+#define KX022_OWUF_1_563HZ 1
+#define KX022_OWUF_3_125HZ 2
+#define KX022_OWUF_6_250HZ 3
+#define KX022_OWUF_12_50HZ 4
+#define KX022_OWUF_25_00HZ 5
+#define KX022_OWUF_50_00HZ 6
+#define KX022_OWUF_100_0HZ 7
+
+#define KX022_INC2_ZPWUE (1 << 0)
+#define KX022_INC2_ZNWUE (1 << 1)
+#define KX022_INC2_YPWUE (1 << 2)
+#define KX022_INC2_YNWUE (1 << 3)
+#define KX022_INC2_XPWUE (1 << 4)
+#define KX022_INC2_XNWUE (1 << 5)
+
+#endif /* __CROS_EC_ACCEL_KX022_H */
diff --git a/driver/accel_kxcj9.c b/driver/accel_kxcj9.c
deleted file mode 100644
index dd0cf49115..0000000000
--- a/driver/accel_kxcj9.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/* 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 "accelgyro.h"
-#include "common.h"
-#include "console.h"
-#include "driver/accel_kxcj9.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "math_util.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_ACCEL, outstr)
-#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args)
-
-/* Number of times to attempt to enable sensor before giving up. */
-#define SENSOR_ENABLE_ATTEMPTS 3
-
-/*
- * Struct for pairing an engineering value with the register value for a
- * parameter.
- */
-struct accel_param_pair {
- int val; /* Value in engineering units. */
- int reg; /* Corresponding register value. */
-};
-
-/* List of range values in +/-G's and their associated register values. */
-static const struct accel_param_pair ranges[] = {
- {2, KXCJ9_GSEL_2G},
- {4, KXCJ9_GSEL_4G},
- {8, KXCJ9_GSEL_8G_14BIT}
-};
-
-/* List of resolution values in bits and their associated register values. */
-static const struct accel_param_pair resolutions[] = {
- {8, KXCJ9_RES_8BIT},
- {12, KXCJ9_RES_12BIT}
-};
-
-/* List of ODR values in mHz and their associated register values. */
-static const struct accel_param_pair datarates[] = {
- {0, KXCJ9_OSA_0_000HZ},
- {781, KXCJ9_OSA_0_781HZ},
- {1563, KXCJ9_OSA_1_563HZ},
- {3125, KXCJ9_OSA_3_125HZ},
- {6250, KXCJ9_OSA_6_250HZ},
- {12500, KXCJ9_OSA_12_50HZ},
- {25000, KXCJ9_OSA_25_00HZ},
- {50000, KXCJ9_OSA_50_00HZ},
- {100000, KXCJ9_OSA_100_0HZ},
- {200000, KXCJ9_OSA_200_0HZ},
- {400000, KXCJ9_OSA_400_0HZ},
- {800000, KXCJ9_OSA_800_0HZ},
- {1600000, KXCJ9_OSA_1600_HZ}
-};
-
-/**
- * Find index into a accel_param_pair that matches the given engineering value
- * passed in. The round_up flag is used to specify whether to round up or down.
- * Note, this function always returns a valid index. If the request is
- * outside the range of values, it returns the closest valid index.
- */
-static int find_param_index(const int eng_val, const int round_up,
- const struct accel_param_pair *pairs, const int size)
-{
- int i;
-
- /* Linear search for index to match. */
- for (i = 0; i < size - 1; i++) {
- if (eng_val <= pairs[i].val)
- return i;
-
- if (eng_val < pairs[i+1].val) {
- if (round_up)
- return i + 1;
- else
- return i;
- }
- }
-
- return i;
-}
-
-/**
- * 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);
-}
-
-/**
- * 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);
-}
-
-/**
- * Disable sensor by taking it out of operating mode. When disabled, the
- * acceleration data does not change.
- *
- * Note: This is intended to be called in a pair with enable_sensor().
- *
- * @data Pointer to motion sensor data
- * @ctrl1 Pointer to location to store KXCJ9_CTRL1 register after disabling
- *
- * @return EC_SUCCESS if successful, EC_ERROR_* otherwise
- */
-static int disable_sensor(const struct motion_sensor_t *s, int *ctrl1)
-{
- int i, ret;
-
- /*
- * Read the current state of the ctrl1 register
- * so that we can restore it later.
- */
- for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) {
- ret = raw_read8(s->addr, KXCJ9_CTRL1, ctrl1);
- if (ret != EC_SUCCESS)
- continue;
-
- *ctrl1 &= ~KXCJ9_CTRL1_PC1;
-
- ret = raw_write8(s->addr, KXCJ9_CTRL1, *ctrl1);
- if (ret == EC_SUCCESS)
- return EC_SUCCESS;
- }
- return ret;
-}
-
-/**
- * Enable sensor by placing it in operating mode.
- *
- * Note: This is intended to be called in a pair with disable_sensor().
- *
- * @data Pointer to motion sensor data
- * @ctrl1 Value of KXCJ9_CTRL1 register to write to sensor
- *
- * @return EC_SUCCESS if successful, EC_ERROR_* otherwise
- */
-static int enable_sensor(const struct motion_sensor_t *s, int ctrl1)
-{
- int i, ret;
-
- for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) {
- ret = raw_read8(s->addr, KXCJ9_CTRL1, &ctrl1);
- if (ret != EC_SUCCESS)
- continue;
-
- /* Enable accelerometer based on ctrl1 value. */
- ret = raw_write8(s->addr, KXCJ9_CTRL1,
- ctrl1 | KXCJ9_CTRL1_PC1);
-
- /* On first success, we are done. */
- if (ret == EC_SUCCESS)
- return EC_SUCCESS;
- }
- return ret;
-}
-
-static int set_range(const struct motion_sensor_t *s,
- int range,
- int rnd)
-{
- int ret, ctrl1, ctrl1_new, index;
- struct kxcj9_data *data = s->drv_data;
-
- /* Find index for interface pair matching the specified range. */
- index = find_param_index(range, rnd, ranges, ARRAY_SIZE(ranges));
-
- /* Disable the sensor to allow for changing of critical parameters. */
- mutex_lock(s->mutex);
- ret = disable_sensor(s, &ctrl1);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
- }
-
- /* Determine new value of CTRL1 reg and attempt to write it. */
- ctrl1_new = (ctrl1 & ~KXCJ9_GSEL_ALL) | ranges[index].reg;
- ret = raw_write8(s->addr, KXCJ9_CTRL1, ctrl1_new);
-
- /* If successfully written, then save the range. */
- if (ret == EC_SUCCESS) {
- data->sensor_range = index;
- ctrl1 = ctrl1_new;
- }
-
- /* Re-enable the sensor. */
- if (enable_sensor(s, ctrl1) != EC_SUCCESS)
- ret = EC_ERROR_UNKNOWN;
-
- mutex_unlock(s->mutex);
- return ret;
-}
-
-static int get_range(const struct motion_sensor_t *s)
-{
- struct kxcj9_data *data = s->drv_data;
- return ranges[data->sensor_range].val;
-}
-
-static int set_resolution(const struct motion_sensor_t *s,
- int res,
- int rnd)
-{
- int ret, ctrl1, ctrl1_new, index;
- struct kxcj9_data *data = s->drv_data;
-
- /* Find index for interface pair matching the specified resolution. */
- index = find_param_index(res, rnd, resolutions,
- ARRAY_SIZE(resolutions));
-
- /* Disable the sensor to allow for changing of critical parameters. */
- mutex_lock(s->mutex);
- ret = disable_sensor(s, &ctrl1);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
- }
-
- /* Determine new value of CTRL1 reg and attempt to write it. */
- ctrl1_new = (ctrl1 & ~KXCJ9_RES_12BIT) | resolutions[index].reg;
- ret = raw_write8(s->addr, KXCJ9_CTRL1, ctrl1_new);
-
- /* If successfully written, then save the range. */
- if (ret == EC_SUCCESS) {
- data->sensor_resolution = index;
- ctrl1 = ctrl1_new;
- }
-
- /* Re-enable the sensor. */
- if (enable_sensor(s, ctrl1) != EC_SUCCESS)
- ret = EC_ERROR_UNKNOWN;
-
- mutex_unlock(s->mutex);
- return ret;
-}
-
-static int get_resolution(const struct motion_sensor_t *s)
-{
- struct kxcj9_data *data = s->drv_data;
- return resolutions[data->sensor_resolution].val;
-}
-
-static int set_data_rate(const struct motion_sensor_t *s,
- int rate,
- int rnd)
-{
- int ret, ctrl1, index;
- struct kxcj9_data *data = s->drv_data;
-
- /* Find index for interface pair matching the specified rate. */
- index = find_param_index(rate, rnd, datarates, ARRAY_SIZE(datarates));
-
- /* Disable the sensor to allow for changing of critical parameters. */
- mutex_lock(s->mutex);
- ret = disable_sensor(s, &ctrl1);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
- }
-
- /* Set output data rate. */
- ret = raw_write8(s->addr, KXCJ9_DATA_CTRL,
- datarates[index].reg);
-
- /* If successfully written, then save the range. */
- if (ret == EC_SUCCESS)
- data->sensor_datarate = index;
-
- /* Re-enable the sensor. */
- if (enable_sensor(s, ctrl1) != EC_SUCCESS)
- ret = EC_ERROR_UNKNOWN;
-
- mutex_unlock(s->mutex);
- return ret;
-}
-
-static int get_data_rate(const struct motion_sensor_t *s)
-{
- struct kxcj9_data *data = s->drv_data;
- return datarates[data->sensor_datarate].val;
-}
-
-static int set_offset(const struct motion_sensor_t *s,
- const int16_t *offset,
- int16_t temp)
-{
- /* temperature is ignored */
- struct kxcj9_data *data = s->drv_data;
- data->offset[X] = offset[X];
- data->offset[Y] = offset[Y];
- data->offset[Z] = offset[Z];
- return EC_SUCCESS;
-}
-
-static int get_offset(const struct motion_sensor_t *s,
- int16_t *offset,
- int16_t *temp)
-{
- struct kxcj9_data *data = s->drv_data;
- offset[X] = data->offset[X];
- offset[Y] = data->offset[Y];
- offset[Z] = data->offset[Z];
- *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP;
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_ACCEL_INTERRUPTS
-static int set_interrupt(const struct motion_sensor_t *s,
- unsigned int threshold)
-{
- int ctrl1, tmp, ret;
- struct kxcj9_data *data = s->drv_data;
-
- /* Disable the sensor to allow for changing of critical parameters. */
- mutex_lock(s->mutex);
- ret = disable_sensor(s, &ctrl1);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
- }
-
- /* Set interrupt timer to 1 so it wakes up immediately. */
- ret = raw_write8(s->addr, KXCJ9_WAKEUP_TIMER, 1);
- if (ret != EC_SUCCESS)
- goto error_enable_sensor;
-
- /*
- * Set threshold, note threshold register is in units of 16 counts, so
- * first we need to divide by 16 to get the value to send.
- */
- threshold >>= 4;
- ret = raw_write8(s->addr, KXCJ9_WAKEUP_THRESHOLD, threshold);
- if (ret != EC_SUCCESS)
- goto error_enable_sensor;
-
- /*
- * Set interrupt enable register on sensor. Note that once this
- * function is called once, the interrupt stays enabled and it is
- * only necessary to clear KXCJ9_INT_REL to allow the next interrupt.
- */
- ret = raw_read8(s->addr, KXCJ9_INT_CTRL1, &tmp);
- if (ret != EC_SUCCESS)
- goto error_enable_sensor;
- if (!(tmp & KXCJ9_INT_CTRL1_IEN)) {
- ret = raw_write8(s->addr, KXCJ9_INT_CTRL1,
- tmp | KXCJ9_INT_CTRL1_IEN);
- if (ret != EC_SUCCESS)
- goto error_enable_sensor;
- }
-
- /*
- * Clear any pending interrupt on sensor by reading INT_REL register.
- * Note: this register latches motion detected above threshold. Once
- * latched, no interrupt can occur until this register is cleared.
- */
- ret = raw_read8(s->addr, KXCJ9_INT_REL, &tmp);
-
-error_enable_sensor:
- /* Re-enable the sensor. */
- if (enable_sensor(s, ctrl1) != EC_SUCCESS)
- ret = EC_ERROR_UNKNOWN;
- mutex_unlock(s->mutex);
- return ret;
-}
-#endif
-
-static int read(const struct motion_sensor_t *s, vector_3_t v)
-{
- uint8_t acc[6];
- uint8_t reg = KXCJ9_XOUT_L;
- int ret, i, range, resolution;
- struct kxcj9_data *data = s->drv_data;
-
- /* Read 6 bytes starting at KXCJ9_XOUT_L. */
- mutex_lock(s->mutex);
- i2c_lock(I2C_PORT_ACCEL, 1);
- ret = i2c_xfer(I2C_PORT_ACCEL, s->addr, &reg, 1, acc, 6,
- I2C_XFER_SINGLE);
- i2c_lock(I2C_PORT_ACCEL, 0);
- mutex_unlock(s->mutex);
-
- if (ret != EC_SUCCESS)
- return ret;
-
- /*
- * Convert acceleration to a signed 16-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
- *
- * Add calibration offset before returning the data.
- */
- resolution = get_resolution(s);
- for (i = X; i <= Z; i++) {
- v[i] = (((int8_t)acc[i * 2 + 1]) << 4) |
- (acc[i * 2] >> 4);
- v[i] <<= (16 - resolution);
- }
- rotate(v, *s->rot_standard_ref, v);
-
- /* apply offset in the device coordinates */
- range = get_range(s);
- for (i = X; i <= Z; i++)
- v[i] += (data->offset[i] << 5) / range;
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_ACCEL_INTERRUPTS
-static int config_interrupt(const struct motion_sensor_t *s)
-{
- int ctrl1;
- mutex_lock(s->mutex);
-
- /* Disable the sensor to allow for changing of critical parameters. */
- ret = disable_sensor(s, &ctrl1);
- if (ret != EC_SUCCESS)
- goto cleanup_exit;
-
- /* Enable wake up (motion detect) functionality. */
- ret = raw_read8(s->addr, KXCJ9_CTRL1, &tmp);
- tmp &= ~KXCJ9_CTRL1_PC1;
- tmp |= KXCJ9_CTRL1_WUFE;
- ret = raw_write8(s->addr, KXCJ9_CTRL1, tmp);
-
- /* Set interrupt polarity to rising edge and keep interrupt disabled. */
- ret = raw_write8(s->addr,
- KXCJ9_INT_CTRL1,
- KXCJ9_INT_CTRL1_IEA);
- if (ret != EC_SUCCESS)
- goto cleanup_exit;
-
- /* Set output data rate for wake-up interrupt function. */
- ret = raw_write8(s->addr, KXCJ9_CTRL2, KXCJ9_OWUF_100_0HZ);
- if (ret != EC_SUCCESS)
- goto cleanup_exit;
-
- /* Set interrupt to trigger on motion on any axis. */
- ret = raw_write8(s->addr, KXCJ9_INT_CTRL2,
- KXCJ9_INT_SRC2_XNWU | KXCJ9_INT_SRC2_XPWU |
- KXCJ9_INT_SRC2_YNWU | KXCJ9_INT_SRC2_YPWU |
- KXCJ9_INT_SRC2_ZNWU | KXCJ9_INT_SRC2_ZPWU);
- if (ret != EC_SUCCESS)
- goto cleanup_exit;
-
- /*
- * Enable accel interrupts. Note: accels will not initiate an interrupt
- * until interrupt enable bit in KXCJ9_INT_CTRL1 is set on the device.
- */
- gpio_enable_interrupt(GPIO_ACCEL_INT_LID);
- gpio_enable_interrupt(GPIO_ACCEL_INT_BASE);
-
- /* Enable the sensor. */
- ret = enable_sensor(s, ctrl1);
-cleanup_exit:
- mutex_unlock(s->mutex);
- return ret;
-}
-#endif
-
-static int init(const struct motion_sensor_t *s)
-{
- int ret = EC_SUCCESS;
- int cnt = 0, tmp;
-
- /*
- * This sensor can be powered through an EC reboot, so the state of
- * the sensor is unknown here. Initiate software reset to restore
- * sensor to default.
- */
- mutex_lock(s->mutex);
- ret = raw_write8(s->addr, KXCJ9_CTRL2, KXCJ9_CTRL2_SRST);
- mutex_unlock(s->mutex);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* Wait until software reset is complete or timeout. */
- do {
- /* Added 1m delay after software reset */
- msleep(1);
-
- ret = raw_read8(s->addr, KXCJ9_CTRL2, &tmp);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* Reset complete. */
- if (ret == EC_SUCCESS && !(tmp & KXCJ9_CTRL2_SRST))
- break;
-
- /* Check for timeout. */
- if (cnt++ > 5) {
- ret = EC_ERROR_TIMEOUT;
- return ret;
- }
- } while (1);
-
- ret = set_range(s, s->default_range, 1);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = set_resolution(s, 12, 1);
- if (ret != EC_SUCCESS)
- return ret;
-
-#ifdef CONFIG_ACCEL_INTERRUPTS
- config_interrupt(s);
-#endif
- CPRINTF("[%T %s: Done Init type:0x%X range:%d]\n",
- s->name, s->type, get_range(s));
-
- return ret;
-}
-
-const struct accelgyro_drv kxcj9_drv = {
- .init = init,
- .read = read,
- .set_range = set_range,
- .get_range = get_range,
- .set_resolution = set_resolution,
- .get_resolution = get_resolution,
- .set_data_rate = set_data_rate,
- .get_data_rate = get_data_rate,
- .set_offset = set_offset,
- .get_offset = get_offset,
- .perform_calib = NULL,
-#ifdef CONFIG_ACCEL_INTERRUPTS
- .set_interrupt = set_interrupt,
-#endif
-};
diff --git a/driver/accel_kxcj9.h b/driver/accel_kxcj9.h
index 6f8560e600..4436f38e8b 100644
--- a/driver/accel_kxcj9.h
+++ b/driver/accel_kxcj9.h
@@ -101,19 +101,6 @@
#define KXCJ9_OSA_400_0HZ 5
#define KXCJ9_OSA_800_0HZ 6
#define KXCJ9_OSA_1600_HZ 7
-
-struct kxcj9_data {
- /* Current range of accelerometer. */
- int sensor_range;
- /* Current output data rate of accelerometer. */
- int sensor_datarate;
- /* Current resolution of accelerometer. */
- int sensor_resolution;
- /* Device address. */
- int accel_addr;
- int16_t offset[3];
-};
-
-extern const struct accelgyro_drv kxcj9_drv;
+#define KXCJ9_OSA_FIELD 0xf
#endif /* __CROS_EC_ACCEL_KXCJ9_H */
diff --git a/driver/build.mk b/driver/build.mk
index 8875d45ccb..fe40382abd 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -7,7 +7,8 @@
#
# Accelerometers
-driver-$(CONFIG_ACCEL_KXCJ9)+=accel_kxcj9.o
+driver-$(CONFIG_ACCEL_KXCJ9)+=accel_kionix.o
+driver-$(CONFIG_ACCEL_KX022)+=accel_kionix.o
driver-$(CONFIG_ACCELGYRO_LSM6DS0)+=accelgyro_lsm6ds0.o
driver-$(CONFIG_ACCELGYRO_BMI160)+=accelgyro_bmi160.o
driver-$(CONFIG_MAG_BMI160_BMM150)+=mag_bmm150.o
diff --git a/include/config.h b/include/config.h
index 5aed0aac2e..e6d4409a5f 100644
--- a/include/config.h
+++ b/include/config.h
@@ -46,6 +46,7 @@
/* Specify type of accelerometers attached. */
#undef CONFIG_ACCEL_KXCJ9
+#undef CONFIG_ACCEL_KX022
#undef CONFIG_ACCELGYRO_LSM6DS0
#undef CONFIG_ACCELGYRO_BMI160
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 6fb784d5f9..f33b2bf16a 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1730,6 +1730,7 @@ enum motionsensor_chip {
MOTIONSENSE_CHIP_SI1141 = 3,
MOTIONSENSE_CHIP_SI1142 = 4,
MOTIONSENSE_CHIP_SI1143 = 5,
+ MOTIONSENSE_CHIP_KX022 = 6,
};
struct ec_response_motion_sensor_data {