| /* Copyright 2020 The ChromiumOS Authors |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* Volteer family-specific sensor configuration */ |
| #include "accelgyro.h" |
| #include "cbi_ec_fw_config.h" |
| #include "cbi_ssfc.h" |
| #include "common.h" |
| #include "driver/accel_bma2x2.h" |
| #include "driver/accel_kionix.h" |
| #include "driver/accelgyro_bmi160.h" |
| #include "driver/accelgyro_bmi_common.h" |
| #include "driver/accelgyro_icm42607.h" |
| #include "driver/accelgyro_icm426xx.h" |
| #include "driver/accelgyro_icm_common.h" |
| #include "driver/als_tcs3400.h" |
| #include "driver/sync.h" |
| #include "gpio.h" |
| #include "hooks.h" |
| #include "i2c.h" |
| #include "keyboard_scan.h" |
| #include "tablet_mode.h" |
| #include "task.h" |
| #include "util.h" |
| |
| #define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ##args) |
| /******************************************************************************/ |
| /* Sensors */ |
| static struct mutex g_lid_accel_mutex; |
| static struct mutex g_base_mutex; |
| |
| /* BMA253 private data */ |
| static struct accelgyro_saved_data_t g_bma253_data; |
| static struct kionix_accel_data g_kx022_data; |
| |
| /* BMI160 private data */ |
| static struct bmi_drv_data_t g_bmi160_data; |
| static struct icm_drv_data_t g_icm426xx_data; |
| |
| /* Rotation matrix for the lid accelerometer */ |
| static const mat33_fp_t lid_standard_ref = { { FLOAT_TO_FP(-1), 0, 0 }, |
| { 0, FLOAT_TO_FP(-1), 0 }, |
| { 0, 0, FLOAT_TO_FP(1) } }; |
| |
| const mat33_fp_t base_standard_ref = { { 0, FLOAT_TO_FP(1), 0 }, |
| { FLOAT_TO_FP(-1), 0, 0 }, |
| { 0, 0, FLOAT_TO_FP(1) } }; |
| |
| static const mat33_fp_t base_icm_ref = { { FLOAT_TO_FP(1), 0, 0 }, |
| { 0, FLOAT_TO_FP(1), 0 }, |
| { 0, 0, FLOAT_TO_FP(1) } }; |
| |
| struct motion_sensor_t kx022_lid_accel = { |
| .name = "Lid Accel", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_KX022, |
| .type = MOTIONSENSE_TYPE_ACCEL, |
| .location = MOTIONSENSE_LOC_LID, |
| .drv = &kionix_accel_drv, |
| .mutex = &g_lid_accel_mutex, |
| .drv_data = &g_kx022_data, |
| .port = I2C_PORT_ACCEL, |
| .i2c_spi_addr_flags = KX022_ADDR0_FLAGS, |
| .rot_standard_ref = &lid_standard_ref, |
| .min_frequency = KX022_ACCEL_MIN_FREQ, |
| .max_frequency = KX022_ACCEL_MAX_FREQ, |
| .default_range = 2, /* g, to support tablet mode */ |
| .config = { |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S0] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| }, |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S3] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| }, |
| }, |
| }; |
| |
| struct motion_sensor_t icm426xx_base_accel = { |
| .name = "Base Accel", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_ICM426XX, |
| .type = MOTIONSENSE_TYPE_ACCEL, |
| .location = MOTIONSENSE_LOC_BASE, |
| .drv = &icm426xx_drv, |
| .mutex = &g_base_mutex, |
| .drv_data = &g_icm426xx_data, |
| .port = I2C_PORT_ACCEL, |
| .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, |
| .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ |
| .rot_standard_ref = &base_icm_ref, |
| .min_frequency = ICM426XX_ACCEL_MIN_FREQ, |
| .max_frequency = ICM426XX_ACCEL_MAX_FREQ, |
| .config = { |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S0] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| .ec_rate = 100 * MSEC, |
| }, |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S3] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| .ec_rate = 100 * MSEC, |
| }, |
| }, |
| }; |
| |
| struct motion_sensor_t icm426xx_base_gyro = { |
| .name = "Base Gyro", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_ICM426XX, |
| .type = MOTIONSENSE_TYPE_GYRO, |
| .location = MOTIONSENSE_LOC_BASE, |
| .drv = &icm426xx_drv, |
| .mutex = &g_base_mutex, |
| .drv_data = &g_icm426xx_data, |
| .port = I2C_PORT_ACCEL, |
| .i2c_spi_addr_flags = ICM426XX_ADDR0_FLAGS, |
| .default_range = 1000, /* dps */ |
| .rot_standard_ref = &base_icm_ref, |
| .min_frequency = ICM426XX_GYRO_MIN_FREQ, |
| .max_frequency = ICM426XX_GYRO_MAX_FREQ, |
| }; |
| |
| struct motion_sensor_t icm42607_base_accel = { |
| .name = "Base Accel", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_ICM42607, |
| .type = MOTIONSENSE_TYPE_ACCEL, |
| .location = MOTIONSENSE_LOC_BASE, |
| .drv = &icm42607_drv, |
| .mutex = &g_base_mutex, |
| .drv_data = &g_icm426xx_data, |
| .port = I2C_PORT_SENSOR, |
| .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, |
| .default_range = 4, /* g, to meet CDD 7.3.1/C-1-4 reqs.*/ |
| .rot_standard_ref = &base_icm_ref, |
| .min_frequency = ICM42607_ACCEL_MIN_FREQ, |
| .max_frequency = ICM42607_ACCEL_MAX_FREQ, |
| .config = { |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S0] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| .ec_rate = 100 * MSEC, |
| }, |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S3] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| .ec_rate = 100 * MSEC, |
| }, |
| }, |
| }; |
| |
| struct motion_sensor_t icm42607_base_gyro = { |
| .name = "Base Gyro", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_ICM42607, |
| .type = MOTIONSENSE_TYPE_GYRO, |
| .location = MOTIONSENSE_LOC_BASE, |
| .drv = &icm42607_drv, |
| .mutex = &g_base_mutex, |
| .drv_data = &g_icm426xx_data, |
| .port = I2C_PORT_SENSOR, |
| .i2c_spi_addr_flags = ICM42607_ADDR0_FLAGS, |
| .default_range = 1000, /* dps */ |
| .rot_standard_ref = &base_icm_ref, |
| .min_frequency = ICM42607_GYRO_MIN_FREQ, |
| .max_frequency = ICM42607_GYRO_MAX_FREQ, |
| }; |
| |
| struct motion_sensor_t motion_sensors[] = { |
| [LID_ACCEL] = { |
| .name = "Lid Accel", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_BMA255, |
| .type = MOTIONSENSE_TYPE_ACCEL, |
| .location = MOTIONSENSE_LOC_LID, |
| .drv = &bma2x2_accel_drv, |
| .mutex = &g_lid_accel_mutex, |
| .drv_data = &g_bma253_data, |
| .port = I2C_PORT_SENSOR, |
| .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, |
| .rot_standard_ref = &lid_standard_ref, |
| .min_frequency = BMA255_ACCEL_MIN_FREQ, |
| .max_frequency = BMA255_ACCEL_MAX_FREQ, |
| .default_range = 2, /* g, to support tablet mode */ |
| .config = { |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S0] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| }, |
| /* Sensor on in S3 */ |
| [SENSOR_CONFIG_EC_S3] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| }, |
| }, |
| }, |
| [BASE_ACCEL] = { |
| .name = "Base Accel", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_BMI160, |
| .type = MOTIONSENSE_TYPE_ACCEL, |
| .location = MOTIONSENSE_LOC_BASE, |
| .drv = &bmi160_drv, |
| .mutex = &g_base_mutex, |
| .drv_data = &g_bmi160_data, |
| .port = I2C_PORT_SENSOR, |
| .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, |
| .rot_standard_ref = &base_standard_ref, |
| .min_frequency = BMI_ACCEL_MIN_FREQ, |
| .max_frequency = BMI_ACCEL_MAX_FREQ, |
| .default_range = 4, /* g */ |
| .config = { |
| /* EC use accel for angle detection */ |
| [SENSOR_CONFIG_EC_S0] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| .ec_rate = 100 * MSEC, |
| }, |
| /* Sensor on in S3 */ |
| [SENSOR_CONFIG_EC_S3] = { |
| .odr = 10000 | ROUND_UP_FLAG, |
| .ec_rate = 100 * MSEC, |
| }, |
| }, |
| }, |
| |
| [BASE_GYRO] = { |
| .name = "Base Gyro", |
| .active_mask = SENSOR_ACTIVE_S0_S3, |
| .chip = MOTIONSENSE_CHIP_BMI160, |
| .type = MOTIONSENSE_TYPE_GYRO, |
| .location = MOTIONSENSE_LOC_BASE, |
| .drv = &bmi160_drv, |
| .mutex = &g_base_mutex, |
| .drv_data = &g_bmi160_data, |
| .port = I2C_PORT_SENSOR, |
| .i2c_spi_addr_flags = BMI160_ADDR0_FLAGS, |
| .default_range = 1000, /* dps */ |
| .rot_standard_ref = &base_standard_ref, |
| .min_frequency = BMI_GYRO_MIN_FREQ, |
| .max_frequency = BMI_GYRO_MAX_FREQ, |
| }, |
| }; |
| unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); |
| |
| static enum ec_ssfc_base_sensor base_gyro_config = SSFC_SENSOR_BASE_DEFAULT; |
| |
| static void board_sensors_init(void) |
| { |
| base_gyro_config = get_cbi_ssfc_base_sensor(); |
| |
| if (ec_cfg_has_tabletmode()) { |
| if (base_gyro_config == SSFC_SENSOR_BASE_ICM426XX) { |
| motion_sensors[BASE_ACCEL] = icm426xx_base_accel; |
| motion_sensors[BASE_GYRO] = icm426xx_base_gyro; |
| ccprints("BASE GYRO is ICM426XX"); |
| } else if (base_gyro_config == SSFC_SENSOR_BASE_ICM42607) { |
| motion_sensors[BASE_ACCEL] = icm42607_base_accel; |
| motion_sensors[BASE_GYRO] = icm42607_base_gyro; |
| ccprints("BASE GYRO is ICM42607"); |
| } else |
| ccprints("BASE GYRO is BMI160"); |
| |
| if (get_cbi_ssfc_lid_sensor() == SSFC_SENSOR_LID_KX022) { |
| motion_sensors[LID_ACCEL] = kx022_lid_accel; |
| ccprints("LID_ACCEL is KX022"); |
| } else |
| ccprints("LID_ACCEL is BMA253"); |
| |
| motion_sensor_count = ARRAY_SIZE(motion_sensors); |
| /* Enable interrupt for the accel/gyro sensor */ |
| gpio_enable_interrupt(GPIO_EC_IMU_INT_L); |
| } else { |
| motion_sensor_count = 0; |
| gmr_tablet_switch_disable(); |
| /* Base accel is not stuffed, don't allow line to float */ |
| gpio_set_flags(GPIO_EC_IMU_INT_L, GPIO_INPUT | GPIO_PULL_DOWN); |
| } |
| } |
| DECLARE_HOOK(HOOK_INIT, board_sensors_init, HOOK_PRIO_DEFAULT); |
| |
| void motion_interrupt(enum gpio_signal signal) |
| { |
| switch (base_gyro_config) { |
| case SSFC_SENSOR_BASE_ICM426XX: |
| icm426xx_interrupt(signal); |
| break; |
| case SSFC_SENSOR_BASE_ICM42607: |
| icm42607_interrupt(signal); |
| break; |
| case SSFC_SENSOR_BASE_BMI160: |
| default: |
| bmi160_interrupt(signal); |
| break; |
| } |
| } |