nova: Support ALS TCS3400
Support ALS TCS3400
BUG=b:328711879
TEST=make BOARD=nova
Change-Id: I9bba39cf1217a9e43a66e23333c56828d845de12
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/5501358
Reviewed-by: Forest Mittelberg <bmbm@google.com>
Auto-Submit: Yu-An Chen <yu-an.chen@quanta.corp-partner.google.com>
Reviewed-by: Bruce Goodwin <bgoodwin@chromium.org>
Commit-Queue: Yu-An Chen <yu-an.chen@quanta.corp-partner.google.com>
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Tested-by: Yu-An Chen <yu-an.chen@quanta.corp-partner.google.com>
diff --git a/board/nova/board.h b/board/nova/board.h
index fd0e46b..59ee29b 100644
--- a/board/nova/board.h
+++ b/board/nova/board.h
@@ -59,6 +59,7 @@
#define GPIO_RECOVERY_L_2 GPIO_GSC_EC_RECOVERY_BTN_OD
/* I2C Bus Configuration */
+#define I2C_PORT_SENSOR NPCX_I2C_PORT3_0
#define I2C_PORT_EEPROM NPCX_I2C_PORT7_0
#define I2C_PORT_MP2964 NPCX_I2C_PORT7_0
@@ -139,6 +140,27 @@
/* Include math_util for bitmask_uint64 used in pd_timers */
#define CONFIG_MATH_UTIL
+/* Sensor */
+#undef CONFIG_MOTION_SENSE_RESUME_DELAY_US
+#define CONFIG_MOTION_SENSE_RESUME_DELAY_US (1000 * MSEC)
+#define CONFIG_CMD_ACCEL_INFO
+/* Enable sensor fifo, must also define the _SIZE and _THRES */
+#define CONFIG_ACCEL_FIFO
+/* FIFO size is in power of 2. */
+#define CONFIG_ACCEL_FIFO_SIZE 256
+/* Depends on how fast the AP boots and typical ODRs */
+#define CONFIG_ACCEL_FIFO_THRES (CONFIG_ACCEL_FIFO_SIZE / 3)
+
+/* TCS3400 ALS */
+#define CONFIG_ALS
+#define ALS_COUNT 1
+#define CONFIG_ALS_TCS3400
+#define CONFIG_ALS_TCS3400_INT_EVENT \
+ TASK_EVENT_MOTION_SENSOR_INTERRUPT(CLEAR_ALS)
+
+/* Sensors without hardware FIFO are in forced mode */
+#define CONFIG_ACCEL_FORCE_MODE_MASK BIT(CLEAR_ALS)
+
#ifndef __ASSEMBLER__
#include "gpio_signal.h" /* needed by registers.h */
@@ -154,6 +176,12 @@
ADC_CH_COUNT
};
+enum sensor_id {
+ CLEAR_ALS,
+ RGB_ALS,
+ SENSOR_COUNT,
+};
+
enum temp_sensor_id {
TEMP_SENSOR_1_CPU,
TEMP_SENSOR_2_CPU_VR,
diff --git a/board/nova/ec.tasklist b/board/nova/ec.tasklist
index 91f90aa..e8e7f82 100644
--- a/board/nova/ec.tasklist
+++ b/board/nova/ec.tasklist
@@ -12,6 +12,7 @@
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \
diff --git a/board/nova/gpio.inc b/board/nova/gpio.inc
index 341ca99..1ddfba5 100644
--- a/board/nova/gpio.inc
+++ b/board/nova/gpio.inc
@@ -79,6 +79,8 @@
/* I2C SCL/SDA */
GPIO(EC_I2C_MISC_SCL_R, PIN(B, 3), GPIO_INPUT)
GPIO(EC_I2C_MISC_SDA_R, PIN(B, 2), GPIO_INPUT)
+GPIO(EC_I2C_ALS_SCL, PIN(D, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_I2C_ALS_SCL */
+GPIO(EC_I2C_ALS_SDA, PIN(D, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_I2C_ALS_SDA */
/* USBA */
GPIO(EN_PP5000_USBA, PIN(D, 7), GPIO_OUT_LOW)
@@ -152,8 +154,6 @@
UNUSED(PIN(B, 4)) /* GPIOB4/I2C0_SDA0 */
UNUSED(PIN(9, 2)) /* GPIO92/I2C2_SCL0 */
UNUSED(PIN(9, 1)) /* GPIO91/I2C2_SDA0 */
-UNUSED(PIN(D, 1)) /* GPIOD1/I2C3_SCL0 */
-UNUSED(PIN(D, 0)) /* GPIOD0/I2C3_SDA0 */
UNUSED(PIN(F, 3)) /* GPIOF3/I2C4_SCL1 */
UNUSED(PIN(F, 2)) /* GPIOF2/I2C4_SDA1 */
UNUSED(PIN(E, 4)) /* GPIOE4/I2C6_SCL1 */
diff --git a/board/nova/i2c.c b/board/nova/i2c.c
index 18650c2..e02668b 100644
--- a/board/nova/i2c.c
+++ b/board/nova/i2c.c
@@ -10,6 +10,14 @@
/* I2C port map configuration */
const struct i2c_port_t i2c_ports[] = {
{
+ /* I2C3 */
+ .name = "sensor",
+ .port = I2C_PORT_SENSOR,
+ .kbps = 400,
+ .scl = GPIO_EC_I2C_ALS_SCL,
+ .sda = GPIO_EC_I2C_ALS_SDA,
+ },
+ {
/* I2C7 */
.name = "eeprom",
.port = I2C_PORT_EEPROM,
diff --git a/board/nova/sensors.c b/board/nova/sensors.c
index 811a84b..9948d4d 100644
--- a/board/nova/sensors.c
+++ b/board/nova/sensors.c
@@ -5,6 +5,7 @@
#include "adc_chip.h"
#include "common.h"
+#include "driver/als_tcs3400.h"
#include "hooks.h"
#include "temp_sensor.h"
#include "temp_sensor/thermistor.h"
@@ -107,3 +108,98 @@
[TEMP_SENSOR_4_DIMM] = thermal_cpu,
};
BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT);
+
+/* TCS3400 private data */
+static struct als_drv_data_t g_tcs3400_data = {
+ .als_cal.scale = 1,
+ .als_cal.uscale = 0,
+ .als_cal.offset = 0,
+ .als_cal.channel_scale = {
+ .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc */
+ .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */
+ },
+};
+
+static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = {
+ /*
+ * b/202465034: calculate the actual coefficients and scaling factors
+ */
+ .calibration.rgb_cal[X] = {
+ .offset = 0,
+ .scale = {
+ .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */
+ .cover_scale = ALS_CHANNEL_SCALE(1.0)
+ },
+ .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0),
+ },
+ .calibration.rgb_cal[Y] = {
+ .offset = 0,
+ .scale = {
+ .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */
+ .cover_scale = ALS_CHANNEL_SCALE(1.0)
+ },
+ .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0.1),
+ },
+ .calibration.rgb_cal[Z] = {
+ .offset = 0,
+ .scale = {
+ .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */
+ .cover_scale = ALS_CHANNEL_SCALE(1.0)
+ },
+ .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0),
+ .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0),
+ },
+ .calibration.irt = INT_TO_FP(1),
+ .saturation.again = TCS_DEFAULT_AGAIN,
+ .saturation.atime = TCS_DEFAULT_ATIME,
+};
+
+struct motion_sensor_t motion_sensors[] = {
+ [CLEAR_ALS] = {
+ .name = "Clear Light",
+ .active_mask = SENSOR_ACTIVE_S0,
+ .chip = MOTIONSENSE_CHIP_TCS3400,
+ .type = MOTIONSENSE_TYPE_LIGHT,
+ .location = MOTIONSENSE_LOC_BASE,
+ .drv = &tcs3400_drv,
+ .drv_data = &g_tcs3400_data,
+ .port = I2C_PORT_SENSOR,
+ .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS,
+ .rot_standard_ref = NULL,
+ .default_range = 0x10000, /* scale = 1x, uscale = 0 */
+ .min_frequency = TCS3400_LIGHT_MIN_FREQ,
+ .max_frequency = TCS3400_LIGHT_MAX_FREQ,
+ .config = {
+ /* Run ALS sensor in S0 */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 1000,
+ },
+ },
+ },
+ [RGB_ALS] = {
+ .name = "RGB Light",
+ .active_mask = SENSOR_ACTIVE_S0,
+ .chip = MOTIONSENSE_CHIP_TCS3400,
+ .type = MOTIONSENSE_TYPE_LIGHT_RGB,
+ .location = MOTIONSENSE_LOC_BASE,
+ .drv = &tcs3400_rgb_drv,
+ .drv_data = &g_tcs3400_rgb_data,
+ .rot_standard_ref = NULL,
+ .default_range = 0x10000, /* scale = 1x, uscale = 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[CLEAR_ALS],
+};
+BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT);