/* Copyright 2016 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. */ /** * Commons acc/gyro function for ST sensors in Chrome EC */ #include "stm_mems_common.h" /** * st_raw_read_n - Read n bytes for read */ int st_raw_read_n(const int port, const int addr, const uint8_t reg, uint8_t *data_ptr, const int len) { int rv = -EC_ERROR_PARAM1; uint8_t reg_a = reg | 0x80; /* TODO: Implement SPI interface support */ i2c_lock(port, 1); rv = i2c_xfer(port, addr, ®_a, 1, data_ptr, len, I2C_XFER_SINGLE); i2c_lock(port, 0); return rv; } /** * st_raw_read_n_noinc - Read n bytes for read (no auto inc address) */ int st_raw_read_n_noinc(const int port, const int addr, const uint8_t reg, uint8_t *data_ptr, const int len) { int rv = -EC_ERROR_PARAM1; /* TODO: Implement SPI interface support */ i2c_lock(port, 1); rv = i2c_xfer(port, addr, ®, 1, data_ptr, len, I2C_XFER_SINGLE); i2c_lock(port, 0); return rv; } /** * st_write_data_with_mask - Write register with mask * @s: Motion sensor pointer * @reg: Device register * @mask: The mask to search * @data: Data pointer */ int st_write_data_with_mask(const struct motion_sensor_t *s, int reg, uint8_t mask, uint8_t data) { int err; int new_data = 0x00, old_data = 0x00; err = st_raw_read8(s->port, s->addr, reg, &old_data); if (err != EC_SUCCESS) return err; new_data = ((old_data & (~mask)) | ((data << __builtin_ctz(mask)) & mask)); if (new_data == old_data) return EC_SUCCESS; return st_raw_write8(s->port, s->addr, reg, new_data); } /** * st_get_resolution - Get bit resolution * @s: Motion sensor pointer */ int st_get_resolution(const struct motion_sensor_t *s) { struct stprivate_data *data = s->drv_data; return data->resol; } /** * st_set_offset - Set data offset * @s: Motion sensor pointer * @offset: offset vector * @temp: Temp */ int st_set_offset(const struct motion_sensor_t *s, const int16_t *offset, int16_t temp) { struct stprivate_data *data = s->drv_data; data->offset[X] = offset[X]; data->offset[Y] = offset[Y]; data->offset[Z] = offset[Z]; return EC_SUCCESS; } /** * st_get_offset - Get data offset * @s: Motion sensor pointer * @offset: offset vector * @temp: Temp */ int st_get_offset(const struct motion_sensor_t *s, int16_t *offset, int16_t *temp) { struct stprivate_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; } /** * st_get_data_rate - Get data rate (ODR) * @s: Motion sensor pointer */ int st_get_data_rate(const struct motion_sensor_t *s) { struct stprivate_data *data = s->drv_data; return data->base.odr; } /** * st_normalize - Apply LSB data sens. and rotation based on sensor resolution * @s: Motion sensor pointer * @v: output vector * @data: LSB raw data */ void st_normalize(const struct motion_sensor_t *s, vector_3_t v, uint8_t *data) { int i, range; struct stprivate_data *drvdata = s->drv_data; for (i = X; i <= Z; i++) { v[i] = (int16_t)((data[i * 2 + 1] << 8) | data[i * 2]) >> (16 - drvdata->resol); } rotate(v, *s->rot_standard_ref, v); /* apply offset in the device coordinates */ range = s->drv->get_range(s); for (i = X; i <= Z; i++) v[i] += (drvdata->offset[i] << 5) / range; }