mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 10:45:22 +00:00
driver: si114x: Add ALS/Proxy sensor SI114x
Add the Silicon Image sensors, add it to the motion_sense module to be used with the FIFO. BRANCH=smaug TEST=Check light and proxy on Smaug: Check Light value in Lux are reasonable. Check Proxy is detecting object, but value are in opposite of distance. BUG=chrome-os-partner:32829 Change-Id: I11419a0f0613f0fae9323f99deedf5a1e6c6e29c Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/291335 Reviewed-by: Sheng-liang Song <ssl@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
59138ad097
commit
bbbbde0fc0
545
driver/als_si114x.c
Normal file
545
driver/als_si114x.c
Normal file
@@ -0,0 +1,545 @@
|
||||
/* 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.
|
||||
*
|
||||
* Silicon Image SI1141/SI1142 light sensor driver
|
||||
*
|
||||
* Started from linux si114x driver.
|
||||
*/
|
||||
#include "accelgyro.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "driver/als_si114x.h"
|
||||
#include "hooks.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)
|
||||
#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args)
|
||||
|
||||
/**
|
||||
* Read 8bit register from device.
|
||||
*/
|
||||
static inline int raw_read8(const int addr, const int reg, int *data_ptr)
|
||||
{
|
||||
return i2c_read8(I2C_PORT_ALS, addr, reg, data_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 8bit register from device.
|
||||
*/
|
||||
static inline int raw_write8(const int addr, const int reg, int data)
|
||||
{
|
||||
return i2c_write8(I2C_PORT_ALS, addr, reg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 16bit register from device.
|
||||
*/
|
||||
static inline int raw_read16(const int addr, const int reg, int *data_ptr)
|
||||
{
|
||||
return i2c_read16(I2C_PORT_ALS, addr, reg, data_ptr);
|
||||
}
|
||||
|
||||
/* helper function to operate on parameter values: op can be query/set/or/and */
|
||||
static int si114x_param_op(const struct motion_sensor_t *s,
|
||||
uint8_t op,
|
||||
uint8_t param,
|
||||
int *value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(s->mutex);
|
||||
|
||||
if (op != SI114X_CMD_PARAM_QUERY) {
|
||||
ret = raw_write8(s->addr, SI114X_REG_PARAM_WR, *value);
|
||||
if (ret != EC_SUCCESS)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = raw_write8(s->addr, SI114X_REG_COMMAND, op | (param & 0x1F));
|
||||
if (ret != EC_SUCCESS)
|
||||
goto error;
|
||||
|
||||
ret = raw_read8(s->addr, SI114X_REG_PARAM_RD, value);
|
||||
if (ret != EC_SUCCESS)
|
||||
goto error;
|
||||
|
||||
mutex_unlock(s->mutex);
|
||||
|
||||
*value &= 0xff;
|
||||
return EC_SUCCESS;
|
||||
error:
|
||||
mutex_unlock(s->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int si114x_read_results(struct motion_sensor_t *s, int nb)
|
||||
{
|
||||
int i, ret, val;
|
||||
struct si114x_typed_data_t *type_data = SI114X_GET_TYPED_DATA(s);
|
||||
#ifdef CONFIG_ACCEL_FIFO
|
||||
struct ec_response_motion_sensor_data vector;
|
||||
#endif
|
||||
|
||||
/* Read ALX result */
|
||||
for (i = 0; i < nb; i++) {
|
||||
ret = raw_read16(s->addr, type_data->base_data_reg + i * 2,
|
||||
&val);
|
||||
if (ret)
|
||||
break;
|
||||
/* Add offset, calibration */
|
||||
if (val + type_data->offset < 0) {
|
||||
val = 0;
|
||||
} else {
|
||||
val += type_data->offset;
|
||||
val = val * type_data->scale +
|
||||
val * type_data->uscale / 10000;
|
||||
}
|
||||
s->raw_xyz[i] = val;
|
||||
}
|
||||
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* Add in fifo if changed only */
|
||||
for (i = 0; i < nb; i++) {
|
||||
if (s->raw_xyz[i] != s->xyz[i])
|
||||
break;
|
||||
}
|
||||
if (i == nb)
|
||||
return EC_SUCCESS;
|
||||
|
||||
#ifdef CONFIG_ACCEL_FIFO
|
||||
vector.flags = 0;
|
||||
for (i = 0; i < nb; i++)
|
||||
vector.data[i] = s->raw_xyz[i];
|
||||
for (i = nb; i < 3; i++)
|
||||
vector.data[i] = 0;
|
||||
motion_sense_fifo_add_unit(&vector, s, 1);
|
||||
#else
|
||||
/* We need to copy raw_xyz into xyz with mutex */
|
||||
#endif
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void si114x_interrupt(enum gpio_signal signal)
|
||||
{
|
||||
task_set_event(TASK_ID_MOTIONSENSE,
|
||||
CONFIG_ALS_SI114X_INT_EVENT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_handler - bottom half of the interrupt stack.
|
||||
* Ran from the motion_sense task, finds the events that raised the interrupt.
|
||||
*
|
||||
* For now, we just print out. We should set a bitmask motion sense code will
|
||||
* act upon.
|
||||
*/
|
||||
static int irq_handler(struct motion_sensor_t *s, uint32_t event)
|
||||
{
|
||||
int ret = EC_SUCCESS, val;
|
||||
struct si114x_drv_data_t *data = SI114X_GET_DATA(s);
|
||||
struct si114x_typed_data_t *type_data = SI114X_GET_TYPED_DATA(s);
|
||||
|
||||
if (!(event & CONFIG_ALS_SI114X_INT_EVENT))
|
||||
return EC_SUCCESS;
|
||||
|
||||
ret = raw_read8(s->addr, SI114X_REG_IRQ_STATUS, &val);
|
||||
if (ret < 0 || !(val & type_data->irq_flags))
|
||||
return EC_SUCCESS;
|
||||
|
||||
/* clearing IRQ */
|
||||
ret = raw_write8(s->addr, SI114X_REG_IRQ_STATUS,
|
||||
val & type_data->irq_flags);
|
||||
if (ret != EC_SUCCESS)
|
||||
CPRINTS("clearing irq failed");
|
||||
|
||||
switch (data->state) {
|
||||
case SI114X_ALS_IN_PROGRESS:
|
||||
case SI114X_ALS_IN_PROGRESS_PS_PENDING:
|
||||
/* We are only reading the visible light sensor */
|
||||
ret = si114x_read_results(s, 1);
|
||||
/* Fire pending requests */
|
||||
if (data->state == SI114X_ALS_IN_PROGRESS_PS_PENDING) {
|
||||
ret = raw_write8(s->addr, SI114X_REG_COMMAND,
|
||||
SI114X_CMD_PS_FORCE);
|
||||
data->state = SI114X_PS_IN_PROGRESS;
|
||||
} else {
|
||||
data->state = SI114X_IDLE;
|
||||
}
|
||||
break;
|
||||
case SI114X_PS_IN_PROGRESS:
|
||||
case SI114X_PS_IN_PROGRESS_ALS_PENDING:
|
||||
/* Read PS results */
|
||||
ret = si114x_read_results(s, SI114X_NUM_LEDS);
|
||||
if (data->state == SI114X_PS_IN_PROGRESS_ALS_PENDING) {
|
||||
ret = raw_write8(s->addr, SI114X_REG_COMMAND,
|
||||
SI114X_CMD_ALS_FORCE);
|
||||
data->state = SI114X_ALS_IN_PROGRESS;
|
||||
} else {
|
||||
data->state = SI114X_IDLE;
|
||||
}
|
||||
break;
|
||||
case SI114X_IDLE:
|
||||
default:
|
||||
CPRINTS("Invalid state");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Just trigger a measurement */
|
||||
static int read(const struct motion_sensor_t *s, vector_3_t v)
|
||||
{
|
||||
int ret;
|
||||
uint8_t cmd;
|
||||
struct si114x_drv_data_t *data = SI114X_GET_DATA(s);
|
||||
|
||||
switch (data->state) {
|
||||
case SI114X_ALS_IN_PROGRESS:
|
||||
if (s->type == MOTIONSENSE_TYPE_PROX)
|
||||
data->state = SI114X_ALS_IN_PROGRESS_PS_PENDING;
|
||||
#if 0
|
||||
else
|
||||
CPRINTS("Invalid state");
|
||||
#endif
|
||||
ret = EC_ERROR_BUSY;
|
||||
break;
|
||||
case SI114X_PS_IN_PROGRESS:
|
||||
if (s->type == MOTIONSENSE_TYPE_LIGHT)
|
||||
data->state = SI114X_PS_IN_PROGRESS_ALS_PENDING;
|
||||
#if 0
|
||||
else
|
||||
CPRINTS("Invalid state");
|
||||
#endif
|
||||
ret = EC_ERROR_BUSY;
|
||||
break;
|
||||
case SI114X_IDLE:
|
||||
switch (s->type) {
|
||||
case MOTIONSENSE_TYPE_LIGHT:
|
||||
cmd = SI114X_CMD_ALS_FORCE;
|
||||
data->state = SI114X_ALS_IN_PROGRESS;
|
||||
break;
|
||||
case MOTIONSENSE_TYPE_PROX:
|
||||
cmd = SI114X_CMD_PS_FORCE;
|
||||
data->state = SI114X_PS_IN_PROGRESS;
|
||||
break;
|
||||
default:
|
||||
CPRINTS("Invalid sensor type");
|
||||
}
|
||||
ret = raw_write8(s->addr, SI114X_REG_COMMAND, cmd);
|
||||
ret = EC_RES_IN_PROGRESS;
|
||||
break;
|
||||
case SI114X_ALS_IN_PROGRESS_PS_PENDING:
|
||||
case SI114X_PS_IN_PROGRESS_ALS_PENDING:
|
||||
default:
|
||||
ret = EC_ERROR_ACCESS_DENIED;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int si114x_set_chlist(const struct motion_sensor_t *s)
|
||||
{
|
||||
int reg = 0;
|
||||
|
||||
/* Not interested in temperature (AUX nor IR) */
|
||||
reg = SI114X_CHLIST_EN_ALSVIS;
|
||||
switch (SI114X_NUM_LEDS) {
|
||||
case 3:
|
||||
reg |= SI114X_CHLIST_EN_PS3;
|
||||
case 2:
|
||||
reg |= SI114X_CHLIST_EN_PS2;
|
||||
case 1:
|
||||
reg |= SI114X_CHLIST_EN_PS1;
|
||||
break;
|
||||
}
|
||||
|
||||
return si114x_param_op(s, SI114X_CMD_PARAM_SET,
|
||||
SI114X_PARAM_CHLIST, ®);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ALS_SI114X_CHECK_REVISION
|
||||
static int si114x_revisions(const struct motion_sensor_t *s)
|
||||
{
|
||||
int val;
|
||||
int ret = raw_read8(s->addr, SI114X_REG_PART_ID, &val);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if (val != CONFIG_ALS_SI114X) {
|
||||
CPRINTS("invalid part");
|
||||
return EC_ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
ret = raw_read8(s->addr, SI114X_REG_SEQ_ID, &val);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
if (val < SI114X_SEQ_REV_A03)
|
||||
CPRINTS("WARNING: old sequencer revision");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int si114x_initialize(const struct motion_sensor_t *s)
|
||||
{
|
||||
int ret, val;
|
||||
|
||||
/* send reset command */
|
||||
ret = raw_write8(s->addr, SI114X_REG_COMMAND, SI114X_CMD_RESET);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
msleep(20);
|
||||
|
||||
/* hardware key, magic value */
|
||||
ret = raw_write8(s->addr, SI114X_REG_HW_KEY, 0x17);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
msleep(20);
|
||||
|
||||
/* interrupt configuration, interrupt output enable */
|
||||
ret = raw_write8(s->addr, SI114X_REG_INT_CFG, SI114X_INT_CFG_OE);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* enable interrupt for certain activities */
|
||||
ret = raw_write8(s->addr, SI114X_REG_IRQ_ENABLE,
|
||||
SI114X_PS3_IE | SI114X_PS2_IE | SI114X_PS1_IE |
|
||||
SI114X_ALS_INT0_IE);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* Only forced mode */
|
||||
ret = raw_write8(s->addr, SI114X_REG_MEAS_RATE, 0);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* measure ALS every time device wakes up */
|
||||
ret = raw_write8(s->addr, SI114X_REG_ALS_RATE, 0);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* measure proximity every time device wakes up */
|
||||
ret = raw_write8(s->addr, SI114X_REG_PS_RATE, 0);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* set LED currents to maximum */
|
||||
switch (SI114X_NUM_LEDS) {
|
||||
case 3:
|
||||
ret = raw_write8(s->addr,
|
||||
SI114X_REG_PS_LED3, 0x0f);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
ret = raw_write8(s->addr,
|
||||
SI114X_REG_PS_LED21, 0xff);
|
||||
break;
|
||||
case 2:
|
||||
ret = raw_write8(s->addr,
|
||||
SI114X_REG_PS_LED21, 0xff);
|
||||
break;
|
||||
case 1:
|
||||
ret = raw_write8(s->addr,
|
||||
SI114X_REG_PS_LED21, 0x0f);
|
||||
break;
|
||||
}
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
ret = si114x_set_chlist(s);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* set normal proximity measurement mode, set high signal range
|
||||
* PS measurement */
|
||||
val = SI114X_PARAM_PS_ADC_MISC_NORMAL_MODE;
|
||||
ret = si114x_param_op(s, SI114X_CMD_PARAM_SET,
|
||||
SI114X_PARAM_PS_ADC_MISC, &val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_resolution(const struct motion_sensor_t *s,
|
||||
int res,
|
||||
int rnd)
|
||||
{
|
||||
int ret, reg1, reg2, val;
|
||||
/* override on resolution: set the gain. between 0 to 7 */
|
||||
if (s->type == MOTIONSENSE_TYPE_PROX) {
|
||||
if (res < 0 || res > 5)
|
||||
return EC_ERROR_PARAM2;
|
||||
reg1 = SI114X_PARAM_PS_ADC_GAIN;
|
||||
reg2 = SI114X_PARAM_PS_ADC_COUNTER;
|
||||
} else {
|
||||
if (res < 0 || res > 7)
|
||||
return EC_ERROR_PARAM2;
|
||||
reg1 = SI114X_PARAM_ALSVIS_ADC_GAIN;
|
||||
reg2 = SI114X_PARAM_ALSVIS_ADC_COUNTER;
|
||||
}
|
||||
|
||||
val = res;
|
||||
ret = si114x_param_op(s, SI114X_CMD_PARAM_SET, reg1, &val);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
/* set recovery period to one's complement of gain */
|
||||
val = (~res & 0x07) << 4;
|
||||
ret = si114x_param_op(s, SI114X_CMD_PARAM_SET, reg2, &val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_resolution(const struct motion_sensor_t *s,
|
||||
int *res)
|
||||
{
|
||||
int ret, reg, val;
|
||||
if (s->type == MOTIONSENSE_TYPE_PROX)
|
||||
reg = SI114X_PARAM_PS_ADC_GAIN;
|
||||
else
|
||||
/* ignore IR led */
|
||||
reg = SI114X_PARAM_ALSVIS_ADC_GAIN;
|
||||
|
||||
val = 0;
|
||||
ret = si114x_param_op(s, SI114X_CMD_PARAM_QUERY, reg, &val);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
|
||||
*res = val & 0x07;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int set_range(const struct motion_sensor_t *s,
|
||||
int range,
|
||||
int rnd)
|
||||
{
|
||||
struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s);
|
||||
data->scale = range >> 16;
|
||||
data->uscale = range & 0xffff;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int get_range(const struct motion_sensor_t *s,
|
||||
int *range)
|
||||
{
|
||||
struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s);
|
||||
*range = (data->scale << 16) | (data->uscale);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int get_data_rate(const struct motion_sensor_t *s,
|
||||
int *rate)
|
||||
{
|
||||
/* Sensor in forced mode, rate is used by motion_sense */
|
||||
struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s);
|
||||
*rate = data->rate;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int set_data_rate(const struct motion_sensor_t *s,
|
||||
int rate,
|
||||
int rnd)
|
||||
{
|
||||
struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s);
|
||||
data->rate = rate;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int set_offset(const struct motion_sensor_t *s,
|
||||
const int16_t *offset,
|
||||
int16_t temp)
|
||||
{
|
||||
struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s);
|
||||
data->offset = offset[X];
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int get_offset(const struct motion_sensor_t *s,
|
||||
int16_t *offset,
|
||||
int16_t *temp)
|
||||
{
|
||||
struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s);
|
||||
offset[X] = data->offset;
|
||||
offset[Y] = 0;
|
||||
offset[Z] = 0;
|
||||
*temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int set_interrupt(const struct motion_sensor_t *s,
|
||||
unsigned int threshold)
|
||||
{
|
||||
/* Currently unsupported. */
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
static int init(const struct motion_sensor_t *s)
|
||||
{
|
||||
int ret, resol;
|
||||
|
||||
/* initialize only once: light must be declared first. */
|
||||
if (s->type == MOTIONSENSE_TYPE_LIGHT) {
|
||||
#ifdef CONFIG_ALS_SI114X_CHECK_REVISION
|
||||
ret = si114x_revisions(s);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
#endif
|
||||
ret = si114x_initialize(s);
|
||||
if (ret != EC_SUCCESS)
|
||||
return ret;
|
||||
resol = 7;
|
||||
} else {
|
||||
resol = 5;
|
||||
}
|
||||
|
||||
set_range(s, s->runtime_config.range, 0);
|
||||
/*
|
||||
* Sensor is most likely behind a glass.
|
||||
* Max out the gain to get correct measurement
|
||||
*/
|
||||
set_resolution(s, resol, 0);
|
||||
|
||||
CPRINTF("[%T %s: MS Done Init type:0x%X range:%d]\n",
|
||||
s->name, s->type, s->runtime_config.range);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
const struct accelgyro_drv si114x_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,
|
||||
.irq_handler = irq_handler,
|
||||
#endif
|
||||
.load_fifo = NULL,
|
||||
};
|
||||
|
||||
struct si114x_drv_data_t g_si114x_data = {
|
||||
.state = SI114X_IDLE,
|
||||
.type_data = {
|
||||
/* Proximity */
|
||||
{
|
||||
.base_data_reg = SI114X_REG_PS1_DATA0,
|
||||
.irq_flags = SI114X_PS_INT_FLAG,
|
||||
.scale = 1,
|
||||
.offset = -256,
|
||||
},
|
||||
/* light */
|
||||
{
|
||||
.base_data_reg = SI114X_REG_ALSVIS_DATA0,
|
||||
.irq_flags = SI114X_ALS_INT_FLAG,
|
||||
.scale = 1,
|
||||
.offset = -256,
|
||||
}
|
||||
}
|
||||
};
|
||||
245
driver/als_si114x.h
Normal file
245
driver/als_si114x.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/* 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.
|
||||
*
|
||||
* Silicon Image SI1141/SI1142 light sensor driver
|
||||
*/
|
||||
|
||||
/*
|
||||
* si114x.c - Support for Silabs si114x combined ambient light and
|
||||
* proximity sensor
|
||||
*
|
||||
* Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net>
|
||||
*
|
||||
* This file is subject to the terms and conditions of version 2 of
|
||||
* the GNU General Public License. See the file COPYING in the main
|
||||
* directory of this archive for more details.
|
||||
*
|
||||
* IIO driver for si114x (7-bit I2C slave address 0x5a) with sequencer
|
||||
* version >= A03
|
||||
*/
|
||||
|
||||
#ifndef __CROS_EC_ALS_SI114X_H
|
||||
#define __CROS_EC_ALS_SI114X_H
|
||||
|
||||
#define SI114X_ADDR (0x5a << 1)
|
||||
|
||||
#define SI114X_REG_PART_ID 0x00
|
||||
#define SI114X_SI1141_ID 0x41
|
||||
#define SI114X_SI1142_ID 0x42
|
||||
#define SI114X_SI1143_ID 0x43
|
||||
|
||||
#define SI114X_NUM_LEDS (CONFIG_ALS_SI114X - 0x40)
|
||||
|
||||
#define SI114X_REG_REV_ID 0x01
|
||||
#define SI114X_REG_SEQ_ID 0x02
|
||||
#define SI114X_REG_INT_CFG 0x03
|
||||
#define SI114X_REG_IRQ_ENABLE 0x04
|
||||
#define SI114X_REG_IRQ_MODE1 0x05
|
||||
#define SI114X_REG_IRQ_MODE2 0x06
|
||||
#define SI114X_REG_HW_KEY 0x07
|
||||
/* RATE stores a 16 bit value compressed to 8 bit */
|
||||
/* Not used, the sensor is in force mode */
|
||||
#define SI114X_REG_MEAS_RATE 0x08
|
||||
|
||||
|
||||
#define SI114X_REG_ALS_RATE 0x09
|
||||
#define SI114X_REG_PS_RATE 0x0a
|
||||
#define SI114X_REG_ALS_LOW_TH0 0x0b
|
||||
#define SI114X_REG_ALS_LOW_TH1 0x0c
|
||||
#define SI114X_REG_ALS_HI_TH0 0x0d
|
||||
#define SI114X_REG_ALS_HI_TH1 0x0e
|
||||
#define SI114X_REG_PS_LED21 0x0f
|
||||
#define SI114X_REG_PS_LED3 0x10
|
||||
/*
|
||||
* for rev A10 and below TH0 stores a 16 bit value compressed to 8 bit and
|
||||
* TH1 is not used; newer revision have the LSB in TH0 and the MSB in TH1
|
||||
*/
|
||||
#define SI114X_REG_PS1_TH0 0x11
|
||||
#define SI114X_REG_PS1_TH1 0x12
|
||||
#define SI114X_REG_PS2_TH0 0x13
|
||||
#define SI114X_REG_PS2_TH1 0x11
|
||||
#define SI114X_REG_PS3_TH0 0x15
|
||||
#define SI114X_REG_PS3_TH1 0x16
|
||||
#define SI114X_REG_PARAM_WR 0x17
|
||||
#define SI114X_REG_COMMAND 0x18
|
||||
#define SI114X_REG_RESPONSE 0x20
|
||||
#define SI114X_REG_IRQ_STATUS 0x21
|
||||
#define SI114X_REG_ALSVIS_DATA0 0x22
|
||||
#define SI114X_REG_ALSVIS_DATA1 0x23
|
||||
#define SI114X_REG_ALSIR_DATA0 0x24
|
||||
#define SI114X_REG_ALSIR_DATA1 0x25
|
||||
#define SI114X_REG_PS1_DATA0 0x26
|
||||
#define SI114X_REG_PS1_DATA1 0x27
|
||||
#define SI114X_REG_PS2_DATA0 0x28
|
||||
#define SI114X_REG_PS2_DATA1 0x29
|
||||
#define SI114X_REG_PS3_DATA0 0x2a
|
||||
#define SI114X_REG_PS3_DATA1 0x2b
|
||||
#define SI114X_REG_AUX_DATA0 0x2c
|
||||
#define SI114X_REG_AUX_DATA1 0x2d
|
||||
#define SI114X_REG_PARAM_RD 0x2e
|
||||
#define SI114X_REG_CHIP_STAT 0x30
|
||||
|
||||
/* helper to figure out PS_LED register / shift per channel */
|
||||
#define SI114X_PS_LED_REG(ch) \
|
||||
(((ch) == 2) ? SI114X_REG_PS_LED3 : SI114X_REG_PS_LED21)
|
||||
#define SI114X_PS_LED_SHIFT(ch) \
|
||||
(((ch) == 1) ? 4 : 0)
|
||||
|
||||
/* Parameter offsets */
|
||||
#define SI114X_PARAM_I2C_ADDR 0x00
|
||||
#define SI114X_PARAM_CHLIST 0x01
|
||||
#define SI114X_PARAM_PSLED12_SELECT 0x02
|
||||
#define SI114X_PARAM_PSLED3_SELECT 0x03
|
||||
#define SI114X_PARAM_FILTER_EN 0x04
|
||||
#define SI114X_PARAM_PS_ENCODING 0x05
|
||||
#define SI114X_PARAM_ALS_ENCODING 0x06
|
||||
#define SI114X_PARAM_PS1_ADC_MUX 0x07
|
||||
#define SI114X_PARAM_PS2_ADC_MUX 0x08
|
||||
#define SI114X_PARAM_PS3_ADC_MUX 0x09
|
||||
#define SI114X_PARAM_PS_ADC_COUNTER 0x0a
|
||||
#define SI114X_PARAM_PS_ADC_GAIN 0x0b
|
||||
#define SI114X_PARAM_PS_ADC_MISC 0x0c
|
||||
#define SI114X_PARAM_PS_ADC_MISC_HIGH_RANGE 0x20
|
||||
#define SI114X_PARAM_PS_ADC_MISC_NORMAL_MODE 0x04
|
||||
#define SI114X_PARAM_ALS_ADC_MUX 0x0d
|
||||
#define SI114X_PARAM_ALSIR_ADC_MUX 0x0e
|
||||
#define SI114X_PARAM_AUX_ADC_MUX 0x0f
|
||||
#define SI114X_PARAM_ALSVIS_ADC_COUNTER 0x10
|
||||
#define SI114X_PARAM_ALSVIS_ADC_GAIN 0x11
|
||||
#define SI114X_PARAM_ALSVIS_ADC_MISC 0x12
|
||||
#define SI114X_PARAM_ALS_HYST 0x16
|
||||
#define SI114X_PARAM_PS_HYST 0x17
|
||||
#define SI114X_PARAM_PS_HISTORY 0x18
|
||||
#define SI114X_PARAM_ALS_HISTORY 0x19
|
||||
#define SI114X_PARAM_ADC_OFFSET 0x1a
|
||||
#define SI114X_PARAM_SLEEP_CTRL 0x1b
|
||||
#define SI114X_PARAM_LED_RECOVERY 0x1c
|
||||
#define SI114X_PARAM_ALSIR_ADC_COUNTER 0x1d
|
||||
#define SI114X_PARAM_ALSIR_ADC_GAIN 0x1e
|
||||
#define SI114X_PARAM_ALSIR_ADC_MISC 0x1f
|
||||
|
||||
/* Channel enable masks for CHLIST parameter */
|
||||
#define SI114X_CHLIST_EN_PS1 0x01
|
||||
#define SI114X_CHLIST_EN_PS2 0x02
|
||||
#define SI114X_CHLIST_EN_PS3 0x04
|
||||
#define SI114X_CHLIST_EN_ALSVIS 0x10
|
||||
#define SI114X_CHLIST_EN_ALSIR 0x20
|
||||
#define SI114X_CHLIST_EN_AUX 0x40
|
||||
|
||||
/* Signal range mask for ADC_MISC parameter */
|
||||
#define SI114X_MISC_RANGE 0x20
|
||||
|
||||
/* Commands for REG_COMMAND */
|
||||
#define SI114X_CMD_NOP 0x00
|
||||
#define SI114X_CMD_RESET 0x01
|
||||
#define SI114X_CMD_BUSADDR 0x02
|
||||
#define SI114X_CMD_PS_FORCE 0x05
|
||||
#define SI114X_CMD_ALS_FORCE 0x06
|
||||
#define SI114X_CMD_PSALS_FORCE 0x07
|
||||
#define SI114X_CMD_PS_PAUSE 0x09
|
||||
#define SI114X_CMD_ALS_PAUSE 0x0a
|
||||
#define SI114X_CMD_PSALS_PAUSE 0x0b
|
||||
#define SI114X_CMD_PS_AUTO 0x0d
|
||||
#define SI114X_CMD_ALS_AUTO 0x0e
|
||||
#define SI114X_CMD_PSALS_AUTO 0x0f
|
||||
#define SI114X_CMD_PARAM_QUERY 0x80
|
||||
#define SI114X_CMD_PARAM_SET 0xa0
|
||||
#define SI114X_CMD_PARAM_AND 0xc0
|
||||
#define SI114X_CMD_PARAM_OR 0xe0
|
||||
|
||||
/* Interrupt configuration masks for INT_CFG register */
|
||||
#define SI114X_INT_CFG_OE 0x01 /* enable interrupt */
|
||||
#define SI114X_INT_CFG_MODE 0x02 /* auto reset interrupt pin */
|
||||
|
||||
/* Interrupt enable masks for IRQ_ENABLE register */
|
||||
#define SI114X_CMD_IE 0x20
|
||||
#define SI114X_PS3_IE 0x10
|
||||
#define SI114X_PS2_IE 0x08
|
||||
#define SI114X_PS1_IE 0x04
|
||||
#define SI114X_ALS_INT1_IE 0x02
|
||||
#define SI114X_ALS_INT0_IE 0x01
|
||||
#define SI114X_ALS_INT_FLAG \
|
||||
(SI114X_ALS_INT1_IE | SI114X_ALS_INT0_IE)
|
||||
#define SI114X_PS_INT_FLAG \
|
||||
(SI114X_PS3_IE | SI114X_PS2_IE | SI114X_PS1_IE)
|
||||
|
||||
|
||||
/* Interrupt mode masks for IRQ_MODE1 register */
|
||||
#define SI114X_PS2_IM_GREATER 0xc0
|
||||
#define SI114X_PS2_IM_CROSS 0x40
|
||||
#define SI114X_PS1_IM_GREATER 0x30
|
||||
#define SI114X_PS1_IM_CROSS 0x10
|
||||
|
||||
/* Interrupt mode masks for IRQ_MODE2 register */
|
||||
#define SI114X_CMD_IM_ERROR 0x04
|
||||
#define SI114X_PS3_IM_GREATER 0x03
|
||||
#define SI114X_PS3_IM_CROSS 0x01
|
||||
|
||||
/* Measurement rate settings */
|
||||
#define SI114X_MEAS_RATE_FORCED 0x00
|
||||
#define SI114X_MEAS_RATE_10MS 0x84
|
||||
#define SI114X_MEAS_RATE_20MS 0x94
|
||||
#define SI114X_MEAS_RATE_100MS 0xb9
|
||||
#define SI114X_MEAS_RATE_496MS 0xdf
|
||||
#define SI114X_MEAS_RATE_1984MS 0xff
|
||||
|
||||
/* ALS rate settings relative to measurement rate */
|
||||
#define SI114X_ALS_RATE_OFF 0x00
|
||||
#define SI114X_ALS_RATE_1X 0x08
|
||||
#define SI114X_ALS_RATE_10X 0x32
|
||||
#define SI114X_ALS_RATE_100X 0x69
|
||||
|
||||
/* PS rate settings relative to measurement rate */
|
||||
#define SI114X_PS_RATE_OFF 0x00
|
||||
#define SI114X_PS_RATE_1X 0x08
|
||||
#define SI114X_PS_RATE_10X 0x32
|
||||
#define SI114X_PS_RATE_100X 0x69
|
||||
|
||||
/* Sequencer revision from SEQ_ID */
|
||||
#define SI114X_SEQ_REV_A01 0x01
|
||||
#define SI114X_SEQ_REV_A02 0x02
|
||||
#define SI114X_SEQ_REV_A03 0x03
|
||||
#define SI114X_SEQ_REV_A10 0x08
|
||||
#define SI114X_SEQ_REV_A11 0x09
|
||||
|
||||
extern const struct accelgyro_drv si114x_drv;
|
||||
|
||||
enum si114x_state {
|
||||
SI114X_IDLE,
|
||||
SI114X_ALS_IN_PROGRESS,
|
||||
SI114X_ALS_IN_PROGRESS_PS_PENDING,
|
||||
SI114X_PS_IN_PROGRESS,
|
||||
SI114X_PS_IN_PROGRESS_ALS_PENDING,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct si114x_data - si114x chip state data
|
||||
* @client: I2C client
|
||||
**/
|
||||
struct si114x_typed_data_t {
|
||||
uint8_t base_data_reg;
|
||||
uint8_t irq_flags;
|
||||
/* requested frequency, in mHz */
|
||||
int rate;
|
||||
/* the coef is scale.uscale */
|
||||
int16_t scale;
|
||||
uint16_t uscale;
|
||||
int16_t offset;
|
||||
};
|
||||
|
||||
struct si114x_drv_data_t {
|
||||
enum si114x_state state;
|
||||
struct si114x_typed_data_t type_data[2];
|
||||
};
|
||||
|
||||
#define SI114X_GET_DATA(_s) \
|
||||
((struct si114x_drv_data_t *)(_s)->drv_data)
|
||||
|
||||
#define SI114X_GET_TYPED_DATA(_s) \
|
||||
(&SI114X_GET_DATA(_s)->type_data[(_s)->type - MOTIONSENSE_TYPE_PROX])
|
||||
|
||||
extern struct si114x_drv_data_t g_si114x_data;
|
||||
void si114x_interrupt(enum gpio_signal signal);
|
||||
|
||||
#endif /* __CROS_EC_ALS_SI114X_H */
|
||||
@@ -15,6 +15,7 @@ driver-$(CONFIG_MAG_BMI160_BMM150)+=mag_bmm150.o
|
||||
# ALS drivers
|
||||
driver-$(CONFIG_ALS_ISL29035)+=als_isl29035.o
|
||||
driver-$(CONFIG_ALS_OPT3001)+=als_opt3001.o
|
||||
driver-$(CONFIG_ALS_SI114X)+=als_si114x.o
|
||||
|
||||
# Batteries
|
||||
driver-$(CONFIG_BATTERY_BQ20Z453)+=battery/bq20z453.o
|
||||
|
||||
@@ -71,6 +71,15 @@
|
||||
#undef CONFIG_ALS
|
||||
#undef CONFIG_ALS_ISL29035
|
||||
#undef CONFIG_ALS_OPT3001
|
||||
/* Define the exact model ID present on the board: SI1141 = 41, SI1142 = 42, */
|
||||
#undef CONFIG_ALS_SI114X
|
||||
/* Check if the device revision is supported */
|
||||
#undef CONFIG_ALS_SI114X_CHECK_REVISION
|
||||
/*
|
||||
* Define the event to raise when BMI160 interrupt.
|
||||
* Must be within TASK_EVENT_MOTION_INTERRUPT_MASK.
|
||||
*/
|
||||
#undef CONFIG_ALS_SI114X_INT_EVENT
|
||||
|
||||
/* Support AP hang detection host command and state machine */
|
||||
#undef CONFIG_AP_HANG_DETECT
|
||||
|
||||
@@ -1709,14 +1709,16 @@ enum motionsensor_type {
|
||||
MOTIONSENSE_TYPE_ACCEL = 0,
|
||||
MOTIONSENSE_TYPE_GYRO = 1,
|
||||
MOTIONSENSE_TYPE_MAG = 2,
|
||||
MOTIONSENSE_TYPE_MAX = 3,
|
||||
MOTIONSENSE_TYPE_PROX = 3,
|
||||
MOTIONSENSE_TYPE_LIGHT = 4,
|
||||
MOTIONSENSE_TYPE_MAX,
|
||||
};
|
||||
|
||||
/* List of motion sensor locations. */
|
||||
enum motionsensor_location {
|
||||
MOTIONSENSE_LOC_BASE = 0,
|
||||
MOTIONSENSE_LOC_LID = 1,
|
||||
MOTIONSENSE_LOC_MAX = 2,
|
||||
MOTIONSENSE_LOC_MAX,
|
||||
};
|
||||
|
||||
/* List of motion sensor chips. */
|
||||
@@ -1724,6 +1726,9 @@ enum motionsensor_chip {
|
||||
MOTIONSENSE_CHIP_KXCJ9 = 0,
|
||||
MOTIONSENSE_CHIP_LSM6DS0 = 1,
|
||||
MOTIONSENSE_CHIP_BMI160 = 2,
|
||||
MOTIONSENSE_CHIP_SI1141 = 3,
|
||||
MOTIONSENSE_CHIP_SI1142 = 4,
|
||||
MOTIONSENSE_CHIP_SI1143 = 5,
|
||||
};
|
||||
|
||||
struct ec_response_motion_sensor_data {
|
||||
|
||||
Reference in New Issue
Block a user