diff options
-rw-r--r-- | board/cyan/board.c | 10 | ||||
-rw-r--r-- | board/kunimitsu/board.c | 10 | ||||
-rw-r--r-- | board/samus/board.c | 7 | ||||
-rw-r--r-- | board/strago/board.c | 10 | ||||
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | driver/accel_kionix.c | 509 | ||||
-rw-r--r-- | driver/accel_kionix.h | 66 | ||||
-rw-r--r-- | driver/accel_kx022.h | 122 | ||||
-rw-r--r-- | driver/accel_kxcj9.c | 546 | ||||
-rw-r--r-- | driver/accel_kxcj9.h | 15 | ||||
-rw-r--r-- | driver/build.mk | 3 | ||||
-rw-r--r-- | include/config.h | 1 | ||||
-rw-r--r-- | include/ec_commands.h | 1 |
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, ®_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, ®_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, ®_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, ®_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, ®, 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, ®, 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 { |