summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/reef/board.c55
-rw-r--r--board/reef/board.h17
-rw-r--r--board/reef/ec.tasklist1
-rw-r--r--common/motion_sense.c16
-rw-r--r--driver/als_opt3001.c211
-rw-r--r--driver/als_opt3001.h44
-rw-r--r--include/ec_commands.h1
-rw-r--r--include/motion_sense.h4
-rw-r--r--util/ectool.c3
9 files changed, 326 insertions, 26 deletions
diff --git a/board/reef/board.c b/board/reef/board.c
index 7074ab4952..141a1cd3e0 100644
--- a/board/reef/board.c
+++ b/board/reef/board.c
@@ -7,7 +7,6 @@
#include "adc.h"
#include "adc_chip.h"
-#include "als.h"
#include "button.h"
#include "charge_manager.h"
#include "charge_ramp.h"
@@ -216,6 +215,8 @@ struct i2c_stress_test i2c_stress_tests[] = {
#endif
#ifdef CONFIG_CMD_I2C_STRESS_TEST_ALS
{
+ .port = I2C_PORT_ALS,
+ .addr = OPT3001_I2C_ADDR1,
.i2c_test = &opt3001_i2c_stress_test_dev,
},
#endif
@@ -441,13 +442,6 @@ const struct temp_sensor_t temp_sensors[] = {
};
BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT);
-/* ALS instances. Must be in same order as enum als_id. */
-struct als_t als[] = {
- /* FIXME(dhendrix): verify attenuation_factor */
- {"TI", opt3001_init, opt3001_read_lux, 5},
-};
-BUILD_ASSERT(ARRAY_SIZE(als) == ALS_COUNT);
-
const struct button_config buttons[CONFIG_BUTTON_COUNT] = {
{"Volume Down", KEYBOARD_BUTTON_VOLUME_DOWN, GPIO_EC_VOLDN_BTN_ODL,
30 * MSEC, 0},
@@ -779,10 +773,13 @@ const matrix_3x3_t mag_standard_ref = {
{ 0, 0, FLOAT_TO_FP(-1)}
};
+/* sensor private data */
struct kionix_accel_data g_kx022_data;
struct bmi160_drv_data_t g_bmi160_data;
struct bmp280_drv_data_t bmp280_drv_data;
-
+struct opt3001_drv_data_t g_opt3001_data = {
+ .attenuation = 5,
+};
/* FIXME(dhendrix): Copied from Amenia, probably need to tweak for Reef */
struct motion_sensor_t motion_sensors[] = {
@@ -967,9 +964,49 @@ struct motion_sensor_t motion_sensors[] = {
},
},
},
+ [LID_ALS] = {
+ .name = "Light",
+ .active_mask = SENSOR_ACTIVE_S0_S3,
+ .chip = MOTIONSENSE_CHIP_OPT3001,
+ .type = MOTIONSENSE_TYPE_LIGHT,
+ .location = MOTIONSENSE_LOC_LID,
+ .drv = &opt3001_drv,
+ .drv_data = &g_opt3001_data,
+ .port = I2C_PORT_ALS,
+ .addr = OPT3001_I2C_ADDR1,
+ .rot_standard_ref = NULL,
+ .default_range = OPT3001_RANGE_AUTOMATIC_FULL_SCALE,
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 1000,
+ .ec_rate = 0,
+ },
+ /* Sensor off in S3/S5 */
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* Sensor off in S3/S5 */
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ },
+ },
};
const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors);
+/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */
+const struct motion_sensor_t *motion_als_sensors[] = {
+ &motion_sensors[LID_ALS],
+};
+BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT);
+
void board_hibernate(void)
{
/*
diff --git a/board/reef/board.h b/board/reef/board.h
index 0dd246b429..0e7ef3b2e0 100644
--- a/board/reef/board.h
+++ b/board/reef/board.h
@@ -202,7 +202,6 @@
#define CONFIG_MAG_CALIBRATE
#define CONFIG_ACCEL_KX022
#define CONFIG_ALS_OPT3001
-#define OPT3001_I2C_ADDR OPT3001_I2C_ADDR1
#define CONFIG_BARO_BMP280
#define CONFIG_LID_ANGLE
#define CONFIG_LID_ANGLE_UPDATE
@@ -257,12 +256,13 @@ enum temp_sensor_id {
TEMP_SENSOR_COUNT
};
-/* Light sensors */
-enum als_id {
- ALS_OPT3001 = 0,
-
- ALS_COUNT
-};
+/*
+ * For backward compatibility, to report ALS via ACPI,
+ * Define the number of ALS sensors: motion_sensor copy the data to the ALS
+ * memmap region.
+ */
+#define CONFIG_ALS
+#define ALS_COUNT 1
/*
* Motion sensors:
@@ -276,6 +276,7 @@ enum sensor_id {
BASE_GYRO,
BASE_MAG,
BASE_BARO,
+ LID_ALS,
};
enum reef_board_version {
@@ -319,7 +320,7 @@ void board_print_tcpc_fw_version(int port);
/* Sensors without hardware FIFO are in forced mode */
#define CONFIG_ACCEL_FORCE_MODE_MASK \
- ((1 << LID_ACCEL) | (1 << BASE_BARO))
+ ((1 << LID_ACCEL) | (1 << BASE_BARO) | (1 << LID_ALS))
#endif /* !__ASSEMBLER__ */
diff --git a/board/reef/ec.tasklist b/board/reef/ec.tasklist
index 47e0048872..e153496b43 100644
--- a/board/reef/ec.tasklist
+++ b/board/reef/ec.tasklist
@@ -22,7 +22,6 @@
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
- TASK_ALWAYS(ALS, als_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(USB_CHG, usb_charger_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \
diff --git a/common/motion_sense.c b/common/motion_sense.c
index 442e957540..2b9d715343 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -575,10 +575,13 @@ static inline void set_present(uint8_t *lpc_status)
#ifdef UPDATE_HOST_MEM_MAP
/* Update/Write LPC data */
-static inline void update_sense_data(uint8_t *lpc_status,
- uint16_t *lpc_data, int *psample_id)
+static inline void update_sense_data(uint8_t *lpc_status, int *psample_id)
{
int i;
+ uint16_t *lpc_data = (uint16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA);
+#if (!defined HAS_TASK_ALS) && (defined CONFIG_ALS)
+ uint16_t *lpc_als = (uint16_t *)host_get_memmap(EC_MEMMAP_ALS);
+#endif
struct motion_sensor_t *sensor;
/*
* Set the busy bit before writing the sensor data. Increment
@@ -610,6 +613,11 @@ static inline void update_sense_data(uint8_t *lpc_status,
lpc_data[3+3*i] = sensor->xyz[Z];
}
+#if (!defined HAS_TASK_ALS) && (defined CONFIG_ALS)
+ for (i = 0; i < EC_ALS_ENTRIES && i < ALS_COUNT; i++)
+ lpc_als[i] = motion_als_sensors[i]->xyz[X];
+#endif
+
/*
* Increment sample id and clear busy bit to signal we finished
* updating data.
@@ -727,10 +735,8 @@ void motion_sense_task(void)
#ifdef UPDATE_HOST_MEM_MAP
int sample_id = 0;
uint8_t *lpc_status;
- uint16_t *lpc_data;
lpc_status = host_get_memmap(EC_MEMMAP_ACC_STATUS);
- lpc_data = (uint16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA);
set_present(lpc_status);
#endif
@@ -832,7 +838,7 @@ void motion_sense_task(void)
}
#endif
#ifdef UPDATE_HOST_MEM_MAP
- update_sense_data(lpc_status, lpc_data, &sample_id);
+ update_sense_data(lpc_status, &sample_id);
#endif
ts_end_task = get_time();
diff --git a/driver/als_opt3001.c b/driver/als_opt3001.c
index bbf61a1064..7e080e8c89 100644
--- a/driver/als_opt3001.c
+++ b/driver/als_opt3001.c
@@ -8,6 +8,7 @@
#include "driver/als_opt3001.h"
#include "i2c.h"
+#ifdef HAS_TASK_ALS
/**
* Read register from OPT3001 light sensor.
*/
@@ -98,4 +99,212 @@ struct i2c_stress_test_dev opt3001_i2c_stress_test_dev = {
.i2c_read_dev = &opt3001_i2c_read,
.i2c_write_dev = &opt3001_i2c_write,
};
-#endif /* CONFIG_CMD_I2C_STRESS_TEST_ALS */
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_ALS */
+#else /* HAS_TASK_ALS */
+#include "accelgyro.h"
+#include "math_util.h"
+
+/**
+ * Read register from OPT3001 light sensor.
+ */
+static int opt3001_i2c_read(const int port, const int addr, const int reg,
+ int *data_ptr)
+{
+ int ret;
+
+ ret = i2c_read16(port, addr, reg, data_ptr);
+ if (!ret)
+ *data_ptr = ((*data_ptr << 8) & 0xFF00) |
+ ((*data_ptr >> 8) & 0x00FF);
+
+ return ret;
+}
+
+/**
+ * Write register to OPT3001 light sensor.
+ */
+static int opt3001_i2c_write(const int port, const int addr, const int reg,
+ int data)
+{
+ data = ((data << 8) & 0xFF00) | ((data >> 8) & 0x00FF);
+ return i2c_write16(port, addr, reg, data);
+}
+
+/**
+ * Read OPT3001 light sensor data.
+ */
+int opt3001_read_lux(const struct motion_sensor_t *s, vector_3_t v)
+{
+ struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s);
+ int ret;
+ int data;
+
+ ret = opt3001_i2c_read(s->port, s->addr, OPT3001_REG_RESULT, &data);
+ if (ret)
+ return ret;
+
+ /*
+ * The default power-on values will give 12 bits of precision:
+ * 0x0000-0x0fff indicates 0 to 1310.40 lux. We multiply the sensor
+ * value by a scaling factor to account for attenuation by glass,
+ * tinting, etc.
+ */
+
+ /*
+ * lux = 2EXP[3:0] × R[11:0] / 100
+ */
+ v[0] = ((1 << ((data & 0xF000) >> 12)) * (data & 0x0FFF) *
+ drv_data->attenuation) / 100;
+ v[1] = 0;
+ v[2] = 0;
+
+ /*
+ * Return an error when nothing change to prevent filling the
+ * fifo with useless data.
+ */
+ if (v[0] == drv_data->last_value)
+ return EC_ERROR_UNCHANGED;
+ else
+ return EC_SUCCESS;
+}
+
+static int opt3001_set_range(const struct motion_sensor_t *s, int range,
+ int rnd)
+{
+ int rv;
+ int reg;
+ struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s);
+
+ if (range < 0 || range > OPT3001_RANGE_AUTOMATIC_FULL_SCALE)
+ return EC_ERROR_INVAL;
+
+ rv = opt3001_i2c_read(s->port, s->addr, OPT3001_REG_CONFIGURE, &reg);
+ if (rv)
+ return rv;
+
+ rv = opt3001_i2c_write(s->port, s->addr, OPT3001_REG_CONFIGURE,
+ (reg & OPT3001_RANGE_MASK) |
+ (range << OPT3001_RANGE_OFFSET));
+ if (rv)
+ return rv;
+
+ drv_data->range = range;
+
+ return EC_SUCCESS;
+}
+
+static int opt3001_get_range(const struct motion_sensor_t *s)
+{
+ struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s);
+
+ return drv_data->range;
+}
+
+static int opt3001_set_data_rate(const struct motion_sensor_t *s,
+ int rate, int roundup)
+{
+ struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s);
+ int rv;
+ int reg;
+ enum opt3001_mode mode;
+
+ if (rate == 0) {
+ /*
+ * Suspend driver:
+ */
+ mode = OPT3001_MODE_SUSPEND;
+ } else {
+ mode = OPT3001_MODE_CONTINUOUS;
+ /*
+ * We set the sensor for continuous mode,
+ * integrating over 800ms.
+ * Do not allow range higher than 1Hz.
+ */
+ if (rate > 1000)
+ rate = 1000;
+ }
+ rv = opt3001_i2c_read(s->port, s->addr, OPT3001_REG_CONFIGURE, &reg);
+ if (rv)
+ return rv;
+
+ rv = opt3001_i2c_write(s->port, s->addr, OPT3001_REG_CONFIGURE,
+ (reg & OPT3001_MODE_MASK) |
+ (mode << OPT3001_MODE_OFFSET));
+ if (rv)
+ return rv;
+
+ drv_data->rate = rate;
+ return EC_SUCCESS;
+}
+
+static int opt3001_get_data_rate(const struct motion_sensor_t *s)
+{
+ struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s);
+
+ return drv_data->rate;
+}
+
+static int opt3001_set_offset(const struct motion_sensor_t *s,
+ const int16_t *offset,
+ int16_t temp)
+{
+ return EC_RES_INVALID_COMMAND;
+}
+
+static int opt3001_get_offset(const struct motion_sensor_t *s,
+ int16_t *offset,
+ int16_t *temp)
+{
+ return EC_RES_INVALID_COMMAND;
+}
+/**
+ * Initialise OPT3001 light sensor.
+ */
+static int opt3001_init(const struct motion_sensor_t *s)
+{
+ int data;
+ int ret;
+
+ ret = opt3001_i2c_read(s->port, s->addr, OPT3001_REG_MAN_ID, &data);
+ if (ret)
+ return ret;
+ if (data != OPT3001_MANUFACTURER_ID)
+ return EC_ERROR_ACCESS_DENIED;
+
+ ret = opt3001_i2c_read(s->port, s->addr, OPT3001_REG_DEV_ID, &data);
+ if (ret)
+ return ret;
+ if (data != OPT3001_DEVICE_ID)
+ return EC_ERROR_ACCESS_DENIED;
+
+ /*
+ * [11] : 1b Conversion time 800ms
+ * [4] : 1b Latched window-style comparison operation
+ */
+ opt3001_i2c_write(s->port, s->addr, OPT3001_REG_CONFIGURE, 0x810);
+ return opt3001_set_range(s, s->default_range, 0);
+}
+
+const struct accelgyro_drv opt3001_drv = {
+ .init = opt3001_init,
+ .read = opt3001_read_lux,
+ .set_range = opt3001_set_range,
+ .get_range = opt3001_get_range,
+ .set_offset = opt3001_set_offset,
+ .get_offset = opt3001_get_offset,
+ .set_data_rate = opt3001_set_data_rate,
+ .get_data_rate = opt3001_get_data_rate,
+};
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ALS
+struct i2c_stress_test_dev opt3001_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = OPT3001_REG_DEV_ID,
+ .read_val = OPT3001_DEVICE_ID,
+ .write_reg = OPT3001_REG_INT_LIMIT_LSB,
+ },
+ .i2c_read = &opt3001_i2c_read,
+ .i2c_write = &opt3001_i2c_write,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_ALS */
+#endif /* HAS_TASK_ALS */
diff --git a/driver/als_opt3001.h b/driver/als_opt3001.h
index 366e957995..b70909f630 100644
--- a/driver/als_opt3001.h
+++ b/driver/als_opt3001.h
@@ -17,17 +17,57 @@
/* OPT3001 registers */
#define OPT3001_REG_RESULT 0x00
#define OPT3001_REG_CONFIGURE 0x01
+#define OPT3001_RANGE_OFFSET 12
+#define OPT3001_RANGE_MASK 0x0fff
+#define OPT3001_MODE_OFFSET 9
+#define OPT3001_MODE_MASK 0xf9ff
+enum opt3001_mode {
+ OPT3001_MODE_SUSPEND,
+ OPT3001_MODE_FORCED,
+ OPT3001_MODE_CONTINUOUS,
+};
+
#define OPT3001_REG_INT_LIMIT_LSB 0x02
#define OPT3001_REG_INT_LIMIT_MSB 0x03
-#define OPT3001_REG_MAN_ID 0x7E
-#define OPT3001_REG_DEV_ID 0x7F
+#define OPT3001_REG_MAN_ID 0x7e
+#define OPT3001_REG_DEV_ID 0x7f
/* OPT3001 register values */
#define OPT3001_MANUFACTURER_ID 0x5449
#define OPT3001_DEVICE_ID 0x3001
+#ifdef HAS_TASK_ALS
int opt3001_init(void);
int opt3001_read_lux(int *lux, int af);
+#else
+/* OPT3001 Full-Scale Range */
+enum opt3001_range {
+ OPT3001_RANGE_40P95_LUX,
+ OPT3001_RANGE_81P90_LUX,
+ OPT3001_RANGE_163P80_LUX,
+ OPT3001_RANGE_327P60_LUX,
+ OPT3001_RANGE_655P20_LUX,
+ OPT3001_RANGE_1310P40_LUX,
+ OPT3001_RANGE_2620P80_LUX,
+ OPT3001_RANGE_5241P60_LUX,
+ OPT3001_RANGE_10483P20_LUX,
+ OPT3001_RANGE_20966P40_LUX,
+ OPT3001_RANGE_41932P80_LUX,
+ OPT3001_RANGE_83865P60_LUX,
+ OPT3001_RANGE_AUTOMATIC_FULL_SCALE,
+};
+
+#define OPT3001_GET_DATA(_s) ((struct opt3001_drv_data_t *)(_s)->drv_data)
+
+struct opt3001_drv_data_t {
+ enum opt3001_range range;
+ int rate;
+ int last_value;
+ int attenuation;
+};
+
+extern const struct accelgyro_drv opt3001_drv;
+#endif
#ifdef CONFIG_CMD_I2C_STRESS_TEST_ALS
extern struct i2c_stress_test_dev opt3001_i2c_stress_test_dev;
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 86fac1d45c..c65d7f9d0c 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1950,6 +1950,7 @@ enum motionsensor_chip {
MOTIONSENSE_CHIP_L3GD20H = 7,
MOTIONSENSE_CHIP_BMA255 = 8,
MOTIONSENSE_CHIP_BMP280 = 9,
+ MOTIONSENSE_CHIP_OPT3001 = 10,
};
struct __ec_todo_packed ec_response_motion_sensor_data {
diff --git a/include/motion_sense.h b/include/motion_sense.h
index 3e56e7597b..0ca7443b98 100644
--- a/include/motion_sense.h
+++ b/include/motion_sense.h
@@ -146,6 +146,10 @@ struct motion_sensor_t {
/* Defined at board level. */
extern struct motion_sensor_t motion_sensors[];
extern const unsigned motion_sensor_count;
+#if (!defined HAS_TASK_ALS) && (defined CONFIG_ALS)
+/* Needed if reading ALS via LPC is needed */
+extern const struct motion_sensor_t *motion_als_sensors[];
+#endif
/* optionally defined at board level */
extern unsigned int motion_min_interval;
diff --git a/util/ectool.c b/util/ectool.c
index 3375935d4b..cb90d1af51 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -3632,6 +3632,9 @@ static int cmd_motionsense(int argc, char **argv)
case MOTIONSENSE_CHIP_BMP280:
printf("bmp280\n");
break;
+ case MOTIONSENSE_CHIP_OPT3001:
+ printf("opt3001\n");
+ break;
default:
printf("unknown\n");
}