Files
OpenCellular/driver/stm_mems_common.c
Mario Tesi 87e769a87e driver: lsm6dsm/lsm6dsl: Add FIFO support
Added FIFO support to Acc and Gyro with
watermark interrupt management.
Watermark is configurable setting macro
CONFIG_ACCEL_FIFO_THRES properly (board.h)

BUG=b:73546254
BRANCH=master
TEST=Pass CTS test cheets_CTS_N.7.1_r15.x86.CtsHardwareTestCases
on meowth.
TEST=Tested on discovery (target stmems) BOARD with LSM6DSM
connected to EC i2c master bus.

Using motion sense console commands is possible to:
 - enable sensor (accelinit 0, accelinit 1 for acc and gyro)
 - set ODR (accelrate 0 x, accelrate 1 y where x, y are mHz)
 - show sensor data (accelinfo on <time> where time is in ms)

Using this procedure is possible to see Green Led of Discovery Board
Blinking each time an interrupt from FIFO arrives. To be sure to
generate interrupt is better to use high ODR and low time in accelinfo.

Change-Id: Icf95b0e889dc806206b8ca50e74636e6a2441a18
Signed-off-by: Mario Tesi <mario.tesi@st.com>
Reviewed-on: https://chromium-review.googlesource.com/467326
Commit-Ready: Gwendal Grignou <gwendal@chromium.org>
Tested-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
2018-04-05 18:41:12 -07:00

168 lines
3.8 KiB
C

/* 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"
/**
* Read single register
*/
int raw_read8(const int port, const int addr, const int reg, int *data_ptr)
{
/* TODO: Implement SPI interface support */
return i2c_read8(port, addr, reg, data_ptr);
}
/**
* Write single register
*/
int raw_write8(const int port, const int addr, const int reg, int data)
{
/* TODO: Implement SPI interface support */
return i2c_write8(port, addr, reg, data);
}
/**
* 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, &reg_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, &reg, 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 = 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 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;
}